初始化项目
11
.gitignore
vendored
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
# Maven #
|
||||||
|
target/
|
||||||
|
|
||||||
|
# IDEA #
|
||||||
|
.idea/
|
||||||
|
*.iml
|
||||||
|
|
||||||
|
# Eclipse #
|
||||||
|
.settings/
|
||||||
|
.classpath
|
||||||
|
.project
|
||||||
201
LICENSE
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
Apache License
|
||||||
|
Version 2.0, January 2004
|
||||||
|
http://www.apache.org/licenses/
|
||||||
|
|
||||||
|
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||||
|
|
||||||
|
1. Definitions.
|
||||||
|
|
||||||
|
"License" shall mean the terms and conditions for use, reproduction,
|
||||||
|
and distribution as defined by Sections 1 through 9 of this document.
|
||||||
|
|
||||||
|
"Licensor" shall mean the copyright owner or entity authorized by
|
||||||
|
the copyright owner that is granting the License.
|
||||||
|
|
||||||
|
"Legal Entity" shall mean the union of the acting entity and all
|
||||||
|
other entities that control, are controlled by, or are under common
|
||||||
|
control with that entity. For the purposes of this definition,
|
||||||
|
"control" means (i) the power, direct or indirect, to cause the
|
||||||
|
direction or management of such entity, whether by contract or
|
||||||
|
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||||
|
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||||
|
|
||||||
|
"You" (or "Your") shall mean an individual or Legal Entity
|
||||||
|
exercising permissions granted by this License.
|
||||||
|
|
||||||
|
"Source" form shall mean the preferred form for making modifications,
|
||||||
|
including but not limited to software source code, documentation
|
||||||
|
source, and configuration files.
|
||||||
|
|
||||||
|
"Object" form shall mean any form resulting from mechanical
|
||||||
|
transformation or translation of a Source form, including but
|
||||||
|
not limited to compiled object code, generated documentation,
|
||||||
|
and conversions to other media types.
|
||||||
|
|
||||||
|
"Work" shall mean the work of authorship, whether in Source or
|
||||||
|
Object form, made available under the License, as indicated by a
|
||||||
|
copyright notice that is included in or attached to the work
|
||||||
|
(an example is provided in the Appendix below).
|
||||||
|
|
||||||
|
"Derivative Works" shall mean any work, whether in Source or Object
|
||||||
|
form, that is based on (or derived from) the Work and for which the
|
||||||
|
editorial revisions, annotations, elaborations, or other modifications
|
||||||
|
represent, as a whole, an original work of authorship. For the purposes
|
||||||
|
of this License, Derivative Works shall not include works that remain
|
||||||
|
separable from, or merely link (or bind by name) to the interfaces of,
|
||||||
|
the Work and Derivative Works thereof.
|
||||||
|
|
||||||
|
"Contribution" shall mean any work of authorship, including
|
||||||
|
the original version of the Work and any modifications or additions
|
||||||
|
to that Work or Derivative Works thereof, that is intentionally
|
||||||
|
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||||
|
or by an individual or Legal Entity authorized to submit on behalf of
|
||||||
|
the copyright owner. For the purposes of this definition, "submitted"
|
||||||
|
means any form of electronic, verbal, or written communication sent
|
||||||
|
to the Licensor or its representatives, including but not limited to
|
||||||
|
communication on electronic mailing lists, source code control systems,
|
||||||
|
and issue tracking systems that are managed by, or on behalf of, the
|
||||||
|
Licensor for the purpose of discussing and improving the Work, but
|
||||||
|
excluding communication that is conspicuously marked or otherwise
|
||||||
|
designated in writing by the copyright owner as "Not a Contribution."
|
||||||
|
|
||||||
|
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||||
|
on behalf of whom a Contribution has been received by Licensor and
|
||||||
|
subsequently incorporated within the Work.
|
||||||
|
|
||||||
|
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
copyright license to reproduce, prepare Derivative Works of,
|
||||||
|
publicly display, publicly perform, sublicense, and distribute the
|
||||||
|
Work and such Derivative Works in Source or Object form.
|
||||||
|
|
||||||
|
3. Grant of Patent License. Subject to the terms and conditions of
|
||||||
|
this License, each Contributor hereby grants to You a perpetual,
|
||||||
|
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||||
|
(except as stated in this section) patent license to make, have made,
|
||||||
|
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||||
|
where such license applies only to those patent claims licensable
|
||||||
|
by such Contributor that are necessarily infringed by their
|
||||||
|
Contribution(s) alone or by combination of their Contribution(s)
|
||||||
|
with the Work to which such Contribution(s) was submitted. If You
|
||||||
|
institute patent litigation against any entity (including a
|
||||||
|
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||||
|
or a Contribution incorporated within the Work constitutes direct
|
||||||
|
or contributory patent infringement, then any patent licenses
|
||||||
|
granted to You under this License for that Work shall terminate
|
||||||
|
as of the date such litigation is filed.
|
||||||
|
|
||||||
|
4. Redistribution. You may reproduce and distribute copies of the
|
||||||
|
Work or Derivative Works thereof in any medium, with or without
|
||||||
|
modifications, and in Source or Object form, provided that You
|
||||||
|
meet the following conditions:
|
||||||
|
|
||||||
|
(a) You must give any other recipients of the Work or
|
||||||
|
Derivative Works a copy of this License; and
|
||||||
|
|
||||||
|
(b) You must cause any modified files to carry prominent notices
|
||||||
|
stating that You changed the files; and
|
||||||
|
|
||||||
|
(c) You must retain, in the Source form of any Derivative Works
|
||||||
|
that You distribute, all copyright, patent, trademark, and
|
||||||
|
attribution notices from the Source form of the Work,
|
||||||
|
excluding those notices that do not pertain to any part of
|
||||||
|
the Derivative Works; and
|
||||||
|
|
||||||
|
(d) If the Work includes a "NOTICE" text file as part of its
|
||||||
|
distribution, then any Derivative Works that You distribute must
|
||||||
|
include a readable copy of the attribution notices contained
|
||||||
|
within such NOTICE file, excluding those notices that do not
|
||||||
|
pertain to any part of the Derivative Works, in at least one
|
||||||
|
of the following places: within a NOTICE text file distributed
|
||||||
|
as part of the Derivative Works; within the Source form or
|
||||||
|
documentation, if provided along with the Derivative Works; or,
|
||||||
|
within a display generated by the Derivative Works, if and
|
||||||
|
wherever such third-party notices normally appear. The contents
|
||||||
|
of the NOTICE file are for informational purposes only and
|
||||||
|
do not modify the License. You may add Your own attribution
|
||||||
|
notices within Derivative Works that You distribute, alongside
|
||||||
|
or as an addendum to the NOTICE text from the Work, provided
|
||||||
|
that such additional attribution notices cannot be construed
|
||||||
|
as modifying the License.
|
||||||
|
|
||||||
|
You may add Your own copyright statement to Your modifications and
|
||||||
|
may provide additional or different license terms and conditions
|
||||||
|
for use, reproduction, or distribution of Your modifications, or
|
||||||
|
for any such Derivative Works as a whole, provided Your use,
|
||||||
|
reproduction, and distribution of the Work otherwise complies with
|
||||||
|
the conditions stated in this License.
|
||||||
|
|
||||||
|
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||||
|
any Contribution intentionally submitted for inclusion in the Work
|
||||||
|
by You to the Licensor shall be under the terms and conditions of
|
||||||
|
this License, without any additional terms or conditions.
|
||||||
|
Notwithstanding the above, nothing herein shall supersede or modify
|
||||||
|
the terms of any separate license agreement you may have executed
|
||||||
|
with Licensor regarding such Contributions.
|
||||||
|
|
||||||
|
6. Trademarks. This License does not grant permission to use the trade
|
||||||
|
names, trademarks, service marks, or product names of the Licensor,
|
||||||
|
except as required for reasonable and customary use in describing the
|
||||||
|
origin of the Work and reproducing the content of the NOTICE file.
|
||||||
|
|
||||||
|
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||||
|
agreed to in writing, Licensor provides the Work (and each
|
||||||
|
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||||
|
implied, including, without limitation, any warranties or conditions
|
||||||
|
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||||
|
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||||
|
appropriateness of using or redistributing the Work and assume any
|
||||||
|
risks associated with Your exercise of permissions under this License.
|
||||||
|
|
||||||
|
8. Limitation of Liability. In no event and under no legal theory,
|
||||||
|
whether in tort (including negligence), contract, or otherwise,
|
||||||
|
unless required by applicable law (such as deliberate and grossly
|
||||||
|
negligent acts) or agreed to in writing, shall any Contributor be
|
||||||
|
liable to You for damages, including any direct, indirect, special,
|
||||||
|
incidental, or consequential damages of any character arising as a
|
||||||
|
result of this License or out of the use or inability to use the
|
||||||
|
Work (including but not limited to damages for loss of goodwill,
|
||||||
|
work stoppage, computer failure or malfunction, or any and all
|
||||||
|
other commercial damages or losses), even if such Contributor
|
||||||
|
has been advised of the possibility of such damages.
|
||||||
|
|
||||||
|
9. Accepting Warranty or Additional Liability. While redistributing
|
||||||
|
the Work or Derivative Works thereof, You may choose to offer,
|
||||||
|
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||||
|
or other liability obligations and/or rights consistent with this
|
||||||
|
License. However, in accepting such obligations, You may act only
|
||||||
|
on Your own behalf and on Your sole responsibility, not on behalf
|
||||||
|
of any other Contributor, and only if You agree to indemnify,
|
||||||
|
defend, and hold each Contributor harmless for any liability
|
||||||
|
incurred by, or claims asserted against, such Contributor by reason
|
||||||
|
of your accepting any such warranty or additional liability.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
APPENDIX: How to apply the Apache License to your work.
|
||||||
|
|
||||||
|
To apply the Apache License to your work, attach the following
|
||||||
|
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||||
|
replaced with your own identifying information. (Don't include
|
||||||
|
the brackets!) The text should be enclosed in the appropriate
|
||||||
|
comment syntax for the file format. We also recommend that a
|
||||||
|
file or class name and description of purpose be included on the
|
||||||
|
same "printed page" as the copyright notice for easier
|
||||||
|
identification within third-party archives.
|
||||||
|
|
||||||
|
Copyright [2018-2019] [macrozheng]
|
||||||
|
|
||||||
|
Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
you may not use this file except in compliance with the License.
|
||||||
|
You may obtain a copy of the License at
|
||||||
|
|
||||||
|
http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
|
||||||
|
Unless required by applicable law or agreed to in writing, software
|
||||||
|
distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
See the License for the specific language governing permissions and
|
||||||
|
limitations under the License.
|
||||||
375
README-DEV.md
Normal file
@@ -0,0 +1,375 @@
|
|||||||
|
# mall
|
||||||
|
|
||||||
|
## 技术选型
|
||||||
|
|
||||||
|
### 后端技术
|
||||||
|
|
||||||
|
技术 | 名称
|
||||||
|
----|----
|
||||||
|
Spring Boot | 容器+MVC框架
|
||||||
|
Spring Security | 认证和授权框架
|
||||||
|
MyBatis | ORM框架
|
||||||
|
MyBatisGenerator | 数据层代码生成
|
||||||
|
PageHelper | MyBatis物理分页插件
|
||||||
|
Swagger-UI | 文档生产工具
|
||||||
|
Hibernator-Validator | 验证框架
|
||||||
|
Elasticsearch | 搜索引擎
|
||||||
|
RabbitMq | 消息队列
|
||||||
|
Redis | 分布式缓存
|
||||||
|
MongoDb | NoSql数据库
|
||||||
|
Docker | 应用容器引擎
|
||||||
|
Druid | 数据库连接池
|
||||||
|
|
||||||
|
### 前端技术
|
||||||
|
|
||||||
|
技术 | 名称
|
||||||
|
----|----
|
||||||
|
Vue | 前端框架
|
||||||
|
Vue-router | 路由框架
|
||||||
|
Vuex | 全局状态管理框架
|
||||||
|
Element | 前端UI框架
|
||||||
|
Axios | 前端HTTP框架
|
||||||
|
Js-cookie | cookie管理工具
|
||||||
|
|
||||||
|
### 框架搭建
|
||||||
|
|
||||||
|
功能 | 完成
|
||||||
|
----|----
|
||||||
|
集成MyBatis | ✔
|
||||||
|
集成MyBatisGenerator | ✔
|
||||||
|
集成SpringSecurity | ✔
|
||||||
|
集成Swagger-UI | ✔
|
||||||
|
集成Hibernator-Validator | ✔
|
||||||
|
集成日志功能 | ✔
|
||||||
|
集成监控功能 | ✔
|
||||||
|
crud操作demo | ✔
|
||||||
|
合理规划包结构 | ✔
|
||||||
|
SpringAOP通用日志处理 | ✔
|
||||||
|
SpringAOP通用验证失败结果返回 | ✔
|
||||||
|
CommonResult对通用返回结果进行封装 | ✔
|
||||||
|
SpringSecurity登录改为Restful形式 | ✔
|
||||||
|
JWT登录、注册、获取token | ✔
|
||||||
|
JTA事务处理 | ✔
|
||||||
|
集成单元测试 | ✔
|
||||||
|
OSS上传功能 | ✔
|
||||||
|
Elasticsearch搜索功能 | ✔
|
||||||
|
HTTPS支持 | ✔
|
||||||
|
Redis数字型ID生成 | ✔
|
||||||
|
SpringTask定时任务支持 | ✔
|
||||||
|
docker容器化部署 | ✔
|
||||||
|
配置区分生产和测试环境 | ✔
|
||||||
|
ELK日志收集功能 | ✔
|
||||||
|
RabbitMq异步通信 | ✔
|
||||||
|
RestTemplate服务间调用 | ✔
|
||||||
|
SpringSecurity权限管理功能 | ✔
|
||||||
|
集成SpringCloud |
|
||||||
|
|
||||||
|
### 使用工具
|
||||||
|
|
||||||
|
工具 | 下载地址
|
||||||
|
----|----
|
||||||
|
开发工具idea | https://www.jetbrains.com/idea/download
|
||||||
|
redis客户端连接工具 | https://redisdesktop.com/download
|
||||||
|
mongo客户端连接工具 | https://robomongo.org/download
|
||||||
|
本地host管理 | https://oldj.github.io/SwitchHosts/
|
||||||
|
Linux远程连接工具 | http://www.netsarang.com/download/software.html
|
||||||
|
数据库连接工具 | http://www.formysql.com/xiazai.html
|
||||||
|
数据库设计工具 | http://powerdesigner.de/
|
||||||
|
原型设计工具 | https://www.axure.com/
|
||||||
|
思维导图设计工具 | http://www.edrawsoft.cn/mindmaster
|
||||||
|
gif录制工具 | https://www.screentogif.com/
|
||||||
|
|
||||||
|
### 后台功能
|
||||||
|
|
||||||
|
#### 后台登录功能 ✔
|
||||||
|
|
||||||
|
- 后台用户注册功能
|
||||||
|
- 后台用户登录后获取token
|
||||||
|
- 刷新token功能
|
||||||
|
|
||||||
|
#### 商品管理 ✔
|
||||||
|
|
||||||
|
> **商品分类管理**
|
||||||
|
|
||||||
|
- 按父分类编号分页查看分类列表
|
||||||
|
- 添加、编辑、删除分类
|
||||||
|
- 转移分类商品
|
||||||
|
|
||||||
|
> **商品品牌管理**
|
||||||
|
|
||||||
|
- 按品牌名称搜索分页查看品牌列表
|
||||||
|
- 添加、编辑、删除品牌
|
||||||
|
- 查看当前品牌的所有产品
|
||||||
|
|
||||||
|
> **商品属性分类管理**
|
||||||
|
|
||||||
|
- 添加商品属性分类(名称)
|
||||||
|
- 分页查询全部商品属性分类
|
||||||
|
- 删除单个商品属性分类
|
||||||
|
- 修改单个属性分类名称
|
||||||
|
- 查询单个属性分类信息
|
||||||
|
|
||||||
|
> **商品属性管理**
|
||||||
|
|
||||||
|
- 根据分类查询属性列表或参数列表(分页,支持类型)
|
||||||
|
- 添加商品属性
|
||||||
|
- 查询单个商品属性
|
||||||
|
- 编辑商品属性
|
||||||
|
- 批量删除商品属性
|
||||||
|
- 分页查询全部商品属性
|
||||||
|
|
||||||
|
> **添加商品**
|
||||||
|
|
||||||
|
- 选择商品分类:根据商品分类id查找分类
|
||||||
|
- 选择品牌:查询全部品牌
|
||||||
|
- 选择运费模版:查询全部运费模版
|
||||||
|
- 设置会员价格:查询所有会员等级,传入List<PmsMemberPrice>
|
||||||
|
- 添加阶梯价格: 参数传入List<PmsProductLadder>
|
||||||
|
- 设置满减价格: 参数传入List<PmsProductFullReduction>
|
||||||
|
- 选择商品属性类别:获取所有商品属性分类,根据商品属性分类的id获取规格和参数(type=0->规格;type=1->参数)
|
||||||
|
- 选择规格并生成库存信息:前端实现
|
||||||
|
- 添加sku库存信息:参数传入List<PmsSkuStock>
|
||||||
|
- 设置属性图片:设置到pic和album_pics字段中去
|
||||||
|
- 添加商品参数:参数传入List<PmsProductAttributeValue>
|
||||||
|
- 添加自定义商品规格:参数传入List<PmsProductAttributeValue>
|
||||||
|
- 关联专题:参数传入List<CmsSubjectProductRelation>关系
|
||||||
|
- 关联优选:参数传入List<CmsPrefrenceAreaProductRelation>关系
|
||||||
|
|
||||||
|
> **修改商品**
|
||||||
|
|
||||||
|
- 根据商品id查询商品信息
|
||||||
|
- 查询商品基本信息:商品分类名称、品牌名称、运费模版名称
|
||||||
|
- 查询商品促销信息:商品的会员价格、阶梯价格、满减价格
|
||||||
|
- 查询商品属性信息:商品属性类别名称、sku库存信息、属性分类对应规格和参数值
|
||||||
|
- 查询商品关联信息:商品关联专题和关联优选
|
||||||
|
- 修改商品信息:商品属性分类及规格不可修改,只支持单个sku的修改、删除、新增;商品属性分类及规格可以修改:修改后同时显示原sku库存及属性分类
|
||||||
|
|
||||||
|
> **商品分页查询**
|
||||||
|
|
||||||
|
- 商品的状态:全部商品、已上架、未上架、待审核、未通过 (publishStatus verifyStatus)
|
||||||
|
- 商品名称(%name%)
|
||||||
|
- 商品货号(productSn)
|
||||||
|
- 商品分类id(productCategoryId)
|
||||||
|
- 商品品牌id(brandId)
|
||||||
|
- 批量操作:上下架、推荐、新品、转移分类、放入回收站、审核
|
||||||
|
- 查看记录:审核记录,操作日志
|
||||||
|
- sku:根据产品及sku编号获取sku信息,批量修改sku信息
|
||||||
|
|
||||||
|
> **商品回收管理**
|
||||||
|
|
||||||
|
- 分页展示回收商品列表
|
||||||
|
- 回收商品还原功能
|
||||||
|
|
||||||
|
#### 促销管理
|
||||||
|
|
||||||
|
> **秒杀活动管理**
|
||||||
|
|
||||||
|
- 活动列表展示
|
||||||
|
- 活动上下线
|
||||||
|
- 设置活动商品
|
||||||
|
- 添加、编辑、删除活动
|
||||||
|
|
||||||
|
> **优惠券管理**
|
||||||
|
|
||||||
|
- 优惠券列表展示
|
||||||
|
- 添加、编辑、删除优惠券
|
||||||
|
- 查看优惠券领取记录
|
||||||
|
|
||||||
|
> **活动管理**
|
||||||
|
|
||||||
|
- 活动列表展示
|
||||||
|
- 添加、编辑、删除活动
|
||||||
|
- 活动上下线
|
||||||
|
- 发布到广告
|
||||||
|
|
||||||
|
> **首页推荐**
|
||||||
|
|
||||||
|
- 品牌推荐:列表展示、是否推荐、排序、删除、多选加入品牌
|
||||||
|
- 新鲜好物:商品列表展示、是否推荐、排序、删除、多选加入商品
|
||||||
|
- 人气推荐:商品列表展示、是否推荐、排序、删除、多选加入商品
|
||||||
|
- 专题精选:专题列表展示、是否推荐、排序、删除、多选加入专题
|
||||||
|
- 广告管理:广告列表展示、是否上线、排序、删除、添加编辑广告
|
||||||
|
|
||||||
|
#### 内容管理
|
||||||
|
|
||||||
|
> **专题管理**
|
||||||
|
|
||||||
|
- 专题列表:查看、删除、推荐专题
|
||||||
|
- 添加、编辑专题:选择专题分类、添加、删除关联商品
|
||||||
|
- 专题分类管理:控制显示、排序、编辑删除分类
|
||||||
|
|
||||||
|
> **优选主题**
|
||||||
|
|
||||||
|
- 优选列表:控制显示、排序、删除
|
||||||
|
- 添加、编辑优选:关联和删除商品
|
||||||
|
|
||||||
|
> **话题管理**
|
||||||
|
|
||||||
|
- 专题列表:查看、删除、热门话题
|
||||||
|
- 话题分类管理:控制显示、排序、编辑删除分类
|
||||||
|
|
||||||
|
> **帮助管理**
|
||||||
|
|
||||||
|
- 帮助列表:查看、删除、控制显示
|
||||||
|
- 添加、编辑帮助:选择帮助分类
|
||||||
|
- 帮助分类管理:控制显示、排序、编辑删除分类
|
||||||
|
|
||||||
|
#### 用户管理
|
||||||
|
|
||||||
|
> **用户管理**
|
||||||
|
|
||||||
|
- 用户列表:帐号启用、删除、群发短信
|
||||||
|
- 批量操作:群发短信、站内信、推送、设置标签、赠送优惠券
|
||||||
|
- 查看、编辑用户信息:用户详情(统计信息、收货地址、订单记录)、编辑资料、登录日志
|
||||||
|
- 购买力筛选:最近消费、消费次数、消费金额、订单均价、商品分类、会员等级、用户标签
|
||||||
|
- 用户标签管理:标签列表、添加、编辑、删除
|
||||||
|
- 会员等级设置:列表、添加、编辑、设置默认会员等级
|
||||||
|
|
||||||
|
> **成才值及积分**
|
||||||
|
|
||||||
|
- 成长值及积分查询:列表展示、积分明细、成长值明细、修改数值
|
||||||
|
- 任务奖励设置:新手任务、日常任务
|
||||||
|
- 更多规则设置:成长值规则、积分规则、积分消费设置
|
||||||
|
|
||||||
|
#### 订单管理
|
||||||
|
|
||||||
|
> **订单列表**
|
||||||
|
|
||||||
|
- 订单搜索:订单编号、收货人姓名/号码、订单状态、订单分类、订单来源、提交时间
|
||||||
|
- 订单操作:查看订单、关闭订单、订单发货、订单跟踪、删除订单
|
||||||
|
- 批量操作:批量发货、关闭订单、删除订单
|
||||||
|
|
||||||
|
> **查看订单**
|
||||||
|
|
||||||
|
- 订单状态:提交订单、支付订单、平台发货、确认收货、完成评价
|
||||||
|
- 订单详情操作:修改发票信息、修改收货人信息、修改商品信息、修改费用信息、发送站内信、关闭订单、备注订单、取消订单、订单跟踪、删除订单
|
||||||
|
- 订单基本信息:订单信息、优惠信息、用户信息
|
||||||
|
- 发票信息:类型、抬头、内容、收票人信息
|
||||||
|
- 收货人信息:收货人、手机号、邮政编码、收货地址
|
||||||
|
- 商品信息:包含商品基本信息
|
||||||
|
- 费用信息:合计及优惠信息
|
||||||
|
- 操作信息:订单状态改变记录
|
||||||
|
|
||||||
|
> **订单设置**
|
||||||
|
|
||||||
|
- 秒杀订单超时时间
|
||||||
|
- 正常订单超时时间
|
||||||
|
- 订单自动完成时间
|
||||||
|
- 自动结束交易时间
|
||||||
|
- 自动好评时间
|
||||||
|
|
||||||
|
> **退货申请处理**
|
||||||
|
|
||||||
|
- 退货申请搜索:服务单号、收货人姓名/号码、处理状态、申请时间、操作人员、处理时间
|
||||||
|
- 批量操作:删除
|
||||||
|
- 查看详情:退货商品、服务单信息、确认退货、拒绝退货、确认收货
|
||||||
|
|
||||||
|
> **退货原因设置**
|
||||||
|
|
||||||
|
- 原因列表:类型、排序、是否启用、添加时间
|
||||||
|
- 添加、编辑原因:同上
|
||||||
|
- 批量操作:删除
|
||||||
|
|
||||||
|
#### 权限管理 ✔
|
||||||
|
|
||||||
|
> **权限管理**
|
||||||
|
|
||||||
|
- 权限管理:添加权限、删除权限、修改权限、以树形结构返回权限
|
||||||
|
- 角色管理:添加角色、删除角色、更新角色、角色列表、获取相应角色权限、修改相应角色权限
|
||||||
|
- 成员管理:添加、编辑、删除成员、成员列表、为成员分配角色、获取成员角色、分配+-权限、获取权限列表
|
||||||
|
|
||||||
|
角色 | 菜单
|
||||||
|
----|----
|
||||||
|
管理员 | 所有菜单权限
|
||||||
|
运营 | 首页、用户、促销、运营、内容
|
||||||
|
财务 | 首页、统计、财务
|
||||||
|
美工 | 首页、商品
|
||||||
|
客服 | 首页、商品、订单
|
||||||
|
|
||||||
|
### 前台功能
|
||||||
|
|
||||||
|
#### 商品搜索 ✔
|
||||||
|
|
||||||
|
> **综合搜索功能**
|
||||||
|
|
||||||
|
- 搜索:根据商品标题、副标题、关键字进行搜索;
|
||||||
|
- 筛选:未选择分类时聚合搜索结果,选择出现次数最多的分类,选择分类以后可以根据选择分类的筛选字段进行筛选;
|
||||||
|
- 排序:按新品、销量、价格进行排序
|
||||||
|
- 搜索返回结果:商品ID、商品图片、名称、副标题、价格、商品销量、新品、商品的参数、品牌名称、分类名称
|
||||||
|
- 接口:从数据库中查询相关数据并导入es,插入(修改)数据接口,删除数据接口
|
||||||
|
- 品牌分类筛选:根据搜索结果聚合返回品牌、分类及属性
|
||||||
|
|
||||||
|
> **商品推荐功能**
|
||||||
|
|
||||||
|
- 推荐某商品的相关商品、根据该商品的品牌(10)、分类(6)、名称(8)、关键字(2)、副标题(2)
|
||||||
|
- 根据用户一周浏览记录推荐商品,根据用户搜索记录推荐商品
|
||||||
|
|
||||||
|
> **商品热搜功能**
|
||||||
|
|
||||||
|
- 根据用户搜索记录聚合生成热搜词
|
||||||
|
|
||||||
|
> **商品搜索联想功能**
|
||||||
|
|
||||||
|
- 根据用户搜索记录聚合生成热搜词
|
||||||
|
|
||||||
|
#### 购物流程 ✔
|
||||||
|
|
||||||
|
> **购物车**
|
||||||
|
|
||||||
|
- 添加商品到购物车
|
||||||
|
- 购物车商品列表(商品主图、商品名称、商品数量、商品规格)
|
||||||
|
- 修改购物车中商品数量
|
||||||
|
- 购物车中商品重选规格
|
||||||
|
- 购物车中商品删除功能
|
||||||
|
|
||||||
|
> **生成确认单**
|
||||||
|
|
||||||
|
- 生成确认单信息:收货信息、商品信息、价格信息、发票信息、支付方式
|
||||||
|
- 选择收货地址:默认收货地址
|
||||||
|
- 选择优惠券及积分抵扣:展示可用优惠券和不可以优惠券
|
||||||
|
- 计算商品价格:商品合计、运费、优惠券抵扣、积分抵扣、活动优惠
|
||||||
|
- 选择支付方式:在线支付及货到付款
|
||||||
|
- 计算应付金额:合计+运费-优惠券抵扣-积分抵扣-活动优惠
|
||||||
|
|
||||||
|
> **提交订单**
|
||||||
|
|
||||||
|
- 将确认单信息转化为订单
|
||||||
|
- 删除购物车中相关商品
|
||||||
|
- 添加订单到数据库并锁定库存
|
||||||
|
- 在线支付选择支付方式:支付宝、微信、银联、ApplePay
|
||||||
|
|
||||||
|
> **支付订单**
|
||||||
|
|
||||||
|
- 支付完成后修改订单状态为已支付、扣除库存
|
||||||
|
|
||||||
|
> **取消订单(未支付情况下)**
|
||||||
|
|
||||||
|
- 订单超时后自动取消订单,解除商品库存锁定,返还优惠券,积分
|
||||||
|
|
||||||
|
#### 会员模块(我的)✔
|
||||||
|
|
||||||
|
> **我的关注**
|
||||||
|
|
||||||
|
- 关注品牌列表:品牌logo、名称、地址、关注数量
|
||||||
|
- 取消关注功能
|
||||||
|
- 关注列表展示
|
||||||
|
|
||||||
|
> **我的收藏**
|
||||||
|
|
||||||
|
- 收藏的商品:商品主图、名称、卖点、价格、找相似
|
||||||
|
- 收藏的专题:专题主图、标题、副标题、收藏数、浏览数、评论数
|
||||||
|
- 收藏的话题:话题主图、标题、副标题、收藏数、浏览数、评论数
|
||||||
|
|
||||||
|
> **我的足迹**
|
||||||
|
|
||||||
|
- 浏览过的商品:商品主图、名称、卖点、价格、找相似
|
||||||
|
- 删除记录功能
|
||||||
|
- 浏览列表展示
|
||||||
|
|
||||||
|
> **会员登录注册**
|
||||||
|
|
||||||
|
- 登录功能:https登录
|
||||||
|
- 注册功能:用户名、密码、手机号、手机验证码
|
||||||
|
- 获取验证码:后台生成验证码,验证码绑定手机号
|
||||||
|
- 忘记密码:手机号、短信验证码、新密码
|
||||||
|
- 登出功能
|
||||||
211
README.md
Normal file
@@ -0,0 +1,211 @@
|
|||||||
|
# mall
|
||||||
|
|
||||||
|
<p>
|
||||||
|
<a href="#公众号"><img src="http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/badge/%E5%85%AC%E4%BC%97%E5%8F%B7-macrozheng-blue.svg" alt="公众号"></a>
|
||||||
|
<a href="https://github.com/macrozheng/mall-learning"><img src="http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/badge/%E5%AD%A6%E4%B9%A0%E6%95%99%E7%A8%8B-mall--learning-green.svg" alt="学习教程"></a>
|
||||||
|
<a href="http://qm.qq.com/cgi-bin/qm/qr?k=V6xu5c12j9qhnMUNdDRzakNxRKzOxibQ"><img src="http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/badge/QQ%E7%BE%A4-959351312-red.svg" alt="QQ群"></a>
|
||||||
|
<a href="http://qm.qq.com/cgi-bin/qm/qr?k=M5Edq2TiJL_ShcOEeYjwcmdGmq4zZrd_"><img src="http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/badge/QQ%E7%BE%A4-553018255-red.svg" alt="QQ群"></a>
|
||||||
|
<a href="https://gitee.com/macrozheng/mall"><img src="http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/badge/%E7%A0%81%E4%BA%91-%E9%A1%B9%E7%9B%AE%E5%9C%B0%E5%9D%80-orange.svg" alt="码云"></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## 前言
|
||||||
|
|
||||||
|
`mall`项目致力于打造一个完整的电商系统,采用现阶段流行技术实现。
|
||||||
|
|
||||||
|
## 特别赞助商
|
||||||
|
|
||||||
|
<p align="left">
|
||||||
|
<a href="https://coding.net/?utm_source=macrozheng&utm_medium=banner&utm_campaign=march2019" target="_blank">
|
||||||
|
<img src="http://macro-oss.oss-cn-shenzhen.aliyuncs.com/mall/banner/coding.png" width=""/>
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
## 项目介绍
|
||||||
|
|
||||||
|
`mall`项目是一套电商系统,包括前台商城系统及后台管理系统,基于SpringBoot+MyBatis实现。
|
||||||
|
前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订单流程、会员中心、客户服务、帮助中心等模块。
|
||||||
|
后台管理系统包含商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等模块。
|
||||||
|
|
||||||
|
### 项目演示
|
||||||
|
|
||||||
|
#### 后台管理系统
|
||||||
|
|
||||||
|
前端项目`mall-admin-web`地址:https://github.com/macrozheng/mall-admin-web
|
||||||
|
|
||||||
|
项目演示地址: [http://39.98.190.128/index.html](http://39.98.190.128/index.html)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 前台商城系统
|
||||||
|
|
||||||
|
前端项目`mall-app-web`地址:敬请期待......
|
||||||
|
|
||||||
|
项目演示地址:[http://39.98.190.128/mall-app/mainpage.html](http://39.98.190.128/mall-app/mainpage.html)
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
### 组织结构
|
||||||
|
|
||||||
|
``` lua
|
||||||
|
mall
|
||||||
|
├── mall-common -- 工具类及通用代码
|
||||||
|
├── mall-mbg -- MyBatisGenerator生成的数据库操作代码
|
||||||
|
├── mall-admin -- 后台商城管理系统接口
|
||||||
|
├── mall-search -- 基于Elasticsearch的商品搜索系统
|
||||||
|
├── mall-portal -- 前台商城系统接口
|
||||||
|
└── mall-demo -- 框架搭建时的测试代码
|
||||||
|
```
|
||||||
|
|
||||||
|
### 技术选型
|
||||||
|
|
||||||
|
#### 后端技术
|
||||||
|
|
||||||
|
技术 | 说明 | 官网
|
||||||
|
----|----|----
|
||||||
|
Spring Boot | 容器+MVC框架 | [https://spring.io/projects/spring-boot](https://spring.io/projects/spring-boot)
|
||||||
|
Spring Security | 认证和授权框架 | [https://spring.io/projects/spring-security](https://spring.io/projects/spring-security)
|
||||||
|
MyBatis | ORM框架 | [http://www.mybatis.org/mybatis-3/zh/index.html](http://www.mybatis.org/mybatis-3/zh/index.html)
|
||||||
|
MyBatisGenerator | 数据层代码生成 | [http://www.mybatis.org/generator/index.html](http://www.mybatis.org/generator/index.html)
|
||||||
|
PageHelper | MyBatis物理分页插件 | [http://git.oschina.net/free/Mybatis_PageHelper](http://git.oschina.net/free/Mybatis_PageHelper)
|
||||||
|
Swagger-UI | 文档生产工具 | [https://github.com/swagger-api/swagger-ui](https://github.com/swagger-api/swagger-ui)
|
||||||
|
Hibernator-Validator | 验证框架 | [http://hibernate.org/validator/](http://hibernate.org/validator/)
|
||||||
|
Elasticsearch | 搜索引擎 | [https://github.com/elastic/elasticsearch](https://github.com/elastic/elasticsearch)
|
||||||
|
RabbitMq | 消息队列 | [https://www.rabbitmq.com/](https://www.rabbitmq.com/)
|
||||||
|
Redis | 分布式缓存 | [https://redis.io/](https://redis.io/)
|
||||||
|
MongoDb | NoSql数据库 | [https://www.mongodb.com/](https://www.mongodb.com/)
|
||||||
|
Docker | 应用容器引擎 | [https://www.docker.com/](https://www.docker.com/)
|
||||||
|
Druid | 数据库连接池 | [https://github.com/alibaba/druid](https://github.com/alibaba/druid)
|
||||||
|
OSS | 对象存储 | [https://github.com/aliyun/aliyun-oss-java-sdk](https://github.com/aliyun/aliyun-oss-java-sdk)
|
||||||
|
JWT | JWT登录支持 | [https://github.com/jwtk/jjwt](https://github.com/jwtk/jjwt)
|
||||||
|
LogStash | 日志收集 | [https://github.com/logstash/logstash-logback-encoder](https://github.com/logstash/logstash-logback-encoder)
|
||||||
|
Lombok | 简化对象封装工具 | [https://github.com/rzwitserloot/lombok](https://github.com/rzwitserloot/lombok)
|
||||||
|
|
||||||
|
#### 前端技术
|
||||||
|
|
||||||
|
技术 | 说明 | 官网
|
||||||
|
----|----|----
|
||||||
|
Vue | 前端框架 | [https://vuejs.org/](https://vuejs.org/)
|
||||||
|
Vue-router | 路由框架 | [https://router.vuejs.org/](https://router.vuejs.org/)
|
||||||
|
Vuex | 全局状态管理框架 | [https://vuex.vuejs.org/](https://vuex.vuejs.org/)
|
||||||
|
Element | 前端UI框架 | [https://element.eleme.io/](https://element.eleme.io/)
|
||||||
|
Axios | 前端HTTP框架 | [https://github.com/axios/axios](https://github.com/axios/axios)
|
||||||
|
v-charts | 基于Echarts的图表框架 | [https://v-charts.js.org/](https://v-charts.js.org/)
|
||||||
|
Js-cookie | cookie管理工具 | [https://github.com/js-cookie/js-cookie](https://github.com/js-cookie/js-cookie)
|
||||||
|
nprogress | 进度条控件 | [https://github.com/rstacruz/nprogress](https://github.com/rstacruz/nprogress)
|
||||||
|
|
||||||
|
#### 架构图
|
||||||
|
|
||||||
|
##### 系统架构图
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
##### 业务架构图
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
#### 模块介绍
|
||||||
|
|
||||||
|
##### 后台管理系统 `mall-admin`
|
||||||
|
|
||||||
|
- 商品管理:[功能结构图-商品.jpg](document/resource/mind_product.jpg)
|
||||||
|
- 订单管理:[功能结构图-订单.jpg](document/resource/mind_order.jpg)
|
||||||
|
- 促销管理:[功能结构图-促销.jpg](document/resource/mind_sale.jpg)
|
||||||
|
- 内容管理:[功能结构图-内容.jpg](document/resource/mind_content.jpg)
|
||||||
|
- 用户管理:[功能结构图-用户.jpg](document/resource/mind_member.jpg)
|
||||||
|
|
||||||
|
##### 前台商城系统 `mall-portal`
|
||||||
|
|
||||||
|
[功能结构图-前台.jpg](document/resource/mind_portal.jpg)
|
||||||
|
|
||||||
|
#### 开发进度
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 环境搭建
|
||||||
|
|
||||||
|
### 开发工具
|
||||||
|
|
||||||
|
工具 | 说明 | 官网
|
||||||
|
----|----|----
|
||||||
|
IDEA | 开发IDE | https://www.jetbrains.com/idea/download
|
||||||
|
RedisDesktop | redis客户端连接工具 | https://redisdesktop.com/download
|
||||||
|
Robomongo | mongo客户端连接工具 | https://robomongo.org/download
|
||||||
|
SwitchHosts| 本地host管理 | https://oldj.github.io/SwitchHosts/
|
||||||
|
X-shell | Linux远程连接工具 | http://www.netsarang.com/download/software.html
|
||||||
|
Navicat | 数据库连接工具 | http://www.formysql.com/xiazai.html
|
||||||
|
PowerDesigner | 数据库设计工具 | http://powerdesigner.de/
|
||||||
|
Axure | 原型设计工具 | https://www.axure.com/
|
||||||
|
MindMaster | 思维导图设计工具 | http://www.edrawsoft.cn/mindmaster
|
||||||
|
ScreenToGif | gif录制工具 | https://www.screentogif.com/
|
||||||
|
ProcessOn | 流程图绘制工具 | https://www.processon.com/
|
||||||
|
PicPick | 屏幕取色工具 | https://picpick.app/zh/
|
||||||
|
|
||||||
|
### 开发环境
|
||||||
|
|
||||||
|
工具 | 版本号 | 下载
|
||||||
|
----|----|----
|
||||||
|
JDK | 1.8 | https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
|
||||||
|
Mysql | 5.7 | https://www.mysql.com/
|
||||||
|
Redis | 3.2 | https://redis.io/download
|
||||||
|
Elasticsearch | 6.2.2 | https://www.elastic.co/downloads
|
||||||
|
MongoDb | 3.2 | https://www.mongodb.com/download-center
|
||||||
|
RabbitMq | 3.7.14 | http://www.rabbitmq.com/download.html
|
||||||
|
nginx | 1.10 | http://nginx.org/en/download.html
|
||||||
|
|
||||||
|
### 搭建步骤
|
||||||
|
|
||||||
|
> Windows环境部署
|
||||||
|
|
||||||
|
- Windows环境搭建请参考:[mall在Windows环境下的部署](https://mp.weixin.qq.com/s/Q9ybpfq8IEdbZmvlaMXJdg);
|
||||||
|
- 安装Windows环境下的所有工具并启动(只启动mall-admin,仅需安装mysql);
|
||||||
|
- 克隆源代码到本地,使用IDEA或Eclipse打开,并完成编译;
|
||||||
|
- 在mysql中新建mall数据库,导入document/sql下的mall.sql文件;
|
||||||
|
- 启动mall-admin项目:直接运行com.macro.mall.MallAdminApplication的main方法即可,
|
||||||
|
接口文档地址:http://localhost:8080/swagger-ui.html;
|
||||||
|
- 启动mall-search项目:直接运行com.macro.mall.search.MallSearchApplication的main方法即可,
|
||||||
|
接口文档地址:http://localhost:8081/swagger-ui.html;
|
||||||
|
- 启动mall-portal项目:直接运行com.macro.mall.portal.MallPortalApplication的main方法即可,
|
||||||
|
接口文档地址:http://localhost:8085/swagger-ui.html;
|
||||||
|
- 克隆`mall-admin-web`项目,并导入到IDEA中完成编译[传送门](https://github.com/macrozheng/mall-admin-web);
|
||||||
|
- 在IDEA命令行中运行命令:npm install,下载相关依赖;
|
||||||
|
- 在IDEA命令行中运行命令:npm run dev,访问地址:[http://localhost:8090](http://localhost:8090) 即可打开后台管理系统页面;
|
||||||
|
- ELK日志收集系统的搭建:参考[elk.md](document/elk/elk.md)。
|
||||||
|
|
||||||
|
> Docker环境部署
|
||||||
|
|
||||||
|
- 在VirtualBox或其他环境中安装CenterOs7.6;
|
||||||
|
- Docker环境的安装请参考:[开发者必备Docker命令](https://mp.weixin.qq.com/s/d_CuljDTJq680NTndAay8g);
|
||||||
|
- 本项目Docker镜像构建请参考:[使用Maven插件构建Docker镜像](https://mp.weixin.qq.com/s/q2KDzHbPkf3Q0EY8qYjYgw);
|
||||||
|
- 本项目在Docker容器下的部署请参考:[mall在Linux环境下的部署(基于Docker容器)](https://mp.weixin.qq.com/s/0fVMK107i5bBq8kGQqg8KA)。
|
||||||
|
|
||||||
|
## 项目相关文档
|
||||||
|
|
||||||
|
具体详见`mall-learning`:[https://github.com/macrozheng/mall-learning](https://github.com/macrozheng/mall-learning)
|
||||||
|
|
||||||
|
## 参考资料
|
||||||
|
|
||||||
|
- [Spring实战(第4版)](https://book.douban.com/subject/26767354/)
|
||||||
|
- [Spring Boot实战](https://book.douban.com/subject/26857423/)
|
||||||
|
- [Spring Cloud微服务实战](https://book.douban.com/subject/27025912/)
|
||||||
|
- [Spring Cloud与Docker微服务架构实战](https://book.douban.com/subject/27028228/)
|
||||||
|
- [Spring Data实战](https://book.douban.com/subject/25975186/)
|
||||||
|
- [MyBatis从入门到精通](https://book.douban.com/subject/27074809/)
|
||||||
|
- [深入浅出MySQL](https://book.douban.com/subject/25817684/)
|
||||||
|
- [循序渐进Linux(第2版)](https://book.douban.com/subject/26758194/)
|
||||||
|
- [Elasticsearch 权威指南](https://www.elastic.co/guide/cn/elasticsearch/guide/current/index.html)
|
||||||
|
- [Elasticsearch 技术解析与实战](https://book.douban.com/subject/26967826/)
|
||||||
|
- [MongoDB实战(第二版)](https://book.douban.com/subject/27061123/)
|
||||||
|
- [Kubernetes权威指南](https://book.douban.com/subject/26902153/)
|
||||||
|
- [Pro Git](https://git-scm.com/book/zh/v2)
|
||||||
|
|
||||||
|
## 公众号
|
||||||
|
|
||||||
|
mall项目全套学习教程连载中,**关注公众号**第一时间获取。
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 许可证
|
||||||
|
|
||||||
|
[Apache License 2.0](https://github.com/macrozheng/mall/blob/master/LICENSE)
|
||||||
|
|
||||||
|
Copyright (c) 2018-2019 macrozheng
|
||||||
27
document/cert/2629214_mall.yusenrong.com.key
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
MIIEpAIBAAKCAQEAgVvtzKTrCPUwQEuwHVC6dselz2mpUbmxg8Z+S4gz3Ff2aeOn
|
||||||
|
QsZxoPYPoYneiMeS7uRGhlJnXdeT4dbqgZzbcMj+erDN51iIR72suUnXpDbHI3CJ
|
||||||
|
V5It4mGoq883U5RQCVDmqTs8pT4SoNxx5/kSp6cJYbLnVwsmV/8crLSKFitAXlaq
|
||||||
|
F01pRAn3FKDFMbytoD8kYoyxbmfC/M2mrvndoWTzwR8/qplgx7gjSLF2PAABg6Ao
|
||||||
|
ILGHx25Hvw6tRD2BRE7yUN/q6I8xe3/0LuCgwZ8iE8FlMvxAKPG651UBOloksu8H
|
||||||
|
Kf71ctJj6/wcdOB3zDYFd5kxjw36TwDAAG2QIwIDAQABAoIBAH58ty9NawydQwr7
|
||||||
|
dz+S+mC+oyEGfiuNWUgyxLdyfNNNp4KuuZQPmnf7YhlgSBqSmtfAmj0pQi1+Z/mC
|
||||||
|
PldyWxgTUNIDI7K83LTZgJTE4XiOn3XFymW4Z+ld+KHWwpCVCxWw53o+k/Q3l9t2
|
||||||
|
8mITJ+yK5h+D4bU5D8snhpBREFzPh3kYMZ1nTrBPtUne+tGjxxhmetBgT7Iy43hO
|
||||||
|
d4eQpJ8PEDHUvFfux5HAkyp58fumnjq9/gotjtFKARwpFlQoiLA40QsPInLuSMsk
|
||||||
|
VLZ76yE7yuPBbHOZOVpHBLImibsg2vrVavT/auhrpoTthuqt3oJkUvidxQ1NHn2N
|
||||||
|
l5Gf5sECgYEA8fuJMP327heZbkHuWuZ17gKDJvgvg1Vvdco9xcX0p0F9qz9VBT4G
|
||||||
|
mbK/UqvdL9irfTVWfBkuO5mm8NbtS2JtdLozER6K6NcWM9XHTuvMBoUTP8Yu1LTs
|
||||||
|
1lyXUkyGFzdDdHse4sS+RKu2V9ykcv4D7byM1WEbu4sYa30IFMRsRxMCgYEAiNpA
|
||||||
|
PDPePipQDsPd6q3X+8U2pNZpvVwlQNcu8H16Os9k1FD4AkT2rwO+1FsJfCUONyKf
|
||||||
|
cmwnTrVMOT+DfqPnkUU5IAleKpN6p15Bn2TwRkqc2pAP5Bno6jAQXRQtApDhb6dr
|
||||||
|
o8hbMWXKwWjFi7m/psyfmki19Ttwf0kRAlufZLECgYEA0KFGD29nTrAaIO3HS6gX
|
||||||
|
VTXlTdv9WwZ2KuBLkhCyduIIL3VTIEnx9uIeAnEbKv1sHW+3ORecvNYlENC9lpku
|
||||||
|
Nc2z6bajnUyUX+yZAnpaVeS2S+3awpma+NarwNEpayrChdMBNhLa2OoTNH2Pa3WG
|
||||||
|
fZpq8i3fczrhuwr5xK31jPECgYBcLIvpQJIm0r77Quc8QnzfodQNMDEmDmM1Cfoe
|
||||||
|
lpT1+WwTKLnyZVq1RFOKmgqIaDjr39D+82OCOtAtGt9JM8IrcTFpp4WaLZ0GD5Ep
|
||||||
|
d4XyAh0lhLR/UQg0e8z5tDYgrU55sozoUnFBkyr+G8A6PRCdmuLAusp7ct5xjNf8
|
||||||
|
+5Me8QKBgQChqG0QQiqnTvKqp8LRng1eUl1n55Pt8WSFr9aZyj3aDgDttcjdBgXQ
|
||||||
|
5ildvumUidU2JWz5NMC/qoTx1Y9yoUW3snQbLWG3pvRPlRPPRRQwTCCPDMf0RDxI
|
||||||
|
6Nx/HFJFuW7jR4c8M/rpp8q7Lm693UPRwb/GICbMHKeHP6bMDbTAgw==
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
59
document/cert/2629214_mall.yusenrong.com.pem
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIFjjCCBHagAwIBAgIQBLkhPdDnB4A4iU84gBdNUjANBgkqhkiG9w0BAQsFADBu
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMS0wKwYDVQQDEyRFbmNyeXB0aW9uIEV2ZXJ5d2hlcmUg
|
||||||
|
RFYgVExTIENBIC0gRzEwHhcNMTkwODA4MDAwMDAwWhcNMjAwODA3MTIwMDAwWjAd
|
||||||
|
MRswGQYDVQQDExJtYWxsLnl1c2Vucm9uZy5jb20wggEiMA0GCSqGSIb3DQEBAQUA
|
||||||
|
A4IBDwAwggEKAoIBAQCBW+3MpOsI9TBAS7AdULp2x6XPaalRubGDxn5LiDPcV/Zp
|
||||||
|
46dCxnGg9g+hid6Ix5Lu5EaGUmdd15Ph1uqBnNtwyP56sM3nWIhHvay5SdekNscj
|
||||||
|
cIlXki3iYairzzdTlFAJUOapOzylPhKg3HHn+RKnpwlhsudXCyZX/xystIoWK0Be
|
||||||
|
VqoXTWlECfcUoMUxvK2gPyRijLFuZ8L8zaau+d2hZPPBHz+qmWDHuCNIsXY8AAGD
|
||||||
|
oCggsYfHbke/Dq1EPYFETvJQ3+rojzF7f/Qu4KDBnyITwWUy/EAo8brnVQE6WiSy
|
||||||
|
7wcp/vVy0mPr/Bx04HfMNgV3mTGPDfpPAMAAbZAjAgMBAAGjggJ3MIICczAfBgNV
|
||||||
|
HSMEGDAWgBRVdE+yck/1YLpQ0dfmUVyaAYca1zAdBgNVHQ4EFgQUYK0PxpTeIGsq
|
||||||
|
x3QEPkeBO1otpYIwHQYDVR0RBBYwFIISbWFsbC55dXNlbnJvbmcuY29tMA4GA1Ud
|
||||||
|
DwEB/wQEAwIFoDAdBgNVHSUEFjAUBggrBgEFBQcDAQYIKwYBBQUHAwIwTAYDVR0g
|
||||||
|
BEUwQzA3BglghkgBhv1sAQIwKjAoBggrBgEFBQcCARYcaHR0cHM6Ly93d3cuZGln
|
||||||
|
aWNlcnQuY29tL0NQUzAIBgZngQwBAgEwgYAGCCsGAQUFBwEBBHQwcjAkBggrBgEF
|
||||||
|
BQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEoGCCsGAQUFBzAChj5odHRw
|
||||||
|
Oi8vY2FjZXJ0cy5kaWdpY2VydC5jb20vRW5jcnlwdGlvbkV2ZXJ5d2hlcmVEVlRM
|
||||||
|
U0NBLUcxLmNydDAJBgNVHRMEAjAAMIIBBQYKKwYBBAHWeQIEAgSB9gSB8wDxAHcA
|
||||||
|
7ku9t3XOYLrhQmkfq+GeZqMPfl+wctiDAMR7iXqo/csAAAFscYgmYAAABAMASDBG
|
||||||
|
AiEAs4Ug6AQihwmd35U43LCeg8Jrp683YQM5Z3QHuyl1VY8CIQDlqqLNBDQpA4t9
|
||||||
|
/KdjCEyaSlE/W17DUoYoEmFQHyQoGgB2AF6nc/nfVsDntTZIfdBJ4DJ6kZoMhKES
|
||||||
|
EoQYdZaBcUVYAAABbHGIJbgAAAQDAEcwRQIhAM74OJiDOG1f6ecIi3n2bcKx25mt
|
||||||
|
iuUcaynWKNe4xTFoAiBmFncbYFSlvkYJU1rCgbygMqYUeIbQN575ZBnbmH5NLzAN
|
||||||
|
BgkqhkiG9w0BAQsFAAOCAQEAAzPrPbwGFbBMyhNPtYimOXGqTj0qZ9i9EhQua4oX
|
||||||
|
JYC5lf0ll8Bhpl8BC8f3FCPEuEtwPp5U5VXSXSbPfHOQfpwRJnmT7LosX3GUzJkU
|
||||||
|
qoTR3+pu3f//vdfvuli03ayVjI7KaelLeGXZa4RB4dxf+s8m7nqI/Y/1aI77OuoU
|
||||||
|
pfD15tezAy6zM86Z9fCGXbLCA/acBAvugA8pxvv2HyAoh+yZqZdaseilloa5yzkT
|
||||||
|
jRBvuwnNm/TOfgw3JnxQtDHM2h0/LTwLx/BS9L7izol9f4hclUG08CAUzU/Lraau
|
||||||
|
OtY1Ge+qb6p8jQ594chLBXxDgd3/hRLLMHFCxjuo5tyOPw==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
MIIEqjCCA5KgAwIBAgIQAnmsRYvBskWr+YBTzSybsTANBgkqhkiG9w0BAQsFADBh
|
||||||
|
MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
|
||||||
|
d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
|
||||||
|
QTAeFw0xNzExMjcxMjQ2MTBaFw0yNzExMjcxMjQ2MTBaMG4xCzAJBgNVBAYTAlVT
|
||||||
|
MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
|
||||||
|
b20xLTArBgNVBAMTJEVuY3J5cHRpb24gRXZlcnl3aGVyZSBEViBUTFMgQ0EgLSBH
|
||||||
|
MTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALPeP6wkab41dyQh6mKc
|
||||||
|
oHqt3jRIxW5MDvf9QyiOR7VfFwK656es0UFiIb74N9pRntzF1UgYzDGu3ppZVMdo
|
||||||
|
lbxhm6dWS9OK/lFehKNT0OYI9aqk6F+U7cA6jxSC+iDBPXwdF4rs3KRyp3aQn6pj
|
||||||
|
pp1yr7IB6Y4zv72Ee/PlZ/6rK6InC6WpK0nPVOYR7n9iDuPe1E4IxUMBH/T33+3h
|
||||||
|
yuH3dvfgiWUOUkjdpMbyxX+XNle5uEIiyBsi4IvbcTCh8ruifCIi5mDXkZrnMT8n
|
||||||
|
wfYCV6v6kDdXkbgGRLKsR4pucbJtbKqIkUGxuZI2t7pfewKRc5nWecvDBZf3+p1M
|
||||||
|
pA8CAwEAAaOCAU8wggFLMB0GA1UdDgQWBBRVdE+yck/1YLpQ0dfmUVyaAYca1zAf
|
||||||
|
BgNVHSMEGDAWgBQD3lA1VtFMu2bwo+IbG8OXsj3RVTAOBgNVHQ8BAf8EBAMCAYYw
|
||||||
|
HQYDVR0lBBYwFAYIKwYBBQUHAwEGCCsGAQUFBwMCMBIGA1UdEwEB/wQIMAYBAf8C
|
||||||
|
AQAwNAYIKwYBBQUHAQEEKDAmMCQGCCsGAQUFBzABhhhodHRwOi8vb2NzcC5kaWdp
|
||||||
|
Y2VydC5jb20wQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybDMuZGlnaWNlcnQu
|
||||||
|
Y29tL0RpZ2lDZXJ0R2xvYmFsUm9vdENBLmNybDBMBgNVHSAERTBDMDcGCWCGSAGG
|
||||||
|
/WwBAjAqMCgGCCsGAQUFBwIBFhxodHRwczovL3d3dy5kaWdpY2VydC5jb20vQ1BT
|
||||||
|
MAgGBmeBDAECATANBgkqhkiG9w0BAQsFAAOCAQEAK3Gp6/aGq7aBZsxf/oQ+TD/B
|
||||||
|
SwW3AU4ETK+GQf2kFzYZkby5SFrHdPomunx2HBzViUchGoofGgg7gHW0W3MlQAXW
|
||||||
|
M0r5LUvStcr82QDWYNPaUy4taCQmyaJ+VB+6wxHstSigOlSNF2a6vg4rgexixeiV
|
||||||
|
4YSB03Yqp2t3TeZHM9ESfkus74nQyW7pRGezj+TC44xCagCQQOzzNmzEAP2SnCrJ
|
||||||
|
sNE2DpRVMnL8J6xBRdjmOsC3N6cQuKuRXbzByVBjCqAA8t1L0I+9wXJerLPyErjy
|
||||||
|
rMKWaBFLmfK/AHNF4ZihwPGOc7w6UHczBZXH5RFzJNnww+WnKuTPI0HfnVH8lg==
|
||||||
|
-----END CERTIFICATE-----
|
||||||
BIN
document/product/banaer图.png
Normal file
|
After Width: | Height: | Size: 217 KiB |
BIN
document/product/公园漫步/gymb1.png
Normal file
|
After Width: | Height: | Size: 562 KiB |
BIN
document/product/公园漫步/gymb2.png
Normal file
|
After Width: | Height: | Size: 214 KiB |
BIN
document/product/公园漫步/gymb3.png
Normal file
|
After Width: | Height: | Size: 497 KiB |
BIN
document/product/公园漫步/gymb4.png
Normal file
|
After Width: | Height: | Size: 258 KiB |
BIN
document/product/公园漫步/gymb5.png
Normal file
|
After Width: | Height: | Size: 330 KiB |
BIN
document/product/公园漫步/gymb6.png
Normal file
|
After Width: | Height: | Size: 422 KiB |
BIN
document/product/公园漫步/gymb7.png
Normal file
|
After Width: | Height: | Size: 366 KiB |
BIN
document/product/公园漫步/gymb_main.png
Normal file
|
After Width: | Height: | Size: 554 KiB |
BIN
document/product/广谱型/gpx1.jpg
Normal file
|
After Width: | Height: | Size: 32 KiB |
BIN
document/product/广谱型/gpx10.jpg
Normal file
|
After Width: | Height: | Size: 78 KiB |
BIN
document/product/广谱型/gpx2.jpg
Normal file
|
After Width: | Height: | Size: 30 KiB |
BIN
document/product/广谱型/gpx3.jpg
Normal file
|
After Width: | Height: | Size: 42 KiB |
BIN
document/product/广谱型/gpx4.jpg
Normal file
|
After Width: | Height: | Size: 34 KiB |
BIN
document/product/广谱型/gpx5.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
document/product/广谱型/gpx6.jpg
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
document/product/广谱型/gpx7.jpg
Normal file
|
After Width: | Height: | Size: 53 KiB |
BIN
document/product/广谱型/gpx8.jpg
Normal file
|
After Width: | Height: | Size: 93 KiB |
BIN
document/product/广谱型/gpx9.jpg
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
document/product/广谱型/gpx_main.jpg
Normal file
|
After Width: | Height: | Size: 74 KiB |
BIN
document/product/康居生活/kjsh1.png
Normal file
|
After Width: | Height: | Size: 618 KiB |
BIN
document/product/康居生活/kjsh2.png
Normal file
|
After Width: | Height: | Size: 214 KiB |
BIN
document/product/康居生活/kjsh3.png
Normal file
|
After Width: | Height: | Size: 497 KiB |
BIN
document/product/康居生活/kjsh4.png
Normal file
|
After Width: | Height: | Size: 258 KiB |
BIN
document/product/康居生活/kjsh5.png
Normal file
|
After Width: | Height: | Size: 307 KiB |
BIN
document/product/康居生活/kjsh6.png
Normal file
|
After Width: | Height: | Size: 422 KiB |
BIN
document/product/康居生活/kjsh7.png
Normal file
|
After Width: | Height: | Size: 336 KiB |
BIN
document/product/康居生活/kjsh_main.png
Normal file
|
After Width: | Height: | Size: 554 KiB |
BIN
document/product/森林幻想/slhx1.png
Normal file
|
After Width: | Height: | Size: 673 KiB |
BIN
document/product/森林幻想/slhx2.png
Normal file
|
After Width: | Height: | Size: 314 KiB |
BIN
document/product/森林幻想/slhx3.png
Normal file
|
After Width: | Height: | Size: 568 KiB |
BIN
document/product/森林幻想/slhx4.png
Normal file
|
After Width: | Height: | Size: 298 KiB |
BIN
document/product/森林幻想/slhx6.png
Normal file
|
After Width: | Height: | Size: 496 KiB |
BIN
document/product/森林幻想/slhx_main.png
Normal file
|
After Width: | Height: | Size: 682 KiB |
BIN
document/product/森林幻想/sxlh5.png
Normal file
|
After Width: | Height: | Size: 347 KiB |
BIN
document/product/特效型/txx1.jpg
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
document/product/特效型/txx10.jpg
Normal file
|
After Width: | Height: | Size: 86 KiB |
BIN
document/product/特效型/txx2.jpg
Normal file
|
After Width: | Height: | Size: 28 KiB |
BIN
document/product/特效型/txx3.jpg
Normal file
|
After Width: | Height: | Size: 37 KiB |
BIN
document/product/特效型/txx4.jpg
Normal file
|
After Width: | Height: | Size: 81 KiB |
BIN
document/product/特效型/txx5.jpg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
document/product/特效型/txx6.jpg
Normal file
|
After Width: | Height: | Size: 122 KiB |
BIN
document/product/特效型/txx7.jpg
Normal file
|
After Width: | Height: | Size: 50 KiB |
BIN
document/product/特效型/txx8.jpg
Normal file
|
After Width: | Height: | Size: 66 KiB |
BIN
document/product/特效型/txx9.jpg
Normal file
|
After Width: | Height: | Size: 97 KiB |
BIN
document/product/特效型/txx_main.jpg
Normal file
|
After Width: | Height: | Size: 124 KiB |
BIN
document/product/蓝色海洋/lshy1.png
Normal file
|
After Width: | Height: | Size: 674 KiB |
BIN
document/product/蓝色海洋/lshy2.png
Normal file
|
After Width: | Height: | Size: 268 KiB |
BIN
document/product/蓝色海洋/lshy3.png
Normal file
|
After Width: | Height: | Size: 527 KiB |
BIN
document/product/蓝色海洋/lshy4.png
Normal file
|
After Width: | Height: | Size: 298 KiB |
BIN
document/product/蓝色海洋/lshy5.png
Normal file
|
After Width: | Height: | Size: 540 KiB |
BIN
document/product/蓝色海洋/lshy_main.png
Normal file
|
After Width: | Height: | Size: 779 KiB |
BIN
document/product/通用型/tyx1.png
Normal file
|
After Width: | Height: | Size: 674 KiB |
BIN
document/product/通用型/tyx2.png
Normal file
|
After Width: | Height: | Size: 268 KiB |
BIN
document/product/通用型/tyx3.png
Normal file
|
After Width: | Height: | Size: 564 KiB |
BIN
document/product/通用型/tyx4.png
Normal file
|
After Width: | Height: | Size: 298 KiB |
BIN
document/product/通用型/tyx5.png
Normal file
|
After Width: | Height: | Size: 540 KiB |
BIN
document/product/通用型/tyx_main.png
Normal file
|
After Width: | Height: | Size: 779 KiB |
2
document/requirement/AccessKey.csv
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
"AccessKeyId","AccessKeySecret"
|
||||||
|
"LTAIuQmZihe6hOk0","2XIDo6yvSDJM2iaEL2EyHBgVF8mMCQ"
|
||||||
|
BIN
document/requirement/logo.jpg
Normal file
|
After Width: | Height: | Size: 110 KiB |
BIN
document/requirement/main.jpg
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
document/requirement/制度说明.doc
Normal file
BIN
document/requirement/制度说明_20190715.doc
Normal file
BIN
document/requirement/渝森蓉劳务计算机制.docx
Normal file
BIN
document/requirement/渝森蓉劳务计算机制_20190718.docx
Normal file
BIN
document/requirement/渝森蓉开发任务表.xlsx
Normal file
BIN
document/requirement/种子宝库放企业介绍.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
document/requirement/系统价格表.doc
Normal file
BIN
document/requirement/购物协议20190815.docx
Normal file
3380
document/sql/mall_data.sql
Normal file
38
document/sql/mall_dms_data.sql
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
|
||||||
|
DELETE FROM `dms_seller_bank_account`;
|
||||||
|
INSERT INTO `dms_seller_bank_account` (`id`, `account_name`, `bank_name`, `bank_card_num`, `open_bank_address`) VALUES
|
||||||
|
(1, '507科技', '507科技', '507y8-507y8-507y8-507y8', '507科技总部大楼');
|
||||||
|
|
||||||
|
|
||||||
|
DELETE FROM `dms_distribution_dictionary`;
|
||||||
|
INSERT INTO `dms_distribution_dictionary` (`id`, `name`, `value`, `comment`, `show_status`, `update_time`) VALUES
|
||||||
|
(1, 'become_consumer', '1914', '成为消费商须购买商品的金额', '1', now()),
|
||||||
|
(2, 'become_partner', '30000', '成为经销商须购买商品的金额', '1', now()),
|
||||||
|
(3, 'become_one_diamond_one', '300000', '成为初级合作商须购买商品的金额', '1', now()),
|
||||||
|
(4, 'become_one_diamond_two', '3', '成为初级合作商须分享经销商的市场数量', '1', now()),
|
||||||
|
(5, 'become_two_diamond', '3', '成为中级合作商须培养出初级合作商的市场数量', '1', now()),
|
||||||
|
(6, 'become_three_diamond', '3', '成为高级合作商须培养出中级合作商的市场数量', '1', now()),
|
||||||
|
(7, 'become_four_diamond', '3', '成为特级合作商须培养出高级合作商的市场数量', '1', now()),
|
||||||
|
|
||||||
|
(8, 'consumer_direct_income', '15', '消费商获得分享劳务费的百分比', '1', now()),
|
||||||
|
(9, 'consumer_indirect_income', '5', '消费商获得服务劳务费的百分比', '1', now()),
|
||||||
|
(10, 'consumer_buy_again', '8', '成为消费商后再次购买的折扣', '1', now()),
|
||||||
|
|
||||||
|
(11, 'partner_direct_income', '20', '经销商获得分享劳务费的百分比', '1', now()),
|
||||||
|
(12, 'partner_indirect_income', '7', '经销商获得服务劳务费的百分比', '1', now()),
|
||||||
|
(13, 'partner_buy_again', '6', '成为经销商后再次购买的折扣', '1', now()),
|
||||||
|
(14, 'partner_store_subsidy', '3', '成为经销商并开店后获得店补的百分比', '1', now()),
|
||||||
|
|
||||||
|
(15, 'diamond_direct_income', '28', '合作商获得分享劳务费的百分比', '1', now()),
|
||||||
|
(16, 'diamond_indirect_income', '9', '合作商获得服务劳务费的百分比', '1', now()),
|
||||||
|
(17, 'diamond_buy_again', '5', '成为合作商后再次购买的折扣', '1', now()),
|
||||||
|
(18, 'diamond_store_subsidy', '3', '成为合作商并开店后获得店补的百分比', '1', now()),
|
||||||
|
|
||||||
|
(19, 'one_diamond_team_income', '10', '初级合作商获得团队服务劳务费的百分比', '1', now()),
|
||||||
|
(20, 'two_diamond_team_income', '14', '中级合作商获得团队服务劳务费的百分比', '1', now()),
|
||||||
|
(21, 'three_diamond_team_income', '16', '高级合作商获得团队服务劳务费的百分比', '1', now()),
|
||||||
|
(22, 'four_diamond_platform_income', '3', '特级合作商获得平台月度加权平均奖励的百分比', '1', now()),
|
||||||
|
|
||||||
|
(23, 'withdraw_poundage', '5', '提现手续费的百分比', '1', now()),
|
||||||
|
(24, 'withdraw_multiple', '100', '提现金额的整数倍数', '1', now());
|
||||||
|
|
||||||
208
document/sql/mall_dms_structure.sql
Normal file
@@ -0,0 +1,208 @@
|
|||||||
|
DROP TABLE IF EXISTS `dms_seller_bank_account`;
|
||||||
|
CREATE TABLE IF NOT EXISTS `dms_seller_bank_account` (
|
||||||
|
`id` int(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',
|
||||||
|
`account_name` varchar(100) DEFAULT NULL COMMENT '账户名',
|
||||||
|
`bank_name` varchar(100) DEFAULT NULL COMMENT '银行名称',
|
||||||
|
`bank_card_num` varchar(50) DEFAULT NULL COMMENT '银行卡号',
|
||||||
|
`open_bank_address` varchar(100) DEFAULT NULL COMMENT '开户行地址',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8 COMMENT='商家银行账户表';
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_offline_payment_record`;
|
||||||
|
CREATE TABLE IF NOT EXISTS `dms_offline_payment_record` (
|
||||||
|
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',
|
||||||
|
`seller_bank_account_id` int(10) DEFAULT NULL COMMENT '商家银行账户id',
|
||||||
|
`member_id` bigint(20) DEFAULT NULL COMMENT '会员id',
|
||||||
|
`order_id` bigint(20) DEFAULT NULL COMMENT '订单id',
|
||||||
|
`order_sn` varchar(64) DEFAULT NULL COMMENT '订单编号',
|
||||||
|
`pay_amount` decimal(10,2) DEFAULT NULL COMMENT '支付金额',
|
||||||
|
`payment_account_name` varchar(100) DEFAULT NULL COMMENT '支付账户名',
|
||||||
|
`payment_bank_name` varchar(100) DEFAULT NULL COMMENT '支付银行名称',
|
||||||
|
`payment_bank_card_num` varchar(50) DEFAULT NULL COMMENT '支付银行卡号',
|
||||||
|
`confirm_status` int(1) DEFAULT NULL COMMENT '确认状态:0->未确认;1->已确认',
|
||||||
|
`confirm_time` datetime DEFAULT NULL COMMENT '确认时间',
|
||||||
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
|
PRIMARY KEY (`id`),
|
||||||
|
UNIQUE KEY `idx_order_id` (`order_id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8 COMMENT='线下支付记录表';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_member_bank_account`;
|
||||||
|
CREATE TABLE IF NOT EXISTS `dms_member_bank_account` (
|
||||||
|
`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',
|
||||||
|
`member_id` bigint(20) DEFAULT NULL COMMENT '会员id',
|
||||||
|
`account_name` varchar(100) DEFAULT NULL COMMENT '账户名',
|
||||||
|
`bank_name` varchar(100) DEFAULT NULL COMMENT '银行名称',
|
||||||
|
`bank_card_num` varchar(50) DEFAULT NULL COMMENT '银行卡号',
|
||||||
|
`open_bank_address` varchar(100) DEFAULT NULL COMMENT '开户行地址',
|
||||||
|
`default_status` int(1) DEFAULT NULL COMMENT '是否默认:0->否;1->是',
|
||||||
|
`update_time` datetime DEFAULT NULL COMMENT '更新时间',
|
||||||
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='会员银行账户表';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_member_withdraw_apply`;
|
||||||
|
CREATE TABLE IF NOT EXISTS `dms_member_withdraw_apply` (
|
||||||
|
`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',
|
||||||
|
`member_id` bigint(20) DEFAULT NULL COMMENT '会员id',
|
||||||
|
`value` decimal(10,2) DEFAULT NULL COMMENT '值',
|
||||||
|
`poundage` decimal(10,2) DEFAULT NULL COMMENT '手续费',
|
||||||
|
`actual_value` decimal(10,2) DEFAULT NULL COMMENT '扣出手续费后的值',
|
||||||
|
`account_name` varchar(100) DEFAULT NULL COMMENT '账户名',
|
||||||
|
`bank_name` varchar(100) DEFAULT NULL COMMENT '银行名称',
|
||||||
|
`bank_card_num` varchar(50) DEFAULT NULL COMMENT '银行卡号',
|
||||||
|
`open_bank_address` varchar(100) DEFAULT NULL COMMENT '开户行地址',
|
||||||
|
`payment_status` int(1) DEFAULT NULL COMMENT '付款状态:0->未打款;1->已打款;2->打款失败',
|
||||||
|
`failed_reason` varchar(255) DEFAULT NULL COMMENT '失败原因',
|
||||||
|
`payment_time` datetime DEFAULT NULL COMMENT '付款时间',
|
||||||
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8 COMMENT='会员提现申请表';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_team_level`;
|
||||||
|
CREATE TABLE IF NOT EXISTS `dms_team_level` (
|
||||||
|
`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键id',
|
||||||
|
`member_id` bigint(20) DEFAULT NULL COMMENT '会员id',
|
||||||
|
`parent_id` bigint(20) DEFAULT NULL COMMENT '推荐人id',
|
||||||
|
`level_tree` varchar(1000) DEFAULT NULL COMMENT '层级树',
|
||||||
|
`level` int(10) DEFAULT NULL COMMENT '当前层级',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB AUTO_INCREMENT=18 DEFAULT CHARSET=utf8 COMMENT='团队层级关系表';
|
||||||
|
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_distribution_dictionary`;
|
||||||
|
CREATE TABLE `dms_distribution_dictionary` (
|
||||||
|
`id` INT(10) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||||
|
`name` VARCHAR(50) NULL DEFAULT NULL COMMENT '名称',
|
||||||
|
`value` VARCHAR(50) NULL DEFAULT NULL COMMENT '参数值',
|
||||||
|
`comment` VARCHAR(50) NULL DEFAULT NULL COMMENT '备注',
|
||||||
|
`show_status` int(1) NULL DEFAULT '1' COMMENT '显示状态( 0: 不显示 1: 显示)',
|
||||||
|
`update_time` TIMESTAMP NULL DEFAULT NULL COMMENT '更新时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='分销字典表';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_member_total_income`;
|
||||||
|
CREATE TABLE `dms_member_total_income` (
|
||||||
|
`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||||
|
`member_id` bigint(20) DEFAULT NULL COMMENT '会员id',
|
||||||
|
`item_type` int(3) NULL DEFAULT NULL COMMENT '项目类型',
|
||||||
|
`value` decimal(10,2) DEFAULT NULL COMMENT '值',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='会员总收入表';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_team_total_income`;
|
||||||
|
CREATE TABLE `dms_team_total_income` (
|
||||||
|
`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||||
|
`member_id` bigint(20) DEFAULT NULL COMMENT '会员id',
|
||||||
|
`value` decimal(10,2) DEFAULT NULL COMMENT '值',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='团队总收入表';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_team_total_consume`;
|
||||||
|
CREATE TABLE `dms_team_total_consume` (
|
||||||
|
`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||||
|
`member_id` bigint(20) DEFAULT NULL COMMENT '会员id',
|
||||||
|
`value` decimal(10,2) DEFAULT NULL COMMENT '值',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='团队累计消费表';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_team_member_number`;
|
||||||
|
CREATE TABLE `dms_team_member_number` (
|
||||||
|
`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||||
|
`member_id` bigint(20) DEFAULT NULL COMMENT '会员id',
|
||||||
|
`total` int(10) DEFAULT '0' COMMENT '团队成员总数',
|
||||||
|
`consumer` int(10) DEFAULT '0' COMMENT '消费者人数',
|
||||||
|
`partner` int(10) DEFAULT '0' COMMENT '经销商人数',
|
||||||
|
`one_diamond` int(10) DEFAULT '0' COMMENT '初级合作商人数',
|
||||||
|
`two_diamond` int(10) DEFAULT '0' COMMENT '中级合作商人数',
|
||||||
|
`three_diamond` int(10) DEFAULT '0' COMMENT '高级合作商人数',
|
||||||
|
`four_diamond` int(10) DEFAULT '0' COMMENT '特级合作商人数',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='团队成员数量表';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_member_trade_record`;
|
||||||
|
CREATE TABLE `dms_member_trade_record` (
|
||||||
|
`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||||
|
`member_id` bigint(20) DEFAULT NULL COMMENT '会员id',
|
||||||
|
`item_type` int(3) NULL DEFAULT NULL COMMENT '项目类型',
|
||||||
|
`type` int(1) NULL DEFAULT NULL COMMENT '收支类型:0->收入;1->支出',
|
||||||
|
`value` decimal(10,2) DEFAULT NULL COMMENT '值',
|
||||||
|
`title` VARCHAR(100) NULL DEFAULT NULL COMMENT '交易标题',
|
||||||
|
`note` VARCHAR(255) NULL DEFAULT NULL COMMENT '备注',
|
||||||
|
`customer_id` bigint(20) DEFAULT NULL COMMENT '消费者Id',
|
||||||
|
`order_id` bigint(20) DEFAULT NULL COMMENT '订单id',
|
||||||
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='会员账户交易记录表';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_member_freeze_account_record`;
|
||||||
|
CREATE TABLE `dms_member_freeze_account_record` (
|
||||||
|
`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||||
|
`member_id` bigint(20) DEFAULT NULL COMMENT '会员id',
|
||||||
|
`item_type` int(3) NULL DEFAULT NULL COMMENT '项目类型',
|
||||||
|
`type` int(1) NULL DEFAULT NULL COMMENT '收支类型:0->收入;1->支出',
|
||||||
|
`value` decimal(10,2) DEFAULT NULL COMMENT '值',
|
||||||
|
`title` VARCHAR(100) NULL DEFAULT NULL COMMENT '交易标题',
|
||||||
|
`note` VARCHAR(255) NULL DEFAULT NULL COMMENT '备注',
|
||||||
|
`customer_id` bigint(20) DEFAULT NULL COMMENT '消费者Id',
|
||||||
|
`order_id` bigint(20) DEFAULT NULL COMMENT '订单id',
|
||||||
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='会员冻结账户记录表';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_platform_income`;
|
||||||
|
CREATE TABLE `dms_platform_income` (
|
||||||
|
`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||||
|
`order_id` bigint(20) DEFAULT NULL COMMENT '订单id',
|
||||||
|
`customer_id` bigint(20) DEFAULT NULL COMMENT '消费者Id',
|
||||||
|
`value` decimal(10,2) DEFAULT NULL COMMENT '值',
|
||||||
|
`note` VARCHAR(255) NULL DEFAULT NULL COMMENT '备注',
|
||||||
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='平台收入表';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_member_transfer_record`;
|
||||||
|
CREATE TABLE `dms_member_transfer_record` (
|
||||||
|
`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||||
|
`member_id` bigint(20) DEFAULT NULL COMMENT '转账会员id',
|
||||||
|
`member_nickname` VARCHAR(255) DEFAULT NULL COMMENT '转账会员昵称',
|
||||||
|
`receiver_id` bigint(20) DEFAULT NULL COMMENT '接收会员Id',
|
||||||
|
`receiver_nickname` VARCHAR(255) DEFAULT NULL COMMENT '接收会员昵称',
|
||||||
|
`receiver_phone` VARCHAR(64) DEFAULT NULL COMMENT '接收会员手机号',
|
||||||
|
`value` decimal(10,2) DEFAULT NULL COMMENT '值',
|
||||||
|
`note` VARCHAR(255) DEFAULT NULL COMMENT '备注',
|
||||||
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='会员转账记录表';
|
||||||
|
|
||||||
|
DROP TABLE IF EXISTS `dms_member_month_reward_record`;
|
||||||
|
CREATE TABLE `dms_member_month_reward_record` (
|
||||||
|
`id` bigint(10) NOT NULL AUTO_INCREMENT COMMENT '主键Id',
|
||||||
|
`member_id` bigint(20) DEFAULT NULL COMMENT '会员id',
|
||||||
|
`value` decimal(10,2) DEFAULT NULL COMMENT '值',
|
||||||
|
`year` int(4) NULL DEFAULT NULL COMMENT '年份',
|
||||||
|
`month` int(2) NULL DEFAULT NULL COMMENT '月份',
|
||||||
|
`create_time` datetime DEFAULT NULL COMMENT '创建时间',
|
||||||
|
PRIMARY KEY (`id`)
|
||||||
|
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='会员月度奖励发放记录表';
|
||||||
|
|
||||||
|
|
||||||
|
alter table `ums_member` add column `member_level` int(1) null COMMENT '分销会员等级(0->普通会员;1->消费商;2->经销商;3->合作商;4->初级合作商;5->中级合作商;6->高级合作商;7->特级合作商))' default '0' AFTER `member_level_id`;
|
||||||
|
alter table `ums_member` add column `store_status` int(1) null COMMENT '分销实体店状态(0->未开店;1->已开店)' default '0';
|
||||||
|
alter table `ums_member` add column `balance` decimal(10,2) null COMMENT '余额' default '0.00';
|
||||||
|
alter table `ums_member` add column `freeze` decimal(10,2) null COMMENT '冻结余额' default '0.00';
|
||||||
|
|
||||||
|
alter table `oms_order` add column settlement_status int(1) null COMMENT '分销结算状态(0->未结算;1->已结算;2->不结算)' default '0';
|
||||||
|
alter table `oms_order` add column settlement_time datetime null COMMENT '分销结算时间';
|
||||||
|
|
||||||
|
alter table `dms_member_withdraw_apply` add column `withdraw_type` int(1) null COMMENT '提现方式(0: 支付宝; 1: 微信; 2: 银行卡)' default null AFTER `open_bank_address`;
|
||||||
|
alter table `dms_member_withdraw_apply` add column `real_name` varchar(100) null COMMENT '真实姓名' default null AFTER `open_bank_address`;
|
||||||
|
alter table `dms_member_withdraw_apply` add column `alipay_account` varchar(100) null COMMENT '支付宝账号' default null AFTER `real_name`;
|
||||||
|
alter table `dms_member_withdraw_apply` add column `wechat_account` varchar(100) null COMMENT '微信账号' default null AFTER `alipay_account`;
|
||||||
|
alter table `dms_member_withdraw_apply` add column `wechat_nickname` varchar(100) null COMMENT '微信昵称' default null AFTER `wechat_account`;
|
||||||
|
|
||||||
|
alter table `ums_member` add column `detail_address` varchar(1000) null COMMENT '详细地址' default null;
|
||||||
|
alter table `ums_member` add column `real_name` varchar(100) null COMMENT '真实姓名' default null;
|
||||||
|
|
||||||
|
alter table `pms_product` add column `distribution_flag` int(1) null COMMENT '分销标志(0->不参与;1->参与)' default 1;
|
||||||
|
|
||||||
1206
document/sql/mall_structure.sql
Normal file
BIN
document/渝森蓉交接文档.docx
Normal file
BIN
keystore.p12
Normal file
124
mall-admin/pom.xml
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<groupId>com.buy507.mall</groupId>
|
||||||
|
<artifactId>mall-admin</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>mall-admin</name>
|
||||||
|
<description>mall-admin project for mall</description>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
|
<java.version>1.8</java.version>
|
||||||
|
<skipTests>true</skipTests>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.buy507.mall</groupId>
|
||||||
|
<artifactId>mall</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.buy507.mall</groupId>
|
||||||
|
<artifactId>mall-dao</artifactId>
|
||||||
|
<version>1.0-SNAPSHOT</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-security</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!--JWT(Json Web Token)登录支持-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>io.jsonwebtoken</groupId>
|
||||||
|
<artifactId>jjwt</artifactId>
|
||||||
|
<version>0.9.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!--redis依赖配置-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!--集成消息队列-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-amqp</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- 阿里云OSS -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.aliyun.oss</groupId>
|
||||||
|
<artifactId>aliyun-sdk-oss</artifactId>
|
||||||
|
<version>2.5.0</version>
|
||||||
|
</dependency>
|
||||||
|
<!--集成logstash-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>net.logstash.logback</groupId>
|
||||||
|
<artifactId>logstash-logback-encoder</artifactId>
|
||||||
|
<version>4.8</version>
|
||||||
|
</dependency>
|
||||||
|
<!--lombok依赖-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
<optional>true</optional>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!-- poi excel -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi</artifactId>
|
||||||
|
<version>3.17</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.poi</groupId>
|
||||||
|
<artifactId>poi-ooxml</artifactId>
|
||||||
|
<version>3.17</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>commons-io</groupId>
|
||||||
|
<artifactId>commons-io</artifactId>
|
||||||
|
<version>2.4</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
</plugin>
|
||||||
|
<!--<plugin>-->
|
||||||
|
<!--<groupId>com.spotify</groupId>-->
|
||||||
|
<!--<artifactId>docker-maven-plugin</artifactId>-->
|
||||||
|
<!--<version>1.1.0</version>-->
|
||||||
|
<!--<executions>-->
|
||||||
|
<!--<execution>-->
|
||||||
|
<!--<id>build-image</id>-->
|
||||||
|
<!--<phase>package</phase>-->
|
||||||
|
<!--<goals>-->
|
||||||
|
<!--<goal>build</goal>-->
|
||||||
|
<!--</goals>-->
|
||||||
|
<!--</execution>-->
|
||||||
|
<!--</executions>-->
|
||||||
|
<!--<configuration>-->
|
||||||
|
<!--<imageName>mall/${project.artifactId}:${project.version}</imageName>-->
|
||||||
|
<!--<dockerHost>http://39.98.190.128:2375</dockerHost>-->
|
||||||
|
<!--<baseImage>java:8</baseImage>-->
|
||||||
|
<!--<entryPoint>["java", "-jar", "-Dspring.profiles.active=prod","/${project.build.finalName}.jar"]</entryPoint>-->
|
||||||
|
<!--<resources>-->
|
||||||
|
<!--<resource>-->
|
||||||
|
<!--<targetPath>/</targetPath>-->
|
||||||
|
<!--<directory>${project.build.directory}</directory>-->
|
||||||
|
<!--<include>${project.build.finalName}.jar</include>-->
|
||||||
|
<!--</resource>-->
|
||||||
|
<!--</resources>-->
|
||||||
|
<!--</configuration>-->
|
||||||
|
<!--</plugin>-->
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
</project>
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
package com.buy507.mall;
|
||||||
|
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 应用启动入口
|
||||||
|
*/
|
||||||
|
@EnableTransactionManagement
|
||||||
|
@SpringBootApplication
|
||||||
|
public class MallAdminApplication {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(MallAdminApplication.class, args);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
public RestTemplate restTemplate() {
|
||||||
|
return new RestTemplate();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,62 @@
|
|||||||
|
package com.buy507.mall.bo;
|
||||||
|
|
||||||
|
import com.buy507.mall.model.UmsAdmin;
|
||||||
|
import com.buy507.mall.model.UmsPermission;
|
||||||
|
import org.springframework.security.core.GrantedAuthority;
|
||||||
|
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* SpringSecurity需要的用户详情
|
||||||
|
*/
|
||||||
|
public class AdminUserDetails implements UserDetails {
|
||||||
|
private UmsAdmin umsAdmin;
|
||||||
|
private List<UmsPermission> permissionList;
|
||||||
|
public AdminUserDetails(UmsAdmin umsAdmin,List<UmsPermission> permissionList) {
|
||||||
|
this.umsAdmin = umsAdmin;
|
||||||
|
this.permissionList = permissionList;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Collection<? extends GrantedAuthority> getAuthorities() {
|
||||||
|
//返回当前用户的权限
|
||||||
|
return permissionList.stream()
|
||||||
|
.filter(permission -> permission.getValue()!=null)
|
||||||
|
.map(permission ->new SimpleGrantedAuthority(permission.getValue()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getPassword() {
|
||||||
|
return umsAdmin.getPassword();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getUsername() {
|
||||||
|
return umsAdmin.getUsername();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isAccountNonLocked() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCredentialsNonExpired() {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEnabled() {
|
||||||
|
return umsAdmin.getStatus().equals(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
143
mall-admin/src/main/java/com/buy507/mall/bo/WebLog.java
Normal file
@@ -0,0 +1,143 @@
|
|||||||
|
package com.buy507.mall.bo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Controller层的日志封装类
|
||||||
|
*/
|
||||||
|
public class WebLog {
|
||||||
|
/**
|
||||||
|
* 操作描述
|
||||||
|
*/
|
||||||
|
private String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作用户
|
||||||
|
*/
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 操作时间
|
||||||
|
*/
|
||||||
|
private Long startTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 消耗时间
|
||||||
|
*/
|
||||||
|
private Integer spendTime;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根路径
|
||||||
|
*/
|
||||||
|
private String basePath;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URI
|
||||||
|
*/
|
||||||
|
private String uri;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* URL
|
||||||
|
*/
|
||||||
|
private String url;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 请求类型
|
||||||
|
*/
|
||||||
|
private String method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* IP地址
|
||||||
|
*/
|
||||||
|
private String ip;
|
||||||
|
|
||||||
|
private Object parameter;
|
||||||
|
|
||||||
|
private Object result;
|
||||||
|
|
||||||
|
public String getDescription() {
|
||||||
|
return description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setDescription(String description) {
|
||||||
|
this.description = description;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUsername() {
|
||||||
|
return username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUsername(String username) {
|
||||||
|
this.username = username;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Long getStartTime() {
|
||||||
|
return startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setStartTime(Long startTime) {
|
||||||
|
this.startTime = startTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSpendTime() {
|
||||||
|
return spendTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSpendTime(Integer spendTime) {
|
||||||
|
this.spendTime = spendTime;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getBasePath() {
|
||||||
|
return basePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBasePath(String basePath) {
|
||||||
|
this.basePath = basePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUri() {
|
||||||
|
return uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUri(String uri) {
|
||||||
|
this.uri = uri;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getUrl() {
|
||||||
|
return url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUrl(String url) {
|
||||||
|
this.url = url;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getMethod() {
|
||||||
|
return method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setMethod(String method) {
|
||||||
|
this.method = method;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getIp() {
|
||||||
|
return ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setIp(String ip) {
|
||||||
|
this.ip = ip;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getParameter() {
|
||||||
|
return parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParameter(Object parameter) {
|
||||||
|
this.parameter = parameter;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getResult() {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setResult(Object result) {
|
||||||
|
this.result = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
package com.buy507.mall.component;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
|
||||||
|
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.buy507.mall.service.OmsOrderService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动确认收货消息的处理者
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@RabbitListener(queues = "mall.receiving.confirm")
|
||||||
|
public class AutoConfirmReceivingReceiver {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(AutoConfirmReceivingReceiver.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OmsOrderService orderService;
|
||||||
|
|
||||||
|
@RabbitHandler
|
||||||
|
public void handle(Long orderId){
|
||||||
|
LOGGER.info("Confirm receiving receive orderId:{}", orderId);
|
||||||
|
orderService.confirmReceiving(orderId, true);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
package com.buy507.mall.component;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.amqp.AmqpException;
|
||||||
|
import org.springframework.amqp.core.AmqpTemplate;
|
||||||
|
import org.springframework.amqp.core.Message;
|
||||||
|
import org.springframework.amqp.core.MessagePostProcessor;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.buy507.mall.dto.ReceivingQueueEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动确认收货消息的发出者
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class AutoConfirmReceivingSender {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(AutoConfirmReceivingSender.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AmqpTemplate amqpTemplate;
|
||||||
|
|
||||||
|
public void sendMessage(Long orderId, final long delayTimes){
|
||||||
|
//给延迟队列发送消息
|
||||||
|
amqpTemplate.convertAndSend(ReceivingQueueEnum.QUEUE_TTL_RECEIVING_CONFIRM.getExchange(), ReceivingQueueEnum.QUEUE_TTL_RECEIVING_CONFIRM.getRouteKey(), orderId, new MessagePostProcessor() {
|
||||||
|
@Override
|
||||||
|
public Message postProcessMessage(Message message) throws AmqpException {
|
||||||
|
//给消息设置延迟毫秒值
|
||||||
|
message.getMessageProperties().setExpiration(String.valueOf(delayTimes));
|
||||||
|
return message;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
LOGGER.info("Confirm receiving send orderId:{}", orderId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,42 @@
|
|||||||
|
package com.buy507.mall.component;
|
||||||
|
|
||||||
|
import com.buy507.mall.common.api.CommonResult;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.validation.FieldError;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* HibernateValidator错误结果处理切面
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
@Order(2)
|
||||||
|
public class BindingResultAspect {
|
||||||
|
@Pointcut("execution(public * com.buy507.mall.controller.*.*(..))")
|
||||||
|
public void BindingResult() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("BindingResult()")
|
||||||
|
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
|
Object[] args = joinPoint.getArgs();
|
||||||
|
for (Object arg : args) {
|
||||||
|
if (arg instanceof BindingResult) {
|
||||||
|
BindingResult result = (BindingResult) arg;
|
||||||
|
if (result.hasErrors()) {
|
||||||
|
FieldError fieldError = result.getFieldError();
|
||||||
|
if(fieldError!=null){
|
||||||
|
return CommonResult.validateFailed(fieldError.getDefaultMessage());
|
||||||
|
}else{
|
||||||
|
return CommonResult.validateFailed();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return joinPoint.proceed();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,100 @@
|
|||||||
|
package com.buy507.mall.component;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.LinkedBlockingQueue;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import com.buy507.mall.mapper.OmsOrderMapper;
|
||||||
|
import com.buy507.mall.model.OmsOrder;
|
||||||
|
import com.buy507.mall.service.DistributionService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分销冻结账户队列处理类
|
||||||
|
* @author wuming
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class DistributeHandlerQueue implements CommandLineRunner {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(DistributeHandlerQueue.class);
|
||||||
|
|
||||||
|
private static LinkedBlockingQueue<Long> queue = new LinkedBlockingQueue<>();
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private DistributionService distributionService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private ExecutorService executorService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private OmsOrderMapper orderMapper;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void run(String... args) throws Exception {
|
||||||
|
|
||||||
|
executorService.execute(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
while(true) {
|
||||||
|
Long orderId = null;
|
||||||
|
try {
|
||||||
|
LOGGER.info("distribution handler queue size: {}", queue.size());
|
||||||
|
orderId = queue.take();
|
||||||
|
LOGGER.info("distribution handler start: {}", orderId);
|
||||||
|
|
||||||
|
OmsOrder order = orderMapper.selectByPrimaryKey(orderId);
|
||||||
|
|
||||||
|
//1. 分享劳务费和服务劳务费计算
|
||||||
|
distributionService.computeRefereeCharge(order.getMemberId(), order);
|
||||||
|
|
||||||
|
//2. 店补计算
|
||||||
|
distributionService.computeStoreSubsidy(order.getMemberId(), order);
|
||||||
|
|
||||||
|
//3. 上级团队的累计消费信息
|
||||||
|
distributionService.computeTeamTotalConsume(order.getMemberId(), order);
|
||||||
|
|
||||||
|
//4. 团队服务劳务费计算
|
||||||
|
distributionService.computeTeamIncome(order.getMemberId(), order);
|
||||||
|
|
||||||
|
//5. 会员等级计算,根据参数和消费情况计算会员等级
|
||||||
|
distributionService.computMemberLevel(order.getMemberId(), order);
|
||||||
|
|
||||||
|
LOGGER.info("distribution handler end: {}", orderId);
|
||||||
|
LOGGER.info("distribution handler queue size: {}", queue.size());
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.error("distribution handler failed");
|
||||||
|
e.printStackTrace();
|
||||||
|
} catch (Exception e) {
|
||||||
|
if(orderId != null) {
|
||||||
|
LOGGER.error("distribution handler failed: {}", orderId);
|
||||||
|
} else {
|
||||||
|
LOGGER.error("distribution handler failed");
|
||||||
|
}
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 添加订单到分销处理队列中
|
||||||
|
* @param order
|
||||||
|
*/
|
||||||
|
public static void addOrderToQueue(Long orderId) {
|
||||||
|
try {
|
||||||
|
queue.put(orderId);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
LOGGER.error("distribution add order to queue failed: {}", orderId);
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.buy507.mall.component;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.amqp.rabbit.annotation.RabbitHandler;
|
||||||
|
import org.springframework.amqp.rabbit.annotation.RabbitListener;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分销预结算消息的处理者
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
@RabbitListener(queues = "mall.distribute.compute")
|
||||||
|
public class DistributeReceiver {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(DistributeReceiver.class);
|
||||||
|
|
||||||
|
@RabbitHandler
|
||||||
|
public void handle(Long orderId){
|
||||||
|
LOGGER.info("Distribute receive orderId:{}", orderId);
|
||||||
|
DistributeHandlerQueue.addOrderToQueue(orderId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
package com.buy507.mall.component;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.amqp.core.AmqpTemplate;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分销预结算消息的发出者
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class DistributeSender {
|
||||||
|
|
||||||
|
private static Logger LOGGER = LoggerFactory.getLogger(DistributeSender.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private AmqpTemplate amqpTemplate;
|
||||||
|
|
||||||
|
public void sendMessage(Long orderId){
|
||||||
|
amqpTemplate.convertAndSend("mall.distribute.compute", orderId);
|
||||||
|
LOGGER.info("Distribute send orderId:{}", orderId);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,61 @@
|
|||||||
|
package com.buy507.mall.component;
|
||||||
|
|
||||||
|
import com.buy507.mall.util.JwtTokenUtil;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||||
|
import org.springframework.security.core.context.SecurityContextHolder;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetails;
|
||||||
|
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||||
|
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
|
||||||
|
import org.springframework.web.filter.OncePerRequestFilter;
|
||||||
|
|
||||||
|
import javax.servlet.FilterChain;
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* JWT登录授权过滤器
|
||||||
|
*/
|
||||||
|
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private UserDetailsService userDetailsService;
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private JwtTokenUtil jwtTokenUtil;
|
||||||
|
|
||||||
|
@Value("${jwt.tokenHeader}")
|
||||||
|
private String tokenHeader;
|
||||||
|
|
||||||
|
@Value("${jwt.tokenHead}")
|
||||||
|
private String tokenHead;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void doFilterInternal(HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
FilterChain chain) throws ServletException, IOException {
|
||||||
|
String authHeader = request.getHeader(this.tokenHeader);
|
||||||
|
if (authHeader != null && authHeader.startsWith(this.tokenHead)) {
|
||||||
|
String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer "
|
||||||
|
String username = jwtTokenUtil.getUserNameFromToken(authToken);
|
||||||
|
LOGGER.info("checking username:{}", username);
|
||||||
|
if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
|
||||||
|
UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
|
||||||
|
if (jwtTokenUtil.validateToken(authToken, userDetails)) {
|
||||||
|
UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());
|
||||||
|
authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
|
||||||
|
LOGGER.info("authenticated user:{}", username);
|
||||||
|
SecurityContextHolder.getContext().setAuthentication(authentication);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
package com.buy507.mall.component;
|
||||||
|
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.data.redis.core.StringRedisTemplate;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
|
||||||
|
@Component
|
||||||
|
public class RedisLock {
|
||||||
|
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(RedisLock.class);
|
||||||
|
|
||||||
|
@Autowired
|
||||||
|
private StringRedisTemplate stringRedisTemplate;
|
||||||
|
|
||||||
|
public static final int TIMEOUT = 60 * 1000; //超时时间 60s
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 加锁
|
||||||
|
* @param key 唯一标识
|
||||||
|
* @param value 当前时间 + 超时时间 也就是时间戳
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public boolean lock(String key, String value){
|
||||||
|
if(stringRedisTemplate.opsForValue().setIfAbsent(key, value)){//对应setnx命令
|
||||||
|
//可以成功设置,也就是key不存在
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
//判断锁超时 - 防止原来的操作异常,没有运行解锁操作 防止死锁
|
||||||
|
String currentValue = stringRedisTemplate.opsForValue().get(key);
|
||||||
|
//如果锁过期
|
||||||
|
if(!StringUtils.isEmpty(currentValue) && Long.parseLong(currentValue) < System.currentTimeMillis()){//currentValue不为空且小于当前时间
|
||||||
|
//获取上一个锁的时间value
|
||||||
|
String oldValue = stringRedisTemplate.opsForValue().getAndSet(key, value);//对应getset,如果key存在
|
||||||
|
|
||||||
|
//假设两个线程同时进来这里,因为key被占用了,而且锁过期了。获取的值currentValue=A(get取的旧的值肯定是一样的),两个线程的value都是B,key都是K.锁时间已经过期了。
|
||||||
|
//而这里面的getAndSet一次只会一个执行,也就是一个执行之后,上一个的value已经变成了B。只有一个线程获取的上一个值会是A,另一个线程拿到的值是B。
|
||||||
|
if(!StringUtils.isEmpty(oldValue) && oldValue.equals(currentValue) ){
|
||||||
|
//oldValue不为空且oldValue等于currentValue,也就是校验是不是上个对应的商品时间戳,也是防止并发
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 解锁
|
||||||
|
* @param key
|
||||||
|
* @param value
|
||||||
|
*/
|
||||||
|
public void unlock(String key, String value){
|
||||||
|
try {
|
||||||
|
String currentValue = stringRedisTemplate.opsForValue().get(key);
|
||||||
|
if(!StringUtils.isEmpty(currentValue) && currentValue.equals(value) ){
|
||||||
|
stringRedisTemplate.opsForValue().getOperations().delete(key);//删除key
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
LOGGER.error("[Redis distributed lock] failed: {}", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package com.buy507.mall.component;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.buy507.mall.common.api.CommonResult;
|
||||||
|
import org.springframework.security.core.AuthenticationException;
|
||||||
|
import org.springframework.security.web.AuthenticationEntryPoint;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当未登录或者token失效访问接口时,自定义的返回结果
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint {
|
||||||
|
@Override
|
||||||
|
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
response.setContentType("application/json");
|
||||||
|
response.getWriter().println(JSONUtil.parse(CommonResult.unauthorized(authException.getMessage())));
|
||||||
|
response.getWriter().flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
package com.buy507.mall.component;
|
||||||
|
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.buy507.mall.common.api.CommonResult;
|
||||||
|
import org.springframework.security.access.AccessDeniedException;
|
||||||
|
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import javax.servlet.ServletException;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpServletResponse;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 当访问接口没有权限时,自定义的返回结果
|
||||||
|
*/
|
||||||
|
@Component
|
||||||
|
public class RestfulAccessDeniedHandler implements AccessDeniedHandler{
|
||||||
|
@Override
|
||||||
|
public void handle(HttpServletRequest request,
|
||||||
|
HttpServletResponse response,
|
||||||
|
AccessDeniedException e) throws IOException, ServletException {
|
||||||
|
response.setCharacterEncoding("UTF-8");
|
||||||
|
response.setContentType("application/json");
|
||||||
|
response.getWriter().println(JSONUtil.parse(CommonResult.forbidden(e.getMessage())));
|
||||||
|
response.getWriter().flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,123 @@
|
|||||||
|
package com.buy507.mall.component;
|
||||||
|
|
||||||
|
import cn.hutool.core.util.StrUtil;
|
||||||
|
import cn.hutool.core.util.URLUtil;
|
||||||
|
import cn.hutool.json.JSON;
|
||||||
|
import cn.hutool.json.JSONUtil;
|
||||||
|
import com.buy507.mall.bo.WebLog;
|
||||||
|
import io.swagger.annotations.ApiOperation;
|
||||||
|
import net.logstash.logback.marker.Markers;
|
||||||
|
import org.aspectj.lang.JoinPoint;
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.Signature;
|
||||||
|
import org.aspectj.lang.annotation.*;
|
||||||
|
import org.aspectj.lang.reflect.MethodSignature;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
import org.springframework.core.annotation.Order;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestParam;
|
||||||
|
import org.springframework.web.context.request.RequestContextHolder;
|
||||||
|
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||||
|
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.lang.reflect.Parameter;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 统一日志处理切面
|
||||||
|
*/
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
@Order(1)
|
||||||
|
public class WebLogAspect {
|
||||||
|
private static final Logger LOGGER = LoggerFactory.getLogger(WebLogAspect.class);
|
||||||
|
private ThreadLocal<Long> startTime = new ThreadLocal<>();
|
||||||
|
|
||||||
|
@Pointcut("execution(public * com.buy507.mall.controller.*.*(..))")
|
||||||
|
public void webLog() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Before("webLog()")
|
||||||
|
public void doBefore(JoinPoint joinPoint) throws Throwable {
|
||||||
|
startTime.set(System.currentTimeMillis());
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterReturning(value = "webLog()", returning = "ret")
|
||||||
|
public void doAfterReturning(Object ret) throws Throwable {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("webLog()")
|
||||||
|
public Object doAround(ProceedingJoinPoint joinPoint) throws Throwable {
|
||||||
|
//获取当前请求对象
|
||||||
|
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||||
|
HttpServletRequest request = attributes.getRequest();
|
||||||
|
//记录请求信息(通过logstash传入elasticsearch)
|
||||||
|
WebLog webLog = new WebLog();
|
||||||
|
Object result = joinPoint.proceed();
|
||||||
|
Signature signature = joinPoint.getSignature();
|
||||||
|
MethodSignature methodSignature = (MethodSignature) signature;
|
||||||
|
Method method = methodSignature.getMethod();
|
||||||
|
if (method.isAnnotationPresent(ApiOperation.class)) {
|
||||||
|
ApiOperation log = method.getAnnotation(ApiOperation.class);
|
||||||
|
webLog.setDescription(log.value());
|
||||||
|
}
|
||||||
|
long endTime = System.currentTimeMillis();
|
||||||
|
String urlStr = request.getRequestURL().toString();
|
||||||
|
webLog.setBasePath(StrUtil.removeSuffix(urlStr, URLUtil.url(urlStr).getPath()));
|
||||||
|
webLog.setIp(request.getRemoteUser());
|
||||||
|
webLog.setMethod(request.getMethod());
|
||||||
|
webLog.setParameter(getParameter(method, joinPoint.getArgs()));
|
||||||
|
webLog.setResult(result);
|
||||||
|
webLog.setSpendTime((int) (endTime - startTime.get()));
|
||||||
|
webLog.setStartTime(startTime.get());
|
||||||
|
webLog.setUri(request.getRequestURI());
|
||||||
|
webLog.setUrl(request.getRequestURL().toString());
|
||||||
|
Map<String,Object> logMap = new HashMap<>();
|
||||||
|
logMap.put("url",webLog.getUrl());
|
||||||
|
logMap.put("method",webLog.getMethod());
|
||||||
|
logMap.put("parameter",webLog.getParameter());
|
||||||
|
logMap.put("spendTime",webLog.getSpendTime());
|
||||||
|
logMap.put("description",webLog.getDescription());
|
||||||
|
// LOGGER.info("{}", JSONUtil.parse(webLog));
|
||||||
|
LOGGER.info(Markers.appendEntries(logMap), JSONUtil.parse(webLog).toString());
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 根据方法和传入的参数获取请求参数
|
||||||
|
*/
|
||||||
|
private Object getParameter(Method method, Object[] args) {
|
||||||
|
List<Object> argList = new ArrayList<>();
|
||||||
|
Parameter[] parameters = method.getParameters();
|
||||||
|
for (int i = 0; i < parameters.length; i++) {
|
||||||
|
RequestBody requestBody = parameters[i].getAnnotation(RequestBody.class);
|
||||||
|
if (requestBody != null) {
|
||||||
|
argList.add(args[i]);
|
||||||
|
}
|
||||||
|
RequestParam requestParam = parameters[i].getAnnotation(RequestParam.class);
|
||||||
|
if (requestParam != null) {
|
||||||
|
Map<String, Object> map = new HashMap<>();
|
||||||
|
String key = parameters[i].getName();
|
||||||
|
if (!StringUtils.isEmpty(requestParam.value())) {
|
||||||
|
key = requestParam.value();
|
||||||
|
}
|
||||||
|
map.put(key, args[i]);
|
||||||
|
argList.add(map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (argList.size() == 0) {
|
||||||
|
return null;
|
||||||
|
} else if (argList.size() == 1) {
|
||||||
|
return argList.get(0);
|
||||||
|
} else {
|
||||||
|
return argList;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package com.buy507.mall.config;
|
||||||
|
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* MyBatis配置类
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableTransactionManagement
|
||||||
|
@MapperScan({"com.buy507.mall.mapper","com.buy507.mall.dao"})
|
||||||
|
public class MyBatisConfig {
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
package com.buy507.mall.config;
|
||||||
|
|
||||||
|
import com.aliyun.oss.OSSClient;
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 阿里云配置类
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class OssConfig {
|
||||||
|
@Value("${aliyun.oss.endpoint}")
|
||||||
|
private String ALIYUN_OSS_ENDPOINT;
|
||||||
|
@Value("${aliyun.oss.accessKeyId}")
|
||||||
|
private String ALIYUN_OSS_ACCESSKEYID;
|
||||||
|
@Value("${aliyun.oss.accessKeySecret}")
|
||||||
|
private String ALIYUN_OSS_ACCESSKEYSECRET;
|
||||||
|
@Bean
|
||||||
|
public OSSClient ossClient(){
|
||||||
|
return new OSSClient(ALIYUN_OSS_ENDPOINT,ALIYUN_OSS_ACCESSKEYID,ALIYUN_OSS_ACCESSKEYSECRET);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
package com.buy507.mall.config;
|
||||||
|
|
||||||
|
import org.springframework.amqp.core.Queue;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分销结算消息队列配置
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class RabbitMqDistributeConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 分销结算实际消费队列
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue predistributeQueue() {
|
||||||
|
return new Queue("mall.distribute.compute");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
package com.buy507.mall.config;
|
||||||
|
|
||||||
|
import org.springframework.amqp.core.Binding;
|
||||||
|
import org.springframework.amqp.core.BindingBuilder;
|
||||||
|
import org.springframework.amqp.core.DirectExchange;
|
||||||
|
import org.springframework.amqp.core.ExchangeBuilder;
|
||||||
|
import org.springframework.amqp.core.Queue;
|
||||||
|
import org.springframework.amqp.core.QueueBuilder;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import com.buy507.mall.dto.ReceivingQueueEnum;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动确认收货消息队列配置
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class RabbitMqReceivingConfig {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动确认收货消息实际消费队列所绑定的交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
DirectExchange receivingDirect() {
|
||||||
|
return (DirectExchange) ExchangeBuilder
|
||||||
|
.directExchange(ReceivingQueueEnum.QUEUE_RECEIVING_CONFIRM.getExchange())
|
||||||
|
.durable(true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动确认收货延迟队列队列所绑定的交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
DirectExchange receivingTtlDirect() {
|
||||||
|
return (DirectExchange) ExchangeBuilder
|
||||||
|
.directExchange(ReceivingQueueEnum.QUEUE_TTL_RECEIVING_CONFIRM.getExchange())
|
||||||
|
.durable(true)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动确认收货实际消费队列
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue receivingQueue() {
|
||||||
|
return new Queue(ReceivingQueueEnum.QUEUE_RECEIVING_CONFIRM.getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 自动确认收货延迟队列(死信队列)
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
public Queue receivingTtlQueue() {
|
||||||
|
return QueueBuilder
|
||||||
|
.durable(ReceivingQueueEnum.QUEUE_TTL_RECEIVING_CONFIRM.getName())
|
||||||
|
.withArgument("x-dead-letter-exchange", ReceivingQueueEnum.QUEUE_RECEIVING_CONFIRM.getExchange())//到期后转发的交换机
|
||||||
|
.withArgument("x-dead-letter-routing-key", ReceivingQueueEnum.QUEUE_RECEIVING_CONFIRM.getRouteKey())//到期后转发的路由键
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将自动确认收货队列绑定到交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
Binding receivingBinding(DirectExchange receivingDirect, Queue receivingQueue){
|
||||||
|
return BindingBuilder
|
||||||
|
.bind(receivingQueue)
|
||||||
|
.to(receivingDirect)
|
||||||
|
.with(ReceivingQueueEnum.QUEUE_RECEIVING_CONFIRM.getRouteKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将自动确认收货延迟队列绑定到交换机
|
||||||
|
*/
|
||||||
|
@Bean
|
||||||
|
Binding receivingTtlBinding(DirectExchange receivingTtlDirect, Queue receivingTtlQueue){
|
||||||
|
return BindingBuilder
|
||||||
|
.bind(receivingTtlQueue)
|
||||||
|
.to(receivingTtlDirect)
|
||||||
|
.with(ReceivingQueueEnum.QUEUE_TTL_RECEIVING_CONFIRM.getRouteKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||