day18【前台】订单

day18【前台】订单

1、搭建环境

1.1、引入依赖

  • order-consumer工程中引入所需依赖

image-20200707154247438

<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、创建yml配置文件

image-20200707154500512

server:
  port: 6000
spring:
  application:
    name: atguigu-crowd-order
  thymeleaf:
    prefix: classpath:/templates/
    suffix: .html
  redis:
    host: 192.168.152.129
  session:
    store-type: redis

eureka:
  client:
    service-url:
      defaultZone: http://localhost:1000/eureka

1.3、创建主启动类

  • @EnableFeignClients:启用Feign客户端功能
  • @EnableDiscoveryClient:启用服务注册发现功能

image-20200707154837840

// 启用Feign客户端功能
@EnableFeignClients
@EnableDiscoveryClient
@SpringBootApplication
public class CrowdMainClass {
	
	public static void main(String[] args) {
		SpringApplication.run(CrowdMainClass.class, args);
	}

}

1.4、配置zuul路由规则

  • 配置atguigu-crowd-order的路由规则

image-20200707155218888

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、订单建模

2.1、实体类结构

image-20200707155302456

2.2、物理建模

2.2.1、订单表

image-20200707155431192

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`)
) ;
2.2.2、收货地址表

image-20200707155547184

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`)
) ;
2.2.3、项目信息表

image-20200707155652480

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、逆向工程

3.1、逆向工程配置文件

image-20200707155814310

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE generatorConfiguration
			  PUBLIC "-//mybatis.org//DTD MyBatis Generator Configuration 1.0//EN"
			  "http://mybatis.org/dtd/mybatis-generator-config_1_0.dtd">
<generatorConfiguration>
	<!-- mybatis-generator:generate -->
	<context id="atguiguTables" targetRuntime="MyBatis3">
		<commentGenerator>
			<!-- 是否去除自动生成的注释 true:是;false:否 -->
			<property name="suppressAllComments" value="true" />
		</commentGenerator>

		<!--数据库连接的信息:驱动类、连接地址、用户名、密码 -->
		<jdbcConnection 
			driverClass="com.mysql.jdbc.Driver"
			connectionURL="jdbc:mysql://localhost:3306/project_crowd" 
			userId="root"
			password="root">
		</jdbcConnection>

		<!-- 默认false,把JDBC DECIMAL 和 NUMERIC 类型解析为 Integer,为 true时把JDBC DECIMAL 
			和 NUMERIC 类型解析为java.math.BigDecimal -->
		<javaTypeResolver>
			<property name="forceBigDecimals" value="false" />
		</javaTypeResolver>

		<!-- targetProject:生成Entity类的路径 -->
		<javaModelGenerator targetProject=".\src\main\java"
			targetPackage="com.atguigu.crowd.entity.po">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
			<!-- 从数据库返回的值被清理前后的空格 -->
			<property name="trimStrings" value="true" />
		</javaModelGenerator>

		<!-- targetProject:XxxMapper.xml映射文件生成的路径 -->
		<sqlMapGenerator targetProject=".\src\main\java"
			targetPackage="com.atguigu.crowd.mapper">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
		</sqlMapGenerator>

		<!-- targetPackage:Mapper接口生成的位置 -->
		<javaClientGenerator type="XMLMAPPER"
			targetProject=".\src\main\java"
			targetPackage="com.atguigu.crowd.mapper">
			<!-- enableSubPackages:是否让schema作为包的后缀 -->
			<property name="enableSubPackages" value="false" />
		</javaClientGenerator>

		<!-- 数据库表名字和我们的entity类对应的映射指定 -->
		<table tableName="t_order" domainObjectName="OrderPO" />
		<table tableName="t_address" domainObjectName="AddressPO" />
		<table tableName="t_order_project" domainObjectName="OrderProjectPO" />

	</context>
</generatorConfiguration>

3.2、执行逆向工程

image-20200707160010937

3.3、资源归位

3.3.1、实体类

image-20200707160127369

3.3.2、Mapper接口

image-20200707160218924

3.3.3、Mapper映射文件

image-20200707160259982

4、确认回报信息

4.1、跳转至支持页面

  • 单击【支持】超链接跳转至支持页面,带上projectIdreturnId(会面编写SQL才发现,原来并不需要携带projectId,不过带了就带了吧)

image-20200707185736950

<a th:href="'http://www.crowd.com/order/confirm/return/info/'+${detailProjectVO.projectId}+'/'+${return.returnId}" class="btn btn-warning btn-lg">支持</a>

4.2、创建VO

  • 创建OrderProjectVO类:支持页面对应的VO类,由于需要存入Redis,该类必须是可序列化类

image-20200707190408016

@Data
@NoArgsConstructor
@AllArgsConstructor
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;

}

4.3、order-consumer调用接口

  • order-consumer调用远程mysql-provider微服务:
    • 获取订单回报页面的数据
    • 并将查询到的数据存入session,以便后一页面使用

image-20200707201548099

@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";
	}

}

4.4、mysql-provider暴露接口

4.4.1、Handler层
  • 调用Service层获取订单回报页面的数据

image-20200707201950335

@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());
		}
		
	}

}
4.4.2、Service层
  • 调用Mapper层获取订单回报页面的数据

image-20200707202025926

@Service
@Transactional(readOnly = true)
public class OrderServiceImpl implements OrderService {
	
	@Autowired
	private OrderProjectPOMapper orderProjectPOMapper;

	@Override
	public OrderProjectVO getOrderProjectVO(Integer projectId, Integer returnId) {
		
		return orderProjectPOMapper.selectOrderProjectVO(returnId);
	}

}

4.5、Mapper层编写SQL

4.5.1、Mapper接口
  • Mapper接口中声明接口

image-20200707202103256

OrderProjectVO selectOrderProjectVO(Integer returnId);
4.5.2、Mapper映射文件
  • t_project表通过memberIdt_member_launch_info相关联
  • t_project表通过projectIdt_return相关联
  • 两个LEFT JOIN完事儿

image-20200707202217914

image-20200707205231317

<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>
  • 不加限定条件,LEFT JOIN得到的结果

image-20200707205705799

SELECT *
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
4.5.3、关于Left Join
  • t_role表:角色表

image-20200707210805962

  • t_admin表:管理员表

image-20200707210846926

  • inner_admin_role表:管理员、角色中间表

image-20200707211712842

  • 目标一:查询拥有指定roleId的管理员信息

    • 不加查询条件(Left Join:坐标所有数据都会出现在结果集中,连接结果表中没有值的字段以null填充)

    image-20200707215251441

    SELECT * 
    FROM t_admin
    LEFT JOIN inner_admin_role ON inner_admin_role.`admin_id` = t_admin.`id`
    
    • 查询所有字段

    image-20200707212722660

    SELECT * 
    FROM t_admin
    LEFT JOIN inner_admin_role ON inner_admin_role.`admin_id` = t_admin.`id`
    WHERE inner_admin_role.`role_id` = 239
    
    • 去除多余字段:adminIdroleId

    image-20200707213143514

    SELECT 
    	t_admin.`id`,
    	t_admin.`login_acct`,
    	t_admin.`user_pswd`,
    	t_admin.`user_name`,
    	t_admin.`email`,
    	t_admin.`create_time`
    FROM t_admin
    LEFT JOIN inner_admin_role ON inner_admin_role.`admin_id` = t_admin.`id`
    WHERE inner_admin_role.`role_id` = 239
    
  • 查询拥有指定roleId的管理员信息及其角色信息

    • 不加限制条件(Left Join:坐标所有数据都会出现在结果集中,连接结果表中没有值的字段以null填充)

    image-20200707215449565

    SELECT *
    FROM t_admin
    LEFT JOIN inner_admin_role ON inner_admin_role.`admin_id` = t_admin.`id`
    LEFT JOIN t_role ON t_role.`id` = inner_admin_role.`role_id`
    
    • 查询所有字段

    image-20200707215518035

    SELECT *
    FROM t_admin
    LEFT JOIN inner_admin_role ON inner_admin_role.`admin_id` = t_admin.`id`
    LEFT JOIN t_role ON t_role.`id` = inner_admin_role.`role_id`
    WHERE inner_admin_role.`role_id` = 239
    
    • 去除多余字段

    image-20200707215612354

    SELECT 
    	t_admin.`id`,
    	t_admin.`login_acct`,
    	t_admin.`user_pswd`,
    	t_admin.`user_name`,
    	t_admin.`email`,
    	t_admin.`create_time`,
    	t_role.`id`,
    	t_role.`name`
    FROM t_admin
    LEFT JOIN inner_admin_role ON inner_admin_role.`admin_id` = t_admin.`id`
    LEFT JOIN t_role ON t_role.`id` = inner_admin_role.`role_id`
    WHERE inner_admin_role.`role_id` = 239
    

4.6、api声明远程调用接口

  • api中的方法声明部分需与mysql-providerHandler方法一致

image-20200707202335496

@RequestMapping("/get/order/project/vo/remote")
ResultEntity<OrderProjectVO> getOrderProjectVORemote(@RequestParam("projectId") Integer projectId, @RequestParam("returnId") Integer returnId);

4.7、确认回报页面

image-20200707202455066

1、页面显示数据
<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>
2、修改商品数量
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));
});
3、提交表单
$("#submitBtn").click(function(){
	var returnCount = $("#returnCountInput").val();
	window.location.href = "order/confirm/order/"+returnCount;
});

4.8、测试

image-20200708171948990

5、确认订单信息

5.1、创建VO

  • 创建AddressVO类:对应页面上的地址信息,由于AddressVO类的对象需要存入Redis缓存中,该类必须支持序列化

image-20200708172905345

@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;

}

5.2、回显确认订单页面

5.2.1、order-consumer调用接口
  • 点击【确认回报信息】页面中的【去结算】按钮,将回报数量提交至后端Handler,所以,后端Handler方法需要做如下处理:
    • 将表单提交的回报数量设置到session域的OrderProjectVO对象中
    • session域中获取memberId,查询用户的收货地址(List<AddressVO>

image-20200708172943031

	@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";
	}
5.2.2、mysql-provider暴露接口
1、Handler层
  • 调用Service层,获取用户地址信息

image-20200708173429056

@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());
    }

}
2、Service层
  • 调用Mapper层,获取用户地址信息(将PO对象转为VO对象,用于页面显示)

image-20200708173454392

@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.3、api声明远程调用接口
  • api工程中声明远程调用接口

image-20200708174010493

@RequestMapping("/get/address/vo/remote")
ResultEntity<List<AddressVO>> getAddressVORemote(@RequestParam("memberId") Integer memberId);

5.3、确认订单页面

5.3.1、页面显示数据

image-20200708192939639

1、收货地址

image-20200708194558931

<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>
2、发票信息

image-20200708194614656

<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="optionsRadios1"
					id="optionsRadios1" value="option1" checked> 无需发票
				</label>
			</div>
			<div class="radio">
				<label> <input type="radio" name="optionsRadios1"
					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 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>
3、项目信息

image-20200708194642793

<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>
4、账单

image-20200708194706227

<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>

5.4、新建收货地址

5.4.1、提交收货地址
  • 提交收货地址时,带上memberId,这样才能知道是哪个用户的收货地址

image-20200708192939639

<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>
5.4.2、order-consumer调用接口
  • 调用mysql-provider保存地址信息,并重定向至当前页面,需带上returnCount(回报数量)

image-20200708172943031

private Logger logger = LoggerFactory.getLogger(OrderHandler.class);

@RequestMapping("/save/address")
public String saveAddress(AddressVO addressVO, HttpSession session) {

    // 1.执行地址信息的保存
    ResultEntity<String> resultEntity = mySQLRemoteService.saveAddressRemote(addressVO);

    logger.debug("地址保存处理结果:"+resultEntity.getResult());

    // 2.从Session域获取orderProjectVO对象
    OrderProjectVO orderProjectVO = (OrderProjectVO) session.getAttribute("orderProjectVO");

    // 3.从orderProjectVO对象中获取returnCount
    Integer returnCount = orderProjectVO.getReturnCount();

    // 4.重定向到指定地址,重新进入确认订单页面
    return "redirect:http://www.crowd.com/order/confirm/order/"+returnCount;
}
5.4.3、mysql-provider暴露接口
1、Handler层
  • 调用Service层保存用户收货地址

image-20200708173429056

@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());
    }

}
2、Service层
  • addressVO对象转换为addressPO对象,保存至数据库

image-20200708173454392

@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);

}
5.4.4、api声明远程调用接口
  • api工程中i声明远程调用接口,由于需要传输AddressVO对象,需要添加@RequestBody注解:以`json字符串格式进行传输

image-20200708174010493

@RequestMapping("/save/address/remote")
ResultEntity<String> saveAddressRemote(@RequestBody AddressVO addressVO);
5.4.5、测试
  • 收货地址回显正常

image-20200708194146179

5.5、立即付款是否生效

5.5.1、代码
  • 勾选用户协议,才能付款

image-20200708192939639

<!-- 页面按钮 -->
<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>

<!-- javascript代码 -->
$("#knowRoleCheckBox").click(function(){
	var currentStatus = this.checked;
	if(currentStatus) {
		$("#payButton").prop("disabled", "");
	}else{
		$("#payButton").prop("disabled","disabled");
	}
});
5.5.2、测试
  • 【立即付款】按钮失效

image-20200708194419094

  • 【立即付款】按钮生效

image-20200708194450529

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值