由于尚硅谷的视频是通过Eclipse软件来做的,其中有些操作与IDEA上有所区别,所以我在这里将IDEA区别于Eclipse的操作、操作过程中涉及的源码(与视频的源码略有出入)以及大家可能遇到的种种问题分享给大家,这些源码在我这里均是通过测试的,仅供参考!
1 模块配置
1.1 Pom配置
修改member-parent\atcrowdfunding14-member-order-consumer\pom.xml
<dependencies>
<dependency>
<groupId>com.atguigu.crowd</groupId>
<artifactId>atcrowdfunding17-member-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<!-- 引入springboot&redis整合场景 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- 引入springboot&springsession整合场景 -->
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-data-redis</artifactId>
</dependency>
</dependencies>
1.2 主启动类&Application
新建order-consumer\src\main\java\com\atguigu\crowd\CrowdMainClass.java
package com.atguigu.crowd;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.EnableFeignClients;
@EnableFeignClients
@EnableEurekaClient
@SpringBootApplication
public class CrowdMainClass {
public static void main(String[] args) {
SpringApplication.run(CrowdMainClass.class, args);
}
}
新建order-consumer\src\main\resources\application.yml
server:
port: 6000
spring:
application:
name: atguigu-crowd-order
thymeleaf:
prefix: classpath:/templates/
suffix: .html
redis:
host: 127.0.0.1
session:
store-type: redis
eureka:
client:
service-url:
defaultZone: http://localhost:1000/eureka
1.3 Zuul路由规则修改
修改member-zuul\src\main\resources\application.yml
zuul:
ignored-services: "*"
sensitive-headers: "*" # 在Zuul向其他微服务重定向时保持原本头信息(请求头、响应头)
routes:
crowd-portal:
service-id: atguigu-crowd-auth
path: /** # 这里一定要使用两个“*”号,不然“/”路径后面的多层路径将无法访问
crowd-project:
service-id: atguigu-crowd-project
path: /project/** # 这里一定要使用两个“*”号,不然“/”路径后面的多层路径将无法访问
crowd-order:
service-id: atguigu-crowd-order
path: /order/**
2 创建数据库表
CREATE TABLE `project_crowd`.`t_order`
(
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
`order_num` CHAR(100) COMMENT '订单号',
`pay_order_num` CHAR(100) COMMENT '支付宝流水号',
`order_amount` DOUBLE(10,5) COMMENT '订单金额',
`invoice` INT COMMENT '是否开发票(0 不开, 1 开) ',
`invoice_title` CHAR(100) COMMENT '发票抬头',
`order_remark` CHAR(100) COMMENT '订单备注',
`address_id` CHAR(100) COMMENT '收货地址 id',
PRIMARY KEY (`id`)
);
CREATE TABLE `project_crowd`.`t_address`
(
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
`receive_name` CHAR(100) COMMENT '收件人',
`phone_num` CHAR(100) COMMENT '手机号',
`address` CHAR(200) COMMENT '收货地址',
`member_id` INT COMMENT '用户 id',
PRIMARY KEY (`id`)
);
CREATE TABLE `project_crowd`.`t_order_project`
(
`id` INT NOT NULL AUTO_INCREMENT COMMENT '主键',
`project_name` CHAR(200) COMMENT '项目名称',
`launch_name` CHAR(100) COMMENT '发起人',
`return_content` CHAR(200) COMMENT '回报内容',
`return_count` INT COMMENT '回报数量',
`support_price` INT COMMENT '支持单价',
`freight` INT COMMENT '配送费用',
`order_id` INT COMMENT '订单表的主键',
PRIMARY KEY (`id`)
);
3 MyBatis逆向工程
修改common-reverse\src\main\resources\generatorConfig.xml
<table tableName="t_order" domainObjectName="OrderPO" />
<table tableName="t_address" domainObjectName="AddressPO" />
<table tableName="t_order_project" domainObjectName="OrderProjectPO" />
在IDEA右侧的maven project找到mybatis-generator:generate并点击运行,生成文件
将结尾为PO.java和POExample.java的文件放入member-entity\src\main\java\com\atguigu\crowd\entity\po中
将结尾为Mapper.java的文件放入member-mysql-provider\src\main\java\com\atguigu\crowd\mapper中
将结尾为Mapper.xml放入member-mysql-provider\src\main\java\com\atguigu\crowd\mapper中
4 订单网页
4.1 前端部分
修改project-consumer\src\main\resources\templates\project-show-detail.html
<a th:href="'http://www.crowd.com/order/confirm/return/info/'+${detailProjectVO.projectId}+'/'+${return.returnId}"
class="btn btn-warning btn-lg">支持</a>
新建order-consumer\src\main\resources\templates\confirm-return.html
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<base th:href="@{/}"/>
<link rel="stylesheet" href="bootstrap/css/bootstrap.css">
<link rel="stylesheet" href="css/font-awesome.min.css">
<link rel="stylesheet" href="css/theme.css">
<script src="jquery/jquery-3.6.0.js"></script>
<script src="bootstrap/js/bootstrap.js"></script>
<script src="script/docs.min.js"></script>
<script src="script/back-to-top.js"></script>
<style>
#footer {
padding: 15px 0;
background: #fff;
border-top: 1px solid #ddd;
text-align: center;
}
#topcontrol {
color: #fff;
z-index: 99;
width: 30px;
height: 30px;
font-size: 20px;
background: #222;
position: relative;
right: 14px !important;
bottom: 11px !important;
border-radius: 3px !important;
}
#topcontrol:after {
/*top: -2px;*/
left: 8.5px;
content: "\f106";
position: absolute;
text-align: center;
font-family: FontAwesome;
}
#topcontrol:hover {
color: #fff;
background: #18ba9b;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
.label-type, .label-status, .label-order {
background-color: #fff;
color: #f60;
padding: 5px;
border: 1px #f60 solid;
}
#typeList :not (:first-child ) {
margin-top: 20px;
}
.label-txt {
margin: 10px 10px;
border: 1px solid #ddd;
padding: 4px;
font-size: 14px;
}
.panel {
border-radius: 0;
}
.progress-bar-default {
background-color: #ddd;
}
</style>
</head>
<body>
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="index.html" style="font-size: 32px;">尚筹网-创意产品众筹平台</a>
</div>
<div id="navbar" class="navbar-collapse collapse"
style="float: right;">
<ul class="nav navbar-nav">
<li class="dropdown"><a href="#" class="dropdown-toggle"
data-toggle="dropdown"><i class="glyphicon glyphicon-user"></i>
[[${session.loginMember.username}]]<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="member.html"><i
class="glyphicon glyphicon-scale"></i> 会员中心</a></li>
<li><a href="#"><i class="glyphicon glyphicon-comment"></i>
消息</a></li>
<li class="divider"></li>
<li><a href="http://www.crowd.com/auth/member/logout"><i
class="glyphicon glyphicon-off"></i> 退出系统</a></li>
</ul></li>
</ul>
</div>
</div>
</nav>
</div>
</div>
<div class="container theme-showcase" role="main">
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="panel panel-default">
<div class="panel-heading" style="text-align: center;">
<div class="container-fluid">
<div class="row clearfix">
<div class="col-md-3 column">
<div class="progress"
style="height: 50px; border-radius: 0; position: absolute; width: 75%; right: 49px;">
<div class="progress-bar progress-bar-success"
role="progressbar" aria-valuenow="60" aria-valuemin="0"
aria-valuemax="100" style="width: 100%; height: 50px;">
<div style="font-size: 16px; margin-top: 15px;">1.
确认回报内容</div>
</div>
</div>
<div
style="right: 0; border: 10px solid #ddd; border-left-color: #88b7d5; border-width: 25px; position: absolute; border-left-color: rgba(92, 184, 92, 1); border-top-color: rgba(92, 184, 92, 0); border-bottom-color: rgba(92, 184, 92, 0); border-right-color: rgba(92, 184, 92, 0);">
</div>
</div>
<div class="col-md-3 column">
<div class="progress"
style="height: 50px; border-radius: 0; position: absolute; width: 75%; right: 49px;">
<div class="progress-bar progress-bar-default"
role="progressbar" aria-valuenow="60" aria-valuemin="0"
aria-valuemax="100" style="width: 100%; height: 50px;">
<div style="font-size: 16px; margin-top: 15px;">2.
确认订单</div>
</div>
</div>
<div
style="right: 0; border: 10px solid #ddd; border-left-color: #88b7d5; border-width: 25px; position: absolute; border-left-color: rgba(221, 221, 221, 1); border-top-color: rgba(221, 221, 221, 0); border-bottom-color: rgba(221, 221, 221, 0); border-right-color: rgba(221, 221, 221, 0);">
</div>
</div>
<div class="col-md-3 column">
<div class="progress"
style="height: 50px; border-radius: 0; position: absolute; width: 75%; right: 49px;">
<div class="progress-bar progress-bar-default"
role="progressbar" aria-valuenow="60" aria-valuemin="0"
aria-valuemax="100" style="width: 100%; height: 50px;">
<div style="font-size: 16px; margin-top: 15px;">3. 付款</div>
</div>
</div>
<div
style="right: 0; border: 10px solid #ddd; border-left-color: #88b7d5; border-width: 25px; position: absolute; border-left-color: rgba(221, 221, 221, 1); border-top-color: rgba(221, 221, 221, 0); border-bottom-color: rgba(221, 221, 221, 0); border-right-color: rgba(221, 221, 221, 0);">
</div>
</div>
<div class="col-md-3 column">
<div class="progress" style="height: 50px; border-radius: 0;">
<div class="progress-bar progress-bar-default"
role="progressbar" aria-valuenow="60" aria-valuemin="0"
aria-valuemax="100" style="width: 100%; height: 50px;">
<div style="font-size: 16px; margin-top: 15px;">4. 完成</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="panel-body">
<div class="container-fluid">
<div class="row clearfix">
<div class="col-md-12 column">
<blockquote
style="border-left: 5px solid #f60; color: #f60; padding: 0 0 0 20px;">
<b> 请确认您所选择的回报项信息和购买数量 </b>
</blockquote>
</div>
<div class="col-md-12 column">
<table class="table table-bordered"
style="text-align: center;">
<thead>
<tr style="background-color: #ddd;">
<td>项目名称</td>
<td>发起人</td>
<td width="300">回报内容</td>
<td width="80">回报数量</td>
<td>支持单价</td>
<td>配送费用</td>
</tr>
</thead>
<tbody>
<tr>
<td th:text="${session.orderProjectVO.projectName}">活性富氢净水直饮机</td>
<td th:text="${session.orderProjectVO.launchName}">深圳市博实永道电子商务有限公司</td>
<td th:text="${session.orderProjectVO.returnContent}">每满1750人抽取一台活性富氢净水直饮机,至少抽取一台。抽取名额(小数点后一位四舍五入)=参与人数÷1750人,由苏宁官方抽取。</td>
<td><input id="returnCountInput" type="text" class="form-control"
style="width: 60px;" th:value="${session.orderProjectVO.returnCount}"></td>
<td style="color: #F60" th:text="${session.orderProjectVO.supportPrice}">¥ 1.00</td>
<td th:if="${session.orderProjectVO.freight == 0}">免运费</td>
<td th:if="${session.orderProjectVO.freight != 0}" th:text="${session.orderProjectVO.freight}">免运费</td>
</tr>
</tbody>
</table>
<div style="float: right;">
<p>
总价(含运费):<span id="totalAmount" style="font-size: 16px; color: #F60;">¥[[${session.orderProjectVO.returnCount*session.orderProjectVO.supportPrice}]]</span>
</p>
<button id="submitBtn" type="button" class="btn btn-warning btn-lg"
style="float: right;">
<i class="glyphicon glyphicon-credit-card"></i> 去结算
</button>
</div>
</div>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<blockquote>
<p>
<i class="glyphicon glyphicon-info-sign"
style="color: #2a6496;"></i> 提示
</p>
<br> <span style="font-size: 12px;">1.众筹并非商品交易,存在一定风险。支持者根据自己的判断选择、支持众筹项目,与发起人共同实现梦想并获得发起人承诺的回报。<br>
2.众筹平台仅提供平台网络空间及技术支持等中介服务,众筹仅存在于发起人和支持者之间,使用众筹平台产生的法律后果由发起人与支持者自行承担。<br>
3.本项目必须在2017-06-04之前达到 ¥1000000.00
的目标才算成功,否则已经支持的订单将取消。订单取消或募集失败的,您支持的金额将原支付路径退回。<br>
4.请在支持项目后15分钟内付款,否则您的支持请求会被自动关闭。<br>
5.众筹成功后由发起人统一进行发货,售后服务由发起人统一提供;如果发生发起人无法发放回报、延迟发放回报、不提供回报后续服务等情况,您需要直接和发起人协商解决。<br>
6.如您不同意上述风险提示内容,您有权选择不支持;一旦选择支持,视为您已确认并同意以上提示内容。
</span>
</blockquote>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container" style="margin-top: 20px;">
<div class="row clearfix">
<div class="col-md-12 column">
<div id="footer">
<div class="footerNav">
<a rel="nofollow" href="http://www.atguigu.com">关于我们</a> | <a
rel="nofollow" href="http://www.atguigu.com">服务条款</a> | <a
rel="nofollow" href="http://www.atguigu.com">免责声明</a> | <a
rel="nofollow" href="http://www.atguigu.com">网站地图</a> | <a
rel="nofollow" href="http://www.atguigu.com">联系我们</a>
</div>
<div class="copyRight">Copyright ?2010-2014atguigu.com 版权所有
</div>
</div>
</div>
</div>
</div>
</div>
<script>
var signalPurchase = [[${session.orderProjectVO.signalPurchase}]];
var purchase = [[${session.orderProjectVO.purchase}]];
$('#myTab a').click(function(e) {
e.preventDefault()
$(this).tab('show')
});
$("#returnCountInput").change(function(){
var returnCount = $.trim($(this).val());
if(returnCount == null || returnCount == "") {
alert("请输入有效数据!");
$(this).val(this.defaultValue);
return ;
}
if(signalPurchase == 1 && returnCount > purchase) {
alert("不能超过限购数量!");
return ;
}
var supportPrice = [[${session.orderProjectVO.supportPrice}]];
$("#totalAmount").text("¥"+(supportPrice * returnCount));
});
$("#submitBtn").click(function(){
var returnCount = $("#returnCountInput").val();
window.location.href = "order/confirm/order/"+returnCount;
});
</script>
</body>
</html>
4.2 后端部分
新建member-entity\src\main\java\com\atguigu\crowd\entity\vo\OrderProjectVO.java
package com.atguigu.crowd.entity.vo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.io.Serializable;
@Data
@AllArgsConstructor
@NoArgsConstructor
public class OrderProjectVO implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String projectName;
private String launchName;
private String returnContent;
private Integer returnCount;
private Integer supportPrice;
private Integer freight;
private Integer orderId;
private Integer signalPurchase;
private Integer purchase;
}
新建order-consumer\src\main\java\com\atguigu\crowd\handler\OrderHandler.java
package com.atguigu.crowd.handler;
import com.atguigu.crowd.api.MySQLRemoteService;
import com.atguigu.crowd.entity.vo.OrderProjectVO;
import com.atguigu.crowd.util.ResultEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpSession;
@Controller
public class OrderHandler {
@Autowired
private MySQLRemoteService mySQLRemoteService;
@RequestMapping("/confirm/return/info/{projectId}/{returnId}")
public String showReturnConfirmInfo(
@PathVariable("projectId") Integer projectId,
@PathVariable("returnId") Integer returnId,
HttpSession session) {
ResultEntity<OrderProjectVO> resultEntity =
mySQLRemoteService.getOrderProjectVORemote(projectId, returnId);
if(ResultEntity.SUCCESS.equals(resultEntity.getResult())) {
OrderProjectVO orderProjectVO = resultEntity.getData();
// 为了能够在后续操作中保持orderProjectVO数据,存入Session域
session.setAttribute("orderProjectVO", orderProjectVO);
}
return "confirm_return";
}
}
新建mysql-provider\src\main\java\com\atguigu\crowd\handler\OrderProviderHandler.java
package com.atguigu.crowd.handler;
import com.atguigu.crowd.entity.vo.OrderProjectVO;
import com.atguigu.crowd.util.ResultEntity;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class OrderProviderHandler {
@Autowired
private OrderService orderService;
@RequestMapping("/get/order/project/vo/remote")
ResultEntity<OrderProjectVO> getOrderProjectVORemote(
@RequestParam("projectId") Integer projectId,
@RequestParam("returnId") Integer returnId) {
try {
OrderProjectVO orderProjectVO = orderService.getOrderProjectVO(projectId, returnId);
return ResultEntity.successWithData(orderProjectVO);
} catch (Exception e) {
e.printStackTrace();
return ResultEntity.failed(e.getMessage());
}
}
}
修改member-api\src\main\java\com\atguigu\crowd\api\MySQLRemoteService.java
@RequestMapping("/get/order/project/vo/remote")
ResultEntity<OrderProjectVO> getOrderProjectVORemote(@RequestParam("projectId") Integer projectId, @RequestParam("returnId") Integer returnId);
并新建getOrderProjectVO()方法及实现类:
新建mysql-provider\src\main\java\com\atguigu\crowd\service\api\OrderService.java
package com.atguigu.crowd.service.api;
import com.atguigu.crowd.entity.vo.OrderProjectVO;
public interface OrderService {
OrderProjectVO getOrderProjectVO(Integer projectId, Integer returnId);
}
新建mysql-provider\src\main\java\com\atguigu\crowd\service\impl\OrderServiceImpl.java
package com.atguigu.crowd.service.impl;
import com.atguigu.crowd.entity.vo.OrderProjectVO;
import com.atguigu.crowd.mapper.OrderProjectPOMapper;
import com.atguigu.crowd.service.api.OrderService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class OrderServiceImpl implements OrderService {
@Autowired
private OrderProjectPOMapper orderProjectPOMapper;
@Override
public OrderProjectVO getOrderProjectVO(Integer projectId, Integer returnId) {
return orderProjectPOMapper.selectOrderProjectVO(returnId);
}
}
并新建selectOrderProjectVO()方法及mapper接口:
修改mysql-provider\src\main\java\com\atguigu\crowd\mapper\OrderProjectPOMapper.java
OrderProjectVO selectOrderProjectVO(Integer returnId);
修改mysql-provider\src\main\resources\mybatis\mapper\OrderProjectPOMapper.xml
<select id="selectOrderProjectVO" resultType="com.atguigu.crowd.entity.vo.OrderProjectVO">
SELECT DISTINCT
t_project.`project_name` projectName,
t_return.`content` returnContent,
t_member_launch_info.`description_simple` launchName,
t_return.`supportmoney` supportPrice,
t_return.`freight` freight,
t_return.`count` returnCount,
t_return.`signalpurchase` signalPurchase,
t_return.`purchase` purchase
FROM t_project
LEFT JOIN t_member_launch_info ON t_project.memberid=t_member_launch_info.memberid
LEFT JOIN t_return ON t_project.id=t_return.projectid
WHERE t_return.id=#{returnId}
</select>
4.3 测试
在项目详情中点击支持:
修改回报数量,会显示:
如果输入非数字,会显示:
5 确认订单
5.1 后端部分
新建member-entity\src\main\java\com\atguigu\crowd\entity\vo\AddressVO.java
@Data
@NoArgsConstructor
@AllArgsConstructor
public class AddressVO implements Serializable {
private static final long serialVersionUID = 1L;
private Integer id;
private String receiveName;
private String phoneNum;
private String address;
private Integer memberId;
}
修改order-consumer\src\main\java\com\atguigu\crowd\handler\OrderHandler.java
@RequestMapping("/confirm/order/{returnCount}")
public String showConfirmOrderInfo(
@PathVariable("returnCount") Integer returnCount,
HttpSession session) {
// 1.把接收到的回报数量合并到Session域
OrderProjectVO orderProjectVO = (OrderProjectVO) session.getAttribute("orderProjectVO");
orderProjectVO.setReturnCount(returnCount);
session.setAttribute("orderProjectVO", orderProjectVO);
// 2.获取当前已登录用户的id
MemberLoginVO memberLoginVO = (MemberLoginVO) session.getAttribute(CrowdConstant.ATTR_NAME_LOGIN_MEMBER);
Integer memberId = memberLoginVO.getId();
// 3.查询目前的收货地址数据
ResultEntity<List<AddressVO>> resultEntity = mySQLRemoteService.getAddressVORemote(memberId);
if(ResultEntity.SUCCESS.equals(resultEntity.getResult())) {
List<AddressVO> list = resultEntity.getData();
session.setAttribute("addressVOList", list);
}
return "confirm_order";
}
并新建getAddressVORemote()远程调用接口:
修改api\src\main\java\com\atguigu\crowd\api\MySQLRemoteService.java
@RequestMapping("/get/address/vo/remote")
ResultEntity<List<AddressVO>> getAddressVORemote(@RequestParam("memberId") Integer memberId);
修改mysql-provider\src\main\java\com\atguigu\crowd\handler\OrderProviderHandler.java
@RequestMapping("/get/address/vo/remote")
ResultEntity<List<AddressVO>> getAddressVORemote(@RequestParam("memberId") Integer memberId) {
try {
List<AddressVO> addressVOList = orderService.getAddressVOList(memberId);
return ResultEntity.successWithData(addressVOList);
} catch (Exception e) {
e.printStackTrace();
return ResultEntity.failed(e.getMessage());
}
}
并新建getAddressVOList()方法及实现类:
修改mysql-provider\src\main\java\com\atguigu\crowd\service\impl\OrderServiceImpl.java
@Autowired
private AddressPOMapper addressPOMapper;
@Override
public List<AddressVO> getAddressVOList(Integer memberId) {
AddressPOExample example = new AddressPOExample();
example.createCriteria().andMemberIdEqualTo(memberId);
List<AddressPO> addressPOList = addressPOMapper.selectByExample(example);
List<AddressVO> addressVOList = new ArrayList<AddressVO>();
for (AddressPO addressPO : addressPOList) {
AddressVO addressVO = new AddressVO();
BeanUtils.copyProperties(addressPO, addressVO);
addressVOList.add(addressVO);
}
return addressVOList;
}
5.2 前端部分
新建order-consumer\src\main\resources\templates\confirm_order.html
<!DOCTYPE html>
<html lang="zh-CN" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<base th:href="@{/}" />
<link rel="stylesheet" href="bootstrap/css/bootstrap.css">
<link rel="stylesheet" href="css/font-awesome.min.css">
<link rel="stylesheet" href="css/theme.css">
<script src="jquery/jquery-3.6.0.js"></script>
<script src="bootstrap/js/bootstrap.js"></script>
<script src="script/docs.min.js"></script>
<script src="script/back-to-top.js"></script>
<style>
#footer {
padding: 15px 0;
background: #fff;
border-top: 1px solid #ddd;
text-align: center;
}
#topcontrol {
color: #fff;
z-index: 99;
width: 30px;
height: 30px;
font-size: 20px;
background: #222;
position: relative;
right: 14px !important;
bottom: 11px !important;
border-radius: 3px !important;
}
#topcontrol:after {
/*top: -2px;*/
left: 8.5px;
content: "\f106";
position: absolute;
text-align: center;
font-family: FontAwesome;
}
#topcontrol:hover {
color: #fff;
background: #18ba9b;
-webkit-transition: all 0.3s ease-in-out;
-moz-transition: all 0.3s ease-in-out;
-o-transition: all 0.3s ease-in-out;
transition: all 0.3s ease-in-out;
}
.label-type, .label-status, .label-order {
background-color: #fff;
color: #f60;
padding: 5px;
border: 1px #f60 solid;
}
#typeList :not (:first-child ) {
margin-top: 20px;
}
.label-txt {
margin: 10px 10px;
border: 1px solid #ddd;
padding: 4px;
font-size: 14px;
}
.panel {
border-radius: 0;
}
.progress-bar-default {
background-color: #ddd;
}
</style>
</head>
<body>
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-fixed-top" role="navigation">
<div class="container">
<div class="navbar-header">
<a class="navbar-brand" href="index.html" style="font-size: 32px;">尚筹网-创意产品众筹平台</a>
</div>
<div id="navbar" class="navbar-collapse collapse"
style="float: right;">
<ul class="nav navbar-nav">
<li class="dropdown"><a href="#" class="dropdown-toggle"
data-toggle="dropdown"><i class="glyphicon glyphicon-user"></i>
[[${session.loginMember.username}]]<span class="caret"></span></a>
<ul class="dropdown-menu" role="menu">
<li><a href="member.html"><i
class="glyphicon glyphicon-scale"></i> 会员中心</a></li>
<li><a href="#"><i class="glyphicon glyphicon-comment"></i>
消息</a></li>
<li class="divider"></li>
<li><a href="http://www.crowd.com/auth/member/logout"><i
class="glyphicon glyphicon-off"></i> 退出系统</a></li>
</ul></li>
</ul>
</div>
</div>
</nav>
</div>
</div>
<div class="container theme-showcase" role="main">
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="panel panel-default">
<div class="panel-heading" style="text-align: center;">
<div class="container-fluid">
<div class="row clearfix">
<div class="col-md-3 column">
<div class="progress"
style="height: 50px; border-radius: 0; position: absolute; width: 75%; right: 49px;">
<div class="progress-bar progress-bar-default"
role="progressbar" aria-valuenow="60" aria-valuemin="0"
aria-valuemax="100" style="width: 100%; height: 50px;">
<div style="font-size: 16px; margin-top: 15px;">1.
确认回报内容</div>
</div>
</div>
<div
style="right: 0; border: 10px solid #ddd; border-left-color: #88b7d5; border-width: 25px; position: absolute; border-left-color: rgba(221, 221, 221, 1); border-top-color: rgba(221, 221, 221, 0); border-bottom-color: rgba(221, 221, 221, 0); border-right-color: rgba(221, 221, 221, 0);">
</div>
</div>
<div class="col-md-3 column">
<div class="progress"
style="height: 50px; border-radius: 0; position: absolute; width: 75%; right: 49px;">
<div class="progress-bar progress-bar-success"
role="progressbar" aria-valuenow="60" aria-valuemin="0"
aria-valuemax="100" style="width: 100%; height: 50px;">
<div style="font-size: 16px; margin-top: 15px;">2.
确认订单</div>
</div>
</div>
<div
style="right: 0; border: 10px solid #ddd; border-left-color: #88b7d5; border-width: 25px; position: absolute; border-left-color: rgba(92, 184, 92, 1); border-top-color: rgba(92, 184, 92, 0); border-bottom-color: rgba(92, 184, 92, 0); border-right-color: rgba(92, 184, 92, 0);">
</div>
</div>
<div class="col-md-3 column">
<div class="progress"
style="height: 50px; border-radius: 0; position: absolute; width: 75%; right: 49px;">
<div class="progress-bar progress-bar-default"
role="progressbar" aria-valuenow="60" aria-valuemin="0"
aria-valuemax="100" style="width: 100%; height: 50px;">
<div style="font-size: 16px; margin-top: 15px;">3. 付款</div>
</div>
</div>
<div
style="right: 0; border: 10px solid #ddd; border-left-color: #88b7d5; border-width: 25px; position: absolute; border-left-color: rgba(221, 221, 221, 1); border-top-color: rgba(221, 221, 221, 0); border-bottom-color: rgba(221, 221, 221, 0); border-right-color: rgba(221, 221, 221, 0);">
</div>
</div>
<div class="col-md-3 column">
<div class="progress" style="height: 50px; border-radius: 0;">
<div class="progress-bar progress-bar-default"
role="progressbar" aria-valuenow="60" aria-valuemin="0"
aria-valuemax="100" style="width: 100%; height: 50px;">
<div style="font-size: 16px; margin-top: 15px;">4. 完成</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="panel-body">
<div class="container-fluid">
<div class="row clearfix">
<div class="col-md-12 column">
<div class="alert alert-warning alert-dismissable"
style="color: red;">
<button type="button" class="close" data-dismiss="alert"
aria-hidden="true">×</button>
<i class="glyphicon glyphicon-info-sign"></i> <strong>请在下单后15分钟内付款,否则您的订单会被自动关闭。</strong>
</div>
</div>
</div>
</div>
<div id="address" class="container-fluid">
<div class="row clearfix">
<div class="col-md-12 column">
<blockquote
style="border-left: 5px solid #f60; color: #f60; padding: 0 0 0 20px;">
<b> 收货地址 </b>
</blockquote>
</div>
<div class="col-md-12 column" style="padding: 0 120px;">
<div th:if="${#strings.isEmpty(session.addressVOList)}">尚未创建收货地址</div>
<div th:if="${not #strings.isEmpty(session.addressVOList)}">
<div th:each="address : ${session.addressVOList}" class="radio">
<label> <input type="radio" name="addressId" th:value="${address.id}"
id="optionsRadios1"/> [[${address.receiveName}]]
[[${address.phoneNum}]] [[${address.address}]]
</label>
</div>
</div>
<div class="radio">
<label> <input type="radio" name="optionsRadios"
id="optionsRadios2" value="option2"> 新地址
</label>
</div>
<div
style="border: 10px solid #f60; border-bottom-color: #eceeef; border-width: 10px; width: 20px; margin-left: 20px; margin-top: -20px; border-left-color: rgba(221, 221, 221, 0); border-top-color: rgba(221, 221, 221, 0); border-right-color: rgba(221, 221, 221, 0);"></div>
<div class="panel panel-default"
style="border-style: dashed; background-color: #eceeef">
<div class="panel-body">
<div class="col-md-12 column">
<form action="order/save/address" method="post" class="form-horizontal">
<input type="hidden" name="memberId" th:value="${session.loginMember.id}" />
<div class="form-group">
<label class="col-sm-2 control-label">收货人(*)</label>
<div class="col-sm-10">
<input type="text" name="receiveName" class="form-control"
style="width: 200px;" placeholder="姓名:xxxx">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">手机(*)</label>
<div class="col-sm-10">
<input class="form-control" name="phoneNum" type="text"
style="width: 200px;" placeholder="请填写11位手机号码"></input>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label">地址(*)</label>
<div class="col-sm-10">
<input class="form-control" name="address" type="text"
style="width: 400px;" placeholder="请填写11位手机号码"></input>
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label"></label>
<div class="col-sm-10">
<button type="submit" class="btn btn-primary">确认配送信息</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row clearfix">
<div class="col-md-12 column">
<blockquote
style="border-left: 5px solid #f60; color: #f60; padding: 0 0 0 20px;">
<b> 发票信息 </b>
</blockquote>
</div>
<div class="col-md-12 column" style="padding: 0 120px;">
<div class="radio">
<label> <input type="radio" name="optionsRadio"
id="optionsRadio1" value="option1" checked> 无需发票
</label>
</div>
<div class="radio">
<label> <input type="radio" name="optionsRadio"
id="optionsRadio2" value="option2"> 需要发票
</label>
</div>
<div
style="border: 10px solid #f60; border-bottom-color: #eceeef; border-width: 10px; width: 20px; margin-left: 20px; margin-top: -20px; border-left-color: rgba(221, 221, 221, 0); border-top-color: rgba(221, 221, 221, 0); border-right-color: rgba(221, 221, 221, 0);"></div>
<div class="panel panel-default"
style="border-style: dashed; background-color: #eceeef">
<div class="panel-body">
<div class="col-md-12 column">
<form class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label">发票抬头(*)</label>
<div class="col-sm-10">
<input type="text" class="form-control"
style="width: 200px;" placeholder="个人">
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container-fluid">
<div class="row clearfix">
<div class="col-md-12 column">
<blockquote
style="border-left: 5px solid #f60; color: #f60; padding: 0 0 0 20px;">
<b> 项目信息 <a style="font-size: 12px;"
href="pay-step-1.html">修改数量</a>
</b>
</blockquote>
</div>
<div class="col-md-12 column">
<table class="table table-bordered"
style="text-align: center;">
<thead>
<tr style="background-color: #ddd;">
<td>项目名称</td>
<td>发起人</td>
<td width="300">回报内容</td>
<td width="80">回报数量</td>
<td>支持单价</td>
<td>配送费用</td>
</tr>
</thead>
<tbody>
<tr>
<td th:text="${session.orderProjectVO.projectName}">活性富氢净水直饮机</td>
<td th:text="${session.orderProjectVO.launchName}">深圳市博实永道电子商务有限公司</td>
<td th:text="${session.orderProjectVO.returnContent}">每满1750人抽取一台活性富氢净水直饮机,至少抽取一台。抽取名额(小数点后一位四舍五入)=参与人数÷1750人,由苏宁官方抽取。</td>
<td th:text="${session.orderProjectVO.returnCount}">55</td>
<td style="color: #F60" th:text="${session.orderProjectVO.supportPrice}">¥ 1.00</td>
<td th:if="${session.orderProjectVO.freight == 0}">免运费</td>
<td th:if="${session.orderProjectVO.freight != 0}" th:text="${session.orderProjectVO.freight}">免运费</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-12 column">
<div class="form-group">
<label class="col-sm-2 control-label">备注</label>
<div class="col-sm-10">
<textarea class="form-control" rows="1"
placeholder="填写关于回报或发起人希望您备注的信息"></textarea>
</div>
</div>
</div>
<div class="col-md-12 column">
<blockquote
style="border-left: 5px solid #f60; color: #f60; padding: 0 0 0 20px;">
<b> 账单 </b>
</blockquote>
</div>
<div class="col-md-12 column">
<div class="alert alert-warning alert-dismissable"
style="text-align: right; border: 2px solid #ffc287;">
<ul style="list-style: none;">
<li style="margin-top: 10px;">支持金额:<span
style="color: red;">¥[[${session.orderProjectVO.returnCount*session.orderProjectVO.supportPrice}]]</span></li>
<li style="margin-top: 10px;">配送费用:<span
style="color: red;">¥[[${session.orderProjectVO.freight}]]</span></li>
<li style="margin-top: 10px; margin-bottom: 10px;"><h2>
支付总金额:<span style="color: red;">¥[[${session.orderProjectVO.returnCount*session.orderProjectVO.supportPrice+session.orderProjectVO.freight}]]</span>
</h2></li>
<li
style="margin-top: 10px; padding: 5px; border: 1px solid #F00; display: initial; background: #FFF;">
<i class="glyphicon glyphicon-info-sign"></i> <strong>您需要先
<a href="#address">设置配送信息</a> ,再提交订单
</strong>
</li>
<li style="margin-top: 10px;">
请在下单后15分钟内付款,否则您的订单会被自动关闭。</li>
<li style="margin-top: 10px;">
<button id="payButton" disabled="disabled" type="button"
class="btn btn-warning btn-lg"
onclick="window.location.href='pay-step-3.html'">
<i class="glyphicon glyphicon-credit-card"></i> 立即付款
</button>
</li>
<li style="margin-top: 10px;">
<div class="checkbox">
<label>
<input id="knowRoleCheckBox" type="checkbox">我已了解风险和规则
</label>
</div>
</li>
</ul>
</div>
</div>
<div class="container">
<div class="row clearfix">
<div class="col-md-12 column">
<blockquote>
<p>
<i class="glyphicon glyphicon-info-sign"
style="color: #2a6496;"></i> 提示
</p>
<br> <span style="font-size: 12px;">1.众筹并非商品交易,存在一定风险。支持者根据自己的判断选择、支持众筹项目,与发起人共同实现梦想并获得发起人承诺的回报。<br>
2.众筹平台仅提供平台网络空间及技术支持等中介服务,众筹仅存在于发起人和支持者之间,使用众筹平台产生的法律后果由发起人与支持者自行承担。<br>
3.本项目必须在2017-06-04之前达到 ¥1000000.00
的目标才算成功,否则已经支持的订单将取消。订单取消或募集失败的,您支持的金额将原支付路径退回。<br>
4.请在支持项目后15分钟内付款,否则您的支持请求会被自动关闭。<br>
5.众筹成功后由发起人统一进行发货,售后服务由发起人统一提供;如果发生发起人无法发放回报、延迟发放回报、不提供回报后续服务等情况,您需要直接和发起人协商解决。<br>
6.如您不同意上述风险提示内容,您有权选择不支持;一旦选择支持,视为您已确认并同意以上提示内容。
</span>
</blockquote>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="container" style="margin-top: 20px;">
<div class="row clearfix">
<div class="col-md-12 column">
<div id="footer">
<div class="footerNav">
<a rel="nofollow" href="http://www.atguigu.com">关于我们</a> | <a
rel="nofollow" href="http://www.atguigu.com">服务条款</a> | <a
rel="nofollow" href="http://www.atguigu.com">免责声明</a> | <a
rel="nofollow" href="http://www.atguigu.com">网站地图</a> | <a
rel="nofollow" href="http://www.atguigu.com">联系我们</a>
</div>
<div class="copyRight">Copyright ?2010-2014atguigu.com 版权所有
</div>
</div>
</div>
</div>
</div>
</div>
<script>
$("#knowRoleCheckBox").click(function(){
var currentStatus = this.checked;
if(currentStatus) {
$("#payButton").prop("disabled", "");
}else{
$("#payButton").prop("disabled","disabled");
}
});
$('#myTab a').click(function(e) {
e.preventDefault()
$(this).tab('show')
})
</script>
</body>
</html>
6 新建收获地址
修改order-consumer\src\main\java\com\atguigu\crowd\handler\OrderHandler.java
@RequestMapping("/save/address")
public String saveAddress(AddressVO addressVO, HttpSession session) {
// 1.保存地址信息
ResultEntity<String> resultEntity = mySQLRemoteService.saveAddressRemote(addressVO);
logger.info(resultEntity.getResult());
// 2.从Session域中获取orderProjectVO
OrderProjectVO orderProjectVO = (OrderProjectVO) session.getAttribute("orderProjectVO");
// 3.获取returnCount
Integer returnCount = orderProjectVO.getReturnCount();
// 4.重定向到指定地址,重新进入确定订单页面(数据库中地址信息已更新,页面中显示的是新的地址信息)
return "redirect:http://crowd.com/order/confirm/order/"+returnCount;
}
并新建saveAddressRemote()远程调用接口:
修改api\src\main\java\com\atguigu\crowd\api\MySQLRemoteService.java
@RequestMapping("/save/address/remote")
ResultEntity<String> saveAddressRemote(@RequestBody AddressVO addressVO);
修改mysql-provider\src\main\java\com\atguigu\crowd\handler\OrderProviderHandler.java
@RequestMapping("/save/address/remote")
public ResultEntity<String> saveAddressRemote(@RequestBody AddressVO addressVO) {
try {
orderService.saveAddress(addressVO);
return ResultEntity.successWithoutData();
} catch (Exception e) {
e.printStackTrace();
return ResultEntity.failed(e.getMessage());
}
}
并新建saveAddress()方法及实现类:
修改mysql-provider\src\main\java\com\atguigu\crowd\service\impl\OrderServiceImpl.java
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
@Override
public void saveAddress(AddressVO addressVO) {
AddressPO addressPO = new AddressPO();
BeanUtils.copyProperties(addressVO, addressPO);
addressPOMapper.insert(addressPO);
}
7 测试
进入确认订单页面:
收货地址可以输入多个并保存在页面中:
确认金额勾选协议显示,不勾选则无法选择: