Merge remote-tracking branch 'origin/master'
# Conflicts: # mobile-web/src/api/promotion.js # mobile-web/src/config/request.js
This commit is contained in:
commit
56c5a2921e
@ -26,6 +26,9 @@ public class DateUtil {
|
|||||||
* @return 计算后的日志
|
* @return 计算后的日志
|
||||||
*/
|
*/
|
||||||
public static Date addDate(Date date, int field, int amount) {
|
public static Date addDate(Date date, int field, int amount) {
|
||||||
|
if (amount == 0) {
|
||||||
|
return date;
|
||||||
|
}
|
||||||
Calendar c = Calendar.getInstance();
|
Calendar c = Calendar.getInstance();
|
||||||
if (date != null) {
|
if (date != null) {
|
||||||
c.setTime(date);
|
c.setTime(date);
|
||||||
|
@ -15,5 +15,45 @@ export function getProductRecommendList() {
|
|||||||
return request({
|
return request({
|
||||||
url: '/promotion-api/users/product_recommend/list',
|
url: '/promotion-api/users/product_recommend/list',
|
||||||
method: 'get',
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Coupon Template
|
||||||
|
|
||||||
|
export function getCouponTemplate(id) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion-api/users/coupon/template/get',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
id,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
export function doAddCouponCard(templateId) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion-api/users/coupon/card/add',
|
||||||
|
method: 'post',
|
||||||
|
params: {
|
||||||
|
templateId,
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Coupon Card
|
||||||
|
|
||||||
|
export function getCouponPage(status, pageNo, pageSize) {
|
||||||
|
return request({
|
||||||
|
url: '/promotion-api/users/coupon/card/page',
|
||||||
|
method: 'get',
|
||||||
|
params: {
|
||||||
|
status,
|
||||||
|
pageNo,
|
||||||
|
pageSize
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -135,8 +135,8 @@ service.interceptors.request.use(
|
|||||||
const { target, prefix } = serviceRouter(config.url)
|
const { target, prefix } = serviceRouter(config.url)
|
||||||
let url = config.url = config.url.replace(`${prefix}`, target);
|
let url = config.url = config.url.replace(`${prefix}`, target);
|
||||||
// TODO 芋艿,这些 url 不用增加认证 token 。可能这么写,有点脏,后面看看咋优化下。
|
// TODO 芋艿,这些 url 不用增加认证 token 。可能这么写,有点脏,后面看看咋优化下。
|
||||||
if (url.indexOf('user-api/users/passport/mobile/send_register_code') != -1
|
if (url.indexOf('user-api/users/passport/mobile/send_register_code') !== -1
|
||||||
|| url.indexOf('user-api/users/passport/mobile/register') != -1) {
|
|| url.indexOf('user-api/users/passport/mobile/register') !== -1) {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import Vue from 'vue';
|
import Vue from 'vue';
|
||||||
import Router from 'vue-router';
|
import Router from 'vue-router';
|
||||||
|
|
||||||
|
import { getAccessToken } from '../utils/cache';
|
||||||
|
|
||||||
Vue.use(Router);
|
Vue.use(Router);
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
@ -84,7 +86,8 @@ const routes = [
|
|||||||
path: '/user/coupon',
|
path: '/user/coupon',
|
||||||
component: () => import('../page/user/coupon/list'),
|
component: () => import('../page/user/coupon/list'),
|
||||||
meta: {
|
meta: {
|
||||||
title: '我的优惠券'
|
title: '我的优惠券',
|
||||||
|
requireAuth: true,
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@ -192,6 +195,13 @@ const routes = [
|
|||||||
title: '分类'
|
title: '分类'
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
path: '/coupon/fetch',
|
||||||
|
component: () => import('../page/coupon/fetch'),
|
||||||
|
meta: {
|
||||||
|
title: '优惠劵领取'
|
||||||
|
}
|
||||||
|
}
|
||||||
];
|
];
|
||||||
|
|
||||||
// add route path
|
// add route path
|
||||||
@ -202,10 +212,23 @@ routes.forEach(route => {
|
|||||||
const router = new Router({ routes });
|
const router = new Router({ routes });
|
||||||
|
|
||||||
router.beforeEach((to, from, next) => {
|
router.beforeEach((to, from, next) => {
|
||||||
|
// 判断是否需要认证
|
||||||
|
const requireAuth = to.meta && to.meta.requireAuth;
|
||||||
|
if (requireAuth) {
|
||||||
|
if (!getAccessToken()) { // 未登陆
|
||||||
|
next({
|
||||||
|
path: '/login',
|
||||||
|
query: {redirect: to.fullPath} // 将跳转的路由path作为参数,登录成功后跳转到该路由
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 处理标题
|
||||||
const title = to.meta && to.meta.title;
|
const title = to.meta && to.meta.title;
|
||||||
if (title) {
|
if (title) {
|
||||||
document.title = title;
|
document.title = title;
|
||||||
}
|
}
|
||||||
|
// 继续路由
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -7,6 +7,8 @@ import VueLazyload from 'vue-lazyload'
|
|||||||
import components from './config/components.js';
|
import components from './config/components.js';
|
||||||
import { Dialog } from 'vant';
|
import { Dialog } from 'vant';
|
||||||
|
|
||||||
|
import { formatDate } from './utils/date.js';
|
||||||
|
|
||||||
Vue.use(components);
|
Vue.use(components);
|
||||||
|
|
||||||
Vue.use(VueLazyload);
|
Vue.use(VueLazyload);
|
||||||
@ -17,3 +19,9 @@ new Vue({
|
|||||||
el: '#app',
|
el: '#app',
|
||||||
render: h => h(App)
|
render: h => h(App)
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Vue.filter('formatDate', function(date, pattern) {
|
||||||
|
if (date) {
|
||||||
|
return formatDate(date, pattern);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
@ -73,8 +73,9 @@ export default {
|
|||||||
message: '登陆成功',
|
message: '登陆成功',
|
||||||
beforeClose: function (action, done) {
|
beforeClose: function (action, done) {
|
||||||
done();
|
done();
|
||||||
// TODO 芋艿,先暂时不做 callback
|
// TODO 芋艿,简单的 callback 后续完善
|
||||||
that.$router.push('/user/index');
|
let redirect = that.$route.query.redirect || '/user/index';
|
||||||
|
that.$router.push(redirect);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
54
mobile-web/src/page/coupon/fetch.vue
Normal file
54
mobile-web/src/page/coupon/fetch.vue
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<van-cell-group>
|
||||||
|
<van-cell title="优惠劵编号" :value="couponTemplate.id" />
|
||||||
|
<van-cell title="优惠劵名" :value="couponTemplate.title"/>
|
||||||
|
</van-cell-group>
|
||||||
|
<van-button slot="button" size="small" type="primary" @click="onFetchClick">领取优惠劵</van-button>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { getCouponTemplate, doAddCouponCard } from '../../api/promotion';
|
||||||
|
import { Dialog } from 'vant';
|
||||||
|
import { setLoginToken } from '../../utils/cache';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
couponTemplate: {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
let id = this.$route.query.id;
|
||||||
|
let response = getCouponTemplate(id);
|
||||||
|
response.then(data => {
|
||||||
|
this.couponTemplate = data;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
|
||||||
|
methods: {
|
||||||
|
onFetchClick: function () {
|
||||||
|
let that = this;
|
||||||
|
let id = this.$route.query.id;
|
||||||
|
let response = doAddCouponCard(id);
|
||||||
|
response.then(data => {
|
||||||
|
Dialog.alert({
|
||||||
|
title: '系统提示',
|
||||||
|
message: '领取成功',
|
||||||
|
beforeClose: function (action, done) {
|
||||||
|
// 关闭弹窗
|
||||||
|
done();
|
||||||
|
// 跳转到我的优惠劵
|
||||||
|
that.$router.push('/user/coupon');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
@ -65,9 +65,9 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
created:function(){
|
created:function(){
|
||||||
GetPage().then(response=>{
|
// GetPage().then(response=>{
|
||||||
this.page=response;
|
// this.page=response;
|
||||||
});
|
// });
|
||||||
},
|
},
|
||||||
mounted: function() {
|
mounted: function() {
|
||||||
// 加载 Banner
|
// 加载 Banner
|
||||||
|
@ -16,40 +16,49 @@
|
|||||||
<van-tab title="未使用">
|
<van-tab title="未使用">
|
||||||
<ul>
|
<ul>
|
||||||
<van-list
|
<van-list
|
||||||
v-model="loading"
|
v-model="unusedData.loading"
|
||||||
:finished="finished"
|
:finished="unusedData.finished"
|
||||||
@load="onLoad"
|
@load="onLoad"
|
||||||
>
|
>
|
||||||
<li v-for="(item,index) in list" :key="index" :class="'couponitem '+(item.show?'show':'') ">
|
<li v-for="(item,index) in unusedData.list" :key="index" :class="'couponitem '+(item.show?'show':'') ">
|
||||||
<div class="couponTop">
|
<div class="couponTop">
|
||||||
<div class="cpnamount">
|
<div class="cpnamount">
|
||||||
<div class="amountWrap">
|
<div class="amountWrap">
|
||||||
<div class="amount">
|
<div class="amount" v-if="item.preferentialType === 1">
|
||||||
<span class="amountSign" v-if="item.SignPosition=='left'" >{{item.Sign}}</span>
|
<span class="amountSign" >¥</span>
|
||||||
<span class="amountNum">{{item.Coupon}}</span>
|
<span class="amountNum">{{item.priceOff / 100}}</span>
|
||||||
<span class="amountSign" v-if="item.SignPosition=='right'" >{{item.Sign}}</span>
|
</div>
|
||||||
|
<div class="amount" v-else="item.preferentialType === 2">
|
||||||
|
<span class="amountNum">{{item.percentOff / 10.0}}</span>
|
||||||
|
<span class="amountSign">折</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="condition">
|
<div class="condition">
|
||||||
<span>{{item.Condition}}</span>
|
<span>满 {{item.priceAvailable}} 元可用</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="couponInfoWrap">
|
<div class="couponInfoWrap">
|
||||||
<div class="cpninfo">
|
<div class="cpninfo">
|
||||||
<div class="detail">
|
<div class="detail">
|
||||||
<span class="name">{{item.Name}}</span></div>
|
<span class="name">{{item.title}}</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="validity">
|
<div class="validity">
|
||||||
<span>{{item.BeginDate}}-{{item.EndDate}}
|
<span>{{item.validStartTime | formatDate('yyyy-MM-dd')}}
|
||||||
</span>
|
~ {{item.validEndTime | formatDate('yyyy-MM-dd')}}</span>
|
||||||
</div>
|
</div>
|
||||||
<van-button type="danger" size="mini">立即使用</van-button>
|
<van-button type="danger" size="mini">立即使用</van-button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="couponMid " v-if="item.Info!=''">
|
<!-- <div class="couponMid " v-if="item.Info!=''">-->
|
||||||
<span>详细信息</span>
|
<!-- <span>详细信息</span>-->
|
||||||
<van-icon name="arrow" class="down" @click="onShowInfo(item.Id,index)" />
|
<!-- <van-icon name="arrow" class="down" @click="onShowInfo(item.Id,index)" />-->
|
||||||
</div>
|
<!-- </div>-->
|
||||||
|
<!-- <div class="info" v-if="item.Info!=''" >-->
|
||||||
|
<!-- <div class="text">-->
|
||||||
|
<!-- {{item.Info}}-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- </div>-->
|
||||||
|
<!-- todo 芋艿,后续做优化。指定哪些商品 / 分类可用 -->
|
||||||
<div class="info" v-if="item.Info!=''" >
|
<div class="info" v-if="item.Info!=''" >
|
||||||
<div class="text">
|
<div class="text">
|
||||||
{{item.Info}}
|
{{item.Info}}
|
||||||
@ -62,32 +71,35 @@
|
|||||||
<van-tab title="使用记录">
|
<van-tab title="使用记录">
|
||||||
<ul class="gray" >
|
<ul class="gray" >
|
||||||
<van-list
|
<van-list
|
||||||
v-model="useLoading"
|
v-model="usedData.loading"
|
||||||
:finished="useFinished"
|
:finished="usedData.finished"
|
||||||
@load="onLoadUse"
|
@load="onLoadUse"
|
||||||
>
|
>
|
||||||
<li v-for="(item,index) in useList" :key="index" class="couponitem">
|
<li v-for="(item,index) in usedData.list" :key="index" class="couponitem">
|
||||||
<div class="couponTop">
|
<div class="couponTop">
|
||||||
<div class="cpnamount">
|
<div class="cpnamount">
|
||||||
<div class="amountWrap">
|
<div class="amountWrap">
|
||||||
<div class="amount">
|
<div class="amount" v-if="item.preferentialType === 1">
|
||||||
<span class="amountSign" v-if="item.SignPosition=='left'" >{{item.Sign}}</span>
|
<span class="amountSign" >¥</span>
|
||||||
<span class="amountNum">{{item.Coupon}}</span>
|
<span class="amountNum">{{item.priceOff / 100}}</span>
|
||||||
<span class="amountSign" v-if="item.SignPosition=='right'" >{{item.Sign}}</span>
|
</div>
|
||||||
|
<div class="amount" v-else="item.preferentialType === 2">
|
||||||
|
<span class="amountNum">{{item.percentOff / 10.0}}</span>
|
||||||
|
<span class="amountSign">折</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="condition">
|
<div class="condition">
|
||||||
<span>{{item.Condition}}</span>
|
<span>满 {{item.priceAvailable}} 元可用</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="couponInfoWrap">
|
<div class="couponInfoWrap">
|
||||||
<div class="cpninfo">
|
<div class="cpninfo">
|
||||||
<div class="detail">
|
<div class="detail">
|
||||||
<span class="name">{{item.Name}}</span></div>
|
<span class="name">{{item.title}}</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="validity">
|
<div class="validity">
|
||||||
<span>{{item.BeginDate}}-{{item.EndDate}}
|
<span>{{item.validStartTime | formatDate('yyyy-MM-dd')}}
|
||||||
</span>
|
~ {{item.validEndTime | formatDate('yyyy-MM-dd')}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -99,32 +111,35 @@
|
|||||||
<ul class="gray" >
|
<ul class="gray" >
|
||||||
|
|
||||||
<van-list
|
<van-list
|
||||||
v-model="endLoading"
|
v-model="expireData.loading"
|
||||||
:finished="endFinished"
|
:finished="expireData.finished"
|
||||||
@load="onLoadEnd"
|
@load="onLoadEnd"
|
||||||
>
|
>
|
||||||
<li v-for="(item,index) in endList" :key="index" class="couponitem">
|
<li v-for="(item,index) in expireData.list" :key="index" class="couponitem">
|
||||||
<div class="couponTop">
|
<div class="couponTop">
|
||||||
<div class="cpnamount">
|
<div class="cpnamount">
|
||||||
<div class="amountWrap">
|
<div class="amountWrap">
|
||||||
<div class="amount">
|
<div class="amount" v-if="item.preferentialType === 1">
|
||||||
<span class="amountSign" v-if="item.SignPosition=='left'" >{{item.Sign}}</span>
|
<span class="amountSign" >¥</span>
|
||||||
<span class="amountNum">{{item.Coupon}}</span>
|
<span class="amountNum">{{item.priceOff / 100}}</span>
|
||||||
<span class="amountSign" v-if="item.SignPosition=='right'" >{{item.Sign}}</span>
|
</div>
|
||||||
|
<div class="amount" v-else="item.preferentialType === 2">
|
||||||
|
<span class="amountNum">{{item.percentOff / 10.0}}</span>
|
||||||
|
<span class="amountSign">折</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="condition">
|
<div class="condition">
|
||||||
<span>{{item.Condition}}</span>
|
<span>满 {{item.priceAvailable}} 元可用</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="couponInfoWrap">
|
<div class="couponInfoWrap">
|
||||||
<div class="cpninfo">
|
<div class="cpninfo">
|
||||||
<div class="detail">
|
<div class="detail">
|
||||||
<span class="name">{{item.Name}}</span></div>
|
<span class="name">{{item.title}}</span></div>
|
||||||
</div>
|
</div>
|
||||||
<div class="validity">
|
<div class="validity">
|
||||||
<span>{{item.BeginDate}}-{{item.EndDate}}
|
<span>{{item.validStartTime | formatDate('yyyy-MM-dd')}}
|
||||||
</span>
|
~ {{item.validEndTime | formatDate('yyyy-MM-dd')}}</span>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -138,83 +153,131 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { GetCoupon,ExchangeCoupon } from "../../../api/user.js";
|
import { GetCoupon,ExchangeCoupon } from "../../../api/user.js";
|
||||||
|
import { getCouponPage } from "../../../api/promotion.js";
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
components: {
|
components: {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
loading:false,
|
// loading:false,
|
||||||
finished:false,
|
// finished:false,
|
||||||
list:[],
|
// list:[],
|
||||||
page:0,
|
// page:0,
|
||||||
|
//
|
||||||
|
//
|
||||||
useLoading:false,
|
// useLoading:false,
|
||||||
useFinished:false,
|
// useFinished:false,
|
||||||
useList:[],
|
// useList:[],
|
||||||
usePage:0,
|
// usePage:0,
|
||||||
|
//
|
||||||
|
//
|
||||||
endLoading:false,
|
// endLoading:false,
|
||||||
endFinished:false,
|
// endFinished:false,
|
||||||
endList:[],
|
// endList:[],
|
||||||
endPage:0,
|
// endPage:0,
|
||||||
|
|
||||||
couponCode:'',
|
couponCode:'',
|
||||||
exchangeLoading:false,
|
exchangeLoading:false,
|
||||||
|
|
||||||
|
unusedData: {
|
||||||
|
page: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
list: [],
|
||||||
|
loading: false,
|
||||||
|
finished: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
usedData: {
|
||||||
|
page: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
list: [],
|
||||||
|
loading: false,
|
||||||
|
finished: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
expireData: {
|
||||||
|
page: 0,
|
||||||
|
pageSize: 10,
|
||||||
|
list: [],
|
||||||
|
loading: false,
|
||||||
|
finished: false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onLoad() {
|
onLoad() {
|
||||||
this.page++;
|
// 进入下一页
|
||||||
GetCoupon({page:this.page}).then(response=>{
|
let page = this.unusedData.page + 1;
|
||||||
response.List.forEach(item => {
|
getCouponPage(1, page, this.unusedData.pageSize).then(data => {
|
||||||
item.show=false;
|
// debugger;
|
||||||
this.list.push(item);
|
// 设置下页面
|
||||||
});
|
this.unusedData.page = page;
|
||||||
this.loading = false;
|
// 数据保存到 list 中
|
||||||
if(response.TotalPage<=this.page){
|
this.unusedData.list.push(...data.list);
|
||||||
this.finished = true;
|
// 判断页数
|
||||||
|
if (this.unusedData.list.length >= data.total) {
|
||||||
|
this.unusedData.finished = true;
|
||||||
}
|
}
|
||||||
|
// 标记不在加载中
|
||||||
|
this.unusedData.loading = false;
|
||||||
|
});
|
||||||
|
|
||||||
})
|
// GetCoupon({page:this.page}).then(response=>{
|
||||||
},
|
// response.List.forEach(item => {
|
||||||
onShowInfo(id,index){
|
// item.show=false;
|
||||||
this.list.forEach((item,itemIndex) => {
|
// this.list.push(item);
|
||||||
if(index==itemIndex){
|
// });
|
||||||
item.show=!item.show;
|
// this.loading = false;
|
||||||
return;
|
// if(response.TotalPage<=this.page){
|
||||||
}
|
// this.finished = true;
|
||||||
});
|
// }
|
||||||
|
//
|
||||||
|
// })
|
||||||
},
|
},
|
||||||
|
// onShowInfo(id,index){
|
||||||
|
// this.list.forEach((item,itemIndex) => {
|
||||||
|
// if(index==itemIndex){
|
||||||
|
// item.show=!item.show;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
// });
|
||||||
|
// },
|
||||||
onLoadUse() {
|
onLoadUse() {
|
||||||
this.usePage++;
|
// 进入下一页
|
||||||
GetCoupon({page:this.usePage}).then(response=>{
|
let page = this.usedData.page + 1;
|
||||||
response.List.forEach(item => {
|
getCouponPage(2, page, this.usedData.pageSize).then(data => {
|
||||||
this.useList.push(item);
|
// debugger;
|
||||||
});
|
// 设置下页面
|
||||||
this.useLoading = false;
|
this.usedData.page = page;
|
||||||
if(response.TotalPage<=this.usePage){
|
// 数据保存到 list 中
|
||||||
this.useFinished = true;
|
this.usedData.list.push(...data.list);
|
||||||
|
// 判断页数
|
||||||
|
if (this.usedData.list.length >= data.total) {
|
||||||
|
this.usedData.finished = true;
|
||||||
}
|
}
|
||||||
|
// 标记不在加载中
|
||||||
})
|
this.usedData.loading = false;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onLoadEnd() {
|
onLoadEnd() {
|
||||||
this.endPage++;
|
// 进入下一页
|
||||||
GetCoupon({page:this.endPage}).then(response=>{
|
let page = this.expireData.page + 1;
|
||||||
response.List.forEach(item => {
|
getCouponPage(3, page, this.expireData.pageSize).then(data => {
|
||||||
this.endList.push(item);
|
// debugger;
|
||||||
});
|
// 设置下页面
|
||||||
this.endLoading = false;
|
this.expireData.page = page;
|
||||||
if(response.TotalPage<=this.endPage){
|
// 数据保存到 list 中
|
||||||
this.endFinished = true;
|
this.expireData.list.push(...data.list);
|
||||||
|
// 判断页数
|
||||||
|
if (this.expireData.list.length >= data.total) {
|
||||||
|
this.expireData.finished = true;
|
||||||
}
|
}
|
||||||
|
// 标记不在加载中
|
||||||
})
|
this.expireData.loading = false;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
onExchange(){
|
onExchange(){
|
||||||
if(this.exchangeLoading){
|
if(this.exchangeLoading){
|
||||||
|
15
mobile-web/src/utils/date.js
Normal file
15
mobile-web/src/utils/date.js
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
|
||||||
|
// TODO 临时代码
|
||||||
|
export function formatDate(date, pattern) {
|
||||||
|
if (!(date instanceof Date)) {
|
||||||
|
date = new Date(date);
|
||||||
|
}
|
||||||
|
if (pattern === 'yyyy-MM-dd') {
|
||||||
|
let d = date.getDate();
|
||||||
|
let m = date.getMonth() + 1; //Month from 0 to 11
|
||||||
|
let y = date.getFullYear();
|
||||||
|
return '' + y + '-' + (m <= 9 ? '0' + m : m) + '-' + (d <= 9 ? '0' + d : d);
|
||||||
|
} else {
|
||||||
|
return '暂不支持';
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,11 @@ package cn.iocoder.mall.promotion.application.config;
|
|||||||
|
|
||||||
import cn.iocoder.common.framework.config.GlobalExceptionHandler;
|
import cn.iocoder.common.framework.config.GlobalExceptionHandler;
|
||||||
import cn.iocoder.common.framework.servlet.CorsFilter;
|
import cn.iocoder.common.framework.servlet.CorsFilter;
|
||||||
|
import cn.iocoder.mall.admin.sdk.interceptor.AdminAccessLogInterceptor;
|
||||||
|
import cn.iocoder.mall.admin.sdk.interceptor.AdminSecurityInterceptor;
|
||||||
|
import cn.iocoder.mall.user.sdk.interceptor.UserAccessLogInterceptor;
|
||||||
|
import cn.iocoder.mall.user.sdk.interceptor.UserSecurityInterceptor;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
import org.springframework.context.annotation.Bean;
|
import org.springframework.context.annotation.Bean;
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
@ -14,23 +19,31 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
|||||||
@EnableWebMvc
|
@EnableWebMvc
|
||||||
@Configuration
|
@Configuration
|
||||||
@Import(value = {GlobalExceptionHandler.class, // 统一全局返回
|
@Import(value = {GlobalExceptionHandler.class, // 统一全局返回
|
||||||
// AdminSecurityInterceptor.class
|
AdminSecurityInterceptor.class, UserAccessLogInterceptor.class,
|
||||||
|
UserSecurityInterceptor.class, AdminAccessLogInterceptor.class,
|
||||||
})
|
})
|
||||||
public class MVCConfiguration implements WebMvcConfigurer {
|
public class MVCConfiguration implements WebMvcConfigurer {
|
||||||
|
|
||||||
// @Autowired
|
// @Autowired
|
||||||
// private UserSecurityInterceptor securityInterceptor;
|
// private UserSecurityInterceptor securityInterceptor;
|
||||||
|
|
||||||
// @Autowired
|
@Autowired
|
||||||
// private AdminSecurityInterceptor adminSecurityInterceptor;
|
private UserSecurityInterceptor userSecurityInterceptor;
|
||||||
// @Autowired
|
@Autowired
|
||||||
// private AdminAccessLogInterceptor adminAccessLogInterceptor;
|
private UserAccessLogInterceptor userAccessLogInterceptor;
|
||||||
|
@Autowired
|
||||||
|
private AdminSecurityInterceptor adminSecurityInterceptor;
|
||||||
|
@Autowired
|
||||||
|
private AdminAccessLogInterceptor adminAccessLogInterceptor;
|
||||||
//
|
//
|
||||||
@Override
|
@Override
|
||||||
public void addInterceptors(InterceptorRegistry registry) {
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
// registry.addInterceptor(securityInterceptor).addPathPatterns("/user/**", "/admin/**"); // 只拦截我们定义的接口
|
// 用户
|
||||||
// registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**");
|
registry.addInterceptor(userAccessLogInterceptor).addPathPatterns("/users/**");
|
||||||
// registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**");
|
registry.addInterceptor(userSecurityInterceptor).addPathPatterns("/users/**"); // 只拦截我们定义的接口
|
||||||
|
// 管理员
|
||||||
|
registry.addInterceptor(adminAccessLogInterceptor).addPathPatterns("/admins/**");
|
||||||
|
registry.addInterceptor(adminSecurityInterceptor).addPathPatterns("/admins/**");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -25,7 +25,7 @@ import java.util.Date;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("admins/coupon")
|
@RequestMapping("admins/coupon")
|
||||||
@Api("优惠劵(码)模块")
|
@Api("优惠劵(码)模块")
|
||||||
public class AdminsCouponTemplateController {
|
public class AdminsCouponController {
|
||||||
|
|
||||||
@Reference(validation = "true")
|
@Reference(validation = "true")
|
||||||
private CouponService couponService;
|
private CouponService couponService;
|
||||||
@ -35,11 +35,14 @@ public class AdminsCouponTemplateController {
|
|||||||
@GetMapping("/template/page")
|
@GetMapping("/template/page")
|
||||||
@ApiOperation(value = "优惠劵(码)模板分页")
|
@ApiOperation(value = "优惠劵(码)模板分页")
|
||||||
@ApiImplicitParams({
|
@ApiImplicitParams({
|
||||||
|
@ApiImplicitParam(name = "type", value = "类型", example = "参考 CouponTemplateTypeEnum 枚举"),
|
||||||
@ApiImplicitParam(name = "title", value = "标题,模糊匹配", example = "活动 A"),
|
@ApiImplicitParam(name = "title", value = "标题,模糊匹配", example = "活动 A"),
|
||||||
|
@ApiImplicitParam(name = "status", value = "状态", example = "参考 CouponTemplateStatusEnum 枚举"),
|
||||||
|
@ApiImplicitParam(name = "preferentialType", value = "优惠类型", example = "参考 CouponTemplatePreferentialTypeEnum 枚举"),
|
||||||
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
|
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
|
||||||
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
|
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
|
||||||
})
|
})
|
||||||
public CommonResult<AdminsCouponTemplatePageVO> page(@RequestParam(value = "type", required = false) Integer type,
|
public CommonResult<AdminsCouponTemplatePageVO> templatePage(@RequestParam(value = "type", required = false) Integer type,
|
||||||
@RequestParam(value = "title", required = false) String title,
|
@RequestParam(value = "title", required = false) String title,
|
||||||
@RequestParam(value = "status", required = false) Integer status,
|
@RequestParam(value = "status", required = false) Integer status,
|
||||||
@RequestParam(value = "preferentialType", required = false) Integer preferentialType,
|
@RequestParam(value = "preferentialType", required = false) Integer preferentialType,
|
||||||
@ -71,7 +74,7 @@ public class AdminsCouponTemplateController {
|
|||||||
@ApiImplicitParam(name = "percentOff", value = "折扣百分比", example = "当 preferentialType 为折扣卷时,非空"),
|
@ApiImplicitParam(name = "percentOff", value = "折扣百分比", example = "当 preferentialType 为折扣卷时,非空"),
|
||||||
@ApiImplicitParam(name = "discountPriceLimit", value = "折扣上限", example = "当 preferentialType 为折扣卷时,非空"),
|
@ApiImplicitParam(name = "discountPriceLimit", value = "折扣上限", example = "当 preferentialType 为折扣卷时,非空"),
|
||||||
})
|
})
|
||||||
public CommonResult<AdminsCouponTemplateVO> add(@RequestParam(value = "title") String title,
|
public CommonResult<AdminsCouponTemplateVO> templateCardAdd(@RequestParam(value = "title") String title,
|
||||||
@RequestParam(value = "description", required = false) String description,
|
@RequestParam(value = "description", required = false) String description,
|
||||||
@RequestParam(value = "quota") Integer quota,
|
@RequestParam(value = "quota") Integer quota,
|
||||||
@RequestParam(value = "total", required = false) Integer total,
|
@RequestParam(value = "total", required = false) Integer total,
|
||||||
@ -116,7 +119,7 @@ public class AdminsCouponTemplateController {
|
|||||||
@ApiImplicitParam(name = "rangeType", value = "可用范围的类型", required = true, example = "参见 CouponTemplateRangeTypeEnum 枚举"),
|
@ApiImplicitParam(name = "rangeType", value = "可用范围的类型", required = true, example = "参见 CouponTemplateRangeTypeEnum 枚举"),
|
||||||
@ApiImplicitParam(name = "rangeValues", value = "指定商品 / 分类列表,使用逗号分隔商品编号"),
|
@ApiImplicitParam(name = "rangeValues", value = "指定商品 / 分类列表,使用逗号分隔商品编号"),
|
||||||
})
|
})
|
||||||
public CommonResult<Boolean> update(@RequestParam(value = "id") Integer id,
|
public CommonResult<Boolean> templateCardUpdate(@RequestParam(value = "id") Integer id,
|
||||||
@RequestParam(value = "title") String title,
|
@RequestParam(value = "title") String title,
|
||||||
@RequestParam(value = "description", required = false) String description,
|
@RequestParam(value = "description", required = false) String description,
|
||||||
@RequestParam(value = "quota") Integer quota,
|
@RequestParam(value = "quota") Integer quota,
|
||||||
@ -138,7 +141,7 @@ public class AdminsCouponTemplateController {
|
|||||||
@ApiImplicitParam(name = "id", value = "Banner 编号", required = true, example = "1"),
|
@ApiImplicitParam(name = "id", value = "Banner 编号", required = true, example = "1"),
|
||||||
@ApiImplicitParam(name = "status", value = "状态。1 - 开启;2 - 禁用", required = true, example = "1"),
|
@ApiImplicitParam(name = "status", value = "状态。1 - 开启;2 - 禁用", required = true, example = "1"),
|
||||||
})
|
})
|
||||||
public CommonResult<Boolean> updateStatus(@RequestParam("id") Integer id,
|
public CommonResult<Boolean> templateUpdateStatus(@RequestParam("id") Integer id,
|
||||||
@RequestParam("status") Integer status) {
|
@RequestParam("status") Integer status) {
|
||||||
return couponService.updateCouponTemplateStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status);
|
return couponService.updateCouponTemplateStatus(AdminSecurityContextHolder.getContext().getAdminId(), id, status);
|
||||||
}
|
}
|
@ -19,7 +19,7 @@ import java.util.List;
|
|||||||
@RestController
|
@RestController
|
||||||
@RequestMapping("users/banner")
|
@RequestMapping("users/banner")
|
||||||
@Api("Banner 模块")
|
@Api("Banner 模块")
|
||||||
public class UsersProductCategoryController {
|
public class UsersBannerController {
|
||||||
|
|
||||||
@Reference(validation = "true")
|
@Reference(validation = "true")
|
||||||
private BannerService bannerService;
|
private BannerService bannerService;
|
||||||
@ -36,3 +36,4 @@ public class UsersProductCategoryController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
|||||||
|
package cn.iocoder.mall.promotion.application.controller.users;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
|
import cn.iocoder.mall.promotion.api.CouponService;
|
||||||
|
import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
|
||||||
|
import cn.iocoder.mall.promotion.api.bo.CouponCardPageBO;
|
||||||
|
import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO;
|
||||||
|
import cn.iocoder.mall.promotion.api.dto.CouponCardPageDTO;
|
||||||
|
import cn.iocoder.mall.promotion.application.convert.CouponCardConvert;
|
||||||
|
import cn.iocoder.mall.promotion.application.convert.CouponTemplateConvert;
|
||||||
|
import cn.iocoder.mall.promotion.application.vo.users.UsersCouponCardPageVO;
|
||||||
|
import cn.iocoder.mall.promotion.application.vo.users.UsersCouponCardVO;
|
||||||
|
import cn.iocoder.mall.promotion.application.vo.users.UsersCouponTemplateVO;
|
||||||
|
import cn.iocoder.mall.user.sdk.annotation.PermitAll;
|
||||||
|
import cn.iocoder.mall.user.sdk.context.UserSecurityContextHolder;
|
||||||
|
import com.alibaba.dubbo.config.annotation.Reference;
|
||||||
|
import io.swagger.annotations.Api;
|
||||||
|
import io.swagger.annotations.ApiImplicitParam;
|
||||||
|
import io.swagger.annotations.ApiImplicitParams;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import org.springframework.web.bind.annotation.*;
|
||||||
|
|
||||||
|
@RestController
|
||||||
|
@RequestMapping("users/coupon")
|
||||||
|
@Api("优惠劵(码)模块")
|
||||||
|
public class UsersCouponController {
|
||||||
|
|
||||||
|
@Reference(validation = "true")
|
||||||
|
private CouponService couponService;
|
||||||
|
|
||||||
|
// ========== 优惠劵(码)模板 ==========
|
||||||
|
|
||||||
|
@GetMapping("/template/get")
|
||||||
|
@ApiOperation(value = "优惠劵(码)模板信息")
|
||||||
|
@ApiImplicitParam(name = "id", value = "优惠劵(码)模板编号", required = true, example = "10")
|
||||||
|
@PermitAll
|
||||||
|
public CommonResult<UsersCouponTemplateVO> templateGet(@RequestParam("id") Integer id) {
|
||||||
|
CouponTemplateBO template = couponService.getCouponTemplate(id).getData();
|
||||||
|
return CommonResult.success(CouponTemplateConvert.INSTANCE.convert2(template));
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 优惠劵 ==========
|
||||||
|
|
||||||
|
@GetMapping("/card/page")
|
||||||
|
@ApiOperation(value = "优惠劵分页")
|
||||||
|
@ApiImplicitParams({
|
||||||
|
@ApiImplicitParam(name = "status", value = "状态", example = "参考 CouponCardStatusEnum 枚举"),
|
||||||
|
@ApiImplicitParam(name = "pageNo", value = "页码,从 1 开始", example = "1"),
|
||||||
|
@ApiImplicitParam(name = "pageSize", value = "每页条数", required = true, example = "10"),
|
||||||
|
})
|
||||||
|
public CommonResult<UsersCouponCardPageVO> cardPage(@RequestParam(value = "status", required = false) Integer status,
|
||||||
|
@RequestParam(value = "pageNo", defaultValue = "0") Integer pageNo,
|
||||||
|
@RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) {
|
||||||
|
CommonResult<CouponCardPageBO> result = couponService.getCouponCardPage(new CouponCardPageDTO()
|
||||||
|
.setStatus(status).setUserId(UserSecurityContextHolder.getContext().getUserId())
|
||||||
|
.setPageNo(pageNo).setPageSize(pageSize));
|
||||||
|
return CouponCardConvert.INSTANCE.convert2(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@PostMapping("/card/add")
|
||||||
|
@ApiOperation(value = "领取优惠劵")
|
||||||
|
@ApiImplicitParam(name = "templateId", value = "优惠劵(码)模板编号", required = true, example = "10")
|
||||||
|
public CommonResult<UsersCouponCardVO> cardAdd(@RequestParam("templateId") Integer templateId) {
|
||||||
|
CommonResult<CouponCardBO> result = couponService.addCouponCard(UserSecurityContextHolder.getContext().getUserId(), templateId);
|
||||||
|
return CouponCardConvert.INSTANCE.convert(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ========== 优惠码 ==========
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,27 @@
|
|||||||
|
package cn.iocoder.mall.promotion.application.convert;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
|
import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
|
||||||
|
import cn.iocoder.mall.promotion.api.bo.CouponCardPageBO;
|
||||||
|
import cn.iocoder.mall.promotion.application.vo.users.UsersCouponCardPageVO;
|
||||||
|
import cn.iocoder.mall.promotion.application.vo.users.UsersCouponCardVO;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mappings;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface CouponCardConvert {
|
||||||
|
|
||||||
|
CouponCardConvert INSTANCE = Mappers.getMapper(CouponCardConvert.class);
|
||||||
|
|
||||||
|
@Mappings({})
|
||||||
|
CommonResult<UsersCouponCardVO> convert(CommonResult<CouponCardBO> result);
|
||||||
|
|
||||||
|
@Mappings({})
|
||||||
|
CommonResult<UsersCouponCardPageVO> convert2(CommonResult<CouponCardPageBO> result);
|
||||||
|
|
||||||
|
//
|
||||||
|
// @Mappings({})
|
||||||
|
// List<UsersCouponTemplateVO> convertList2(List<CouponTemplateBO> banners);
|
||||||
|
|
||||||
|
}
|
@ -5,6 +5,7 @@ import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO;
|
|||||||
import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO;
|
import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO;
|
||||||
import cn.iocoder.mall.promotion.application.vo.admins.AdminsCouponTemplatePageVO;
|
import cn.iocoder.mall.promotion.application.vo.admins.AdminsCouponTemplatePageVO;
|
||||||
import cn.iocoder.mall.promotion.application.vo.admins.AdminsCouponTemplateVO;
|
import cn.iocoder.mall.promotion.application.vo.admins.AdminsCouponTemplateVO;
|
||||||
|
import cn.iocoder.mall.promotion.application.vo.users.UsersCouponTemplateVO;
|
||||||
import org.mapstruct.Mapper;
|
import org.mapstruct.Mapper;
|
||||||
import org.mapstruct.Mappings;
|
import org.mapstruct.Mappings;
|
||||||
import org.mapstruct.factory.Mappers;
|
import org.mapstruct.factory.Mappers;
|
||||||
@ -28,6 +29,9 @@ public interface CouponTemplateConvert {
|
|||||||
@Mappings({})
|
@Mappings({})
|
||||||
List<AdminsCouponTemplateVO> convertList(List<CouponTemplateBO> templates);
|
List<AdminsCouponTemplateVO> convertList(List<CouponTemplateBO> templates);
|
||||||
|
|
||||||
|
@Mappings({})
|
||||||
|
UsersCouponTemplateVO convert2(CouponTemplateBO template);
|
||||||
|
|
||||||
//
|
//
|
||||||
// @Mappings({})
|
// @Mappings({})
|
||||||
// List<UsersCouponTemplateVO> convertList2(List<CouponTemplateBO> banners);
|
// List<UsersCouponTemplateVO> convertList2(List<CouponTemplateBO> banners);
|
||||||
|
@ -59,7 +59,7 @@ public class AdminsCouponTemplateVO {
|
|||||||
// ========== 使用规则 END ==========
|
// ========== 使用规则 END ==========
|
||||||
|
|
||||||
// ========== 使用效果 BEGIN ==========
|
// ========== 使用效果 BEGIN ==========
|
||||||
@ApiModelProperty(value = "优惠类型", example = "参见 CouponTemplatePreferentialTypeEnum 枚举")
|
@ApiModelProperty(value = "优惠类型", required = true, example = "参见 CouponTemplatePreferentialTypeEnum 枚举")
|
||||||
private Integer preferentialType;
|
private Integer preferentialType;
|
||||||
@ApiModelProperty(value = "折扣百分比")
|
@ApiModelProperty(value = "折扣百分比")
|
||||||
private Integer percentOff;
|
private Integer percentOff;
|
||||||
@ -70,11 +70,11 @@ public class AdminsCouponTemplateVO {
|
|||||||
// ========== 使用效果 END ==========
|
// ========== 使用效果 END ==========
|
||||||
|
|
||||||
// ========== 统计信息 BEGIN ==========
|
// ========== 统计信息 BEGIN ==========
|
||||||
@ApiModelProperty(value = "折扣上限", required = true)
|
@ApiModelProperty(value = "领取优惠券的次数", required = true)
|
||||||
private Integer statFetchNum;
|
private Integer statFetchNum;
|
||||||
// ========== 统计信息 END ==========
|
// ========== 统计信息 END ==========
|
||||||
|
|
||||||
@ApiModelProperty(value = "折扣上限", required = true)
|
@ApiModelProperty(value = "创建时间", required = true)
|
||||||
private Date createTime;
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,20 @@
|
|||||||
|
package cn.iocoder.mall.promotion.application.vo.users;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@ApiModel("优惠劵分页 VO")
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class UsersCouponCardPageVO {
|
||||||
|
|
||||||
|
@ApiModelProperty(value = "优惠劵数组")
|
||||||
|
private List<UsersCouponCardVO> list;
|
||||||
|
@ApiModelProperty(value = "优惠劵总数")
|
||||||
|
private Integer total;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
package cn.iocoder.mall.promotion.application.vo.users;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优惠劵 VO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class UsersCouponCardVO {
|
||||||
|
|
||||||
|
// ========== 基本信息 BEGIN ==========
|
||||||
|
@ApiModelProperty(value = "优惠劵编号", required = true, example = "1")
|
||||||
|
private Integer id;
|
||||||
|
@ApiModelProperty(value = "模板编号,自增唯一", required = true, example = "1")
|
||||||
|
private Integer templateId;
|
||||||
|
@ApiModelProperty(value = "优惠劵名", required = true, example = "大保剑")
|
||||||
|
private String title;
|
||||||
|
@ApiModelProperty(value = "优惠码状态", required = true, example = "参见 CouponCardStatusEnum 枚举")
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
// ========== 基本信息 END ==========
|
||||||
|
|
||||||
|
// ========== 使用规则 BEGIN ==========
|
||||||
|
@ApiModelProperty(value = "是否设置满多少金额可用,单位:分", required = true)
|
||||||
|
private Integer priceAvailable;
|
||||||
|
@ApiModelProperty(value = "固定日期-生效开始时间", required = true)
|
||||||
|
private Date validStartTime;
|
||||||
|
@ApiModelProperty(value = "固定日期-生效结束时间", required = true)
|
||||||
|
private Date validEndTime;
|
||||||
|
// ========== 使用规则 END ==========
|
||||||
|
|
||||||
|
// ========== 使用效果 BEGIN ==========
|
||||||
|
@ApiModelProperty(value = "优惠类型", required = true, example = "参见 CouponTemplatePreferentialTypeEnum 枚举")
|
||||||
|
private Integer preferentialType;
|
||||||
|
@ApiModelProperty(value = "折扣百分比")
|
||||||
|
private Integer percentOff;
|
||||||
|
@ApiModelProperty(value = "优惠金额,单位:分")
|
||||||
|
private Integer priceOff;
|
||||||
|
@ApiModelProperty(value = "折扣上限")
|
||||||
|
private Integer discountPriceLimit;
|
||||||
|
// ========== 使用效果 END ==========
|
||||||
|
|
||||||
|
// ========== 使用情况 BEGIN ==========
|
||||||
|
/**
|
||||||
|
* 是否使用
|
||||||
|
*/
|
||||||
|
@ApiModelProperty(value = "是否使用", required = true)
|
||||||
|
private Boolean used;
|
||||||
|
|
||||||
|
// TODO 芋艿,后续要加优惠劵的使用日志,因为下单后,可能会取消。
|
||||||
|
|
||||||
|
// ========== 使用情况 END ==========
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,54 @@
|
|||||||
|
package cn.iocoder.mall.promotion.application.vo.users;
|
||||||
|
|
||||||
|
import io.swagger.annotations.ApiModel;
|
||||||
|
import io.swagger.annotations.ApiModelProperty;
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
@ApiModel("CouponTemplate VO")
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class UsersCouponTemplateVO {
|
||||||
|
|
||||||
|
// ========== 基本信息 BEGIN ==========
|
||||||
|
@ApiModelProperty(value = "模板编号,自增唯一", required = true, example = "1")
|
||||||
|
private Integer id;
|
||||||
|
@ApiModelProperty(value = "标题", required = true, example = "优惠劵牛逼")
|
||||||
|
private String title;
|
||||||
|
@ApiModelProperty(value = "优惠码状态", required = true, example = "参见 CouponTemplateStatusEnum 枚举")
|
||||||
|
private Integer status;
|
||||||
|
// ========== 领取规则 END ==========
|
||||||
|
|
||||||
|
// ========== 使用规则 BEGIN ==========
|
||||||
|
@ApiModelProperty(value = "是否设置满多少金额可用,单位:分", required = true, example = "0-不限制;大于0-多少金额可用")
|
||||||
|
private Integer priceAvailable;
|
||||||
|
@ApiModelProperty(value = "可用范围的类型", required = true, example = "参见 CouponTemplateRangeTypeEnum 枚举")
|
||||||
|
private Integer rangeType;
|
||||||
|
@ApiModelProperty(value = "指定商品 / 分类列表,使用逗号分隔商品编号", example = "参见 CouponTemplateRangeTypeEnum 枚举")
|
||||||
|
private String rangeValues;
|
||||||
|
@ApiModelProperty(value = "生效日期类型", example = "参见 CouponTemplateDateTypeEnum 枚举")
|
||||||
|
private Integer dateType;
|
||||||
|
@ApiModelProperty(value = "固定日期-生效开始时间")
|
||||||
|
private Date validStartTime;
|
||||||
|
@ApiModelProperty(value = "固定日期-生效结束时间")
|
||||||
|
private Date validEndTime;
|
||||||
|
@ApiModelProperty(value = "领取日期-开始天数", example = "例如,0-当天;1-次天")
|
||||||
|
private Integer fixedStartTerm;
|
||||||
|
@ApiModelProperty(value = "领取日期-结束天数")
|
||||||
|
private Integer fixedEndTerm;
|
||||||
|
// ========== 使用规则 END ==========
|
||||||
|
|
||||||
|
// ========== 使用效果 BEGIN ==========
|
||||||
|
@ApiModelProperty(value = "优惠类型", required = true, example = "参见 CouponTemplatePreferentialTypeEnum 枚举")
|
||||||
|
private Integer preferentialType;
|
||||||
|
@ApiModelProperty(value = "折扣百分比")
|
||||||
|
private Integer percentOff;
|
||||||
|
@ApiModelProperty(value = "优惠金额,单位:分")
|
||||||
|
private Integer priceOff;
|
||||||
|
@ApiModelProperty(value = "折扣上限")
|
||||||
|
private Integer discountPriceLimit;
|
||||||
|
// ========== 使用效果 END ==========
|
||||||
|
|
||||||
|
}
|
@ -3,6 +3,7 @@ package cn.iocoder.mall.promotion.api;
|
|||||||
import cn.iocoder.common.framework.validator.InEnum;
|
import cn.iocoder.common.framework.validator.InEnum;
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
|
import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
|
||||||
|
import cn.iocoder.mall.promotion.api.bo.CouponCardPageBO;
|
||||||
import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO;
|
import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO;
|
||||||
import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO;
|
import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO;
|
||||||
import cn.iocoder.mall.promotion.api.constant.CouponTemplateStatusEnum;
|
import cn.iocoder.mall.promotion.api.constant.CouponTemplateStatusEnum;
|
||||||
@ -12,6 +13,8 @@ public interface CouponService {
|
|||||||
|
|
||||||
// ========== 优惠劵(码)模板 ==========
|
// ========== 优惠劵(码)模板 ==========
|
||||||
|
|
||||||
|
CommonResult<CouponTemplateBO> getCouponTemplate(Integer couponTemplateId);
|
||||||
|
|
||||||
CommonResult<CouponTemplatePageBO> getCouponTemplatePage(CouponTemplatePageDTO couponTemplatePageDTO);
|
CommonResult<CouponTemplatePageBO> getCouponTemplatePage(CouponTemplatePageDTO couponTemplatePageDTO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -59,6 +62,8 @@ public interface CouponService {
|
|||||||
|
|
||||||
// ========== 优惠劵 ==========
|
// ========== 优惠劵 ==========
|
||||||
|
|
||||||
|
CommonResult<CouponCardPageBO> getCouponCardPage(CouponCardPageDTO couponCardPageDTO);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 基于优惠劵模板,领取优惠劵
|
* 基于优惠劵模板,领取优惠劵
|
||||||
*
|
*
|
||||||
|
@ -3,10 +3,121 @@ package cn.iocoder.mall.promotion.api.bo;
|
|||||||
import lombok.Data;
|
import lombok.Data;
|
||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 优惠劵 BO
|
* 优惠劵 BO
|
||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class CouponCardBO {
|
public class CouponCardBO {
|
||||||
|
|
||||||
|
// ========== 基本信息 BEGIN ==========
|
||||||
|
/**
|
||||||
|
* 优惠劵编号
|
||||||
|
*/
|
||||||
|
private Integer id;
|
||||||
|
/**
|
||||||
|
* 优惠劵(码)分组编号
|
||||||
|
*/
|
||||||
|
private Integer templateId;
|
||||||
|
/**
|
||||||
|
* 优惠劵名
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
|
// /**
|
||||||
|
// * 核销码
|
||||||
|
// */
|
||||||
|
// private String verifyCode;
|
||||||
|
/**
|
||||||
|
* 优惠码状态
|
||||||
|
*
|
||||||
|
* 1-未使用
|
||||||
|
* 2-已使用
|
||||||
|
* 3-已失效
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
// ========== 基本信息 END ==========
|
||||||
|
|
||||||
|
// ========== 领取情况 BEGIN ==========
|
||||||
|
/**
|
||||||
|
* 用户编号
|
||||||
|
*/
|
||||||
|
private Integer userId;
|
||||||
|
/**
|
||||||
|
* 领取类型
|
||||||
|
*
|
||||||
|
* 1 - 用户主动领取
|
||||||
|
* 2 - 后台自动发放
|
||||||
|
*/
|
||||||
|
private Integer takeType;
|
||||||
|
// ========== 领取情况 END ==========
|
||||||
|
|
||||||
|
// ========== 使用规则 BEGIN ==========
|
||||||
|
/**
|
||||||
|
* 是否设置满多少金额可用,单位:分
|
||||||
|
*/
|
||||||
|
private Integer priceAvailable;
|
||||||
|
/**
|
||||||
|
* 生效开始时间
|
||||||
|
*/
|
||||||
|
private Date validStartTime;
|
||||||
|
/**
|
||||||
|
* 生效结束时间
|
||||||
|
*/
|
||||||
|
private Date validEndTime;
|
||||||
|
// ========== 使用规则 END ==========
|
||||||
|
|
||||||
|
// ========== 使用效果 BEGIN ==========
|
||||||
|
/**
|
||||||
|
* 优惠类型
|
||||||
|
*
|
||||||
|
* 1-代金卷
|
||||||
|
* 2-折扣卷
|
||||||
|
*/
|
||||||
|
private Integer preferentialType;
|
||||||
|
/**
|
||||||
|
* 折扣
|
||||||
|
*/
|
||||||
|
private Integer percentOff;
|
||||||
|
/**
|
||||||
|
* 优惠金额,单位:分。
|
||||||
|
*/
|
||||||
|
private Integer priceOff;
|
||||||
|
/**
|
||||||
|
* 折扣上限,仅在 {@link #preferentialType} 等于 2 时生效。
|
||||||
|
*
|
||||||
|
* 例如,折扣上限为 20 元,当使用 8 折优惠券,订单金额为 1000 元时,最高只可折扣 20 元,而非 80 元。
|
||||||
|
*/
|
||||||
|
private Integer discountPriceLimit;
|
||||||
|
// ========== 使用效果 END ==========
|
||||||
|
|
||||||
|
// ========== 使用情况 BEGIN ==========
|
||||||
|
/**
|
||||||
|
* 是否使用
|
||||||
|
*/
|
||||||
|
private Boolean used;
|
||||||
|
/**
|
||||||
|
* 使用订单号
|
||||||
|
*/
|
||||||
|
private Integer usedOrderId;
|
||||||
|
/**
|
||||||
|
* 订单中优惠面值,单位:分
|
||||||
|
*/
|
||||||
|
private Integer usedPrice;
|
||||||
|
/**
|
||||||
|
* 使用时间
|
||||||
|
*/
|
||||||
|
private Date usedTime;
|
||||||
|
|
||||||
|
// TODO 芋艿,后续要加优惠劵的使用日志,因为下单后,可能会取消。
|
||||||
|
|
||||||
|
// ========== 使用情况 END ==========
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建时间
|
||||||
|
*/
|
||||||
|
private Date createTime;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,24 @@
|
|||||||
|
package cn.iocoder.mall.promotion.api.bo;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优惠劵分页 BO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class CouponCardPageBO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优惠劵数组
|
||||||
|
*/
|
||||||
|
private List<CouponCardBO> list;
|
||||||
|
/**
|
||||||
|
* 总量
|
||||||
|
*/
|
||||||
|
private Integer total;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
package cn.iocoder.mall.promotion.api.constant;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.core.IntArrayValuable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优惠劵状态枚举
|
||||||
|
*/
|
||||||
|
public enum CouponCardStatusEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
UNUSED(1, "未使用"),
|
||||||
|
USED(2, "已使用"),
|
||||||
|
EXPIRE(3, "已过期"),
|
||||||
|
;
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponCardStatusEnum::getValue).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 值
|
||||||
|
*/
|
||||||
|
private final Integer value;
|
||||||
|
/**
|
||||||
|
* 名字
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
CouponCardStatusEnum(Integer value, String name) {
|
||||||
|
this.value = value;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,44 @@
|
|||||||
|
package cn.iocoder.mall.promotion.api.constant;
|
||||||
|
|
||||||
|
import cn.iocoder.common.framework.core.IntArrayValuable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优惠劵领取方式
|
||||||
|
*/
|
||||||
|
public enum CouponCardTakeTypeEnum implements IntArrayValuable {
|
||||||
|
|
||||||
|
BY_USER(1, "用户主动领取"),
|
||||||
|
BY_ADMIN(2, "已使用"),
|
||||||
|
;
|
||||||
|
|
||||||
|
public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponCardTakeTypeEnum::getValue).toArray();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 值
|
||||||
|
*/
|
||||||
|
private final Integer value;
|
||||||
|
/**
|
||||||
|
* 名字
|
||||||
|
*/
|
||||||
|
private final String name;
|
||||||
|
|
||||||
|
CouponCardTakeTypeEnum(Integer value, String name) {
|
||||||
|
this.value = value;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getValue() {
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() {
|
||||||
|
return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int[] array() {
|
||||||
|
return ARRAYS;
|
||||||
|
}
|
||||||
|
}
|
@ -6,8 +6,8 @@ import java.util.Arrays;
|
|||||||
|
|
||||||
public enum CouponTemplateStatusEnum implements IntArrayValuable {
|
public enum CouponTemplateStatusEnum implements IntArrayValuable {
|
||||||
|
|
||||||
ENABLE(1, "开启中"),
|
ENABLE(1, "生效中"),
|
||||||
DISABLE(2, "禁用中"),
|
DISABLE(2, "已失效"),
|
||||||
// EXPIRE(3, "已过期"), TODO 芋艿,暂时不考虑过期的
|
// EXPIRE(3, "已过期"), TODO 芋艿,暂时不考虑过期的
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -21,7 +21,9 @@ public enum PromotionErrorCodeEnum {
|
|||||||
PRODUCT_TEMPLATE_NOT_CARD(1006002001, "不是优惠劵模板"),
|
PRODUCT_TEMPLATE_NOT_CARD(1006002001, "不是优惠劵模板"),
|
||||||
PRODUCT_TEMPLATE_NOT_CODE(1006002002, "不是优惠码模板"),
|
PRODUCT_TEMPLATE_NOT_CODE(1006002002, "不是优惠码模板"),
|
||||||
PRODUCT_TEMPLATE_TOTAL_CAN_NOT_REDUCE(1006002003, "优惠劵(码)模板的发放数量不能减小"),
|
PRODUCT_TEMPLATE_TOTAL_CAN_NOT_REDUCE(1006002003, "优惠劵(码)模板的发放数量不能减小"),
|
||||||
|
PRODUCT_TEMPLATE_STATUS_NOT_ENABLE(1006002004, "优惠劵模板(码)未开启"),
|
||||||
|
PRODUCT_TEMPLATE_TOTAL_NOT_ENOUGH(1006002005, "优惠劵(码)模板的发放量不足"),
|
||||||
|
PRODUCT_TEMPLATE_CARD_ADD_EXCEED_QUOTA(1006002006, "优惠劵领取到达上限"),
|
||||||
;
|
;
|
||||||
|
|
||||||
private final int code;
|
private final int code;
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
package cn.iocoder.mall.promotion.api.dto;
|
||||||
|
|
||||||
|
import lombok.Data;
|
||||||
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
|
import javax.validation.constraints.NotNull;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优惠劵分页 DTO
|
||||||
|
*/
|
||||||
|
@Data
|
||||||
|
@Accessors(chain = true)
|
||||||
|
public class CouponCardPageDTO {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 用户编号
|
||||||
|
*/
|
||||||
|
private Integer userId;
|
||||||
|
/**
|
||||||
|
* 状态
|
||||||
|
*/
|
||||||
|
private Integer status;
|
||||||
|
|
||||||
|
@NotNull(message = "页码不能为空")
|
||||||
|
private Integer pageNo;
|
||||||
|
@NotNull(message = "每页条数不能为空")
|
||||||
|
private Integer pageSize;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,25 @@
|
|||||||
|
package cn.iocoder.mall.promotion.biz.convert;
|
||||||
|
|
||||||
|
import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
|
||||||
|
import cn.iocoder.mall.promotion.biz.dataobject.CouponCardDO;
|
||||||
|
import org.mapstruct.Mapper;
|
||||||
|
import org.mapstruct.Mappings;
|
||||||
|
import org.mapstruct.factory.Mappers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Mapper
|
||||||
|
public interface CouponCardConvert {
|
||||||
|
|
||||||
|
CouponCardConvert INSTANCE = Mappers.getMapper(CouponCardConvert.class);
|
||||||
|
|
||||||
|
// @Mappings({})
|
||||||
|
// CouponCardBO convertToBO(CouponCardDO banner);
|
||||||
|
//
|
||||||
|
@Mappings({})
|
||||||
|
List<CouponCardBO> convertToBO(List<CouponCardDO> cardList);
|
||||||
|
|
||||||
|
@Mappings({})
|
||||||
|
CouponCardBO convert(CouponCardDO card);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,29 @@
|
|||||||
|
package cn.iocoder.mall.promotion.biz.dao;
|
||||||
|
|
||||||
|
import cn.iocoder.mall.promotion.biz.dataobject.CouponCardDO;
|
||||||
|
import org.apache.ibatis.annotations.Param;
|
||||||
|
import org.springframework.stereotype.Repository;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Repository
|
||||||
|
public interface CouponCardMapper {
|
||||||
|
|
||||||
|
CouponCardDO selectById(@Param("id") Integer id);
|
||||||
|
|
||||||
|
List<CouponCardDO> selectListByPage(@Param("userId") Integer userId,
|
||||||
|
@Param("status") Integer status,
|
||||||
|
@Param("offset") Integer offset,
|
||||||
|
@Param("limit") Integer limit);
|
||||||
|
|
||||||
|
Integer selectCountByPage(@Param("userId") Integer userId,
|
||||||
|
@Param("status") Integer status);
|
||||||
|
|
||||||
|
int selectCountByUserIdAndTemplateId(@Param("userId") Integer userId,
|
||||||
|
@Param("templateId") Integer templateId);
|
||||||
|
|
||||||
|
void insert(CouponCardDO couponCardDO);
|
||||||
|
|
||||||
|
int update(CouponCardDO couponCardDO);
|
||||||
|
|
||||||
|
}
|
@ -27,4 +27,6 @@ public interface CouponTemplateMapper {
|
|||||||
|
|
||||||
int update(CouponTemplateDO couponTemplate);
|
int update(CouponTemplateDO couponTemplate);
|
||||||
|
|
||||||
|
int updateStatFetchNumIncr(@Param("id") Integer id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -22,6 +22,14 @@ public class CouponCardDO extends BaseDO {
|
|||||||
* 优惠劵(码)分组编号,{@link CouponTemplateDO} 的 id
|
* 优惠劵(码)分组编号,{@link CouponTemplateDO} 的 id
|
||||||
*/
|
*/
|
||||||
private Integer templateId;
|
private Integer templateId;
|
||||||
|
/**
|
||||||
|
* 优惠劵名
|
||||||
|
*
|
||||||
|
* 冗余自 {@link CouponTemplateDO} 的 title
|
||||||
|
*
|
||||||
|
* TODO 芋艿,暂时不考虑冗余的更新
|
||||||
|
*/
|
||||||
|
private String title;
|
||||||
// /**
|
// /**
|
||||||
// * 核销码
|
// * 核销码
|
||||||
// */
|
// */
|
||||||
@ -53,11 +61,15 @@ public class CouponCardDO extends BaseDO {
|
|||||||
|
|
||||||
// ========== 使用规则 BEGIN ==========
|
// ========== 使用规则 BEGIN ==========
|
||||||
/**
|
/**
|
||||||
* 固定日期-生效开始时间
|
* 是否设置满多少金额可用,单位:分
|
||||||
|
*/
|
||||||
|
private Integer priceAvailable;
|
||||||
|
/**
|
||||||
|
* 生效开始时间
|
||||||
*/
|
*/
|
||||||
private Date validStartTime;
|
private Date validStartTime;
|
||||||
/**
|
/**
|
||||||
* 固定日期-生效结束时间
|
* 生效结束时间
|
||||||
*/
|
*/
|
||||||
private Date validEndTime;
|
private Date validEndTime;
|
||||||
// ========== 使用规则 END ==========
|
// ========== 使用规则 END ==========
|
||||||
@ -73,7 +85,7 @@ public class CouponCardDO extends BaseDO {
|
|||||||
/**
|
/**
|
||||||
* 折扣
|
* 折扣
|
||||||
*/
|
*/
|
||||||
private Double percentOff;
|
private Integer percentOff;
|
||||||
/**
|
/**
|
||||||
* 优惠金额,单位:分。
|
* 优惠金额,单位:分。
|
||||||
*/
|
*/
|
||||||
@ -87,14 +99,10 @@ public class CouponCardDO extends BaseDO {
|
|||||||
// ========== 使用效果 END ==========
|
// ========== 使用效果 END ==========
|
||||||
|
|
||||||
// ========== 使用情况 BEGIN ==========
|
// ========== 使用情况 BEGIN ==========
|
||||||
/**
|
|
||||||
* 是否使用
|
|
||||||
*/
|
|
||||||
private Boolean used;
|
|
||||||
/**
|
/**
|
||||||
* 使用订单号
|
* 使用订单号
|
||||||
*/
|
*/
|
||||||
private String usedOrderId;
|
private Integer usedOrderId;
|
||||||
/**
|
/**
|
||||||
* 订单中优惠面值,单位:分
|
* 订单中优惠面值,单位:分
|
||||||
*/
|
*/
|
||||||
|
@ -38,4 +38,6 @@ public class CouponCodeDO extends BaseDO {
|
|||||||
*/
|
*/
|
||||||
private Integer couponId;
|
private Integer couponId;
|
||||||
|
|
||||||
|
// TODO 芋艿,后续要考虑状态的追踪
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,15 +35,6 @@ public class CouponTemplateDO extends BaseDO {
|
|||||||
* 2-优惠码
|
* 2-优惠码
|
||||||
*/
|
*/
|
||||||
private Integer type;
|
private Integer type;
|
||||||
/**
|
|
||||||
* 码类型
|
|
||||||
*
|
|
||||||
* 1-一卡一码(UNIQUE)
|
|
||||||
* 2-通用码(GENERAL)
|
|
||||||
*
|
|
||||||
* 【优惠码独有】 @see CouponCodeDO
|
|
||||||
*/
|
|
||||||
private Integer codeType;
|
|
||||||
/**
|
/**
|
||||||
* 优惠码状态
|
* 优惠码状态
|
||||||
*
|
*
|
||||||
@ -212,4 +203,20 @@ public class CouponTemplateDO extends BaseDO {
|
|||||||
// private Integer statUseNum;
|
// private Integer statUseNum;
|
||||||
// ========== 统计信息 END ==========
|
// ========== 统计信息 END ==========
|
||||||
|
|
||||||
|
// ========== 优惠码 BEGIN ==========
|
||||||
|
/**
|
||||||
|
* 码类型
|
||||||
|
*
|
||||||
|
* 1-一卡一码(UNIQUE)
|
||||||
|
* 2-通用码(GENERAL)
|
||||||
|
*
|
||||||
|
* 【优惠码独有】 @see CouponCodeDO
|
||||||
|
*/
|
||||||
|
private Integer codeType;
|
||||||
|
/**
|
||||||
|
* 通用码
|
||||||
|
*/
|
||||||
|
private String commonCode;
|
||||||
|
// ========== 优惠码 BEGIN ==========
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
package cn.iocoder.mall.promotion.biz.scheduler;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 优惠劵过期 Job
|
||||||
|
*
|
||||||
|
* TODO 芋艿
|
||||||
|
*/
|
||||||
|
public class CouponCardExpireJob {
|
||||||
|
}
|
@ -1,20 +1,28 @@
|
|||||||
package cn.iocoder.mall.promotion.biz.service;
|
package cn.iocoder.mall.promotion.biz.service;
|
||||||
|
|
||||||
import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
|
import cn.iocoder.common.framework.constant.SysErrorCodeEnum;
|
||||||
|
import cn.iocoder.common.framework.util.DateUtil;
|
||||||
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
import cn.iocoder.common.framework.util.ServiceExceptionUtil;
|
||||||
import cn.iocoder.common.framework.vo.CommonResult;
|
import cn.iocoder.common.framework.vo.CommonResult;
|
||||||
import cn.iocoder.mall.promotion.api.CouponService;
|
import cn.iocoder.mall.promotion.api.CouponService;
|
||||||
import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
|
import cn.iocoder.mall.promotion.api.bo.CouponCardBO;
|
||||||
|
import cn.iocoder.mall.promotion.api.bo.CouponCardPageBO;
|
||||||
import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO;
|
import cn.iocoder.mall.promotion.api.bo.CouponTemplateBO;
|
||||||
import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO;
|
import cn.iocoder.mall.promotion.api.bo.CouponTemplatePageBO;
|
||||||
import cn.iocoder.mall.promotion.api.constant.*;
|
import cn.iocoder.mall.promotion.api.constant.*;
|
||||||
import cn.iocoder.mall.promotion.api.dto.*;
|
import cn.iocoder.mall.promotion.api.dto.*;
|
||||||
|
import cn.iocoder.mall.promotion.biz.convert.CouponCardConvert;
|
||||||
import cn.iocoder.mall.promotion.biz.convert.CouponTemplateConvert;
|
import cn.iocoder.mall.promotion.biz.convert.CouponTemplateConvert;
|
||||||
|
import cn.iocoder.mall.promotion.biz.convert.CouponTemplateConvertImpl;
|
||||||
|
import cn.iocoder.mall.promotion.biz.dao.CouponCardMapper;
|
||||||
import cn.iocoder.mall.promotion.biz.dao.CouponTemplateMapper;
|
import cn.iocoder.mall.promotion.biz.dao.CouponTemplateMapper;
|
||||||
|
import cn.iocoder.mall.promotion.biz.dataobject.CouponCardDO;
|
||||||
import cn.iocoder.mall.promotion.biz.dataobject.CouponTemplateDO;
|
import cn.iocoder.mall.promotion.biz.dataobject.CouponTemplateDO;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
|
import org.springframework.transaction.annotation.Transactional;
|
||||||
|
|
||||||
|
import java.util.Calendar;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
@Service // 实际上不用添加。添加的原因是,必须 Spring 报错提示
|
@Service // 实际上不用添加。添加的原因是,必须 Spring 报错提示
|
||||||
@ -23,9 +31,17 @@ public class CouponServiceImpl implements CouponService {
|
|||||||
|
|
||||||
@Autowired
|
@Autowired
|
||||||
private CouponTemplateMapper couponTemplateMapper;
|
private CouponTemplateMapper couponTemplateMapper;
|
||||||
|
@Autowired
|
||||||
|
private CouponCardMapper couponCardMapper;
|
||||||
|
|
||||||
// ========== 优惠劵(码)模板 ==========
|
// ========== 优惠劵(码)模板 ==========
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public CommonResult<CouponTemplateBO> getCouponTemplate(Integer couponTemplateId) {
|
||||||
|
CouponTemplateDO template = couponTemplateMapper.selectById(couponTemplateId);
|
||||||
|
return CommonResult.success(CouponTemplateConvertImpl.INSTANCE.convert(template));
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CommonResult<CouponTemplatePageBO> getCouponTemplatePage(CouponTemplatePageDTO couponTemplatePageDTO) {
|
public CommonResult<CouponTemplatePageBO> getCouponTemplatePage(CouponTemplatePageDTO couponTemplatePageDTO) {
|
||||||
CouponTemplatePageBO couponTemplatePageBO = new CouponTemplatePageBO();
|
CouponTemplatePageBO couponTemplatePageBO = new CouponTemplatePageBO();
|
||||||
@ -162,8 +178,68 @@ public class CouponServiceImpl implements CouponService {
|
|||||||
// ========== 优惠劵 ==========
|
// ========== 优惠劵 ==========
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
public CommonResult<CouponCardPageBO> getCouponCardPage(CouponCardPageDTO couponCardPageDTO) {
|
||||||
|
CouponCardPageBO pageBO = new CouponCardPageBO();
|
||||||
|
// 查询分页数据
|
||||||
|
int offset = (couponCardPageDTO.getPageNo() - 1) * couponCardPageDTO.getPageSize();
|
||||||
|
pageBO.setList(CouponCardConvert.INSTANCE.convertToBO(couponCardMapper.selectListByPage(
|
||||||
|
couponCardPageDTO.getUserId(), couponCardPageDTO.getStatus(),
|
||||||
|
offset, couponCardPageDTO.getPageSize())));
|
||||||
|
// 查询分页总数
|
||||||
|
pageBO.setTotal(couponCardMapper.selectCountByPage(
|
||||||
|
couponCardPageDTO.getUserId(), couponCardPageDTO.getStatus()));
|
||||||
|
return CommonResult.success(pageBO);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@Transactional
|
||||||
public CommonResult<CouponCardBO> addCouponCard(Integer userId, Integer couponTemplateId) {
|
public CommonResult<CouponCardBO> addCouponCard(Integer userId, Integer couponTemplateId) {
|
||||||
return null;
|
// 校验 CouponCardTemplate 存在
|
||||||
|
CouponTemplateDO template = couponTemplateMapper.selectById(couponTemplateId);
|
||||||
|
if (template == null) {
|
||||||
|
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_NOT_EXISTS.getCode());
|
||||||
|
}
|
||||||
|
// 校验 CouponCardTemplate 是 CARD
|
||||||
|
if (!CouponTemplateTypeEnum.CARD.getValue().equals(template.getType())) {
|
||||||
|
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_NOT_CARD.getCode());
|
||||||
|
}
|
||||||
|
// 校验 CouponCardTemplate 状态是否开启
|
||||||
|
if (!CouponTemplateStatusEnum.ENABLE.getValue().equals(template.getStatus())) {
|
||||||
|
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_STATUS_NOT_ENABLE.getCode());
|
||||||
|
}
|
||||||
|
// 校验 CouponCardTemplate 是否到达可领取的上限
|
||||||
|
if (template.getStatFetchNum() > template.getTotal()) {
|
||||||
|
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_TOTAL_NOT_ENOUGH.getCode());
|
||||||
|
}
|
||||||
|
// 校验单人可领取优惠劵是否到达上限
|
||||||
|
if (couponCardMapper.selectCountByUserIdAndTemplateId(userId, couponTemplateId) > template.getQuota()) {
|
||||||
|
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_CARD_ADD_EXCEED_QUOTA.getCode());
|
||||||
|
}
|
||||||
|
// 增加优惠劵已领取量
|
||||||
|
int updateTemplateCount = couponTemplateMapper.updateStatFetchNumIncr(couponTemplateId);
|
||||||
|
if (updateTemplateCount == 0) { // 超过 CouponCardTemplate 发放量
|
||||||
|
return ServiceExceptionUtil.error(PromotionErrorCodeEnum.PRODUCT_TEMPLATE_CARD_ADD_EXCEED_QUOTA.getCode());
|
||||||
|
}
|
||||||
|
// 创建优惠劵
|
||||||
|
// 1. 基本信息 + 领取情况
|
||||||
|
CouponCardDO card = new CouponCardDO()
|
||||||
|
.setTemplateId(couponTemplateId)
|
||||||
|
.setTitle(template.getTitle())
|
||||||
|
.setStatus(CouponCardStatusEnum.UNUSED.getValue())
|
||||||
|
.setUserId(userId)
|
||||||
|
.setTakeType(CouponCardTakeTypeEnum.BY_USER.getValue()); // TODO 需要改
|
||||||
|
// 2. 使用规则
|
||||||
|
card.setPriceAvailable(template.getPriceAvailable());
|
||||||
|
setCouponCardValidTime(card, template);
|
||||||
|
// 3. 使用效果
|
||||||
|
card.setPreferentialType(template.getPreferentialType())
|
||||||
|
.setPriceOff(template.getPriceOff())
|
||||||
|
.setPercentOff(template.getPercentOff()).setDiscountPriceLimit(template.getDiscountPriceLimit());
|
||||||
|
// 保存优惠劵模板到数据库
|
||||||
|
card.setCreateTime(new Date());
|
||||||
|
couponCardMapper.insert(card);
|
||||||
|
// 返回成功
|
||||||
|
return CommonResult.success(CouponCardConvert.INSTANCE.convert(card));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -176,6 +252,17 @@ public class CouponServiceImpl implements CouponService {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void setCouponCardValidTime(CouponCardDO card, CouponTemplateDO template) {
|
||||||
|
if (CouponTemplateDateTypeEnum.FIXED_DATE.getValue().equals(template.getDateType())) {
|
||||||
|
card.setValidStartTime(template.getValidStartTime()).setValidEndTime(template.getValidEndTime());
|
||||||
|
} else if (CouponTemplateDateTypeEnum.FIXED_TERM.getValue().equals(template.getDateType())) {
|
||||||
|
Date validStartTime = DateUtil.getDayBegin(new Date());
|
||||||
|
card.setValidStartTime(DateUtil.addDate(validStartTime, Calendar.DAY_OF_YEAR, template.getFixedStartTerm()));
|
||||||
|
Date validEndTime = DateUtil.getDayEnd(card.getValidStartTime());
|
||||||
|
card.setValidEndTime(DateUtil.addDate(validEndTime, Calendar.DAY_OF_YEAR, template.getFixedEndTerm() - 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// ========== 优惠码 ==========
|
// ========== 优惠码 ==========
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -0,0 +1,112 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8" ?>
|
||||||
|
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd" >
|
||||||
|
<mapper namespace="cn.iocoder.mall.promotion.biz.dao.CouponCardMapper">
|
||||||
|
|
||||||
|
<sql id="FIELDS">
|
||||||
|
id, template_id, title, status, user_id, take_type,
|
||||||
|
price_available, valid_start_time, valid_end_time, preferential_type, percent_off, price_off,
|
||||||
|
discount_price_limit, used_order_id, used_price, used_time,
|
||||||
|
create_time
|
||||||
|
</sql>
|
||||||
|
|
||||||
|
<!-- <select id="selectListByPidAndStatusOrderBySort" resultType="CouponCardDO">-->
|
||||||
|
<!-- SELECT-->
|
||||||
|
<!-- <include refid="FIELDS" />-->
|
||||||
|
<!-- FROM coupon_card-->
|
||||||
|
<!-- WHERE pid = #{pid}-->
|
||||||
|
<!-- AND status = #{status}-->
|
||||||
|
<!-- AND deleted = 0-->
|
||||||
|
<!-- ORDER BY sort ASC-->
|
||||||
|
<!-- </select>-->
|
||||||
|
|
||||||
|
<!-- <select id="selectList" resultType="CouponCardDO">-->
|
||||||
|
<!-- SELECT-->
|
||||||
|
<!-- <include refid="FIELDS" />-->
|
||||||
|
<!-- FROM coupon_card-->
|
||||||
|
<!-- WHERE deleted = 0-->
|
||||||
|
<!-- </select>-->
|
||||||
|
|
||||||
|
<select id="selectById" parameterType="Integer" resultType="CouponCardDO">
|
||||||
|
SELECT
|
||||||
|
<include refid="FIELDS" />
|
||||||
|
FROM coupon_card
|
||||||
|
WHERE id = #{id}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectListByPage" resultType="CouponCardDO">
|
||||||
|
SELECT
|
||||||
|
<include refid="FIELDS" />
|
||||||
|
FROM coupon_card
|
||||||
|
<where>
|
||||||
|
<if test="userId != null">
|
||||||
|
AND user_id = #{userId}
|
||||||
|
</if>
|
||||||
|
<if test="status != null">
|
||||||
|
AND status = #{status}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
LIMIT #{offset}, #{limit}
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectCountByPage" resultType="Integer">
|
||||||
|
SELECT
|
||||||
|
COUNT(1)
|
||||||
|
FROM coupon_card
|
||||||
|
<where>
|
||||||
|
<if test="userId != null">
|
||||||
|
AND user_id = #{userId}
|
||||||
|
</if>
|
||||||
|
<if test="status != null">
|
||||||
|
AND status = #{status}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<select id="selectCountByUserIdAndTemplateId" resultType="Integer">
|
||||||
|
SELECT
|
||||||
|
COUNT(1)
|
||||||
|
FROM coupon_card
|
||||||
|
<where>
|
||||||
|
<if test="userId != null">
|
||||||
|
AND user_id = #{userId}
|
||||||
|
</if>
|
||||||
|
<if test="templateId != null">
|
||||||
|
AND template_id = #{templateId}
|
||||||
|
</if>
|
||||||
|
</where>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<insert id="insert" parameterType="CouponCardDO" useGeneratedKeys="true" keyColumn="id" keyProperty="id">
|
||||||
|
INSERT INTO coupon_card (
|
||||||
|
template_id, title, status, user_id, take_type,
|
||||||
|
price_available, valid_start_time, valid_end_time, preferential_type, percent_off, price_off,
|
||||||
|
discount_price_limit, used_order_id, used_price, used_time,
|
||||||
|
create_time
|
||||||
|
) VALUES (
|
||||||
|
#{templateId}, #{title}, #{status}, #{userId}, #{takeType},
|
||||||
|
#{priceAvailable}, #{validStartTime}, #{validEndTime}, #{preferentialType}, #{percentOff}, #{priceOff},
|
||||||
|
#{discountPriceLimit}, #{usedOrderId}, #{usedPrice}, #{usedTime},
|
||||||
|
#{createTime}
|
||||||
|
)
|
||||||
|
</insert>
|
||||||
|
|
||||||
|
<update id="update" parameterType="CouponCardDO">
|
||||||
|
UPDATE coupon_card
|
||||||
|
<set>
|
||||||
|
<if test="status != null">
|
||||||
|
status = #{status},
|
||||||
|
</if>
|
||||||
|
<if test="usedOrderId != null">
|
||||||
|
used_order_id = #{usedOrderId},
|
||||||
|
</if>
|
||||||
|
<if test="usedPrice != null">
|
||||||
|
used_price = #{usedPrice},
|
||||||
|
</if>
|
||||||
|
<if test="usedTime != null">
|
||||||
|
used_time = #{usedTime},
|
||||||
|
</if>
|
||||||
|
</set>
|
||||||
|
WHERE id = #{id}
|
||||||
|
</update>
|
||||||
|
|
||||||
|
</mapper>
|
@ -149,4 +149,11 @@
|
|||||||
WHERE id = #{id}
|
WHERE id = #{id}
|
||||||
</update>
|
</update>
|
||||||
|
|
||||||
|
<update id="updateStatFetchNumIncr" parameterType="Integer">
|
||||||
|
UPDATE coupon_template
|
||||||
|
SET stat_fetch_Num = stat_fetch_Num + 1
|
||||||
|
WHERE id = #{id}
|
||||||
|
AND total > stat_fetch_Num
|
||||||
|
</update>
|
||||||
|
|
||||||
</mapper>
|
</mapper>
|
||||||
|
@ -4,6 +4,7 @@ import lombok.Data;
|
|||||||
import lombok.experimental.Accessors;
|
import lombok.experimental.Accessors;
|
||||||
|
|
||||||
import javax.validation.constraints.NotNull;
|
import javax.validation.constraints.NotNull;
|
||||||
|
import java.io.Serializable;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -11,7 +12,7 @@ import java.util.Date;
|
|||||||
*/
|
*/
|
||||||
@Data
|
@Data
|
||||||
@Accessors(chain = true)
|
@Accessors(chain = true)
|
||||||
public class UserAccessLogAddDTO {
|
public class UserAccessLogAddDTO implements Serializable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 用户编号 - 空
|
* 用户编号 - 空
|
||||||
|
Loading…
Reference in New Issue
Block a user