From e7b9b4fd2a13847a642954e7936c75a7cc2ea74c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 8 May 2019 00:18:18 +0800 Subject: [PATCH] =?UTF-8?q?-=20=E5=89=8D=E7=AB=AF=EF=BC=9A=E6=BB=A1?= =?UTF-8?q?=E5=87=8F=E9=80=81=E5=88=97=E8=A1=A8=20-=20=E5=89=8D=E7=AB=AF?= =?UTF-8?q?=EF=BC=9A=E9=99=90=E6=97=B6=E6=8A=98=E6=89=A3=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- admin-web/config/router.config.js | 10 + admin-web/src/locales/zh-CN/menu.js | 2 + .../src/models/promotion/fullPrivilegeList.js | 126 +++++++ .../models/promotion/productRecommendList.js | 2 +- .../promotion/timeLimitedDiscountList.js | 126 +++++++ .../src/pages/Promotion/FullPrivilegeList.js | 325 ++++++++++++++++++ .../pages/Promotion/FullPrivilegeList.less | 15 + .../Promotion/TimeLimitedDiscountList.js | 290 ++++++++++++++++ .../Promotion/TimeLimitedDiscountList.less | 15 + admin-web/src/services/promotion.js | 9 + .../AdminsPromotionActivityController.java | 4 +- .../promotion/api/bo/PromotionActivityBO.java | 11 +- 12 files changed, 931 insertions(+), 4 deletions(-) create mode 100644 admin-web/src/models/promotion/fullPrivilegeList.js create mode 100644 admin-web/src/models/promotion/timeLimitedDiscountList.js create mode 100644 admin-web/src/pages/Promotion/FullPrivilegeList.js create mode 100644 admin-web/src/pages/Promotion/FullPrivilegeList.less create mode 100644 admin-web/src/pages/Promotion/TimeLimitedDiscountList.js create mode 100644 admin-web/src/pages/Promotion/TimeLimitedDiscountList.less diff --git a/admin-web/config/router.config.js b/admin-web/config/router.config.js index de37a709c..d8426e9e0 100644 --- a/admin-web/config/router.config.js +++ b/admin-web/config/router.config.js @@ -130,6 +130,16 @@ export default [ name: 'coupon-card-template-list', component: './Promotion/CouponCardTemplateList', }, + { + path: '/promotion/time-limit-discount-list', + name: 'time-limit-discount-list', + component: './Promotion/TimeLimitedDiscountList', + }, + { + path: '/promotion/full-privilege-list', + name: 'full-privilege-list', + component: './Promotion/FullPrivilegeList', + } ], }, { diff --git a/admin-web/src/locales/zh-CN/menu.js b/admin-web/src/locales/zh-CN/menu.js index a9b5533bc..86202bdbd 100644 --- a/admin-web/src/locales/zh-CN/menu.js +++ b/admin-web/src/locales/zh-CN/menu.js @@ -58,4 +58,6 @@ export default { 'menu.promotion.promotion-banner-list': '首页广告', 'menu.promotion.product-recommend-list': '商品推荐', 'menu.promotion.coupon-card-template-list': '优惠劵管理', + 'menu.promotion.time-limit-discount-list': '限时折扣', + 'menu.promotion.full-privilege-list': '满减送', }; diff --git a/admin-web/src/models/promotion/fullPrivilegeList.js b/admin-web/src/models/promotion/fullPrivilegeList.js new file mode 100644 index 000000000..a2cda79a7 --- /dev/null +++ b/admin-web/src/models/promotion/fullPrivilegeList.js @@ -0,0 +1,126 @@ +import { message } from 'antd'; +import { productSpuPage, productSpuUpdateSort } from '../../services/product'; +import {routerRedux} from "dva/router"; +import PaginationHelper from '../../../helpers/PaginationHelper'; +import {getPromotionActivityPage} from "../../services/promotion"; + +const SEARCH_PARAMS_DEFAULT = { + title: '', + activityType: 2, + status: 'ALL', +}; + +export default { + namespace: 'fullPrivilegeList', + + state: { + // 分页列表相关 + list: [], + listLoading: false, + pagination: PaginationHelper.defaultPaginationConfig, + searchParams: SEARCH_PARAMS_DEFAULT, + + // 添加 or 修改表单相关 + }, + + effects: { + *page({ payload }, { call, put }) { + // const { queryParams } = payload; + // const response = yield call(productSpuPage, payload); + // message.info('查询成功!'); + // yield put({ + // type: 'treeSuccess', + // payload: { + // list: response.data, + // }, + // }); + + // 显示加载中 + yield put({ + type: 'changeListLoading', + payload: true, + }); + + // 请求 + const response = yield call(getPromotionActivityPage, payload); + // 响应 + yield put({ + type: 'setAll', + payload: { + list: response.data.list, + pagination: PaginationHelper.formatPagination(response.data, payload), + searchParams: { + title: payload.title, + status: payload.status, + activityType: payload.activityType, + } + }, + }); + + // 隐藏加载中 + yield put({ + type: 'changeListLoading', + payload: false, + }); + }, + *updateSort({ payload }, { call, put }) { + // 显示加载中 + yield put({ + type: 'changeSortModalLoading', + payload: true, + }); + + // 请求 + const { callback, body } = payload; + // 响应 + const response = yield call(productSpuUpdateSort, body); + if(response.code === 0) { + if (callback) { + callback(response); + } + yield put({ + type: 'page', + payload: { + ...this.state.pagination, + ...this.state.searchParams, + }, + }); + } + + // 隐藏加载中 + yield put({ + type: 'changeSortModalLoading', + payload: false, + }); + }, + }, + + reducers: { + treeSuccess(state, { payload }) { + return { + ...state, + ...payload, + }; + }, + // 修改加载中的状态 + changeSortModalLoading(state, { payload }) { + return { + ...state, + sortModalLoading: payload, + }; + }, + changeListLoading(state, { payload }) { + return { + ...state, + listLoading: payload, + }; + }, + // 设置所有属性 + setAll(state, { payload }) { + return { + ...state, + ...payload, + }; + } + }, +}; diff --git a/admin-web/src/models/promotion/productRecommendList.js b/admin-web/src/models/promotion/productRecommendList.js index f3e0b63fa..c1fd57ded 100644 --- a/admin-web/src/models/promotion/productRecommendList.js +++ b/admin-web/src/models/promotion/productRecommendList.js @@ -7,7 +7,7 @@ import { updateProductRecommendStatus, } from '../../services/promotion'; import PaginationHelper from '../../../helpers/PaginationHelper'; -import {productSpuList, productSpuSearchList} from "../../services/product"; +import {productSpuSearchList} from "../../services/product"; const SEARCH_PARAMS_DEFAULT = { type: undefined, diff --git a/admin-web/src/models/promotion/timeLimitedDiscountList.js b/admin-web/src/models/promotion/timeLimitedDiscountList.js new file mode 100644 index 000000000..e69773cfb --- /dev/null +++ b/admin-web/src/models/promotion/timeLimitedDiscountList.js @@ -0,0 +1,126 @@ +import { message } from 'antd'; +import { productSpuPage, productSpuUpdateSort } from '../../services/product'; +import {routerRedux} from "dva/router"; +import PaginationHelper from '../../../helpers/PaginationHelper'; +import {getPromotionActivityPage} from "../../services/promotion"; + +const SEARCH_PARAMS_DEFAULT = { + title: '', + activityType: 1, + status: 'ALL', +}; + +export default { + namespace: 'timeLimitedDiscountList', + + state: { + // 分页列表相关 + list: [], + listLoading: false, + pagination: PaginationHelper.defaultPaginationConfig, + searchParams: SEARCH_PARAMS_DEFAULT, + + // 添加 or 修改表单相关 + }, + + effects: { + *page({ payload }, { call, put }) { + // const { queryParams } = payload; + // const response = yield call(productSpuPage, payload); + // message.info('查询成功!'); + // yield put({ + // type: 'treeSuccess', + // payload: { + // list: response.data, + // }, + // }); + + // 显示加载中 + yield put({ + type: 'changeListLoading', + payload: true, + }); + + // 请求 + const response = yield call(getPromotionActivityPage, payload); + // 响应 + yield put({ + type: 'setAll', + payload: { + list: response.data.list, + pagination: PaginationHelper.formatPagination(response.data, payload), + searchParams: { + title: payload.title, + status: payload.status, + activityType: payload.activityType, + } + }, + }); + + // 隐藏加载中 + yield put({ + type: 'changeListLoading', + payload: false, + }); + }, + *updateSort({ payload }, { call, put }) { + // 显示加载中 + yield put({ + type: 'changeSortModalLoading', + payload: true, + }); + + // 请求 + const { callback, body } = payload; + // 响应 + const response = yield call(productSpuUpdateSort, body); + if(response.code === 0) { + if (callback) { + callback(response); + } + yield put({ + type: 'page', + payload: { + ...this.state.pagination, + ...this.state.searchParams, + }, + }); + } + + // 隐藏加载中 + yield put({ + type: 'changeSortModalLoading', + payload: false, + }); + }, + }, + + reducers: { + treeSuccess(state, { payload }) { + return { + ...state, + ...payload, + }; + }, + // 修改加载中的状态 + changeSortModalLoading(state, { payload }) { + return { + ...state, + sortModalLoading: payload, + }; + }, + changeListLoading(state, { payload }) { + return { + ...state, + listLoading: payload, + }; + }, + // 设置所有属性 + setAll(state, { payload }) { + return { + ...state, + ...payload, + }; + } + }, +}; diff --git a/admin-web/src/pages/Promotion/FullPrivilegeList.js b/admin-web/src/pages/Promotion/FullPrivilegeList.js new file mode 100644 index 000000000..75b76a266 --- /dev/null +++ b/admin-web/src/pages/Promotion/FullPrivilegeList.js @@ -0,0 +1,325 @@ +/* eslint-disable */ + +import React, { PureComponent, Fragment } from 'react'; +import { connect } from 'dva'; +import moment from 'moment'; +import { + Card, + Form, + Input, + Row, + Col, + Button, + Modal, + message, + Table, + Divider, + Tree, + Tabs, + TreeSelect, + Spin, + InputNumber +} from 'antd'; +const TabPane = Tabs.TabPane; +import PageHeaderWrapper from '@/components/PageHeaderWrapper'; + +import styles from './FullPrivilegeList.less'; +import PaginationHelper from "../../../helpers/PaginationHelper"; + +const FormItem = Form.Item; + +const statuses = { + 10: '未开始', + 20: '进行中', + 30: '已结束', + 40: '已撤销', + 50: '已删除', +}; + +const meetTypes = { + 1: '满 N 元减/送', + 2: '满 N 件减/送', +}; + +// 列表 +function List({ dataSource, loading, pagination, searchParams, dispatch,}) { + + const handleTabsChange = (value) => { + dispatch({ + type: 'fullPrivilegeList/page', + payload: { + ...searchParams, + status: value, + ...PaginationHelper.defaultPayload, + } + }) + }; + + function onPageChange(page) { // 翻页 + dispatch({ + type: 'fullPrivilegeList/page', + payload: { + pageNo: page.current, + pageSize: page.pageSize, + ...searchParams + } + }) + } + + function formatFullPrivilegeText(activity) { + let text = ''; + let fullPrivilege = activity.fullPrivilege; + for (let i in fullPrivilege.privileges) { + let privilege = fullPrivilege.privileges[i]; + if (i > 0) { + text += ';'; + } + if (fullPrivilege.cycled) { + text += '每'; + } + if (privilege.meetType === 1) { + text += '满 ' + privilege.meetValue / 100.0 + ' 元,'; + } else if (privilege.meetType === 2) { + text += '满 ' + privilege.meetValue + ' 件,'; + } + if (privilege.preferentialType === 1) { + text += '减 ' + privilege.preferentialValue / 100.0 + ' 元'; + } else if (privilege.preferentialType === 2) { + text += '打 ' + privilege.preferentialValue / 10.0 + ' 折'; + } + } + return text; + }; + + const columns = [ + // { + // title: 'id', + // dataIndex: 'id', + // render: text => {text}, + // }, + { + title: '活动名称', + dataIndex: 'title', + }, + { + title: '类型', + dataIndex: 'fullPrivilege', + render: val => meetTypes[val.privileges[0].meetType + ''], + }, + { + title: '活动详情', + render: (text, record) => formatFullPrivilegeText(record), + }, + { + title: '活动时间', + render: (text, record) => ( + + {moment(record.startTime).format('YYYY-MM-DD HH:mm:ss')} +  至  + {moment(record.endTime).format('YYYY-MM-DD HH:mm:ss')} + + ), + }, + { + title: '状态', + dataIndex: 'status', + render: val => statuses[val + ''], + }, + { + title: '创建时间', + dataIndex: 'createTime', + render: val => {moment(val).format('YYYY-MM-DD')}, + }, + { + title: '操作', + width: 300, + render: (text, record) => ( + + {/* this.handleModalVisible(true, 'update', record)}>更新*/} + alert('正在开发中')}>编辑 + { + record.status === 10 || record.status === 20 ? + + alert('正在开发中')}> + 撤销 + + : undefined + } + { + record.status !== 50 ? + + alert('正在开发中')}> + 删除 + + : undefined + } + + ), + }, + ]; + + // console.log(pagination); + + return ( +
+ + + + + + + + + + ) +} + +// 搜索表单 +const SearchForm = Form.create()(props => { + const { + form, + form: { getFieldDecorator }, + dispatch, + searchParams, + } = props; + + function search() { + dispatch({ + type: 'fullPrivilegeList/page', + payload: { + ...PaginationHelper.defaultPayload, + ...searchParams, + ...form.getFieldsValue(), + } + }) + } + + // 提交搜索 + function handleSubmit(e) { + // 阻止默认事件 + e.preventDefault(); + // 提交搜索 + search(); + } + + // 重置搜索 + function handleReset() { + // 重置表单 + form.resetFields(); + // 执行搜索 + search(); + } + + return ( + + + + + {getFieldDecorator('title')()} + + + + + + + + + + + ); +}); + +// fullPrivilegeList +@connect(({ fullPrivilegeList }) => ({ + ...fullPrivilegeList, + // list: fullPrivilegeList.list.spus, + // loading: loading.models.fullPrivilegeList, +})) + +@Form.create() +class FullPrivilegeList extends PureComponent { + state = { + modalVisible: false, + modalType: 'add', //add update + initValues: {}, + }; + + componentDidMount() { + const { dispatch, searchParams } = this.props; + // 查询初始数据 + dispatch({ + type: 'fullPrivilegeList/page', + payload: { + ...searchParams, + ...PaginationHelper.defaultPayload, + }, + }); + } + + handleSortModalVisible = (sortModalVisible, record) => { + const { dispatch } = this.props; + dispatch({ + type: 'fullPrivilegeList/setAll', + payload: { + sortModalVisible, + formVals: record || {} + }, + }); + }; + + render() { + const { dispatch, + list, listLoading, searchParams, pagination, + categoryTree, formVals, } = this.props; + + // 列表属性 + const listProps = { + dataSource: list, + pagination, + searchParams, + dispatch, + categoryTree, + loading: listLoading, + handleSortModalVisible: this.handleSortModalVisible, // Func + }; + + // 搜索表单属性 + const searchFormProps = { + dispatch, + categoryTree, + searchParams, + }; + + return ( + + +
+
+ +
+
+ + +
+
+ ); + } +} + +export default FullPrivilegeList; diff --git a/admin-web/src/pages/Promotion/FullPrivilegeList.less b/admin-web/src/pages/Promotion/FullPrivilegeList.less new file mode 100644 index 000000000..ebb45c292 --- /dev/null +++ b/admin-web/src/pages/Promotion/FullPrivilegeList.less @@ -0,0 +1,15 @@ +@import '~antd/lib/style/themes/default.less'; +@import '~@/utils/utils.less'; + +.tableList { + .tableListOperator { + margin-bottom: 16px; + button { + margin-right: 8px; + } + } +} + +.tableDelete { + color: red; +} diff --git a/admin-web/src/pages/Promotion/TimeLimitedDiscountList.js b/admin-web/src/pages/Promotion/TimeLimitedDiscountList.js new file mode 100644 index 000000000..0939327a4 --- /dev/null +++ b/admin-web/src/pages/Promotion/TimeLimitedDiscountList.js @@ -0,0 +1,290 @@ +/* eslint-disable */ + +import React, { PureComponent, Fragment } from 'react'; +import { connect } from 'dva'; +import moment from 'moment'; +import { + Card, + Form, + Input, + Row, + Col, + Button, + Modal, + message, + Table, + Divider, + Tree, + Tabs, + TreeSelect, + Spin, + InputNumber +} from 'antd'; +const TabPane = Tabs.TabPane; +import PageHeaderWrapper from '@/components/PageHeaderWrapper'; + +import styles from './TimeLimitedDiscountList.less'; +import PaginationHelper from "../../../helpers/PaginationHelper"; + +const FormItem = Form.Item; + +const statuses = { + 10: '未开始', + 20: '进行中', + 30: '已结束', + 40: '已撤销', + 50: '已删除', +} + +// 列表 +function List({ dataSource, loading, pagination, searchParams, dispatch,}) { + + const handleTabsChange = (value) => { + dispatch({ + type: 'timeLimitedDiscountList/page', + payload: { + ...searchParams, + status: value, + ...PaginationHelper.defaultPayload, + } + }) + }; + + function onPageChange(page) { // 翻页 + dispatch({ + type: 'timeLimitedDiscountList/page', + payload: { + pageNo: page.current, + pageSize: page.pageSize, + ...searchParams + } + }) + } + + const columns = [ + // { + // title: 'id', + // dataIndex: 'id', + // render: text => {text}, + // }, + { + title: '活动名称', + dataIndex: 'title', + }, + { + title: '活动标签', // TODO 芋艿,未来增加 + + }, + { + title: '活动时间', + render: (text, record) => ( + + {moment(record.startTime).format('YYYY-MM-DD HH:mm:ss')} +  至  + {moment(record.endTime).format('YYYY-MM-DD HH:mm:ss')} + + ), + }, + { + title: '状态', + dataIndex: 'status', + render: val => statuses[val + ''], + }, + { + title: '创建时间', + dataIndex: 'createTime', + render: val => {moment(val).format('YYYY-MM-DD')}, + }, + { + title: '操作', + width: 300, + render: (text, record) => ( + + {/* this.handleModalVisible(true, 'update', record)}>更新*/} + alert('正在开发中')}>编辑 + { + record.status === 10 || record.status === 20 ? + + alert('正在开发中')}> + 撤销 + + : undefined + } + { + record.status !== 50 ? + + alert('正在开发中')}> + 删除 + + : undefined + } + + ), + }, + ]; + + // console.log(pagination); + + return ( +
+ + + + + + + +
+ + ) +} + +// 搜索表单 +const SearchForm = Form.create()(props => { + const { + form, + form: { getFieldDecorator }, + dispatch, + searchParams, + } = props; + + function search() { + dispatch({ + type: 'timeLimitedDiscountList/page', + payload: { + ...PaginationHelper.defaultPayload, + ...searchParams, + ...form.getFieldsValue(), + } + }) + } + + // 提交搜索 + function handleSubmit(e) { + // 阻止默认事件 + e.preventDefault(); + // 提交搜索 + search(); + } + + // 重置搜索 + function handleReset() { + // 重置表单 + form.resetFields(); + // 执行搜索 + search(); + } + + return ( + + + + + {getFieldDecorator('title')()} + + + + + + + + + + + ); +}); + +// timeLimitedDiscountList +@connect(({ timeLimitedDiscountList }) => ({ + ...timeLimitedDiscountList, + // list: timeLimitedDiscountList.list.spus, + // loading: loading.models.timeLimitedDiscountList, +})) + +@Form.create() +class TimeLimitedDiscountList extends PureComponent { + state = { + modalVisible: false, + modalType: 'add', //add update + initValues: {}, + }; + + componentDidMount() { + const { dispatch, searchParams } = this.props; + // 查询初始数据 + dispatch({ + type: 'timeLimitedDiscountList/page', + payload: { + ...searchParams, + ...PaginationHelper.defaultPayload, + }, + }); + } + + handleSortModalVisible = (sortModalVisible, record) => { + const { dispatch } = this.props; + dispatch({ + type: 'timeLimitedDiscountList/setAll', + payload: { + sortModalVisible, + formVals: record || {} + }, + }); + }; + + render() { + const { dispatch, + list, listLoading, searchParams, pagination, + categoryTree, formVals, } = this.props; + + // 列表属性 + const listProps = { + dataSource: list, + pagination, + searchParams, + dispatch, + categoryTree, + loading: listLoading, + handleSortModalVisible: this.handleSortModalVisible, // Func + }; + + // 搜索表单属性 + const searchFormProps = { + dispatch, + categoryTree, + searchParams, + }; + + return ( + + +
+
+ +
+
+ + +
+
+ ); + } +} + +export default TimeLimitedDiscountList; diff --git a/admin-web/src/pages/Promotion/TimeLimitedDiscountList.less b/admin-web/src/pages/Promotion/TimeLimitedDiscountList.less new file mode 100644 index 000000000..ebb45c292 --- /dev/null +++ b/admin-web/src/pages/Promotion/TimeLimitedDiscountList.less @@ -0,0 +1,15 @@ +@import '~antd/lib/style/themes/default.less'; +@import '~@/utils/utils.less'; + +.tableList { + .tableListOperator { + margin-bottom: 16px; + button { + margin-right: 8px; + } + } +} + +.tableDelete { + color: red; +} diff --git a/admin-web/src/services/promotion.js b/admin-web/src/services/promotion.js index bfef93ba3..81b6a003e 100644 --- a/admin-web/src/services/promotion.js +++ b/admin-web/src/services/promotion.js @@ -90,3 +90,12 @@ export async function updateCouponCardTemplateStatus(params) { method: 'POST', }); } + +// Promotion Activity + +export async function getPromotionActivityPage(params) { + return request(`/promotion-api/admins/promotion_activity/page?${stringify(params)}`, { + method: 'GET', + }); +} + diff --git a/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/controller/admins/AdminsPromotionActivityController.java b/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/controller/admins/AdminsPromotionActivityController.java index 8071b1a84..13a83ec92 100644 --- a/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/controller/admins/AdminsPromotionActivityController.java +++ b/promotion/promotion-application/src/main/java/cn/iocoder/mall/promotion/application/controller/admins/AdminsPromotionActivityController.java @@ -26,8 +26,8 @@ public class AdminsPromotionActivityController { private PromotionActivityService promotionActivityService; @GetMapping("/page") // TODO 芋艿,BO => VO - public CommonResult page(@RequestParam("title") String title, - @RequestParam("activityType") Integer activityType, + public CommonResult page(@RequestParam(value = "title", required = false) String title, + @RequestParam(value = "activityType") Integer activityType, @RequestParam(value = "status") String status, @RequestParam(value = "pageNo", defaultValue = "1") Integer pageNo, @RequestParam(value = "pageSize", defaultValue = "10") Integer pageSize) { diff --git a/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/bo/PromotionActivityBO.java b/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/bo/PromotionActivityBO.java index 272aa36af..42f160893 100644 --- a/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/bo/PromotionActivityBO.java +++ b/promotion/promotion-service-api/src/main/java/cn/iocoder/mall/promotion/api/bo/PromotionActivityBO.java @@ -4,6 +4,7 @@ import lombok.Data; import lombok.experimental.Accessors; import java.io.Serializable; +import java.util.Date; import java.util.List; @Data @@ -30,6 +31,14 @@ public class PromotionActivityBO implements Serializable { * 参见 {@link cn.iocoder.mall.promotion.api.constant.PromotionActivityStatusEnum} 枚举 */ private Integer status; + /** + * 开始时间 + */ + private Date startTime; + /** + * 结束时间 + */ + private Date endTime; /** * 限制折扣 */ @@ -40,7 +49,7 @@ public class PromotionActivityBO implements Serializable { private FullPrivilege fullPrivilege; /** - * 限制折扣 + * 限时折扣 */ @Data @Accessors(chain = true)