Compare commits
12 Commits
6f2f58fbe9
...
6de437634c
Author | SHA1 | Date | |
---|---|---|---|
6de437634c | |||
af92c1ca00 | |||
53128f0685 | |||
13eb6a75a9 | |||
78d3175151 | |||
b7f71f6018 | |||
da363831e8 | |||
02cc14d9f6 | |||
00551ec8fe | |||
0da862a180 | |||
8fc219ad38 | |||
d13cfad70c |
@ -3,7 +3,8 @@ import request from '@/config/axios'
|
||||
// 付费会员权益 VO
|
||||
export interface PaidMemberBenefitVO {
|
||||
id: number // 编号
|
||||
name: string // 名称
|
||||
benName: string // 权益名称
|
||||
showName: string // 展示名称
|
||||
iconUrl: string // 图标地址
|
||||
intro: string // 描述
|
||||
status: boolean // 状态:(默认)0隐藏 1显示
|
||||
|
49
yudao-admin-vue3/src/api/mall/promotion/pointorder/index.ts
Normal file
@ -0,0 +1,49 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 兑换记录 VO
|
||||
export interface PointOrderVO {
|
||||
id: number // id
|
||||
orderNumber: string // 订单号
|
||||
userId: number // 用户id
|
||||
productId: number // 商品id
|
||||
integral: number // 兑换积分
|
||||
orderStatus: number // 订单状态
|
||||
orderTime: Date // 下单时间
|
||||
userName: string
|
||||
productName: string
|
||||
imageUrl: string
|
||||
|
||||
}
|
||||
|
||||
// 兑换记录 API
|
||||
export const PointOrderApi = {
|
||||
// 查询兑换记录分页
|
||||
getPointOrderPage: async (params: any) => {
|
||||
return await request.get({ url: `/promotion/point-order/page`, params })
|
||||
},
|
||||
|
||||
// 查询兑换记录详情
|
||||
getPointOrder: async (id: number) => {
|
||||
return await request.get({ url: `/promotion/point-order/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增兑换记录
|
||||
createPointOrder: async (data: PointOrderVO) => {
|
||||
return await request.post({ url: `/promotion/point-order/create`, data })
|
||||
},
|
||||
|
||||
// 修改兑换记录
|
||||
updatePointOrder: async (data: PointOrderVO) => {
|
||||
return await request.put({ url: `/promotion/point-order/update`, data })
|
||||
},
|
||||
|
||||
// 删除兑换记录
|
||||
deletePointOrder: async (id: number) => {
|
||||
return await request.delete({ url: `/promotion/point-order/delete?id=` + id })
|
||||
},
|
||||
|
||||
// 导出兑换记录 Excel
|
||||
exportPointOrder: async (params) => {
|
||||
return await request.download({ url: `/promotion/point-order/export-excel`, params })
|
||||
},
|
||||
}
|
45
yudao-admin-vue3/src/api/member/type/index.ts
Normal file
@ -0,0 +1,45 @@
|
||||
import request from '@/config/axios'
|
||||
|
||||
// 会员卡类型 VO
|
||||
export interface cardVO {
|
||||
id: number // id
|
||||
name: string // 会员名
|
||||
vid: string // 有效期
|
||||
originalPrice: number // 原价
|
||||
specialPrice: number // 优惠价
|
||||
sort: string // 排序
|
||||
status: number// 是否禁用
|
||||
}
|
||||
|
||||
// 会员卡类型 API
|
||||
export const cardApi = {
|
||||
// 查询会员卡类型分页
|
||||
getcardPage: async (params: any) => {
|
||||
return await request.get({ url: `/paid/member/card/type/page`, params })
|
||||
},
|
||||
|
||||
// 查询会员卡类型详情
|
||||
getcard: async (id: number) => {
|
||||
return await request.get({ url: `/paid/member/card/type/get?id=` + id })
|
||||
},
|
||||
|
||||
// 新增会员卡类型
|
||||
createcard: async (data: cardVO) => {
|
||||
return await request.post({ url: `/paid/member/card/type/create`, data })
|
||||
},
|
||||
|
||||
// 修改会员卡类型
|
||||
updatecard: async (data: cardVO) => {
|
||||
return await request.put({ url: `/paid/member/card/type/update`, data })
|
||||
},
|
||||
|
||||
// 删除会员卡类型
|
||||
deletecard: async (id: number) => {
|
||||
return await request.delete({ url: `/paid/member/card/type/delete?id=` + id })
|
||||
},
|
||||
|
||||
// 导出会员卡类型 Excel
|
||||
exportcard: async (params) => {
|
||||
return await request.download({ url: `/paid/member/card/type/export-excel`, params })
|
||||
},
|
||||
}
|
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-01.png
Normal file
After Width: | Height: | Size: 640 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-02.png
Normal file
After Width: | Height: | Size: 573 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-03.png
Normal file
After Width: | Height: | Size: 462 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-04.png
Normal file
After Width: | Height: | Size: 615 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-05.png
Normal file
After Width: | Height: | Size: 369 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-06.png
Normal file
After Width: | Height: | Size: 534 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-07.png
Normal file
After Width: | Height: | Size: 466 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-08.png
Normal file
After Width: | Height: | Size: 480 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-09.png
Normal file
After Width: | Height: | Size: 514 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-10.png
Normal file
After Width: | Height: | Size: 404 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-11.png
Normal file
After Width: | Height: | Size: 545 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-12.png
Normal file
After Width: | Height: | Size: 335 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-13.png
Normal file
After Width: | Height: | Size: 529 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-14.png
Normal file
After Width: | Height: | Size: 759 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-15.png
Normal file
After Width: | Height: | Size: 609 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-16.png
Normal file
After Width: | Height: | Size: 440 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-17.png
Normal file
After Width: | Height: | Size: 821 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-18.png
Normal file
After Width: | Height: | Size: 814 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-19.png
Normal file
After Width: | Height: | Size: 604 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-20.png
Normal file
After Width: | Height: | Size: 339 B |
BIN
yudao-admin-vue3/src/assets/imgs/DiyEditorImges/组件图标-21.png
Normal file
After Width: | Height: | Size: 573 B |
BIN
yudao-admin-vue3/src/assets/imgs/userCar/seckilbg.png
Normal file
After Width: | Height: | Size: 36 KiB |
@ -23,8 +23,11 @@
|
||||
<div>
|
||||
<div class="drag-placement">组件放置区域</div>
|
||||
<div class="component">
|
||||
<Icon :icon="element.icon" :size="32" />
|
||||
<span class="mt-4px text-12px">{{ element.name }}</span>
|
||||
<!-- <Icon :icon="element.icon" :size="32" /> -->
|
||||
<div>
|
||||
<img :src="element.icon" />
|
||||
</div>
|
||||
<span class="text-12px">{{ element.name }}</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -142,8 +145,9 @@ const handleCloneComponent = (component: DiyComponent<any>) => {
|
||||
|
||||
.component.active,
|
||||
.component:hover {
|
||||
color: var(--el-color-white);
|
||||
background: var(--el-color-primary);
|
||||
// color: var(--el-color-white);
|
||||
// background: var(--el-color-primary);
|
||||
background: #f6f6f6;
|
||||
|
||||
.el-icon {
|
||||
color: var(--el-color-white);
|
||||
|
@ -26,12 +26,13 @@ export interface CarouselItemProperty {
|
||||
// 跳转链接
|
||||
url: string
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-09.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'Carousel',
|
||||
name: '轮播图',
|
||||
icon: 'system-uicons:carousel',
|
||||
// icon: 'system-uicons:carousel',
|
||||
icon: logo,
|
||||
property: {
|
||||
type: 'default',
|
||||
indicator: 'dot',
|
||||
|
@ -67,7 +67,8 @@ export const CouponValidTerm = defineComponent({
|
||||
coupon.validEndTime,
|
||||
'YYYY-MM-DD'
|
||||
)}`
|
||||
: `领取后第 ${coupon.fixedStartTerm} - ${coupon.fixedEndTerm} 天内可用`
|
||||
// : `领取后第 ${coupon.fixedStartTerm} - ${coupon.fixedEndTerm} 天内可用`
|
||||
: `领取后 ${coupon.fixedEndTerm} 天内可用`
|
||||
return () => <div>{text}</div>
|
||||
}
|
||||
})
|
||||
|
@ -22,12 +22,13 @@ export interface CouponCardProperty {
|
||||
// 组件样式
|
||||
style: ComponentStyle
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-19.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'CouponCard',
|
||||
name: '优惠券',
|
||||
icon: 'ep:ticket',
|
||||
// icon: 'ep:ticket',
|
||||
icon: logo,
|
||||
property: {
|
||||
columns: 1,
|
||||
bgImg: '',
|
||||
|
@ -13,12 +13,13 @@ export interface DividerProperty {
|
||||
// 类型
|
||||
borderType: 'solid' | 'dashed' | 'dotted' | 'none'
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-12.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'Divider',
|
||||
name: '分割线',
|
||||
icon: 'tdesign:component-divider-vertical',
|
||||
// icon: 'tdesign:component-divider-vertical',
|
||||
icon: logo,
|
||||
property: {
|
||||
height: 30,
|
||||
lineWidth: 1,
|
||||
|
@ -21,12 +21,13 @@ export interface FloatingActionButtonItemProperty {
|
||||
// 文字颜色
|
||||
textColor: string
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-07.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'FloatingActionButton',
|
||||
name: '悬浮按钮',
|
||||
icon: 'tabler:float-right',
|
||||
// icon: 'tabler:float-right',
|
||||
icon: logo,
|
||||
position: 'fixed',
|
||||
property: {
|
||||
direction: 'vertical',
|
||||
|
@ -25,12 +25,13 @@ export interface HotZoneItemProperty {
|
||||
// 左
|
||||
left: number
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-14.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'HotZone',
|
||||
name: '热区',
|
||||
icon: 'tabler:hand-click',
|
||||
// icon: 'tabler:hand-click',
|
||||
icon: logo,
|
||||
property: {
|
||||
imgUrl: '',
|
||||
list: [] as HotZoneItemProperty[],
|
||||
|
@ -9,12 +9,13 @@ export interface ImageBarProperty {
|
||||
// 组件样式
|
||||
style: ComponentStyle
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-08.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'ImageBar',
|
||||
name: '图片展示',
|
||||
icon: 'ep:picture',
|
||||
// icon: 'ep:picture',
|
||||
icon: logo,
|
||||
property: {
|
||||
imgUrl: '',
|
||||
url: '',
|
||||
|
@ -29,12 +29,13 @@ export interface MagicCubeItemProperty {
|
||||
// 左
|
||||
left: number
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-13.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'MagicCube',
|
||||
name: '广告魔方',
|
||||
icon: 'bi:columns',
|
||||
// icon: 'bi:columns',
|
||||
icon: logo,
|
||||
property: {
|
||||
borderRadiusTop: 0,
|
||||
borderRadiusBottom: 0,
|
||||
|
@ -49,12 +49,13 @@ export const EMPTY_MENU_GRID_ITEM_PROPERTY = {
|
||||
bgColor: '#FF6000'
|
||||
}
|
||||
} as MenuGridItemProperty
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-04.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'MenuGrid',
|
||||
name: '宫格导航',
|
||||
icon: 'bi:grid-3x3-gap',
|
||||
// icon: 'bi:grid-3x3-gap',
|
||||
icon: logo,
|
||||
property: {
|
||||
column: 3,
|
||||
list: [cloneDeep(EMPTY_MENU_GRID_ITEM_PROPERTY)],
|
||||
|
@ -6,6 +6,7 @@
|
||||
<el-radio-group v-model="formData.column">
|
||||
<el-radio :label="3">3个</el-radio>
|
||||
<el-radio :label="4">4个</el-radio>
|
||||
<el-radio :label="5">5个</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
|
||||
|
@ -31,12 +31,13 @@ export const EMPTY_MENU_LIST_ITEM_PROPERTY = {
|
||||
subtitle: '副标题',
|
||||
subtitleColor: '#bbb'
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-05.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'MenuList',
|
||||
name: '列表导航',
|
||||
icon: 'fa-solid:list',
|
||||
// icon: 'fa-solid:list',
|
||||
icon: logo,
|
||||
property: {
|
||||
list: [cloneDeep(EMPTY_MENU_LIST_ITEM_PROPERTY)],
|
||||
style: {
|
||||
|
@ -46,12 +46,13 @@ export const EMPTY_MENU_SWIPER_ITEM_PROPERTY = {
|
||||
bgColor: '#FF6000'
|
||||
}
|
||||
} as MenuSwiperItemProperty
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-03.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'MenuSwiper',
|
||||
name: '菜单导航',
|
||||
icon: 'bi:grid-3x2-gap',
|
||||
// icon: 'bi:grid-3x2-gap',
|
||||
icon: logo,
|
||||
property: {
|
||||
layout: 'iconText',
|
||||
row: 1,
|
||||
|
@ -21,12 +21,13 @@ export interface NoticeContentProperty {
|
||||
// 链接地址
|
||||
url: string
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-02.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'NoticeBar',
|
||||
name: '公告栏',
|
||||
icon: 'ep:bell',
|
||||
// icon: 'ep:bell',
|
||||
icon: logo,
|
||||
property: {
|
||||
iconUrl: 'http://mall.yudao.iocoder.cn/static/images/xinjian.png',
|
||||
contents: [
|
||||
|
@ -13,12 +13,13 @@ export interface PopoverItemProperty {
|
||||
// 显示类型:仅显示一次、每次启动都会显示
|
||||
showType: 'once' | 'always'
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-06.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'Popover',
|
||||
name: '弹窗广告',
|
||||
icon: 'carbon:popup',
|
||||
// icon: 'carbon:popup',
|
||||
icon: logo,
|
||||
position: 'fixed',
|
||||
property: {
|
||||
list: [{ showType: 'once' }]
|
||||
|
@ -57,12 +57,13 @@ export interface ProductCardFieldProperty {
|
||||
// 颜色
|
||||
color: string
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-15.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'ProductCard',
|
||||
name: '商品卡片',
|
||||
icon: 'fluent:text-column-two-left-24-filled',
|
||||
// icon: 'fluent:text-column-two-left-24-filled',
|
||||
icon: logo,
|
||||
property: {
|
||||
layoutType: 'oneColBigImg',
|
||||
fields: {
|
||||
|
@ -36,12 +36,13 @@ export interface ProductListFieldProperty {
|
||||
// 颜色
|
||||
color: string
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-16.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'ProductList',
|
||||
name: '商品栏',
|
||||
icon: 'fluent:text-column-two-24-filled',
|
||||
// icon: 'fluent:text-column-two-24-filled',
|
||||
icon: logo,
|
||||
property: {
|
||||
layoutType: 'twoCol',
|
||||
fields: {
|
||||
|
@ -7,12 +7,13 @@ export interface PromotionArticleProperty {
|
||||
// 组件样式
|
||||
style: ComponentStyle
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-20.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'PromotionArticle',
|
||||
name: '营销文章',
|
||||
icon: 'ph:article-medium',
|
||||
// icon: 'ph:article-medium',
|
||||
icon: logo,
|
||||
property: {
|
||||
style: {
|
||||
bgType: 'color',
|
||||
|
@ -37,12 +37,13 @@ export interface PromotionCombinationFieldProperty {
|
||||
// 颜色
|
||||
color: string
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-17.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'PromotionCombination',
|
||||
name: '拼团',
|
||||
icon: 'mdi:account-group',
|
||||
// icon: 'mdi:account-group',
|
||||
icon: logo,
|
||||
property: {
|
||||
layoutType: 'oneCol',
|
||||
fields: {
|
||||
|
@ -58,12 +58,13 @@ export interface PromotionPointFieldProperty {
|
||||
// 颜色
|
||||
color: string
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-21.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'PromotionPoint',
|
||||
name: '积分商城',
|
||||
icon: 'ep:present',
|
||||
// icon: 'ep:present',
|
||||
icon: logo,
|
||||
property: {
|
||||
layoutType: 'oneColBigImg',
|
||||
fields: {
|
||||
|
@ -36,12 +36,13 @@ export interface PromotionSeckillFieldProperty {
|
||||
// 颜色
|
||||
color: string
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-18.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'PromotionSeckill',
|
||||
name: '秒杀',
|
||||
icon: 'mdi:calendar-time',
|
||||
// icon: 'mdi:calendar-time',
|
||||
icon: logo,
|
||||
property: {
|
||||
activityId: undefined,
|
||||
layoutType: 'oneCol',
|
||||
|
@ -15,12 +15,12 @@ export interface SearchProperty {
|
||||
|
||||
// 文字位置
|
||||
export type PlaceholderPosition = 'left' | 'center'
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-01.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'SearchBar',
|
||||
name: '搜索框',
|
||||
icon: 'ep:search',
|
||||
icon: logo,
|
||||
property: {
|
||||
height: 28,
|
||||
showScan: false,
|
||||
|
@ -38,12 +38,13 @@ export interface TitleBarProperty {
|
||||
// 组件样式
|
||||
style: ComponentStyle
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-10.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'TitleBar',
|
||||
name: '标题栏',
|
||||
icon: 'material-symbols:line-start',
|
||||
icon: logo,
|
||||
property: {
|
||||
title: '主标题',
|
||||
description: '副标题',
|
||||
|
@ -1,29 +1,115 @@
|
||||
<template>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex items-center justify-between p-x-18px p-y-24px">
|
||||
<div class="flex flex-1 items-center gap-16px">
|
||||
<el-avatar :size="60">
|
||||
<Icon icon="ep:avatar" :size="60" />
|
||||
</el-avatar>
|
||||
<span class="text-18px font-bold">芋道源码</span>
|
||||
</div>
|
||||
<Icon icon="tdesign:qrcode" :size="20" />
|
||||
</div>
|
||||
<div
|
||||
<div class="flex flex-col" style=" margin-bottom: 27px;">
|
||||
|
||||
<div class="new-main">
|
||||
<div class="flex items-center justify-between p-x-18px p-y-24px " style="padding-bottom:15px;">
|
||||
<div class="flex flex-1 items-center gap-16px">
|
||||
<el-avatar :size="60">
|
||||
<Icon icon="ep:avatar" :size="60" />
|
||||
</el-avatar>
|
||||
<span class="text-18px font-bold">用户名称</span>
|
||||
</div>
|
||||
<Icon icon="tdesign:qrcode" :size="20" />
|
||||
</div>
|
||||
|
||||
<div class="new-usercard" style="z-index: 9999;">
|
||||
<div class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center">
|
||||
<div class="value-box ss-flex ss-col-bottom">
|
||||
<div class="value-text ss-line-1">0.00</div>
|
||||
<div class="unit-text ss-m-l-6">
|
||||
<!-- 元 -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-title ss-m-t-28">余额</div>
|
||||
</div>
|
||||
|
||||
<div class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center">
|
||||
<div class="value-box ss-flex ss-col-bottom">
|
||||
<div class="value-text">0</div>
|
||||
<div class="unit-text ss-m-l-6">
|
||||
<!-- 张 -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-title ss-m-t-28">优惠券</div>
|
||||
</div>
|
||||
<div class="menu-item ss-flex-1 ss-flex-col ss-row-center ss-col-center">
|
||||
<div class="value-box ss-flex ss-col-bottom">
|
||||
<div class="value-text">0</div>
|
||||
<div class="unit-text ss-m-l-6">
|
||||
<!-- 个 -->
|
||||
</div>
|
||||
</div>
|
||||
<div class="menu-title ss-m-t-28">积分</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="new-bottom">
|
||||
<img src="https://zysc.fjptzykj.com:3000/shangcheng/64776e2edc3c2f15295e7c3976ba301e08f9170f99a2e845d8f33bd65179b177.png"
|
||||
alt="" />
|
||||
<div class="btn">
|
||||
立即开通
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- <div
|
||||
class="flex items-center justify-between justify-between bg-white p-x-20px p-y-8px text-12px"
|
||||
>
|
||||
<span class="color-#ff690d">点击绑定手机号</span>
|
||||
<span class="rounded-26px bg-#ff6100 p-x-8px p-y-5px color-white">去绑定</span>
|
||||
</div>
|
||||
</div>
|
||||
</div> -->
|
||||
</div>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { UserCardProperty } from './config'
|
||||
import { UserCardProperty } from './config'
|
||||
|
||||
/** 用户卡片 */
|
||||
defineOptions({ name: 'UserCard' })
|
||||
// 定义属性
|
||||
defineProps<{ property: UserCardProperty }>()
|
||||
/** 用户卡片 */
|
||||
defineOptions({ name: 'UserCard' })
|
||||
// 定义属性
|
||||
defineProps<{ property : UserCardProperty }>()
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss"></style>
|
||||
<style scoped lang="scss">
|
||||
.new-main {
|
||||
position: relative;
|
||||
background: url('@/assets/imgs/userCar/seckilbg.png') no-repeat;
|
||||
background-size: cover;
|
||||
padding-bottom: 53px;
|
||||
|
||||
.value-box {
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.new-usercard {
|
||||
width: 100%;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
|
||||
div {
|
||||
text-align: center;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.new-bottom {
|
||||
position: absolute;
|
||||
bottom: -28px;
|
||||
width: 100%;
|
||||
z-index: 999999999999999;
|
||||
|
||||
img {
|
||||
width: 92%;
|
||||
}
|
||||
|
||||
.btn {
|
||||
position: absolute;
|
||||
bottom: 19px;
|
||||
right: 29px;
|
||||
background: white;
|
||||
border-radius: 12px;
|
||||
padding: 4px 8px;
|
||||
font-size: 14px;
|
||||
color: #946d2d;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,5 +1,6 @@
|
||||
<template>
|
||||
<el-image src="https://shopro.sheepjs.com/admin/static/images/shop/decorate/orderCardStyle.png" />
|
||||
<!-- <el-image src="https://shopro.sheepjs.com/admin/static/images/shop/decorate/orderCardStyle.png" /> -->
|
||||
<el-image src=" https://zysc.fjptzykj.com:3000/shangcheng/0ba158a1a2de7d39c6cec22cfe54736237438f63893b09c7453b5b5e3482f826.png" />
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { UserOrderProperty } from './config'
|
||||
|
@ -17,12 +17,13 @@ export interface VideoPlayerStyle extends ComponentStyle {
|
||||
// 视频高度
|
||||
height: number
|
||||
}
|
||||
|
||||
import logo from '@/assets/imgs/DiyEditorImges/组件图标-11.png'
|
||||
// 定义组件
|
||||
export const component = {
|
||||
id: 'VideoPlayer',
|
||||
name: '视频播放',
|
||||
icon: 'ep:video-play',
|
||||
// icon: 'ep:video-play',
|
||||
icon: logo,
|
||||
property: {
|
||||
videoUrl: '',
|
||||
posterUrl: '',
|
||||
|
@ -28,7 +28,8 @@ export const validityTypeFormat = (row: CouponTemplateVO) => {
|
||||
return `${formatDate(row.validStartTime)} 至 ${formatDate(row.validEndTime)}`
|
||||
}
|
||||
if (row.validityType === CouponTemplateValidityTypeEnum.TERM.type) {
|
||||
return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`
|
||||
// return `领取后第 ${row.fixedStartTerm} - ${row.fixedEndTerm} 天内可用`
|
||||
return `领取后 ${row.fixedEndTerm + 1} 天内可用`
|
||||
}
|
||||
return '未知【' + row.validityType + '】'
|
||||
}
|
||||
|
@ -38,7 +38,7 @@
|
||||
<el-form-item label="优惠类型" prop="discountType">
|
||||
<el-radio-group v-model="formData.discountType">
|
||||
<el-radio
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.PROMOTION_DISCOUNT_TYPE)"
|
||||
v-for="dict in filteredDictOptions()"
|
||||
:key="dict.value"
|
||||
:label="dict.value"
|
||||
>
|
||||
@ -151,10 +151,10 @@
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="formData.validityType === CouponTemplateValidityTypeEnum.TERM.type"
|
||||
label="领取日期"
|
||||
label="有效日期"
|
||||
prop="fixedStartTerm"
|
||||
>
|
||||
第
|
||||
<!-- 第
|
||||
<el-input-number
|
||||
v-model="formData.fixedStartTerm"
|
||||
:min="0"
|
||||
@ -162,13 +162,13 @@
|
||||
class="mx-2"
|
||||
placeholder="0 为今天生效"
|
||||
/>
|
||||
至
|
||||
至 -->
|
||||
<el-input-number
|
||||
v-model="formData.fixedEndTerm"
|
||||
:min="0"
|
||||
:min="1"
|
||||
:precision="0"
|
||||
class="mx-2"
|
||||
placeholder="请输入结束天数"
|
||||
placeholder="请输入有效天数"
|
||||
/>
|
||||
天有效
|
||||
</el-form-item>
|
||||
@ -215,7 +215,7 @@ const formData = ref({
|
||||
validTimes: [],
|
||||
validStartTime: undefined,
|
||||
validEndTime: undefined,
|
||||
fixedStartTerm: undefined,
|
||||
fixedStartTerm: 0,
|
||||
fixedEndTerm: undefined,
|
||||
productScope: PromotionProductScopeEnum.ALL.scope,
|
||||
productScopeValues: [], // 商品范围:值为 品类编号列表 或 商品编号列表 ,用于提交
|
||||
@ -255,6 +255,7 @@ const open = async (type: string, id?: number) => {
|
||||
const data = await CouponTemplateApi.getCouponTemplate(id)
|
||||
formData.value = {
|
||||
...data,
|
||||
fixedEndTerm: data.fixedEndTerm - data.fixedStartTerm + 1, // 显示时总天数(实际需要+1)
|
||||
discountPrice: formatToFraction(data.discountPrice),
|
||||
discountPercent:
|
||||
data.discountPercent !== undefined ? data.discountPercent / 10.0 : undefined,
|
||||
@ -283,6 +284,7 @@ const submitForm = async () => {
|
||||
try {
|
||||
const data = {
|
||||
...formData.value,
|
||||
fixedEndTerm: (formData.value.fixedEndTerm || 0) + formData.value.fixedStartTerm - 1, // 得到结束的天数
|
||||
discountPrice: convertToInteger(formData.value.discountPrice),
|
||||
discountPercent:
|
||||
formData.value.discountPercent !== undefined
|
||||
@ -335,7 +337,7 @@ const resetForm = () => {
|
||||
validTimes: [],
|
||||
validStartTime: undefined,
|
||||
validEndTime: undefined,
|
||||
fixedStartTerm: undefined,
|
||||
fixedStartTerm: 0,
|
||||
fixedEndTerm: undefined,
|
||||
productScope: PromotionProductScopeEnum.ALL.scope,
|
||||
productScopeValues: [],
|
||||
@ -383,6 +385,12 @@ function setProductScopeValues(data: CouponTemplateApi.CouponTemplateVO) {
|
||||
break
|
||||
}
|
||||
}
|
||||
/** 暂时隐藏掉字典中的折扣 */
|
||||
function filteredDictOptions() {
|
||||
return getIntDictOptions(DICT_TYPE.PROMOTION_DISCOUNT_TYPE).filter(
|
||||
dict => dict.value !== 2 // 过滤掉 value 为 2 的选项
|
||||
);
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped></style>
|
||||
|
@ -2,19 +2,19 @@
|
||||
<DiyEditor v-if="formData && !formLoading" v-model="currentFormData!.property"
|
||||
:title="templateItems[selectedTemplateItem].name" :libs="libs" :show-page-config="selectedTemplateItem !== 0"
|
||||
:show-tab-bar="selectedTemplateItem === 0" :show-navigation-bar="selectedTemplateItem !== 0"
|
||||
:preview-url="previewUrl" @save="submitForm" @reset="handleEditorReset">
|
||||
:preview-url="previewUrl" @save="submitForm" @reset="handleEditorReset" :isShow="false">
|
||||
<template #toolBarLeft>
|
||||
<!-- <el-radio-group
|
||||
v-model="selectedTemplateItem"
|
||||
class="h-full!"
|
||||
@change="handleTemplateItemChange"
|
||||
>
|
||||
<el-tooltip v-for="(item, index) in templateItems" :key="index" :content="item.name">
|
||||
<el-radio-button :label="index">
|
||||
<Icon :icon="item.icon" :size="24" />
|
||||
</el-radio-button>
|
||||
</el-tooltip>
|
||||
</el-radio-group> -->
|
||||
v-model="selectedTemplateItem"
|
||||
class="h-full!"
|
||||
@change="handleTemplateItemChange"
|
||||
>
|
||||
<el-tooltip v-for="(item, index) in templateItems" :key="index" :content="item.name">
|
||||
<el-radio-button :label="index">
|
||||
<Icon :icon="item.icon" :size="24" />
|
||||
</el-radio-button>
|
||||
</el-tooltip>
|
||||
</el-radio-group> -->
|
||||
</template>
|
||||
</DiyEditor>
|
||||
</template>
|
||||
@ -147,7 +147,7 @@
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
|
||||
|
||||
|
||||
onMounted(async () => {
|
||||
resetForm()
|
||||
@ -167,7 +167,7 @@
|
||||
console.log(currentRoute.value.params.id, "currentRoute.value.params.id");
|
||||
|
||||
})
|
||||
|
||||
|
||||
// watch(() => route.path, (newPath, oldPath) => {
|
||||
// console.log(newPath,'newPathnewPath');
|
||||
// // handleTemplateItemChange()
|
||||
|
@ -22,8 +22,8 @@
|
||||
<div class="ml-10px w-100%">
|
||||
<div class="flex justify-between items-center w-100%">
|
||||
<span class="username">{{ item.userNickname }}</span>
|
||||
<span class="color-[#989EA6]">
|
||||
{{ formatPast(item.lastMessageTime, 'YYYY-mm-dd') }}
|
||||
<span class="color-[var(--left-menu-text-color)]" style="font-size: 13px">
|
||||
{{ formatPast(item.lastMessageTime, 'YYYY-MM-DD') }}
|
||||
</span>
|
||||
</div>
|
||||
<!-- 最后聊天内容 -->
|
||||
@ -31,8 +31,9 @@
|
||||
v-dompurify-html="
|
||||
getConversationDisplayText(item.lastMessageContentType, item.lastMessageContent)
|
||||
"
|
||||
class="last-message flex items-center color-[#989EA6]"
|
||||
></div>
|
||||
class="last-message flex items-center color-[var(--left-menu-text-color)]"
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -182,7 +183,7 @@ watch(showRightMenu, (val) => {
|
||||
&-conversation {
|
||||
height: 60px;
|
||||
padding: 10px;
|
||||
background-color: #fff;
|
||||
//background-color: #fff;
|
||||
transition: border-left 0.05s ease-in-out; /* 设置过渡效果 */
|
||||
|
||||
.username {
|
||||
@ -196,6 +197,7 @@ watch(showRightMenu, (val) => {
|
||||
}
|
||||
|
||||
.last-message {
|
||||
font-size: 13px;
|
||||
width: 200px;
|
||||
overflow: hidden; // 隐藏超出的文本
|
||||
white-space: nowrap; // 禁止换行
|
||||
@ -205,17 +207,17 @@ watch(showRightMenu, (val) => {
|
||||
|
||||
.active {
|
||||
border-left: 5px #3271ff solid;
|
||||
background-color: #eff0f1;
|
||||
background-color: var(--login-bg-color);
|
||||
}
|
||||
|
||||
.pinned {
|
||||
background-color: #eff0f1;
|
||||
background-color: var(--left-menu-bg-active-color);
|
||||
}
|
||||
|
||||
.right-menu-ul {
|
||||
position: absolute;
|
||||
background-color: #fff;
|
||||
padding: 10px;
|
||||
background-color: var(--app-content-bg-color);
|
||||
padding: 5px;
|
||||
margin: 0;
|
||||
list-style-type: none; /* 移除默认的项目符号 */
|
||||
border-radius: 12px;
|
||||
@ -228,7 +230,7 @@ watch(showRightMenu, (val) => {
|
||||
border-radius: 12px;
|
||||
transition: background-color 0.3s; /* 平滑过渡 */
|
||||
&:hover {
|
||||
background-color: #e0e0e0; /* 悬停时的背景颜色 */
|
||||
background-color: var(--left-menu-bg-active-color); /* 悬停时的背景颜色 */
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -71,6 +71,7 @@
|
||||
<MessageItem :message="item">
|
||||
<ProductItem
|
||||
v-if="KeFuMessageContentTypeEnum.PRODUCT === item.contentType"
|
||||
:spuId="getMessageContent(item).spuId"
|
||||
:picUrl="getMessageContent(item).picUrl"
|
||||
:price="getMessageContent(item).price"
|
||||
:skuText="getMessageContent(item).introduction"
|
||||
@ -85,7 +86,7 @@
|
||||
<OrderItem
|
||||
v-if="KeFuMessageContentTypeEnum.ORDER === item.contentType"
|
||||
:message="item"
|
||||
class="max-w-70%"
|
||||
class="max-w-100%"
|
||||
/>
|
||||
</MessageItem>
|
||||
</div>
|
||||
@ -369,9 +370,10 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
||||
position: absolute;
|
||||
bottom: 35px;
|
||||
right: 35px;
|
||||
background-color: #fff;
|
||||
background-color: var(--app-content-bg-color);
|
||||
padding: 10px;
|
||||
border-radius: 30px;
|
||||
font-size: 12px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1); /* 阴影效果 */
|
||||
}
|
||||
|
||||
@ -392,7 +394,7 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
||||
border-left: 5px solid transparent;
|
||||
border-bottom: 5px solid transparent;
|
||||
border-top: 5px solid transparent;
|
||||
border-right: 5px solid #ffffff;
|
||||
border-right: 5px solid var(--app-content-bg-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -411,7 +413,7 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
||||
right: -19px;
|
||||
top: calc(50% - 10px);
|
||||
position: absolute;
|
||||
border-left: 5px solid #ffffff;
|
||||
border-left: 5px solid var(--app-content-bg-color);
|
||||
border-bottom: 5px solid transparent;
|
||||
border-top: 5px solid transparent;
|
||||
border-right: 5px solid transparent;
|
||||
@ -421,9 +423,9 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
||||
|
||||
// 消息气泡
|
||||
.kefu-message {
|
||||
color: #333;
|
||||
color: #a9a9a9;
|
||||
border-radius: 5px;
|
||||
box-shadow: 3px 5px 15px rgba(0, 0, 0, 0.2);
|
||||
box-shadow: 3px 3px 5px rgba(220, 220, 220, 0.1);
|
||||
padding: 5px 10px;
|
||||
width: auto;
|
||||
max-width: 50%;
|
||||
@ -431,7 +433,7 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
||||
display: inline-block !important;
|
||||
position: relative;
|
||||
word-break: break-all;
|
||||
background-color: #ffffff;
|
||||
background-color: var(--app-content-bg-color);
|
||||
transition: all 0.2s;
|
||||
|
||||
&:hover {
|
||||
@ -445,7 +447,7 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
||||
border-radius: 12rpx;
|
||||
padding: 8rpx 16rpx;
|
||||
margin-bottom: 16rpx;
|
||||
background-color: #e8e8e8;
|
||||
//background-color: #e8e8e8;
|
||||
color: #999;
|
||||
font-size: 24rpx;
|
||||
}
|
||||
@ -453,7 +455,7 @@ const showTime = computed(() => (item: KeFuMessageRespVO, index: number) => {
|
||||
|
||||
.chat-tools {
|
||||
width: 100%;
|
||||
border: #e4e0e0 solid 1px;
|
||||
border: var(--el-border-color) solid 1px;
|
||||
border-radius: 10px;
|
||||
height: 44px;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
<el-tab-pane label="订单列表" name="b" />
|
||||
</el-tabs>
|
||||
<div>
|
||||
<el-scrollbar ref="scrollbarRef" always height="calc(100vh - 400px)" @scroll="handleScroll">
|
||||
<el-scrollbar ref="scrollbarRef" always height="calc(115vh - 400px)" @scroll="handleScroll">
|
||||
<!-- 最近浏览 -->
|
||||
<ProductBrowsingHistory v-if="activeName === 'a'" ref="productBrowsingHistoryRef" />
|
||||
<!-- 订单列表 -->
|
||||
@ -25,7 +25,7 @@ import OrderBrowsingHistory from './OrderBrowsingHistory.vue'
|
||||
import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
|
||||
import { isEmpty } from '@/utils/is'
|
||||
import { debounce } from 'lodash-es'
|
||||
import { ElScrollbar as ElScrollbarType } from 'element-plus/es/components/scrollbar'
|
||||
import { ElScrollbar as ElScrollbarType } from 'element-plus/es/components/scrollbar/index'
|
||||
|
||||
defineOptions({ name: 'MemberBrowsingHistory' })
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
<template>
|
||||
<ProductItem
|
||||
v-for="item in list"
|
||||
:spu-id="item.spuId"
|
||||
:key="item.id"
|
||||
:picUrl="item.picUrl"
|
||||
:price="item.price"
|
||||
|
@ -1,14 +1,20 @@
|
||||
<template>
|
||||
<div v-if="isObject(getMessageContent)">
|
||||
<div :key="getMessageContent.id" class="order-list-card-box mt-14px">
|
||||
<div class="order-card-header flex items-center justify-between p-x-20px">
|
||||
<div class="order-no">订单号:{{ getMessageContent.no }}</div>
|
||||
<div class="order-card-header flex items-center justify-between p-x-5px">
|
||||
<div class="order-no">
|
||||
订单号:
|
||||
<span style="cursor: pointer" @click="openDetail(getMessageContent.id)">
|
||||
{{ getMessageContent.no }}
|
||||
</span>
|
||||
</div>
|
||||
<div :class="formatOrderColor(getMessageContent)" class="order-state font-16">
|
||||
{{ formatOrderStatus(getMessageContent) }}
|
||||
</div>
|
||||
</div>
|
||||
<div v-for="item in getMessageContent.items" :key="item.id" class="border-bottom">
|
||||
<ProductItem
|
||||
:spu-id="item.spuId"
|
||||
:num="item.count"
|
||||
:picUrl="item.picUrl"
|
||||
:price="item.price"
|
||||
@ -16,7 +22,7 @@
|
||||
:title="item.spuName"
|
||||
/>
|
||||
</div>
|
||||
<div class="pay-box flex justify-end pr-20px">
|
||||
<div class="pay-box flex justify-end pr-5px">
|
||||
<div class="flex items-center">
|
||||
<div class="discounts-title pay-color"
|
||||
>共 {{ getMessageContent?.productCount }} 件商品,总金额:
|
||||
@ -36,6 +42,8 @@ import { KeFuMessageRespVO } from '@/api/mall/promotion/kefu/message'
|
||||
import { isObject } from '@/utils/is'
|
||||
import ProductItem from '@/views/mall/promotion/kefu/components/message/ProductItem.vue'
|
||||
|
||||
const { push } = useRouter()
|
||||
|
||||
defineOptions({ name: 'OrderItem' })
|
||||
const props = defineProps<{
|
||||
message?: KeFuMessageRespVO
|
||||
@ -46,6 +54,12 @@ const getMessageContent = computed(() =>
|
||||
typeof props.message !== 'undefined' ? jsonParse(props!.message!.content) : props.order
|
||||
)
|
||||
|
||||
/** 查看订单详情 */
|
||||
const openDetail = (id: number) => {
|
||||
console.log(getMessageContent)
|
||||
push({ name: 'TradeOrderDetail', params: { id } })
|
||||
}
|
||||
|
||||
/**
|
||||
* 格式化订单状态的颜色
|
||||
*
|
||||
@ -97,18 +111,28 @@ function formatOrderStatus(order: any) {
|
||||
.order-list-card-box {
|
||||
border-radius: 10px;
|
||||
padding: 10px;
|
||||
background-color: #e2e2e2;
|
||||
border: 1px var(--el-border-color) solid;
|
||||
background-color: var(--app-content-bg-color);
|
||||
|
||||
.order-card-header {
|
||||
height: 28px;
|
||||
|
||||
.order-no {
|
||||
font-size: 16px;
|
||||
font-size: 12px;
|
||||
font-weight: 500;
|
||||
|
||||
span {
|
||||
&:hover {
|
||||
text-decoration: underline;
|
||||
color: var(--left-menu-bg-active-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.pay-box {
|
||||
padding-top: 10px;
|
||||
|
||||
.discounts-title {
|
||||
font-size: 16px;
|
||||
line-height: normal;
|
||||
@ -123,24 +147,33 @@ function formatOrderStatus(order: any) {
|
||||
}
|
||||
|
||||
.pay-color {
|
||||
color: #333;
|
||||
font-size: 13px;
|
||||
color: var(--left-menu-text-color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.warning-color {
|
||||
color: #faad14;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.danger-color {
|
||||
color: #ff3000;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.success-color {
|
||||
color: #52c41a;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.info-color {
|
||||
color: #999999;
|
||||
font-size: 11px;
|
||||
font-weight: bold;
|
||||
}
|
||||
</style>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div>
|
||||
<div @click.stop="openDetail(props.spuId)" style="cursor: pointer;">
|
||||
<div>
|
||||
<slot name="top"></slot>
|
||||
</div>
|
||||
@ -15,6 +15,7 @@
|
||||
class="order-img"
|
||||
fit="contain"
|
||||
preview-teleported
|
||||
@click.stop
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
@ -53,8 +54,14 @@
|
||||
<script lang="ts" setup>
|
||||
import { fenToYuan } from '@/utils'
|
||||
|
||||
const { push } = useRouter()
|
||||
|
||||
defineOptions({ name: 'ProductItem' })
|
||||
const props = defineProps({
|
||||
spuId: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
picUrl: {
|
||||
type: String,
|
||||
default: 'https://img1.baidu.com/it/u=1601695551,235775011&fm=26&fmt=auto'
|
||||
@ -107,13 +114,20 @@ const skuString = computed(() => {
|
||||
}
|
||||
return props.skuText
|
||||
})
|
||||
|
||||
/** 查看商品详情 */
|
||||
const openDetail = (spuId: number) => {
|
||||
console.log(props.spuId)
|
||||
push({ name: 'ProductSpuDetail', params: { id: spuId } })
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.ss-order-card-warp {
|
||||
padding: 20px;
|
||||
border-radius: 10px;
|
||||
background-color: #e2e2e2;
|
||||
border: 1px var(--el-border-color) solid;
|
||||
background-color: var(--app-content-bg-color);
|
||||
|
||||
.img-box {
|
||||
width: 80px;
|
||||
@ -133,19 +147,19 @@ const skuString = computed(() => {
|
||||
|
||||
.tool-box {
|
||||
position: absolute;
|
||||
right: 0px;
|
||||
right: 0;
|
||||
bottom: -10px;
|
||||
}
|
||||
}
|
||||
|
||||
.title-text {
|
||||
font-size: 16px;
|
||||
font-size: 13px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
}
|
||||
|
||||
.spec-text {
|
||||
font-size: 16px;
|
||||
font-size: 10px;
|
||||
font-weight: 400;
|
||||
color: #999999;
|
||||
min-width: 0;
|
||||
@ -157,13 +171,13 @@ const skuString = computed(() => {
|
||||
}
|
||||
|
||||
.price-text {
|
||||
font-size: 16px;
|
||||
font-size: 11px;
|
||||
font-weight: 500;
|
||||
font-family: OPPOSANS;
|
||||
}
|
||||
|
||||
.total-text {
|
||||
font-size: 16px;
|
||||
font-size: 10px;
|
||||
font-weight: 400;
|
||||
line-height: 16px;
|
||||
color: #999999;
|
||||
|
@ -66,7 +66,7 @@ export const useEmoji = () => {
|
||||
)
|
||||
for (const path in pathList) {
|
||||
const imageModule: any = await pathList[path]()
|
||||
emojiPathList.value.push(imageModule.default)
|
||||
emojiPathList.value.push({ path: path, src: imageModule.default })
|
||||
}
|
||||
}
|
||||
|
||||
@ -80,8 +80,8 @@ export const useEmoji = () => {
|
||||
/**
|
||||
* 将文本中的表情替换成图片
|
||||
*
|
||||
* @param data 文本
|
||||
* @return 替换后的文本
|
||||
* @param content 消息内容
|
||||
*/
|
||||
const replaceEmoji = (content: string) => {
|
||||
let newData = content
|
||||
@ -93,7 +93,7 @@ export const useEmoji = () => {
|
||||
const emojiFile = getEmojiFileByName(item)
|
||||
newData = newData.replace(
|
||||
item,
|
||||
`<img class="chat-img" style="width: 24px;height: 24px;margin: 0 3px;" src="${emojiFile}"/>`
|
||||
`<img class="chat-img" style="width: 24px;height: 24px;margin: 0 3px;" src="${emojiFile}" alt=""/>`
|
||||
)
|
||||
})
|
||||
}
|
||||
@ -116,7 +116,10 @@ export const useEmoji = () => {
|
||||
function getEmojiFileByName(name: string) {
|
||||
for (const emoji of emojiList) {
|
||||
if (emoji.name === name) {
|
||||
return emojiPathList.value.find((item: string) => item.indexOf(emoji.file) > -1)
|
||||
const emojiPath = emojiPathList.value.find(
|
||||
(item: { path: string; src: string }) => item.path.indexOf(emoji.file) > -1
|
||||
)
|
||||
return emojiPath ? emojiPath.src : undefined
|
||||
}
|
||||
}
|
||||
return false
|
||||
|
@ -22,119 +22,118 @@
|
||||
</template>
|
||||
|
||||
<script lang="ts" setup>
|
||||
import { KeFuConversationList, KeFuMessageList, MemberBrowsingHistory } from './components'
|
||||
import { WebSocketMessageTypeConstants } from './components/tools/constants'
|
||||
import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
|
||||
import { getAccessToken } from '@/utils/auth'
|
||||
import { useWebSocket } from '@vueuse/core'
|
||||
import { KeFuConversationList, KeFuMessageList, MemberBrowsingHistory } from './components'
|
||||
import { WebSocketMessageTypeConstants } from './components/tools/constants'
|
||||
import { KeFuConversationRespVO } from '@/api/mall/promotion/kefu/conversation'
|
||||
import { getRefreshToken } from '@/utils/auth'
|
||||
import { useWebSocket } from '@vueuse/core'
|
||||
|
||||
defineOptions({ name: 'KeFu' })
|
||||
defineOptions({ name: 'KeFu' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
// ======================= WebSocket start =======================
|
||||
const server = ref(
|
||||
(import.meta.env.VITE_BASE_URL + '/infra/ws').replace('http', 'ws') + '?token=' + getAccessToken()
|
||||
) // WebSocket 服务地址
|
||||
// ======================= WebSocket start =======================
|
||||
const server = ref(
|
||||
(import.meta.env.VITE_BASE_URL + '/infra/ws').replace('http', 'ws') +
|
||||
'?token=' +
|
||||
getRefreshToken() // 使用 getRefreshToken() 方法,而不使用 getAccessToken() 方法的原因:WebSocket 无法方便的刷新访问令牌
|
||||
) // WebSocket 服务地址
|
||||
|
||||
/** 发起 WebSocket 连接 */
|
||||
const { data, close, open } = useWebSocket(server.value, {
|
||||
autoReconnect: true,
|
||||
heartbeat: true
|
||||
})
|
||||
/** 发起 WebSocket 连接 */
|
||||
const { data, close, open } = useWebSocket(server.value, {
|
||||
autoReconnect: true,
|
||||
heartbeat: true
|
||||
})
|
||||
|
||||
/** 监听 WebSocket 数据 */
|
||||
watchEffect(() => {
|
||||
if (!data.value) {
|
||||
console.log('111')
|
||||
return
|
||||
/** 监听 WebSocket 数据 */
|
||||
watchEffect(() => {
|
||||
if (!data.value) {
|
||||
return
|
||||
}
|
||||
try {
|
||||
// 1. 收到心跳
|
||||
if (data.value === 'pong') {
|
||||
return
|
||||
}
|
||||
|
||||
// 2.1 解析 type 消息类型
|
||||
const jsonMessage = JSON.parse(data.value)
|
||||
const type = jsonMessage.type
|
||||
if (!type) {
|
||||
message.error('未知的消息类型:' + data.value)
|
||||
return
|
||||
}
|
||||
// 2.2 消息类型:KEFU_MESSAGE_TYPE
|
||||
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_TYPE) {
|
||||
// 刷新会话列表
|
||||
// TODO @puhui999:不应该刷新列表,而是根据消息,本地 update 列表的数据;
|
||||
getConversationList()
|
||||
// 刷新消息列表
|
||||
keFuChatBoxRef.value?.refreshMessageList(JSON.parse(jsonMessage.content))
|
||||
return
|
||||
}
|
||||
// 2.3 消息类型:KEFU_MESSAGE_ADMIN_READ
|
||||
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_ADMIN_READ) {
|
||||
// 刷新会话列表
|
||||
// TODO @puhui999:不应该刷新列表,而是根据消息,本地 update 列表的数据;
|
||||
getConversationList()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
}
|
||||
})
|
||||
// ======================= WebSocket end =======================
|
||||
/** 加载会话列表 */
|
||||
const keFuConversationRef = ref<InstanceType<typeof KeFuConversationList>>()
|
||||
const getConversationList = () => {
|
||||
keFuConversationRef.value?.getConversationList()
|
||||
}
|
||||
try {
|
||||
// 1. 收到心跳
|
||||
if (data.value === 'pong') {
|
||||
console.log('666')
|
||||
return
|
||||
}
|
||||
|
||||
console.log('777')
|
||||
// 2.1 解析 type 消息类型
|
||||
const jsonMessage = JSON.parse(data.value)
|
||||
const type = jsonMessage.type
|
||||
if (!type) {
|
||||
message.error('未知的消息类型:' + data.value)
|
||||
return
|
||||
}
|
||||
// 2.2 消息类型:KEFU_MESSAGE_TYPE
|
||||
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_TYPE) {
|
||||
// 刷新会话列表
|
||||
// TODO @puhui999:不应该刷新列表,而是根据消息,本地 update 列表的数据;
|
||||
getConversationList()
|
||||
// 刷新消息列表
|
||||
keFuChatBoxRef.value?.refreshMessageList(JSON.parse(jsonMessage.content))
|
||||
return
|
||||
}
|
||||
// 2.3 消息类型:KEFU_MESSAGE_ADMIN_READ
|
||||
if (type === WebSocketMessageTypeConstants.KEFU_MESSAGE_ADMIN_READ) {
|
||||
// 刷新会话列表
|
||||
// TODO @puhui999:不应该刷新列表,而是根据消息,本地 update 列表的数据;
|
||||
getConversationList()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
|
||||
/** 加载指定会话的消息列表 */
|
||||
const keFuChatBoxRef = ref<InstanceType<typeof KeFuMessageList>>()
|
||||
const memberBrowsingHistoryRef = ref<InstanceType<typeof MemberBrowsingHistory>>()
|
||||
const handleChange = (conversation: KeFuConversationRespVO) => {
|
||||
keFuChatBoxRef.value?.getNewMessageList(conversation)
|
||||
memberBrowsingHistoryRef.value?.initHistory(conversation)
|
||||
}
|
||||
})
|
||||
// ======================= WebSocket end =======================
|
||||
/** 加载会话列表 */
|
||||
const keFuConversationRef = ref<InstanceType<typeof KeFuConversationList>>()
|
||||
const getConversationList = () => {
|
||||
keFuConversationRef.value?.getConversationList()
|
||||
}
|
||||
|
||||
/** 加载指定会话的消息列表 */
|
||||
const keFuChatBoxRef = ref<InstanceType<typeof KeFuMessageList>>()
|
||||
const memberBrowsingHistoryRef = ref<InstanceType<typeof MemberBrowsingHistory>>()
|
||||
const handleChange = (conversation: KeFuConversationRespVO) => {
|
||||
keFuChatBoxRef.value?.getNewMessageList(conversation)
|
||||
memberBrowsingHistoryRef.value?.initHistory(conversation)
|
||||
}
|
||||
/** 初始化 */
|
||||
onMounted(() => {
|
||||
getConversationList()
|
||||
// 打开 websocket 连接
|
||||
open()
|
||||
})
|
||||
|
||||
/** 初始化 */
|
||||
onMounted(() => {
|
||||
getConversationList()
|
||||
// 打开 websocket 连接
|
||||
open()
|
||||
})
|
||||
|
||||
/** 销毁 */
|
||||
onBeforeUnmount(() => {
|
||||
// 关闭 websocket 连接
|
||||
close()
|
||||
})
|
||||
/** 销毁 */
|
||||
onBeforeUnmount(() => {
|
||||
// 关闭 websocket 连接
|
||||
close()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.kefu {
|
||||
height: calc(100vh - 165px);
|
||||
overflow: auto; /* 确保内容可滚动 */
|
||||
}
|
||||
.kefu {
|
||||
height: calc(100vh - 165px);
|
||||
overflow: auto; /* 确保内容可滚动 */
|
||||
}
|
||||
|
||||
/* 定义滚动条样式 */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 6px;
|
||||
}
|
||||
/* 定义滚动条样式 */
|
||||
::-webkit-scrollbar {
|
||||
width: 10px;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
/* 定义滚动条轨道 内阴影+圆角 */
|
||||
::-webkit-scrollbar-track {
|
||||
box-shadow: inset 0 0 0 rgba(240, 240, 240, 0.5);
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
/* 定义滚动条轨道 内阴影+圆角 */
|
||||
::-webkit-scrollbar-track {
|
||||
box-shadow: inset 0 0 0 rgba(240, 240, 240, 0.5);
|
||||
border-radius: 10px;
|
||||
background-color: #fff;
|
||||
}
|
||||
|
||||
/* 定义滑块 内阴影+圆角 */
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
box-shadow: inset 0 0 0 rgba(240, 240, 240, 0.5);
|
||||
background-color: rgba(240, 240, 240, 0.5);
|
||||
}
|
||||
/* 定义滑块 内阴影+圆角 */
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
box-shadow: inset 0 0 0 rgba(240, 240, 240, 0.5);
|
||||
background-color: rgba(240, 240, 240, 0.5);
|
||||
}
|
||||
</style>
|
||||
|
@ -7,15 +7,15 @@
|
||||
label-width="100px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入名称" />
|
||||
<el-form-item label="权益名称" prop="benName">
|
||||
<el-input v-model="formData.benName" placeholder="请输入权益名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="展示名称" prop="showName">
|
||||
<el-input v-model="formData.showName" placeholder="请输入展示名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="图标" prop="iconUrl">
|
||||
<UploadImg v-model="formData.iconUrl" :limit="1" :is-show-tip="false" />
|
||||
</el-form-item>
|
||||
<el-form-item label="描述" prop="intro">
|
||||
<el-input v-model="formData.intro" placeholder="请输入描述" />
|
||||
</el-form-item>
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-select v-model="formData.status" class="!w-240px" placeholder="请选择" clearable>
|
||||
<el-option
|
||||
@ -26,7 +26,7 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="会员等级" prop="levelIdList">
|
||||
<!-- <el-form-item label="会员等级" prop="levelIdList">
|
||||
<el-checkbox-group v-model="formData.levelIdList">
|
||||
<el-checkbox
|
||||
v-for="dict in memberLevelList"
|
||||
@ -36,12 +36,14 @@
|
||||
{{ dict.name }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="权益简介" prop="intro">
|
||||
<el-input v-model="formData.intro" placeholder="请输入描述" />
|
||||
</el-form-item>
|
||||
|
||||
|
||||
<el-form-item label="排序" prop="sort">
|
||||
<!-- <el-form-item label="排序" prop="sort">
|
||||
<el-input v-model="formData.sort" placeholder="请输入排序" />
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
@ -65,7 +67,8 @@ const formLoading = ref(false) // 表单的加载中:1)修改时的数据加
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
benName: undefined,
|
||||
showName: undefined,
|
||||
iconUrl: undefined,
|
||||
intro: undefined,
|
||||
status: undefined,
|
||||
@ -73,10 +76,10 @@ const formData = ref({
|
||||
levelIdList: []
|
||||
})
|
||||
const formRules = reactive({
|
||||
name: [{ required: true, message: '名称不能为空', trigger: 'blur' }],
|
||||
benName: [{ required: true, message: '权益名称不能为空', trigger: 'blur' }],
|
||||
showName: [{ required: true, message: '展示名称不能为空', trigger: 'blur' }],
|
||||
iconUrl: [{ required: true, message: '图标地址不能为空', trigger: 'blur' }],
|
||||
status: [{ required: true, message: '状态', trigger: 'blur' }],
|
||||
sort: [{ required: true, message: '排序不能为空', trigger: 'blur' }],
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
const memberLevelList = ref() // 等级列表
|
||||
@ -136,7 +139,8 @@ const submitForm = async () => {
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
benName: undefined,
|
||||
showName: undefined,
|
||||
iconUrl: undefined,
|
||||
intro: undefined,
|
||||
status: undefined,
|
||||
|
@ -8,10 +8,10 @@
|
||||
:inline="true"
|
||||
label-width="68px"
|
||||
>
|
||||
<el-form-item label="名称" prop="name">
|
||||
<el-form-item label="权益名称" prop="benName">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入名称"
|
||||
v-model="queryParams.benName"
|
||||
placeholder="请输入权益名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
@ -35,7 +35,7 @@
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="状态" prop="status">
|
||||
<el-form-item label="权益状态" prop="status">
|
||||
<el-select v-model="queryParams.status" class="!w-240px" placeholder="请选择" clearable>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.MEMBER_BENEFIT_STATUS)"
|
||||
@ -45,7 +45,7 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="会员等级" prop="levelId">
|
||||
<!-- <el-form-item label="会员等级" prop="levelId">
|
||||
<el-select v-model="queryParams.levelId" class="!w-240px" placeholder="请选择" clearable>
|
||||
<el-option
|
||||
v-for="dict in memberLevelList"
|
||||
@ -54,7 +54,7 @@
|
||||
:value="dict.id"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form-item> -->
|
||||
<!-- <el-form-item label="排序" prop="sort">
|
||||
<el-input
|
||||
v-model="queryParams.sort"
|
||||
@ -102,35 +102,35 @@
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label=" 编号" align="center" prop="id" />
|
||||
<el-table-column label="名称" align="center" prop="name" />
|
||||
<el-table-column align="center" label="图标" prop="avatar" width="80px">
|
||||
<el-table-column label="权益名称" align="center" prop="benName" />
|
||||
<el-table-column label="展示名称" align="center" prop="showName" />
|
||||
<el-table-column align="center" label="权益图标" prop="avatar" width="80px">
|
||||
<template #default="scope">
|
||||
<img :src="scope.row.iconUrl" style="width: 40px" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="描述" align="center" prop="intro" />
|
||||
<el-table-column align="center" label="状态" min-width="80">
|
||||
<el-table-column label="权益简介" align="center" prop="intro" />
|
||||
<el-table-column align="center" label="权益状态" min-width="80">
|
||||
<template #default="{ row }">
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
:active-value="1"
|
||||
:inactive-value="0"
|
||||
active-text="显示"
|
||||
inactive-text="隐藏"
|
||||
active-text="启用"
|
||||
inactive-text="禁用"
|
||||
inline-prompt
|
||||
@click="handleStatusChange(row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="排序" align="center" prop="sort" />
|
||||
<!-- <el-table-column label="排序" align="center" prop="sort" />
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/>
|
||||
/> -->
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
@ -193,7 +193,7 @@ const queryParams = reactive({
|
||||
createTime: [],
|
||||
levelId: undefined
|
||||
})
|
||||
const memberLevelList = ref() // 等级列表
|
||||
// const memberLevelList = ref() // 等级列表
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
/** 查询列表 */
|
||||
@ -208,14 +208,14 @@ const getList = async () => {
|
||||
}
|
||||
}
|
||||
|
||||
/**查询等级列表 */
|
||||
const getMemberLevelList = async () => {
|
||||
const queryLevelParams = reactive({
|
||||
status: 0
|
||||
})
|
||||
const resultData = await LevelApi.getLevelList(queryLevelParams)
|
||||
memberLevelList.value = resultData
|
||||
}
|
||||
// /**查询等级列表 */
|
||||
// const getMemberLevelList = async () => {
|
||||
// const queryLevelParams = reactive({
|
||||
// status: 0
|
||||
// })
|
||||
// const resultData = await LevelApi.getLevelList(queryLevelParams)
|
||||
// memberLevelList.value = resultData
|
||||
// }
|
||||
|
||||
/** 搜索按钮操作 */
|
||||
const handleQuery = () => {
|
||||
@ -265,18 +265,18 @@ const handleExport = async () => {
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getMemberLevelList()
|
||||
// getMemberLevelList()
|
||||
getList()
|
||||
})
|
||||
/** 更新显示/隐藏状态 */
|
||||
const handleStatusChange = async (row: any) => {
|
||||
try {
|
||||
// 二次确认
|
||||
const text = row.status ? '显示' : '隐藏'
|
||||
await message.confirm(`确认要${text}"${row.name}"吗?`)
|
||||
// const text = row.status ? '显示' : '隐藏'
|
||||
// await message.confirm(`确认要${text}"${row.name}"吗?`)
|
||||
// 发起修改
|
||||
await PaidMemberBenefitApi.updatePaidMemberBenefitStatus({id: row.id, status: row.status })
|
||||
message.success(text + '成功')
|
||||
// message.success(text + '成功')
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {
|
||||
|
@ -0,0 +1,123 @@
|
||||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="订单号" prop="orderNumber">
|
||||
<el-input v-model="formData.orderNumber" placeholder="请输入订单号" />
|
||||
</el-form-item>
|
||||
<el-form-item label="用户id" prop="userId">
|
||||
<el-input v-model="formData.userId" placeholder="请输入用户" />
|
||||
</el-form-item>
|
||||
<el-form-item label="商品id" prop="productId">
|
||||
<el-input v-model="formData.productId" placeholder="请输入商品" />
|
||||
</el-form-item>
|
||||
<el-form-item label="兑换积分" prop="integral">
|
||||
<el-input v-model="formData.integral" placeholder="请输入兑换积分" />
|
||||
</el-form-item>
|
||||
<el-form-item label="订单状态" prop="orderStatus">
|
||||
<el-radio-group v-model="formData.orderStatus">
|
||||
<el-radio label="1">请选择字典生成</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="下单时间" prop="orderTime">
|
||||
<el-date-picker
|
||||
v-model="formData.orderTime"
|
||||
type="date"
|
||||
value-format="x"
|
||||
placeholder="选择下单时间"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { PointOrderApi, PointOrderVO } from '@/api/mall/promotion/pointorder'
|
||||
|
||||
/** 兑换记录 表单 */
|
||||
defineOptions({ name: 'PointOrderForm' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
orderNumber: undefined,
|
||||
userId: undefined,
|
||||
productId: undefined,
|
||||
integral: undefined,
|
||||
orderStatus: undefined,
|
||||
orderTime: undefined,
|
||||
})
|
||||
const formRules = reactive({
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await PointOrderApi.getPointOrder(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as PointOrderVO
|
||||
if (formType.value === 'create') {
|
||||
await PointOrderApi.createPointOrder(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await PointOrderApi.updatePointOrder(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
orderNumber: undefined,
|
||||
userId: undefined,
|
||||
productId: undefined,
|
||||
integral: undefined,
|
||||
orderStatus: undefined,
|
||||
orderTime: undefined,
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
220
yudao-admin-vue3/src/views/mall/promotion/pointorder/index.vue
Normal file
@ -0,0 +1,220 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form class="-mb-15px" :model="queryParams" ref="queryFormRef" :inline="true" label-width="68px">
|
||||
<el-form-item label="订单号" prop="orderNumber">
|
||||
<el-input v-model="queryParams.orderNumber" placeholder="请输入订单号" clearable @keyup.enter="handleQuery"
|
||||
class="!w-240px" />
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="用户" prop="userId">
|
||||
<el-input
|
||||
v-model="queryParams.userId"
|
||||
placeholder="请输入用户"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="商品id" prop="productId">
|
||||
<el-input
|
||||
v-model="queryParams.productId"
|
||||
placeholder="请输入商品id"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="兑换积分" prop="integral">
|
||||
<el-input v-model="queryParams.integral" placeholder="请输入兑换积分" clearable @keyup.enter="handleQuery"
|
||||
class="!w-240px" />
|
||||
</el-form-item>
|
||||
<el-form-item label="订单状态" prop="orderStatus">
|
||||
<el-select v-model="queryParams.orderStatus" class="!w-280px" clearable placeholder="全部">
|
||||
<el-option v-for="dict in getIntDictOptions(DICT_TYPE.TRADE_ORDER_STATUS)" :key="dict.value"
|
||||
:label="dict.label" :value="dict.value" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- <el-form-item label="下单时间" prop="orderTime">
|
||||
<el-date-picker
|
||||
v-model="queryParams.orderTime"
|
||||
value-format="YYYY-MM-DD HH:mm:ss"
|
||||
type="daterange"
|
||||
start-placeholder="开始日期"
|
||||
end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item> -->
|
||||
<el-form-item label="创建时间" prop="createTime">
|
||||
<el-date-picker v-model="queryParams.createTime" value-format="YYYY-MM-DD HH:mm:ss" type="daterange"
|
||||
start-placeholder="开始日期" end-placeholder="结束日期"
|
||||
:default-time="[new Date('1 00:00:00'), new Date('1 23:59:59')]" class="!w-240px" />
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery">
|
||||
<Icon icon="ep:search" class="mr-5px" /> 搜索
|
||||
</el-button>
|
||||
<el-button @click="resetQuery">
|
||||
<Icon icon="ep:refresh" class="mr-5px" /> 重置
|
||||
</el-button>
|
||||
<!-- <el-button type="primary" plain @click="openForm('create')"
|
||||
v-hasPermi="['promotion:point-order:create']">
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button> -->
|
||||
<el-button type="success" plain @click="handleExport" :loading="exportLoading"
|
||||
v-hasPermi="['promotion:point-order:export']">
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<!-- <el-table-column label="ID" align="center" prop="id" /> -->
|
||||
<el-table-column label="订单号" align="center" prop="orderNumber" />
|
||||
<el-table-column label="用户" align="center" prop="userName" />
|
||||
<el-table-column label="商品信息" align="center">
|
||||
<template #default="{ row }">
|
||||
<div style="display: flex; align-items: center;">
|
||||
<img :src="row.imageUrl" alt="Product Image" style="width: 50px; height: 50px; margin-right: 10px;" />
|
||||
<span>{{ row.productName }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column label="兑换积分" align="center" prop="integral" />
|
||||
<!-- <el-table-column label="订单状态" align="center" prop="orderStatus" /> -->
|
||||
<el-table-column label="订单状态" align="center" prop="orderStatus">
|
||||
<template #default="scope">
|
||||
<dict-tag :type="DICT_TYPE.TRADE_ORDER_STATUS" :value="scope.row.orderStatus" />
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="下单时间" align="center" prop="orderTime" :formatter="dateFormatter" width="180px" />
|
||||
<!-- <el-table-column
|
||||
label="创建时间"
|
||||
align="center"
|
||||
prop="createTime"
|
||||
:formatter="dateFormatter"
|
||||
width="180px"
|
||||
/> -->
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<!-- <el-button link type="primary" @click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['promotion:point-order:update']">
|
||||
编辑
|
||||
</el-button> -->
|
||||
<el-button link type="danger" @click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['promotion:point-order:delete']">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination :total="total" v-model:page="queryParams.pageNo" v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList" />
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<PointOrderForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { DICT_TYPE, getIntDictOptions } from '@/utils/dict'
|
||||
import { dateFormatter } from '@/utils/formatTime'
|
||||
import download from '@/utils/download'
|
||||
import { PointOrderApi, PointOrderVO } from '@/api/mall/promotion/pointorder'
|
||||
import PointOrderForm from './PointOrderForm.vue'
|
||||
|
||||
/** 兑换记录 列表 */
|
||||
defineOptions({ name: 'PointOrder' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<PointOrderVO[]>([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
orderNumber: undefined,
|
||||
userId: undefined,
|
||||
productId: undefined,
|
||||
integral: undefined,
|
||||
orderStatus: undefined,
|
||||
orderTime: [],
|
||||
createTime: [],
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await PointOrderApi.getPointOrderPage(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 formRef = ref()
|
||||
const openForm = (type : string, id ?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id : number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await PointOrderApi.deletePointOrder(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch { }
|
||||
}
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await PointOrderApi.exportPointOrder(queryParams)
|
||||
download.excel(data, '兑换记录.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
||||
|
||||
<style>
|
||||
|
||||
</style>
|
112
yudao-admin-vue3/src/views/member/type/cardForm.vue
Normal file
@ -0,0 +1,112 @@
|
||||
<template>
|
||||
<Dialog :title="dialogTitle" v-model="dialogVisible">
|
||||
<el-form
|
||||
ref="formRef"
|
||||
:model="formData"
|
||||
:rules="formRules"
|
||||
label-width="100px"
|
||||
v-loading="formLoading"
|
||||
>
|
||||
<el-form-item label="会员卡名称" prop="name">
|
||||
<el-input v-model="formData.name" placeholder="请输入会员卡名称" />
|
||||
</el-form-item>
|
||||
<el-form-item label="会员有效期(天)" prop="vid">
|
||||
<el-input v-model="formData.vid" placeholder="请输入会员有效期(天)" />
|
||||
</el-form-item>
|
||||
<el-form-item label="会员卡原价" prop="originalPrice">
|
||||
<el-input v-model="formData.originalPrice" placeholder="请输入会员卡原价" />
|
||||
</el-form-item>
|
||||
<el-form-item label="会员卡优惠价" prop="specialPrice">
|
||||
<el-input v-model="formData.specialPrice" placeholder="请输入会员卡优惠价" />
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<template #footer>
|
||||
<el-button @click="submitForm" type="primary" :disabled="formLoading">确 定</el-button>
|
||||
<el-button @click="dialogVisible = false">取 消</el-button>
|
||||
</template>
|
||||
</Dialog>
|
||||
</template>
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import { cardApi, cardVO } from '@/api/member/type'
|
||||
|
||||
/** 会员卡类型 表单 */
|
||||
defineOptions({ name: 'cardForm' })
|
||||
|
||||
const { t } = useI18n() // 国际化
|
||||
const message = useMessage() // 消息弹窗
|
||||
|
||||
const dialogVisible = ref(false) // 弹窗的是否展示
|
||||
const dialogTitle = ref('') // 弹窗的标题
|
||||
const formLoading = ref(false) // 表单的加载中:1)修改时的数据加载;2)提交的按钮禁用
|
||||
const formType = ref('') // 表单的类型:create - 新增;update - 修改
|
||||
const formData = ref({
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
vid: undefined,
|
||||
originalPrice: undefined,
|
||||
specialPrice: undefined,
|
||||
status: undefined,
|
||||
})
|
||||
const formRules = reactive({
|
||||
name: [{ required: true, message: '会员卡名称不能为空', trigger: 'blur' }],
|
||||
vid: [{ required: true, message: '会员有效期(天)不能为空', trigger: 'blur' }],
|
||||
originalPrice: [{ required: true, message: '会员卡原价不能为空', trigger: 'blur' }],
|
||||
})
|
||||
const formRef = ref() // 表单 Ref
|
||||
|
||||
/** 打开弹窗 */
|
||||
const open = async (type: string, id?: number) => {
|
||||
dialogVisible.value = true
|
||||
dialogTitle.value = t('action.' + type)
|
||||
formType.value = type
|
||||
resetForm()
|
||||
// 修改时,设置数据
|
||||
if (id) {
|
||||
formLoading.value = true
|
||||
try {
|
||||
formData.value = await cardApi.getcard(id)
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
}
|
||||
defineExpose({ open }) // 提供 open 方法,用于打开弹窗
|
||||
|
||||
/** 提交表单 */
|
||||
const emit = defineEmits(['success']) // 定义 success 事件,用于操作成功后的回调
|
||||
const submitForm = async () => {
|
||||
// 校验表单
|
||||
await formRef.value.validate()
|
||||
// 提交请求
|
||||
formLoading.value = true
|
||||
try {
|
||||
const data = formData.value as unknown as cardVO
|
||||
if (formType.value === 'create') {
|
||||
await cardApi.createcard(data)
|
||||
message.success(t('common.createSuccess'))
|
||||
} else {
|
||||
await cardApi.updatecard(data)
|
||||
message.success(t('common.updateSuccess'))
|
||||
}
|
||||
dialogVisible.value = false
|
||||
// 发送操作成功的事件
|
||||
emit('success')
|
||||
} finally {
|
||||
formLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 重置表单 */
|
||||
const resetForm = () => {
|
||||
formData.value = {
|
||||
id: undefined,
|
||||
name: undefined,
|
||||
vid: undefined,
|
||||
originalPrice: undefined,
|
||||
specialPrice: undefined,
|
||||
status: undefined,
|
||||
}
|
||||
formRef.value?.resetFields()
|
||||
}
|
||||
</script>
|
251
yudao-admin-vue3/src/views/member/type/index.vue
Normal file
@ -0,0 +1,251 @@
|
||||
<template>
|
||||
<ContentWrap>
|
||||
<!-- 搜索工作栏 -->
|
||||
<el-form
|
||||
class="-mb-15px"
|
||||
:model="queryParams"
|
||||
ref="queryFormRef"
|
||||
:inline="true"
|
||||
label-width="140px"
|
||||
>
|
||||
<el-form-item label="会员卡名称" prop="name">
|
||||
<el-input
|
||||
v-model="queryParams.name"
|
||||
placeholder="请输入会员卡名称"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="会员有效期(天)" prop="vid">
|
||||
<el-input
|
||||
v-model="queryParams.vid"
|
||||
placeholder="请输入会员有效期(天)"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="会员卡原价" prop="originalPrice">
|
||||
<el-input
|
||||
v-model="queryParams.originalPrice"
|
||||
placeholder="请输入会员卡原价"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="会员卡优惠价" prop="specialPrice">
|
||||
<el-input
|
||||
v-model="queryParams.specialPrice"
|
||||
placeholder="请输入会员卡优惠价"
|
||||
clearable
|
||||
@keyup.enter="handleQuery"
|
||||
class="!w-240px"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否启用" prop="status">
|
||||
<el-select
|
||||
v-model="queryParams.status"
|
||||
placeholder="请选择会员卡是否禁用"
|
||||
clearable
|
||||
class="!w-240px"
|
||||
>
|
||||
<el-option
|
||||
v-for="dict in getIntDictOptions(DICT_TYPE.COMMON_STATUS)"
|
||||
:key="dict.value"
|
||||
:label="dict.label"
|
||||
:value="dict.value"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item>
|
||||
<el-button @click="handleQuery"><Icon icon="ep:search" class="mr-5px" /> 搜索</el-button>
|
||||
<el-button @click="resetQuery"><Icon icon="ep:refresh" class="mr-5px" /> 重置</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
plain
|
||||
@click="openForm('create')"
|
||||
v-hasPermi="['member:paid-member-card-type:create']"
|
||||
>
|
||||
<Icon icon="ep:plus" class="mr-5px" /> 新增
|
||||
</el-button>
|
||||
<el-button
|
||||
type="success"
|
||||
plain
|
||||
@click="handleExport"
|
||||
:loading="exportLoading"
|
||||
v-hasPermi="['member:paid-member-card-type:export']"
|
||||
>
|
||||
<Icon icon="ep:download" class="mr-5px" /> 导出
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 列表 -->
|
||||
<ContentWrap>
|
||||
<el-table v-loading="loading" :data="list" :stripe="true" :show-overflow-tooltip="true">
|
||||
<el-table-column label="会员卡id" align="center" prop="id" />
|
||||
<el-table-column label="会员卡名称" align="center" prop="name" />
|
||||
<el-table-column label="会员有效期(天)" align="center" prop="vid" />
|
||||
<el-table-column label="会员卡原价" align="center" prop="originalPrice" />
|
||||
<el-table-column label="会员卡优惠价" align="center" prop="specialPrice" />
|
||||
<el-table-column label="是否启用" align="center" prop="status">
|
||||
<template #default="{row}">
|
||||
<template v-if="row.status >= 0">
|
||||
<el-switch
|
||||
v-model="row.status"
|
||||
inline-prompt
|
||||
:active-value=1
|
||||
:inactive-value=0
|
||||
active-text="是"
|
||||
inactive-text="否"
|
||||
@change="handleStatusChange(row)"
|
||||
/>
|
||||
</template>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column label="操作" align="center">
|
||||
<template #default="scope">
|
||||
<el-button
|
||||
link
|
||||
type="primary"
|
||||
@click="openForm('update', scope.row.id)"
|
||||
v-hasPermi="['member:paid-member-card-type:update']"
|
||||
>
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
link
|
||||
type="danger"
|
||||
@click="handleDelete(scope.row.id)"
|
||||
v-hasPermi="['member:paid-member-card-type:delete']"
|
||||
>
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 分页 -->
|
||||
<Pagination
|
||||
:total="total"
|
||||
v-model:page="queryParams.pageNo"
|
||||
v-model:limit="queryParams.pageSize"
|
||||
@pagination="getList"
|
||||
/>
|
||||
</ContentWrap>
|
||||
|
||||
<!-- 表单弹窗:添加/修改 -->
|
||||
<cardForm ref="formRef" @success="getList" />
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { getIntDictOptions, DICT_TYPE } from '@/utils/dict'
|
||||
import download from '@/utils/download'
|
||||
import { cardApi, cardVO } from '@/api/member/type'
|
||||
import * as typeapi from '@/api/member/type'
|
||||
import cardForm from './cardForm.vue'
|
||||
import { any } from 'vue-types'
|
||||
|
||||
/** 会员卡类型 列表 */
|
||||
defineOptions({ name: 'Membercard' })
|
||||
|
||||
const message = useMessage() // 消息弹窗
|
||||
const { t } = useI18n() // 国际化
|
||||
|
||||
const loading = ref(true) // 列表的加载中
|
||||
const list = ref<cardVO[]>([]) // 列表的数据
|
||||
const total = ref(0) // 列表的总页数
|
||||
const queryParams = reactive({
|
||||
pageNo: 1,
|
||||
pageSize: 10,
|
||||
name: undefined,
|
||||
vid: undefined,
|
||||
originalPrice: undefined,
|
||||
specialPrice: undefined,
|
||||
sort: undefined,
|
||||
status: undefined,
|
||||
})
|
||||
const queryFormRef = ref() // 搜索的表单
|
||||
const exportLoading = ref(false) // 导出的加载中
|
||||
|
||||
/** 查询列表 */
|
||||
const getList = async () => {
|
||||
loading.value = true
|
||||
try {
|
||||
const data = await cardApi.getcardPage(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 formRef = ref()
|
||||
const openForm = (type: int, id?: number) => {
|
||||
formRef.value.open(type, id)
|
||||
}
|
||||
|
||||
/** 状态操作: 启用/禁用 */
|
||||
const handleStatusChange = async (row: any) =>{
|
||||
const originalStatus = row.status
|
||||
try{
|
||||
//发起修改
|
||||
await cardApi.updatecard(row)
|
||||
// //刷新列表
|
||||
await getList()
|
||||
}
|
||||
catch{
|
||||
row.status = originalStatus
|
||||
}
|
||||
}
|
||||
|
||||
/** 删除按钮操作 */
|
||||
const handleDelete = async (id: number) => {
|
||||
try {
|
||||
// 删除的二次确认
|
||||
await message.delConfirm()
|
||||
// 发起删除
|
||||
await cardApi.deletecard(id)
|
||||
message.success(t('common.delSuccess'))
|
||||
// 刷新列表
|
||||
await getList()
|
||||
} catch {}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** 导出按钮操作 */
|
||||
const handleExport = async () => {
|
||||
try {
|
||||
// 导出的二次确认
|
||||
await message.exportConfirm()
|
||||
// 发起导出
|
||||
exportLoading.value = true
|
||||
const data = await cardApi.exportcard(queryParams)
|
||||
download.excel(data, '会员卡类型.xls')
|
||||
} catch {
|
||||
} finally {
|
||||
exportLoading.value = false
|
||||
}
|
||||
}
|
||||
|
||||
/** 初始化 **/
|
||||
onMounted(() => {
|
||||
getList()
|
||||
})
|
||||
</script>
|
@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.SortablePageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.SortingField;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.enums.SqlConstants;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.JdbcUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.util.MyBatisUtils;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import com.baomidou.mybatisplus.core.conditions.Wrapper;
|
||||
@ -151,7 +152,8 @@ public interface BaseMapperX<T> extends MPJBaseMapper<T> {
|
||||
*/
|
||||
default Boolean insertBatch(Collection<T> entities) {
|
||||
// 特殊:SQL Server 批量插入后,获取 id 会报错,因此通过循环处理
|
||||
if (Objects.equals(SqlConstants.DB_TYPE, DbType.SQL_SERVER)) {
|
||||
DbType dbType = JdbcUtils.getDbType();
|
||||
if (JdbcUtils.isSQLServer(dbType)) {
|
||||
entities.forEach(this::insert);
|
||||
return CollUtil.isNotEmpty(entities);
|
||||
}
|
||||
|
@ -1,9 +1,11 @@
|
||||
package cn.iocoder.yudao.framework.mybatis.core.util;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.object.ObjectUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.spring.SpringUtils;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.enums.DbTypeEnum;
|
||||
import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
|
||||
import com.baomidou.mybatisplus.annotation.DbType;
|
||||
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
import java.sql.Connection;
|
||||
@ -43,14 +45,28 @@ public class JdbcUtils {
|
||||
return com.baomidou.mybatisplus.extension.toolkit.JdbcUtils.getDbType(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断 JDBC 连接是否为 SQLServer 数据库
|
||||
*
|
||||
* @param dbType DB 类型
|
||||
* @return 是否为 SQLServer 数据库
|
||||
*/
|
||||
public static boolean isSQLServer(DbType dbType) {
|
||||
return ObjectUtils.equalsAny(dbType, DbType.SQL_SERVER, DbType.SQL_SERVER2005);
|
||||
}
|
||||
/**
|
||||
* 通过当前数据库连接获得对应的 DB 类型
|
||||
*
|
||||
* @return DB 类型
|
||||
*/
|
||||
public static DbType getDbType() {
|
||||
DynamicRoutingDataSource dynamicRoutingDataSource = SpringUtils.getBean(DynamicRoutingDataSource.class);
|
||||
DataSource dataSource = dynamicRoutingDataSource.determineDataSource();
|
||||
DataSource dataSource;
|
||||
try {
|
||||
DynamicRoutingDataSource dynamicRoutingDataSource = SpringUtils.getBean(DynamicRoutingDataSource.class);
|
||||
dataSource = dynamicRoutingDataSource.determineDataSource();
|
||||
} catch (NoSuchBeanDefinitionException e) {
|
||||
dataSource = SpringUtils.getBean(DataSource.class);
|
||||
}
|
||||
try (Connection conn = dataSource.getConnection()) {
|
||||
return DbTypeEnum.find(conn.getMetaData().getDatabaseProductName());
|
||||
} catch (SQLException e) {
|
||||
|
@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.product.api.spu.dto;
|
||||
import cn.iocoder.yudao.module.product.enums.spu.ProductSpuStatusEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
// TODO @LeeYan9: ProductSpuRespDTO
|
||||
/**
|
||||
* 商品 SPU 信息 Response DTO
|
||||
@ -69,6 +71,13 @@ public class ProductSpuRespDTO {
|
||||
|
||||
// ========== 物流相关字段 =========
|
||||
|
||||
/**
|
||||
* 配送方式数组
|
||||
*
|
||||
* 对应 DeliveryTypeEnum 枚举
|
||||
*/
|
||||
private List<Integer> deliveryTypes;
|
||||
|
||||
/**
|
||||
* 物流配置模板编号
|
||||
*
|
||||
|
@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵 API 接口
|
||||
@ -20,6 +21,15 @@ public interface CouponApi {
|
||||
*/
|
||||
void useCoupon(@Valid CouponUseReqDTO useReqDTO);
|
||||
|
||||
/**
|
||||
* 获得用户的优惠劵列表
|
||||
*
|
||||
* @param userId 用户编号
|
||||
* @param status 优惠劵状态
|
||||
* @return 优惠劵列表
|
||||
*/
|
||||
List<CouponRespDTO> getCouponListByUserId(Long userId, Integer status);
|
||||
|
||||
/**
|
||||
* 退还已使用的优惠券
|
||||
*
|
||||
|
@ -27,4 +27,6 @@ public interface RewardActivityApi {
|
||||
*/
|
||||
RewardActivityDTO getRewardActivityById(Long id);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,9 +1,14 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.reward.dto;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
|
||||
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 满减送活动的匹配 Response DTO
|
||||
@ -13,6 +18,12 @@ import java.util.List;
|
||||
@Data
|
||||
public class RewardActivityMatchRespDTO {
|
||||
|
||||
/**
|
||||
* 匹配的 SPU 数组
|
||||
*/
|
||||
private List<Long> spuIds;
|
||||
|
||||
|
||||
/**
|
||||
* 活动编号,主键自增
|
||||
*/
|
||||
@ -21,28 +32,50 @@ public class RewardActivityMatchRespDTO {
|
||||
* 活动标题
|
||||
*/
|
||||
private String name;
|
||||
/**
|
||||
* 状态
|
||||
*
|
||||
* 枚举 {@link CommonStatusEnum}
|
||||
*/
|
||||
private Integer status;
|
||||
/**
|
||||
* 开始时间
|
||||
*/
|
||||
private LocalDateTime startTime;
|
||||
/**
|
||||
* 结束时间
|
||||
*/
|
||||
private LocalDateTime endTime;
|
||||
/**
|
||||
* 备注
|
||||
*/
|
||||
private String remark;
|
||||
/**
|
||||
* 条件类型
|
||||
*
|
||||
* 枚举 {@link PromotionConditionTypeEnum}
|
||||
*/
|
||||
private Integer conditionType;
|
||||
/**
|
||||
* 商品范围
|
||||
*
|
||||
* 枚举 {@link PromotionProductScopeEnum}
|
||||
*/
|
||||
private Integer productScope;
|
||||
/**
|
||||
* 商品 SPU 编号的数组
|
||||
*/
|
||||
private List<Long> productScopeValues;
|
||||
/**
|
||||
* 优惠规则的数组
|
||||
*/
|
||||
private List<Rule> rules;
|
||||
|
||||
/**
|
||||
* 商品 SPU 编号的数组
|
||||
*/
|
||||
private List<Long> spuIds;
|
||||
|
||||
// TODO 芋艿:后面 RewardActivityRespDTO 有了之后,Rule 可以放过去
|
||||
/**
|
||||
* 优惠规则
|
||||
*/
|
||||
@Data
|
||||
public static class Rule {
|
||||
public static class Rule implements Serializable {
|
||||
|
||||
/**
|
||||
* 优惠门槛
|
||||
@ -64,13 +97,21 @@ public class RewardActivityMatchRespDTO {
|
||||
*/
|
||||
private Integer point;
|
||||
/**
|
||||
* 赠送的优惠劵编号的数组
|
||||
* 赠送的优惠劵
|
||||
*
|
||||
* key: 优惠劵模版编号
|
||||
* value:对应的优惠券数量
|
||||
*
|
||||
* 目的:用于订单支付后赠送优惠券
|
||||
*/
|
||||
private List<Long> couponIds;
|
||||
private Map<Long, Integer> giveCouponTemplateCounts;
|
||||
|
||||
/**
|
||||
* 赠送的优惠券数量的数组
|
||||
* 规则描述
|
||||
*
|
||||
* 通过 {@link #limit}、{@link #discountPrice} 等字段进行拼接
|
||||
*/
|
||||
private List<Integer> couponCounts;
|
||||
private String description;
|
||||
|
||||
}
|
||||
|
||||
|
@ -16,6 +16,9 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_001_003, "限时折扣活动未关闭,不能删除");
|
||||
ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_004, "限时折扣活动已关闭,不能重复关闭");
|
||||
|
||||
// ========== 兑换记录 TODO 补充编号 ==========
|
||||
ErrorCode POINT_ORDER_NOT_EXISTS = new ErrorCode(11111, "兑换记录不存在");
|
||||
|
||||
// ========== Banner 相关 1-013-002-000 ============
|
||||
ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1_013_002_000, "Banner 不存在");
|
||||
|
||||
|
@ -5,6 +5,7 @@ import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* 营销的商品范围枚举
|
||||
@ -15,10 +16,9 @@ import java.util.Arrays;
|
||||
@AllArgsConstructor
|
||||
public enum PromotionProductScopeEnum implements IntArrayValuable {
|
||||
|
||||
ALL(1, "通用券"), // 全部商品
|
||||
SPU(2, "商品券"), // 指定商品
|
||||
CATEGORY(3, "品类券"), // 指定品类
|
||||
;
|
||||
ALL(1, "全部商品"),
|
||||
SPU(2, "指定商品"),
|
||||
CATEGORY(3, "指定品类");
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(PromotionProductScopeEnum::getScope).toArray();
|
||||
|
||||
@ -36,4 +36,17 @@ public enum PromotionProductScopeEnum implements IntArrayValuable {
|
||||
return ARRAYS;
|
||||
}
|
||||
|
||||
public static boolean isAll(Integer scope) {
|
||||
return Objects.equals(scope, ALL.scope);
|
||||
}
|
||||
|
||||
public static boolean isSpu(Integer scope) {
|
||||
return Objects.equals(scope, SPU.scope);
|
||||
}
|
||||
|
||||
public static boolean isCategory(Integer scope) {
|
||||
return Objects.equals(scope, CATEGORY.scope);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.coupon;
|
||||
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponUseReqDTO;
|
||||
import cn.iocoder.yudao.module.promotion.api.coupon.dto.CouponValidReqDTO;
|
||||
@ -11,6 +12,7 @@ import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 优惠劵 API 实现类
|
||||
@ -24,6 +26,11 @@ public class CouponApiImpl implements CouponApi {
|
||||
@Resource
|
||||
private CouponService couponService;
|
||||
|
||||
@Override
|
||||
public List<CouponRespDTO> getCouponListByUserId(Long userId, Integer status) {
|
||||
return BeanUtils.toBean(couponService.getCouponList(userId, status), CouponRespDTO.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void useCoupon(CouponUseReqDTO useReqDTO) {
|
||||
couponService.useCoupon(useReqDTO.getId(), useReqDTO.getUserId(),
|
||||
|
@ -1,7 +1,9 @@
|
||||
package cn.iocoder.yudao.module.promotion.api.discount;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
|
||||
import cn.iocoder.yudao.module.promotion.convert.discount.DiscountActivityConvert;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.discount.DiscountActivityService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -24,7 +26,7 @@ public class DiscountActivityApiImpl implements DiscountActivityApi {
|
||||
|
||||
@Override
|
||||
public List<DiscountProductRespDTO> getMatchDiscountProductList(Collection<Long> skuIds) {
|
||||
return DiscountActivityConvert.INSTANCE.convertList02(discountActivityService.getMatchDiscountProductList(skuIds));
|
||||
}
|
||||
List<DiscountProductDO> list = discountActivityService.getMatchDiscountProductList(skuIds);
|
||||
return BeanUtils.toBean(list, DiscountProductRespDTO.class); }
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,95 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.pointorder;
|
||||
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.security.access.prepost.PreAuthorize;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
|
||||
|
||||
import javax.validation.*;
|
||||
import javax.servlet.http.*;
|
||||
import java.util.*;
|
||||
import java.io.IOException;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
|
||||
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
|
||||
|
||||
import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
|
||||
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.*;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.pointorder.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.pointorder.PointOrderDO;
|
||||
import cn.iocoder.yudao.module.promotion.service.pointorder.PointOrderService;
|
||||
|
||||
@Tag(name = "管理后台 - 兑换记录")
|
||||
@RestController
|
||||
@RequestMapping("/promotion/point-order")
|
||||
@Validated
|
||||
public class PointOrderController {
|
||||
|
||||
@Resource
|
||||
private PointOrderService pointOrderService;
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建兑换记录")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:point-order:create')")
|
||||
public CommonResult<Long> createPointOrder(@Valid @RequestBody PointOrderSaveReqVO createReqVO) {
|
||||
return success(pointOrderService.createPointOrder(createReqVO));
|
||||
}
|
||||
|
||||
@PutMapping("/update")
|
||||
@Operation(summary = "更新兑换记录")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:point-order:update')")
|
||||
public CommonResult<Boolean> updatePointOrder(@Valid @RequestBody PointOrderSaveReqVO updateReqVO) {
|
||||
pointOrderService.updatePointOrder(updateReqVO);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@DeleteMapping("/delete")
|
||||
@Operation(summary = "删除兑换记录")
|
||||
@Parameter(name = "id", description = "编号", required = true)
|
||||
@PreAuthorize("@ss.hasPermission('promotion:point-order:delete')")
|
||||
public CommonResult<Boolean> deletePointOrder(@RequestParam("id") Long id) {
|
||||
pointOrderService.deletePointOrder(id);
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@GetMapping("/get")
|
||||
@Operation(summary = "获得兑换记录")
|
||||
@Parameter(name = "id", description = "编号", required = true, example = "1024")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:point-order:query')")
|
||||
public CommonResult<PointOrderRespVO> getPointOrder(@RequestParam("id") Long id) {
|
||||
PointOrderDO pointOrder = pointOrderService.getPointOrder(id);
|
||||
return success(BeanUtils.toBean(pointOrder, PointOrderRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/page")
|
||||
@Operation(summary = "获得兑换记录分页")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:point-order:query')")
|
||||
public CommonResult<PageResult<PointOrderRespVO>> getPointOrderPage(@Valid PointOrderPageReqVO pageReqVO) {
|
||||
PageResult<PointOrderDO> pageResult = pointOrderService.getPointOrderPage(pageReqVO);
|
||||
return success(BeanUtils.toBean(pageResult, PointOrderRespVO.class));
|
||||
}
|
||||
|
||||
@GetMapping("/export-excel")
|
||||
@Operation(summary = "导出兑换记录 Excel")
|
||||
@PreAuthorize("@ss.hasPermission('promotion:point-order:export')")
|
||||
@ApiAccessLog(operateType = EXPORT)
|
||||
public void exportPointOrderExcel(@Valid PointOrderPageReqVO pageReqVO,
|
||||
HttpServletResponse response) throws IOException {
|
||||
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
|
||||
List<PointOrderDO> list = pointOrderService.getPointOrderPage(pageReqVO).getList();
|
||||
// 导出 Excel
|
||||
ExcelUtils.write(response, "兑换记录.xls", "数据", PointOrderRespVO.class,
|
||||
BeanUtils.toBean(list, PointOrderRespVO.class));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,41 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.pointorder.vo;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
|
||||
|
||||
@Schema(description = "管理后台 - 兑换记录分页 Request VO")
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
public class PointOrderPageReqVO extends PageParam {
|
||||
|
||||
@Schema(description = "订单号")
|
||||
private String orderNumber;
|
||||
|
||||
@Schema(description = "用户id", example = "13639")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "商品id", example = "2315")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "兑换积分")
|
||||
private Integer integral;
|
||||
|
||||
@Schema(description = "订单状态", example = "2")
|
||||
private Integer orderStatus;
|
||||
|
||||
@Schema(description = "下单时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] orderTime;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
|
||||
private LocalDateTime[] createTime;
|
||||
|
||||
}
|
@ -0,0 +1,53 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.pointorder.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
import com.alibaba.excel.annotation.*;
|
||||
|
||||
@Schema(description = "管理后台 - 兑换记录 Response VO")
|
||||
@Data
|
||||
@ExcelIgnoreUnannotated
|
||||
public class PointOrderRespVO {
|
||||
|
||||
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19849")
|
||||
@ExcelProperty("id")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "订单号")
|
||||
@ExcelProperty("订单号")
|
||||
private String orderNumber;
|
||||
|
||||
@Schema(description = "用户id", example = "13639")
|
||||
@ExcelProperty("用户id")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "商品id", example = "2315")
|
||||
@ExcelProperty("商品id")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "兑换积分")
|
||||
@ExcelProperty("兑换积分")
|
||||
private Integer integral;
|
||||
|
||||
@Schema(description = "订单状态", example = "2")
|
||||
@ExcelProperty("订单状态")
|
||||
private Integer orderStatus;
|
||||
|
||||
@Schema(description = "下单时间")
|
||||
@ExcelProperty("下单时间")
|
||||
private LocalDateTime orderTime;
|
||||
|
||||
@Schema(description = "创建时间")
|
||||
@ExcelProperty("创建时间")
|
||||
private LocalDateTime createTime;
|
||||
|
||||
private String userName;
|
||||
|
||||
private String productName;
|
||||
|
||||
private String imageUrl;
|
||||
|
||||
}
|
@ -0,0 +1,35 @@
|
||||
package cn.iocoder.yudao.module.promotion.controller.admin.pointorder.vo;
|
||||
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import javax.validation.constraints.*;
|
||||
import org.springframework.format.annotation.DateTimeFormat;
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Schema(description = "管理后台 - 兑换记录新增/修改 Request VO")
|
||||
@Data
|
||||
public class PointOrderSaveReqVO {
|
||||
|
||||
@Schema(description = "id", requiredMode = Schema.RequiredMode.REQUIRED, example = "19849")
|
||||
private Long id;
|
||||
|
||||
@Schema(description = "订单号")
|
||||
private String orderNumber;
|
||||
|
||||
@Schema(description = "用户id", example = "13639")
|
||||
private Long userId;
|
||||
|
||||
@Schema(description = "商品id", example = "2315")
|
||||
private Long productId;
|
||||
|
||||
@Schema(description = "兑换积分")
|
||||
private Integer integral;
|
||||
|
||||
@Schema(description = "订单状态", example = "2")
|
||||
private Integer orderStatus;
|
||||
|
||||
@Schema(description = "下单时间")
|
||||
private LocalDateTime orderTime;
|
||||
|
||||
}
|
@ -130,16 +130,19 @@ public class AppSeckillActivityController {
|
||||
|
||||
@GetMapping("/spuList")
|
||||
@Parameter(name = "count", description = "需要展示的数量", example = "6")
|
||||
@Operation(summary = "获得现在进行的秒杀活动分页")
|
||||
@Operation(summary = "获得秒杀活动分页")
|
||||
public CommonResult<List<ProductSpuRespDTO>> getSeckillActivitySupList(@RequestParam(name = "count", defaultValue = "3") Integer count) {
|
||||
AppSeckillActivityPageReqVO pageReqVO = new AppSeckillActivityPageReqVO();
|
||||
Page<SeckillActivityDO> page = new Page<>(1, 3);
|
||||
;
|
||||
if (count != null && count != 0) {
|
||||
page = new Page<>(1, count);
|
||||
pageReqVO.setPageNo(1);
|
||||
pageReqVO.setPageSize(count);
|
||||
}
|
||||
// Page<SeckillActivityDO> page = new Page<>(1, 3);
|
||||
// if (count != null && count != 0) {
|
||||
// page = new Page<>(1, count);
|
||||
// }
|
||||
// 先找出当前时间对应的配置时间段id
|
||||
List<Long> configIdList = new ArrayList<>();
|
||||
/* List<Long> configIdList = new ArrayList<>();
|
||||
try {
|
||||
List<SeckillConfigDO> timeList = configService.getSeckillConfigListByStatus(CommonStatusEnum.ENABLE.getStatus());
|
||||
SimpleDateFormat format = new SimpleDateFormat("HH:mm");
|
||||
@ -159,9 +162,9 @@ public class AppSeckillActivityController {
|
||||
return success(null);
|
||||
}
|
||||
// 获取满足当前正在进行的活动
|
||||
PageResult<SeckillActivityDO> pageResult = activityService.getRunningActivityByConfigIdsCount(configIdList, page);
|
||||
PageResult<SeckillActivityDO> pageResult = activityService.getRunningActivityByConfigIdsCount(configIdList, page);*/
|
||||
// 1. 查询满足当前阶段的活动
|
||||
// PageResult<SeckillActivityDO> pageResult = activityService.getSeckillActivityAppPageByConfigId(pageReqVO);
|
||||
PageResult<SeckillActivityDO> pageResult = activityService.getSeckillActivityAppPageByConfigId(pageReqVO);
|
||||
if (CollUtil.isEmpty(pageResult.getList())) {
|
||||
return success(null);
|
||||
}
|
||||
|
@ -0,0 +1,71 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.dataobject.pointorder;
|
||||
|
||||
import lombok.*;
|
||||
import java.util.*;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalDateTime;
|
||||
import com.baomidou.mybatisplus.annotation.*;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
|
||||
|
||||
/**
|
||||
* 兑换记录 DO
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
@TableName("promotion_point_order")
|
||||
@KeySequence("promotion_point_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
|
||||
@Data
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@ToString(callSuper = true)
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class PointOrderDO extends BaseDO {
|
||||
|
||||
/**
|
||||
* id
|
||||
*/
|
||||
@TableId
|
||||
private Long id;
|
||||
/**
|
||||
* 订单号
|
||||
*/
|
||||
private String orderNumber;
|
||||
/**
|
||||
* 用户id
|
||||
*/
|
||||
private Long userId;
|
||||
/**
|
||||
* 商品id
|
||||
*/
|
||||
private Long productId;
|
||||
/**
|
||||
* 兑换积分
|
||||
*/
|
||||
private Integer integral;
|
||||
/**
|
||||
* 订单状态
|
||||
*/
|
||||
private Integer orderStatus;
|
||||
/**
|
||||
* 下单时间
|
||||
*/
|
||||
private LocalDateTime orderTime;
|
||||
|
||||
/**
|
||||
* 用户名称
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String userName;
|
||||
|
||||
/**
|
||||
* 商品名称
|
||||
*/
|
||||
@TableField(exist = false)
|
||||
private String productName;
|
||||
|
||||
@TableField(exist = false)
|
||||
private String imageUrl;
|
||||
|
||||
}
|
@ -1,11 +1,13 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.discount;
|
||||
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -22,6 +24,15 @@ public interface DiscountProductMapper extends BaseMapperX<DiscountProductDO> {
|
||||
return selectList(DiscountProductDO::getSkuId, skuIds);
|
||||
}
|
||||
|
||||
default List<DiscountProductDO> selectListBySkuIdsAndStatusAndNow(Collection<Long> skuIds, Integer status) {
|
||||
LocalDateTime now = LocalDateTime.now();
|
||||
return selectList(new LambdaQueryWrapperX<DiscountProductDO>()
|
||||
.in(DiscountProductDO::getSkuId, skuIds)
|
||||
.eq(DiscountProductDO::getActivityStatus,status)
|
||||
.lt(DiscountProductDO::getActivityStartTime, now)
|
||||
.gt(DiscountProductDO::getActivityEndTime, now));
|
||||
}
|
||||
|
||||
default List<DiscountProductDO> selectListByActivityId(Long activityId) {
|
||||
return selectList(DiscountProductDO::getActivityId, activityId);
|
||||
}
|
||||
|
@ -0,0 +1,32 @@
|
||||
package cn.iocoder.yudao.module.promotion.dal.mysql.pointorder;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.pointorder.PointOrderDO;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.pointorder.vo.*;
|
||||
|
||||
/**
|
||||
* 兑换记录 Mapper
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
@Mapper
|
||||
public interface PointOrderMapper extends BaseMapperX<PointOrderDO> {
|
||||
|
||||
default PageResult<PointOrderDO> selectPage(PointOrderPageReqVO reqVO) {
|
||||
return selectPage(reqVO, new LambdaQueryWrapperX<PointOrderDO>()
|
||||
.eqIfPresent(PointOrderDO::getOrderNumber, reqVO.getOrderNumber())
|
||||
.eqIfPresent(PointOrderDO::getUserId, reqVO.getUserId())
|
||||
.eqIfPresent(PointOrderDO::getProductId, reqVO.getProductId())
|
||||
.eqIfPresent(PointOrderDO::getIntegral, reqVO.getIntegral())
|
||||
.eqIfPresent(PointOrderDO::getOrderStatus, reqVO.getOrderStatus())
|
||||
.betweenIfPresent(PointOrderDO::getOrderTime, reqVO.getOrderTime())
|
||||
.betweenIfPresent(PointOrderDO::getCreateTime, reqVO.getCreateTime())
|
||||
.orderByDesc(PointOrderDO::getId));
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.pointorder;
|
||||
|
||||
import java.util.*;
|
||||
import javax.validation.*;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.pointorder.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.pointorder.PointOrderDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
|
||||
/**
|
||||
* 兑换记录 Service 接口
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
public interface PointOrderService {
|
||||
|
||||
/**
|
||||
* 创建兑换记录
|
||||
*
|
||||
* @param createReqVO 创建信息
|
||||
* @return 编号
|
||||
*/
|
||||
Long createPointOrder(@Valid PointOrderSaveReqVO createReqVO);
|
||||
|
||||
/**
|
||||
* 更新兑换记录
|
||||
*
|
||||
* @param updateReqVO 更新信息
|
||||
*/
|
||||
void updatePointOrder(@Valid PointOrderSaveReqVO updateReqVO);
|
||||
|
||||
/**
|
||||
* 删除兑换记录
|
||||
*
|
||||
* @param id 编号
|
||||
*/
|
||||
void deletePointOrder(Long id);
|
||||
|
||||
/**
|
||||
* 获得兑换记录
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 兑换记录
|
||||
*/
|
||||
PointOrderDO getPointOrder(Long id);
|
||||
|
||||
/**
|
||||
* 获得兑换记录分页
|
||||
*
|
||||
* @param pageReqVO 分页查询
|
||||
* @return 兑换记录分页
|
||||
*/
|
||||
PageResult<PointOrderDO> getPointOrderPage(PointOrderPageReqVO pageReqVO);
|
||||
|
||||
}
|
@ -0,0 +1,100 @@
|
||||
package cn.iocoder.yudao.module.promotion.service.pointorder;
|
||||
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
|
||||
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
|
||||
import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
|
||||
import org.springframework.stereotype.Service;
|
||||
import javax.annotation.Resource;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.util.*;
|
||||
import cn.iocoder.yudao.module.promotion.controller.admin.pointorder.vo.*;
|
||||
import cn.iocoder.yudao.module.promotion.dal.dataobject.pointorder.PointOrderDO;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageParam;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
|
||||
import cn.iocoder.yudao.module.promotion.dal.mysql.pointorder.PointOrderMapper;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
|
||||
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
|
||||
|
||||
/**
|
||||
* 兑换记录 Service 实现类
|
||||
*
|
||||
* @author 管理员
|
||||
*/
|
||||
@Service
|
||||
@Validated
|
||||
public class PointOrderServiceImpl implements PointOrderService {
|
||||
|
||||
@Resource
|
||||
private PointOrderMapper pointOrderMapper;
|
||||
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
@Resource
|
||||
private ProductSpuApi productSpuApi;
|
||||
|
||||
@Override
|
||||
public Long createPointOrder(PointOrderSaveReqVO createReqVO) {
|
||||
// 插入
|
||||
PointOrderDO pointOrder = BeanUtils.toBean(createReqVO, PointOrderDO.class);
|
||||
pointOrderMapper.insert(pointOrder);
|
||||
// 返回
|
||||
return pointOrder.getId();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updatePointOrder(PointOrderSaveReqVO updateReqVO) {
|
||||
// 校验存在
|
||||
validatePointOrderExists(updateReqVO.getId());
|
||||
// 更新
|
||||
PointOrderDO updateObj = BeanUtils.toBean(updateReqVO, PointOrderDO.class);
|
||||
pointOrderMapper.updateById(updateObj);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deletePointOrder(Long id) {
|
||||
// 校验存在
|
||||
validatePointOrderExists(id);
|
||||
// 删除
|
||||
pointOrderMapper.deleteById(id);
|
||||
}
|
||||
|
||||
private void validatePointOrderExists(Long id) {
|
||||
if (pointOrderMapper.selectById(id) == null) {
|
||||
throw exception(POINT_ORDER_NOT_EXISTS);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PointOrderDO getPointOrder(Long id) {
|
||||
return pointOrderMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<PointOrderDO> getPointOrderPage(PointOrderPageReqVO pageReqVO) {
|
||||
PageResult<PointOrderDO> pointOrderDOPageResult = pointOrderMapper.selectPage(pageReqVO);
|
||||
List<PointOrderDO> list = pointOrderDOPageResult.getList();
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
PointOrderDO pointOrderDO = list.get(i);
|
||||
|
||||
//设置用户名称
|
||||
MemberUserRespDTO user = memberUserApi.getUser(pointOrderDO.getUserId());
|
||||
pointOrderDO.setUserName(user.getNickname());
|
||||
|
||||
//获取商品信息
|
||||
ProductSpuRespDTO spu = productSpuApi.getSpu(pointOrderDO.getProductId());
|
||||
pointOrderDO.setProductName(spu.getName());
|
||||
pointOrderDO.setImageUrl(spu.getPicUrl());
|
||||
|
||||
|
||||
}
|
||||
return pointOrderDOPageResult;
|
||||
}
|
||||
|
||||
}
|
@ -35,6 +35,7 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode ORDER_RECEIVE_FAIL_DELIVERY_TYPE_NOT_PICK_UP = new ErrorCode(1_011_000_030, "交易订单自提失败,收货方式不是【用户自提】");
|
||||
ErrorCode ORDER_UPDATE_ADDRESS_FAIL_STATUS_NOT_DELIVERED = new ErrorCode(1_011_000_031, "交易订单修改收货地址失败,原因:订单不是【待发货】状态");
|
||||
ErrorCode ORDER_CREATE_FAIL_EXIST_UNPAID = new ErrorCode(1_011_000_032, "交易订单创建失败,原因:存在未付款订单");
|
||||
ErrorCode ORDER_CANCEL_PAID_FAIL = new ErrorCode(1_011_000_033, "交易订单取消支付失败,原因:订单不是【{}】状态");
|
||||
|
||||
// ========== After Sale 模块 1-011-000-100 ==========
|
||||
ErrorCode AFTER_SALE_NOT_FOUND = new ErrorCode(1_011_000_100, "售后单不存在");
|
||||
@ -53,12 +54,15 @@ public interface ErrorCodeConstants {
|
||||
|
||||
// ========== Cart 模块 1-011-002-000 ==========
|
||||
ErrorCode CARD_ITEM_NOT_FOUND = new ErrorCode(1_011_002_000, "购物车项不存在");
|
||||
ErrorCode PRICE_CALCULATE_POINT_TOTAL_LIMIT_COUNT = new ErrorCode(1_011_003_004, "参与积分活动的商品,超过了积分活动商品总限购数量");
|
||||
|
||||
// ========== Price 相关 1-011-003-000 ============
|
||||
ErrorCode PRICE_CALCULATE_PAY_PRICE_ILLEGAL = new ErrorCode(1_011_003_000, "支付价格计算异常,原因:价格小于等于 0");
|
||||
ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TEMPLATE_NOT_FOUND = new ErrorCode(1_011_003_002, "计算快递运费异常,找不到对应的运费模板");
|
||||
ErrorCode PRICE_CALCULATE_COUPON_NOT_MATCH_NORMAL_ORDER = new ErrorCode(1_011_003_004, "参与秒杀、拼团、砍价的营销商品,无法使用优惠劵");
|
||||
ErrorCode PRICE_CALCULATE_SECKILL_TOTAL_LIMIT_COUNT = new ErrorCode(1_011_003_005, "参与秒杀的商品,超过了秒杀总限购数量");
|
||||
ErrorCode PRICE_CALCULATE_DELIVERY_PRICE_TYPE_ILLEGAL = new ErrorCode(1_011_003_005, "计算快递运费异常,配送方式不匹配");
|
||||
ErrorCode PRICE_CALCULATE_COUPON_CAN_NOT_USE = new ErrorCode(1_011_003_006, "该优惠劵无法使用,原因:{}」");
|
||||
|
||||
// ========== 物流 Express 模块 1-011-004-000 ==========
|
||||
ErrorCode EXPRESS_NOT_EXISTS = new ErrorCode(1_011_004_000, "快递公司不存在");
|
||||
|
@ -12,5 +12,7 @@ public interface MessageTemplateConstants {
|
||||
|
||||
String BROKERAGE_WITHDRAW_AUDIT_APPROVE = "brokerage_withdraw_audit_approve"; // 佣金提现(审核通过)
|
||||
String BROKERAGE_WITHDRAW_AUDIT_REJECT = "brokerage_withdraw_audit_reject"; // 佣金提现(审核不通过)
|
||||
// ======================= 小程序订阅消息模版 =======================
|
||||
|
||||
String WXA_ORDER_DELIVERY = "订单发货通知";
|
||||
}
|
||||
|
@ -17,8 +17,8 @@ public enum TradeOrderCancelTypeEnum implements IntArrayValuable {
|
||||
|
||||
PAY_TIMEOUT(10, "超时未支付"),
|
||||
AFTER_SALE_CLOSE(20, "退款关闭"),
|
||||
MEMBER_CANCEL(30, "买家取消");
|
||||
|
||||
MEMBER_CANCEL(30, "买家取消"),
|
||||
COMBINATION_CLOSE(40, "拼团关闭");
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderCancelTypeEnum::getType).toArray();
|
||||
|
||||
/**
|
||||
|
@ -15,11 +15,11 @@ import java.util.Arrays;
|
||||
@RequiredArgsConstructor
|
||||
@Getter
|
||||
public enum TradeOrderTypeEnum implements IntArrayValuable {
|
||||
|
||||
NORMAL(0, "普通订单"),
|
||||
SECKILL(1, "秒杀订单"),
|
||||
BARGAIN(2, "砍价订单"),
|
||||
COMBINATION(3, "拼团订单"),
|
||||
POINT(4, "积分商城"),
|
||||
;
|
||||
|
||||
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(TradeOrderTypeEnum::getType).toArray();
|
||||
@ -54,4 +54,8 @@ public enum TradeOrderTypeEnum implements IntArrayValuable {
|
||||
return ObjectUtil.equal(type, COMBINATION.getType());
|
||||
}
|
||||
|
||||
public static boolean isPoint(Integer type) {
|
||||
return ObjectUtil.equal(type, POINT.getType());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -92,6 +92,11 @@
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-spring-boot-starter-excel</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>cn.iocoder.boot</groupId>
|
||||
<artifactId>yudao-module-promotion-biz</artifactId>
|
||||
<version>${revision}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -1,33 +0,0 @@
|
||||
### 获得交易售后分页 => 成功
|
||||
GET {{baseUrl}}/trade/after-sale/page?pageNo=1&pageSize=10
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
|
||||
### 同意售后 => 成功
|
||||
PUT {{baseUrl}}/trade/after-sale/agree?id=7
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
Content-Type: application/json
|
||||
|
||||
### 拒绝售后 => 成功
|
||||
PUT {{baseUrl}}/trade/after-sale/disagree
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 6,
|
||||
"auditReason": "阿巴巴"
|
||||
}
|
||||
|
||||
### 确认退款 => 成功
|
||||
PUT {{baseUrl}}/trade/after-sale/refund?id=6
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
Content-Type: application/json
|
||||
|
||||
### 确认收货 => 成功
|
||||
PUT {{baseUrl}}/trade/after-sale/receive?id=7
|
||||
Authorization: Bearer {{token}}
|
||||
tenant-id: {{adminTenentId}}
|
||||
Content-Type: application/json
|
@ -1,8 +1,6 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.admin.order;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
@ -12,13 +10,9 @@ import cn.iocoder.yudao.module.trade.convert.order.TradeOrderConvert;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderItemDO;
|
||||
import cn.iocoder.yudao.module.trade.dal.dataobject.order.TradeOrderLogDO;
|
||||
import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService;
|
||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderLogService;
|
||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
|
||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONArray;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
@ -28,11 +22,10 @@ import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.time.OffsetDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
|
||||
@ -121,94 +114,6 @@ public class TradeOrderController {
|
||||
return success(true);
|
||||
}
|
||||
|
||||
@PostMapping("/test")
|
||||
public CommonResult<String> test(@RequestBody Map<String, String> map){
|
||||
System.out.println("==========================================================");
|
||||
for (String s : map.keySet()) {
|
||||
System.out.println(map.get(s));
|
||||
}
|
||||
System.out.println("==========================================================");
|
||||
return success("成功");
|
||||
}
|
||||
@PostMapping("/test2")
|
||||
public void test2(){
|
||||
//获取access_token
|
||||
String accessTokenApiurl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx63c280fe3248a3e7&secret=6f270509224a7ae1296bbf1c8cb97aed";
|
||||
|
||||
// JSONObject map = new JSONObject();
|
||||
// map.put("grant_type","client_credential");
|
||||
// map.put("appid","wx63c280fe3248a3e7");
|
||||
// map.put("secret","6f270509224a7ae1296bbf1c8cb97aed");
|
||||
HttpResponse get = HttpUtil.createGet(accessTokenApiurl).execute();
|
||||
String body = get.body();
|
||||
System.out.println("-----------------------------------------------");
|
||||
// String jsonString = "82_fCctY_2YxIDOQMpk315ZH76M0J49nXlx_aEdbrDfJEF_-E640cLl0_Yu3kAh4eHgAgtTpu2SskXMNFCsraCBvlGlEOKsXtpqEbkrh5Ydi2arCv-MoHWiS45UyzEMDYfAJAYPK";
|
||||
JSONObject jsonObject = JSON.parseObject(body);
|
||||
System.out.println(jsonObject);
|
||||
System.out.println(body);
|
||||
String token = jsonObject.getString("access_token");
|
||||
System.out.println(token);
|
||||
System.out.println("-----------------------------------------------");
|
||||
|
||||
//查询小程序是否已开通发货信息管理服务
|
||||
String apiurlSec = "https://api.weixin.qq.com/wxa/sec/order/is_trade_managed?access_token="+token;
|
||||
JSONObject mapSec = new JSONObject();
|
||||
mapSec.put("appid","wx63c280fe3248a3e7");
|
||||
HttpResponse postSec = HttpUtil.createPost(apiurlSec)
|
||||
// .header("Authorization","Bearer 8e79d003102a4b5c80fd823c3c04347c")
|
||||
// .header("tenant-id","1")
|
||||
.body(mapSec.toJSONString())
|
||||
.execute();
|
||||
String bodySec = postSec.body();
|
||||
System.out.println("-----------------------------------------------6");
|
||||
System.out.println(bodySec);
|
||||
System.out.println("-----------------------------------------------6");
|
||||
|
||||
|
||||
// 微信官方发货信息录入接口
|
||||
// String apiurl = "https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token="+token;
|
||||
//
|
||||
// JSONObject map = new JSONObject();
|
||||
// map.put("order_id","P202407170517541");
|
||||
//
|
||||
// JSONObject orderKey = new JSONObject();
|
||||
// orderKey.put("order_number_type",1);
|
||||
//
|
||||
// map.put("order_key",orderKey);
|
||||
// map.put("logistics_type",3);
|
||||
// map.put("delivery_mode",1);
|
||||
//
|
||||
// JSONArray shippingList = new JSONArray();
|
||||
// JSONObject object = new JSONObject();
|
||||
// object.put("item_desc","测试商品666");
|
||||
// shippingList.add(object);
|
||||
//
|
||||
// map.put("shipping_list",shippingList);
|
||||
// // 获取当前时间的 OffsetDateTime 对象
|
||||
// OffsetDateTime currentDateTime = OffsetDateTime.now();
|
||||
//
|
||||
// // 定义日期时间格式化器,用于格式化成特定格式
|
||||
// DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
|
||||
//
|
||||
// // 格式化 OffsetDateTime 对象为指定格式的字符串
|
||||
// String formattedDateTime = currentDateTime.format(formatter);
|
||||
// map.put("upload_time",formattedDateTime);
|
||||
// JSONObject payer = new JSONObject();
|
||||
// payer.put("openid","oWKZ063Eb6IGr63vJT9Zgf3jufOY");
|
||||
// map.put("payer",payer);
|
||||
//
|
||||
// HttpResponse post = HttpUtil.createPost(apiurl)
|
||||
//// .header("Authorization","Bearer 8e79d003102a4b5c80fd823c3c04347c")
|
||||
//// .header("tenant-id","1")
|
||||
// .body(map.toJSONString())
|
||||
// .execute();
|
||||
// String Pbody = post.body();
|
||||
// System.out.println("-----------------------------------------------");
|
||||
// System.out.println(Pbody);
|
||||
// System.out.println(apiurl);
|
||||
// System.out.println("-----------------------------------------------");
|
||||
}
|
||||
|
||||
@PutMapping("/update-remark")
|
||||
@Operation(summary = "订单备注")
|
||||
@PreAuthorize("@ss.hasPermission('trade:order:update')")
|
||||
|
@ -1,42 +0,0 @@
|
||||
### 请求 /trade/cart/add 接口 => 成功
|
||||
POST {{appApi}}/trade/cart/add
|
||||
tenant-id: {{appTenentId}}
|
||||
Authorization: Bearer {{appToken}}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"skuId": 1,
|
||||
"count": 10,
|
||||
"addStatus": true
|
||||
}
|
||||
|
||||
### 请求 /trade/cart/update 接口 => 成功
|
||||
PUT {{appApi}}/trade/cart/update
|
||||
tenant-id: {{appTenentId}}
|
||||
Authorization: Bearer {{appToken}}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": 35,
|
||||
"count": 5
|
||||
}
|
||||
|
||||
### 请求 /trade/cart/delete 接口 => 成功
|
||||
DELETE {{appApi}}/trade/cart/delete?ids=1
|
||||
tenant-id: {{appTenentId}}
|
||||
Authorization: Bearer {{appToken}}
|
||||
|
||||
### 请求 /trade/cart/get-count 接口 => 成功
|
||||
GET {{appApi}}/trade/cart/get-count
|
||||
tenant-id: {{appTenentId}}
|
||||
Authorization: Bearer {{appToken}}
|
||||
|
||||
### 请求 /trade/cart/get-count-map 接口 => 成功
|
||||
GET {{appApi}}/trade/cart/get-count-map
|
||||
tenant-id: {{appTenentId}}
|
||||
Authorization: Bearer {{appToken}}
|
||||
|
||||
### 请求 /trade/cart/list 接口 => 成功
|
||||
GET {{appApi}}/trade/cart/list
|
||||
tenant-id: {{appTenentId}}
|
||||
Authorization: Bearer {{appToken}}
|
@ -62,3 +62,8 @@ tenant-id: {{appTenentId}}
|
||||
GET {{appApi}}/trade/order/get-express-track-list?id=70
|
||||
Authorization: Bearer {{appToken}}
|
||||
tenant-id: {{appTenentId}}
|
||||
|
||||
### /trade-order/settlement-product 获得商品结算信息
|
||||
GET {{appApi}}/trade/order/settlement-product?spuIds=633
|
||||
Authorization: Bearer {{appToken}}
|
||||
tenant-id: {{appTenentId}}
|
@ -1,12 +1,7 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.app.order;
|
||||
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.http.HttpUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
|
||||
import cn.iocoder.yudao.module.member.api.config.MemberConfigApi;
|
||||
import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
|
||||
import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.*;
|
||||
import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
|
||||
@ -21,17 +16,18 @@ import cn.iocoder.yudao.module.trade.service.aftersale.AfterSaleService;
|
||||
import cn.iocoder.yudao.module.trade.service.delivery.DeliveryExpressService;
|
||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderQueryService;
|
||||
import cn.iocoder.yudao.module.trade.service.order.TradeOrderUpdateService;
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import cn.iocoder.yudao.module.trade.service.price.TradePriceService;
|
||||
import com.google.common.collect.Maps;
|
||||
import io.swagger.v3.oas.annotations.Operation;
|
||||
import io.swagger.v3.oas.annotations.Parameter;
|
||||
import io.swagger.v3.oas.annotations.Parameters;
|
||||
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.annotation.security.PermitAll;
|
||||
import javax.validation.Valid;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -53,28 +49,24 @@ public class AppTradeOrderController {
|
||||
private TradeOrderQueryService tradeOrderQueryService;
|
||||
@Resource
|
||||
private DeliveryExpressService deliveryExpressService;
|
||||
|
||||
@Resource
|
||||
private AfterSaleService afterSaleService;
|
||||
@Resource
|
||||
private TradePriceService priceService;
|
||||
|
||||
@Resource
|
||||
private TradeOrderProperties tradeOrderProperties;
|
||||
@Resource
|
||||
private MemberUserApi memberUserApi;
|
||||
|
||||
@GetMapping("/settlement")
|
||||
@Operation(summary = "获得订单结算信息")
|
||||
@PreAuthenticated
|
||||
public CommonResult<AppTradeOrderSettlementRespVO> settlementOrder(@Valid AppTradeOrderSettlementReqVO settlementReqVO) {
|
||||
AppTradeOrderSettlementRespVO order = tradeOrderUpdateService.settlementOrder(getLoginUserId(), settlementReqVO);
|
||||
order.setTotalPoint(memberUserApi.getUser(getLoginUserId()).getPoint());
|
||||
order.setUsedPoint(0);
|
||||
return success(order);
|
||||
return success(tradeOrderUpdateService.settlementOrder(getLoginUserId(), settlementReqVO));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@PostMapping("/create")
|
||||
@Operation(summary = "创建订单")
|
||||
@PreAuthenticated
|
||||
public CommonResult<AppTradeOrderCreateRespVO> createOrder(@Valid @RequestBody AppTradeOrderCreateReqVO createReqVO) {
|
||||
TradeOrderDO order = tradeOrderUpdateService.createOrder(getLoginUserId(), createReqVO);
|
||||
return success(new AppTradeOrderCreateRespVO().setId(order.getId()).setPayOrderId(order.getPayOrderId()));
|
||||
@ -82,6 +74,7 @@ public class AppTradeOrderController {
|
||||
|
||||
@PostMapping("/update-paid")
|
||||
@Operation(summary = "更新订单为已支付") // 由 pay-module 支付服务,进行回调,可见 PayNotifyJob
|
||||
@PermitAll
|
||||
public CommonResult<Boolean> updateOrderPaid(@RequestBody PayOrderNotifyReqDTO notifyReqDTO) {
|
||||
tradeOrderUpdateService.updateOrderPaid(Long.valueOf(notifyReqDTO.getMerchantOrderId()),
|
||||
notifyReqDTO.getPayOrderId());
|
||||
@ -90,20 +83,31 @@ public class AppTradeOrderController {
|
||||
|
||||
@GetMapping("/get-detail")
|
||||
@Operation(summary = "获得交易订单")
|
||||
@Parameter(name = "id", description = "交易订单编号")
|
||||
public CommonResult<AppTradeOrderDetailRespVO> getOrder(@RequestParam("id") Long id) {
|
||||
// 查询订单
|
||||
@Parameters({
|
||||
@Parameter(name = "id", description = "交易订单编号"),
|
||||
@Parameter(name = "sync", description = "是否同步支付状态", example = "true")
|
||||
})
|
||||
public CommonResult<AppTradeOrderDetailRespVO> getOrderDetail(@RequestParam("id") Long id,
|
||||
@RequestParam(value = "sync", required = false) Boolean sync) {
|
||||
// 1.1 查询订单
|
||||
TradeOrderDO order = tradeOrderQueryService.getOrder(getLoginUserId(), id);
|
||||
if (order == null) {
|
||||
return success(null);
|
||||
}
|
||||
// 1.2 sync 仅在等待支付
|
||||
if (Boolean.TRUE.equals(sync)
|
||||
&& TradeOrderStatusEnum.isUnpaid(order.getStatus()) && !order.getPayStatus()) {
|
||||
tradeOrderUpdateService.syncOrderPayStatusQuietly(order.getId(), order.getPayOrderId());
|
||||
// 重新查询,因为同步后,可能会有变化
|
||||
order = tradeOrderQueryService.getOrder(id);
|
||||
}
|
||||
|
||||
// 查询订单项
|
||||
// 2.1 查询订单项
|
||||
List<TradeOrderItemDO> orderItems = tradeOrderQueryService.getOrderItemListByOrderId(order.getId());
|
||||
// 查询物流公司
|
||||
// 2.2 查询物流公司
|
||||
DeliveryExpressDO express = order.getLogisticsId() != null && order.getLogisticsId() > 0 ?
|
||||
deliveryExpressService.getDeliveryExpress(order.getLogisticsId()) : null;
|
||||
// 最终组合
|
||||
// 2.3 最终组合
|
||||
return success(TradeOrderConvert.INSTANCE.convert02(order, orderItems, tradeOrderProperties, express));
|
||||
}
|
||||
|
||||
@ -158,32 +162,6 @@ public class AppTradeOrderController {
|
||||
return success(true);
|
||||
}
|
||||
|
||||
// @PostMapping("/test")
|
||||
// public void test(){
|
||||
// //获取access_token
|
||||
// String accessTokenApiurl = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=wx63c280fe3248a3e7&secret=6f270509224a7ae1296bbf1c8cb97aed";
|
||||
// HttpResponse get = HttpUtil.createGet(accessTokenApiurl).execute();
|
||||
// String body = get.body();
|
||||
// System.out.println("-----------------------------------------------");
|
||||
// JSONObject jsonObject = JSON.parseObject(body);
|
||||
// System.out.println(jsonObject);
|
||||
// System.out.println(body);
|
||||
// String token = jsonObject.getString("access_token");
|
||||
// System.out.println(token);
|
||||
// System.out.println("-----------------------------------------------");
|
||||
//
|
||||
// String apiurlSec = "https://api.weixin.qq.com/wxa/sec/order/is_trade_managed?access_token="+token;
|
||||
// JSONObject mapSec = new JSONObject();
|
||||
// mapSec.put("out_order_id","wx63c280fe3248a3e7");
|
||||
// mapSec.put("openid","wx63c280fe3248a3e7");
|
||||
// HttpResponse postSec = HttpUtil.createPost(apiurlSec)
|
||||
//// .header("Authorization","Bearer 8e79d003102a4b5c80fd823c3c04347c")
|
||||
//// .header("tenant-id","1")
|
||||
// .body(mapSec.toJSONString())
|
||||
// .execute();
|
||||
// String bodySec = postSec.body();
|
||||
// }
|
||||
|
||||
@DeleteMapping("/cancel")
|
||||
@Operation(summary = "取消交易订单")
|
||||
@Parameter(name = "id", description = "交易订单编号")
|
||||
@ -216,4 +194,9 @@ public class AppTradeOrderController {
|
||||
return success(tradeOrderUpdateService.createOrderItemCommentByMember(getLoginUserId(), createReqVO));
|
||||
}
|
||||
|
||||
@GetMapping("/getPointOrder")
|
||||
public CommonResult<List<AppPointOrderVO>> getPointOrder(){
|
||||
return success(tradeOrderQueryService.getPointOrder(getLoginUserId()));
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,18 @@
|
||||
package cn.iocoder.yudao.module.trade.controller.app.order.vo;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
public class AppPointOrderVO {
|
||||
private String status; //状态
|
||||
private String label;
|
||||
private LocalDateTime createTime; //时间
|
||||
private Integer payPrice; //支付金额
|
||||
private Integer usePoint; //兑换积分
|
||||
private String name; //产品名称
|
||||
private String picUrl; //图片
|
||||
private Integer count; //兑换数量
|
||||
}
|