SpringBoot + VUE实现订单案例
Vue是一个前端的双向绑定类的框架,使用它完成前端页面逻辑非常方便,按照其约定可以高效完成前端复杂业务逻辑,用户不必再关心数据正确回显问题,只要数据格式是正确的,配置双向绑定规则是正确的,系统就能正确显示页面。尤其在单网页应用中,用法最为方便。如下介绍如何快速使用VUE设计案例。什么是双向绑定Vue框架很核心的功能就是双向的数据绑定。 双向是指:HTML标签数据 绑定到 Vue对象,另外反方向..
Vue是一个前端的双向绑定类的框架,使用它完成前端页面逻辑非常方便,按照其约定可以高效完成前端复杂业务逻辑,用户不必再关心数据正确回显问题,只要数据格式是正确的,配置双向绑定规则是正确的,系统就能正确显示页面。尤其在单网页应用中,用法最为方便。如下介绍如何快速使用VUE设计案例。
什么是双向绑定
Vue框架很核心的功能就是双向的数据绑定。 双向是指:HTML标签数据 绑定到 Vue对象,另外反方向数据也是绑定的。通俗点说就是,Vue对象的改变会直接影响到HTML的标签的变化,而且标签的变化也会反过来影响Vue对象的属性的变化。
开发步骤:
下载VUE
从官网下载
或从CDN下载
Staticfile CDN(国内) : https://cdn.staticfile.org/vue/2.2.2/vue.min.js
unpkg:https://unpkg.com/vue/dist/vue.js, 会保持和 npm 发布的最新的版本一致。
cdnjs : https://cdnjs.cloudflare.com/ajax/libs/vue/2.1.8/vue.min.js
下载AXIOS
AXIOS是基于promise用于浏览器和node.js的http客户端
1、 利用npm安装npm install axios --save
2、 利用bower安装bower install axios --save
3、 直接利用cdn引入 https://unpkg.com/axios/dist/axios.min.js
SQL
create table t_order(order_id int auto_increment primary key,
user_id varchar(100),payment int,payment_type int,
order_status int,create_time datetime,payment_time datetime);
alter table t_order add province varchar(10);
alter table t_order add city varchar(10);
alter table t_order add county varchar(10);
create table t_orderitem(id int auto_increment primary key,
item_id varchar(100),order_id int,item_num int,item_price int,
total_fee int);
create table t_store(id int auto_increment primary key,
item_id varchar(100),item_info varchar(200),item_price int,
inventor_num int);
CREATE TABLE `t_address` (
`code` varchar(255) NOT NULL,
`name` varchar(255) DEFAULT NULL,
PRIMARY KEY (`code`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `t_address` VALUES ('130000','河北省'),('130100','石家庄市'),('130102','长安区'),('130104','桥东区'),('130105','新华区'),('320000','江苏省'),('320100','南京市'),('320102','玄武区'),('320103','白下区'),('320104','秦淮区');
1 耐克男运动鞋 789
2 女风衣 1688
3 《thinking in java》 78
insert into t_store(item_id,item_info,item_price,inventor_num)
values(1,'耐克男运动鞋',789,10000);
insert into t_store(item_id,item_info,item_price,inventor_num)
values(2,'女风衣 ',1688,10000);
insert into t_store(item_id,item_info,item_price,inventor_num)
values(3,'《thinking in java》',78,10000);
设计网页
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>订单列表</title>
<link rel="stylesheet" type="text/css" href="/js/base.css">
<script type="text/javascript" src="/js/jquery.min.js"></script>
<script type="text/javascript" src="/js/base.js"></script>
<script type="text/javascript" src="/js/vue.js"></script>
<script type="text/javascript" src="/js/axios.min.js"></script>
<script>
//点击新增时,通过后台加载订单,调用VUE对象的loadorder方法
//如果新增返回订单空对象,VUE根据数据绑定规则将对应数据显示在网页上
function doadd()
{
app.loadorder('');
//新增订单的DIV层取消显示
$('#orderitemdiv').css('display','block');
}
//通过订单ID打开订单
function openorder(id)
{
app.loadorder(id);
//新增订单的DIV层显示,VUE根据数据绑定规则将对应数据显示在网页上
$('#orderitemdiv').css('display','block');
}
//添加订单明细,这里只操作订单JS对象,VUE根据数据绑定规则将对应数据显示在网页上
function doadditem()
{
//添加订单明细项
var oi={
item_id:1,
item_num:1,
item_price:10,
uuid:Math.random()//定义唯一uuid,用于前台页面删除此项订单明细
}
//向订单JS数据对象添加订单明细
app.order.items.push(oi);
}
//通过订单明细UUID删除此时订单明细
//这里只操作订单JS对象,VUE根据数据绑定规则将对应数据显示在网页上
function dodelitem(uuid)
{
for(var i=0;i<app.order.items.length;i++)
{
var oi = app.order.items[i];
if(uuid == oi.uuid)
{
//删除订单JS对象中明细集合中相应的元素
//参考JS操作集合的方法splice
//arrayObj.splice(start, deleteCount,[itemObj]...);
app.order.items.splice(i,1);
}
}
}
//通过Ajax向后台保存订单JS数据对象
function dosaveorder()
{
//var obj = JSON.stringify(app.order);
//调用定义VUE对象中的保存方法,将当前订单JS对象提交到后台
app.dosave();
}
//关闭订单明细DIV
function doclose()
{
$('#orderitemdiv').css('display','none');
}
</script>
</head>
<body>
<div id="app">
<input type="button" value="添加订单" onclick="doadd()"/>
<table>
<tr>
<th>用户</th>
<th>订单时间</th>
<th>支付时间</th>
</tr>
<!--
绑定VUE对象中数据对象list,循环显示到Table的Tr控件上,迭代对象命名为o
-->
<tr v-for="o in list">
<!-- 如果VUE将数据拼接字符串必须使用+连接,不能使用{{}} -->
<td><a v-bind:href="'javascript:openorder('+o.order_id+')'">{{ o.user_id }}</a></td>
<!-- VUE使用{{}}绑定数据到DOM控件上,dateFormat上日期处理函数-->
<td>{{ dateFormat(o.create_time) }}</td>
<td>{{ dateFormat(o.payment_time) }}</td>
</tr>
</table>
<!-- VUE绑定HTML代码片断使用 v-html,普通字符绑定使用v-bind,v-model -->
<div class="pdiv" v-html="pagediv"></div>
<div id="orderitemdiv" style="display:none">
<h3>添加订单明细</h3>
<form id="frm" name="frm" action="/saveitem">
<input type="hidden" name="uuid" value=""/>
<input type="button" value="添加商品" onclick="doadditem()"/>
<input type="button" value="提交订单" onclick="dosaveorder()"/>
<input type="button" value="关闭" onclick="doclose()"/>
<table>
<tr>
<td>订单用户</td>
<td>
<!-- 绑定定义用户数据到输入控件 -->
<input type="text" v-model="order.user_id">
</td>
</tr>
<tr>
<td>省份</td>
<td>
<!-- 绑定定义地址中省份数据到下拉列表框,绑定选中事件使用@,
onProvinceSelected是VUE中用户自定义的方法-->
<select id="province" name="province" v-model="order.province"
@change="onProvinceSelected">
<!-- 循环显示各省份 -->
<option v-for="c in order.provinceList" :value="c.code">{{c.name}}</option>
</select>
</td>
</tr>
<tr>
<td>地区</td>
<td>
<select id="city" name="city" v-model="order.city"
@change="onCitySelected">
<option v-for="c in order.cityList" :value="c.code" >{{c.name}}</option>
</select>
</td>
</tr>
<tr>
<td>县市</td>
<td>
<select id="county" name="county" v-model="order.county">
<option v-for="c in order.countyList" :value="c.code" >{{c.name}}</option>
</select>
</td>
</tr>
</table>
<div id="itemdiv">
<br>
<h3>所选商品</h3>
<table id="itemtab">
<tr>
<th>商品名称</th>
<th>数量</th>
<th>数量</th>
<th>价格</th>
<th>总计</th>
<th>删除</th>
</tr>
<!--
绑定VUE对象中订单数据对象order的明细,循环显示到Table的Tr控件上,迭代对象命名为oi
-->
<tr v-for="oi in order.items">
<td>
<select v-model="oi.item_id">
<option v-for="c in productList" :value="c.code">{{c.name}}</option>
</select>
</td>
<td>{{ oi.item_num }}</td>
<td><input type="text" v-model="oi.item_num"/></td>
<td>{{ oi.item_price }}</td>
<td>{{ oi.item_price * oi.item_num}}</td>
<td><input type="button" value="删除" v-bind:onclick="'dodelitem('+oi.uuid+')'"/></td>
</tr>
</table>
</div>
</form>
</div>
</div>
<script>
//定义VUE对象,加载数据并绑定到HTML DOM元素上
var app = new Vue({
el: '#app',//VUE数据对象绑定DIV控件,el变量名称不可改变
data: {//定义数据对象,data变量名称不可改变
//所有自定义变量名称可以修改
order:{},//自定义代表订单对象变量
productList:[//自定义产品集合
{"code":1,"name":"手机"},
{"code":2,"name":"笔记本"},
{"code":3,"name":"电脑"}
],
list:[],//每页显示记录集合
page:1,//当前页面
rows:4,//每页显示记录数
pagediv:''//分页DIV HTML代码片段,这里使用JS前台分页技术
},
created: function(){//在VUE对象生命周期中,创建对象时调用
this.dopageload();//调用自定义方法加载分页数据
},
methods:{//自定义函数
dateFormat:function(time) {//处理日期时间函数
var date=new Date(time);
var year=date.getFullYear();
var month= date.getMonth()+1<10 ? "0"+(date.getMonth()+1) : date.getMonth()+1;
var day=date.getDate()<10 ? "0"+date.getDate() : date.getDate();
var hours=date.getHours()<10 ? "0"+date.getHours() : date.getHours();
var minutes=date.getMinutes()<10 ? "0"+date.getMinutes() : date.getMinutes();
var seconds=date.getSeconds()<10 ? "0"+date.getSeconds() : date.getSeconds();
return year+"-"+month+"-"+day+" "+hours+":"+minutes+":"+seconds;
},
loadorder:function(id)//根据订单ID装载订单数据对象
{
_this = this;
axios.get('/findorder?id='+id)
.then(function(res){
_this.order = res.data;
});
},
onProvinceSelected:function(){//选择省份时调用的方法
console.log(this.order.province)
_this = this;
//当选中省份下拉框时,Ajax选中地区
axios.get('/findcity?code='+_this.order.province)
.then(function(res){
//当选中地区下拉框时,Ajax选中县级市
_this.order.cityList = res.data;
_this.order.city = res.data[0].code;
axios.get('/findcounty?code='+_this.order.city)
.then(function(res2){
_this.order.countyList = res2.data;
_this.order.county = res2.data[0].code;
});
});
},
onCitySelected:function(){//选择地区时调用的方法
console.log(this.order.province)
_this = this;
//当选选中地区下拉框时,Ajax选中县级市
axios.get('/findcounty?code='+_this.order.city)
.then(function(res2){
_this.order.countyList = res2.data;
_this.order.county = res2.data[0].code;
});
},
dopageload:function(page,rows){//使用Ajax加载分页数据
_this = this;
if(page == null)
page = 1;
if(rows == null)
rows = 4;
//使用Ajax请求分页数据
axios.get('/findpage?page='+page+"&rows="+rows)
.then(function(res2){
_this.list = res2.data.list;//当前页显示订单对象集合
_this.total = res2.data.total;//订单总数
//使用pagedivjs公共JS方法处理分页,此方法在base.js文件中
//需要传入每次点击分页时调用的JS方法,本例中为dopageload,但需要传入其VUE对象限定app,
//app是在153行定义的 var app = new Vue({
_this.pagediv = pagedivjs('app.dopageload',_this.page,_this.rows,_this.total);//res2.data.pagediv;
});
},
dosave:function(){//使用Ajax保持订单方法
_this = this;
axios.post('/saveorder',this.order)
.then(function(res){
if(res.data == true)
{
alert('保持成功');
//保存成功后刷新订单列表
_this.dopageload(_this.page,_this.rows);
//关闭当前订单明细窗口
doclose();
}
else
alert('保存失败');
});
}
}
});
</script>
</body>
</html>
设计后台Controller
package com.test.ctrl;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import org.aspectj.util.FileUtil;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.alibaba.dubbo.config.annotation.Reference;
import com.alibaba.fastjson.JSONObject;
import com.test.model.AddressInfo;
import com.test.model.OrderInfo;
import com.test.model.OrderItemInfo;
import com.test.service.IService;
import com.test.util.PageUtil;
@Controller
public class OrderCtrl {
@Reference(timeout=3000)
private IService serv;
/**
* 跳转页面
* @param req
* @param page
* @param rows
* @return
*/
@RequestMapping("/list")
public String list(HttpServletRequest req,Integer page,Integer rows)
{
return "order";
}
/**
* Ajax异步加载分页数据
* @param page
* @param rows
* @return
*/
@RequestMapping("/findpage")
@ResponseBody
public Map findpage(Integer page,Integer rows)
{
System.out.println("page="+page+",rows="+rows);
if(page == null)
page = 1;
if(rows == null)
rows = 4;
System.out.println("page="+page+",rows="+rows);
Map map = serv.getOrder(page,rows);
List<OrderInfo> orders = (List<OrderInfo>)map.get("orders");
System.out.println("orders="+orders);
Long total = (Long)map.get("total");
Map m = new HashMap();
m.put("total", total);
m.put("list", orders);
String url = "/list";
PageUtil pu = new PageUtil(url,page,rows,total);
String htmlPage = pu.toHtml();
m.put("pagediv", htmlPage);
return m;
}
@RequestMapping("/address")
public String address(HttpServletRequest req)
{
return "address";
}
@RequestMapping("/saveorder")
@ResponseBody
public Boolean saveorder(HttpServletRequest req)
{
try
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
FileUtil.copyStream(req.getInputStream(), baos);
JSONObject jsonObj = JSONObject.parseObject(new String(baos.toByteArray()));
OrderInfo oi = (OrderInfo)JSONObject.toJavaObject(jsonObj,OrderInfo.class);
oi.setPayment_time(new Timestamp(System.currentTimeMillis()));
oi.setCreate_time(new Timestamp(System.currentTimeMillis()));
if(oi.getOrder_id() == null)
serv.saveOrder(oi);
else
serv.updateOrder(oi);
}
catch(Exception e)
{
e.printStackTrace();
}
return true;
}
@RequestMapping("/findorder")
@ResponseBody
public OrderInfo findorder(String id)
{
Integer id2 = null;
try
{
id2 = Integer.parseInt(id);
}
catch(Exception e)
{}
OrderInfo oi = null;
if(id2 != null)
oi = serv.getOrderById(id2);
List<AddressInfo> plist = this.findprovince();
if(oi != null)
{
List<OrderItemInfo> items = serv.getItemByOrderId(id2);
oi.setItems(items);
oi.setProvinceList(plist);
oi.setCityList(this.findcity(oi.getProvince()));
oi.setCountyList(this.findcounty(oi.getCity()));
}
else
{
oi = new OrderInfo();
oi.setProvince(plist.get(0).getCode());
oi.setProvinceList(plist);
List<AddressInfo> clist = this.findcity(oi.getProvince());
oi.setCityList(clist);
oi.setCity(clist.get(0).getCode());
List<AddressInfo> ctlist = this.findcounty(oi.getCity());
oi.setCountyList(ctlist);
oi.setCounty(ctlist.get(0).getCode());
}
return oi;
}
@RequestMapping("/findprovince")
@ResponseBody
public List<AddressInfo> findprovince()
{
return serv.findProvince();
}
@RequestMapping("/findcity")
@ResponseBody
public List<AddressInfo> findcity(String code)
{
List<AddressInfo> lst = new ArrayList<AddressInfo>();
List<AddressInfo> rtns = serv.findCityByPrvnc(code);
for(AddressInfo ai:rtns)
{
if(!ai.getCode().equals(code))
lst.add(ai);
}
return lst;
}
@RequestMapping("/findcounty")
@ResponseBody
public List<AddressInfo> findcounty(String code)
{
List<AddressInfo> lst = new ArrayList<AddressInfo>();
List<AddressInfo> rtns = serv.findCountyByCity(code);
for(AddressInfo ai:rtns)
{
if(!ai.getCode().equals(code))
lst.add(ai);
}
return lst;
}
}
工具JS前台分页方法
/**
* 使用VUE前台分页公共方法
* @param js 点击页面调用JS方法
* @param page 查询页码
* @param rows 每页显示记录数
* @param total 总记录数
* @returns {String}
*/
function pagedivjs(js,page,rows,total)
{
var pages = 0;
if(total%rows==0)
pages = parseInt(total/rows);
else
pages = parseInt(total/rows) + 1;
var pageDiv = "<div id='pagediv'>";
page=1;
pageDiv = pageDiv + "<a href='javascript:"+js+"("+page+","+rows+");'>首页</a>";
page = (page==1)?1:(page-1);
pageDiv = pageDiv + "<a href='javascript:"+js+"("+page+","+rows+");'>上一页</a>";
for(var i=1;i<=pages;i++)
{
if(i == page)
pageDiv = pageDiv + "<a href='javascript:"+js+"("+i+","+rows+");'><b><font color='red'>"+i+"</font></b></a> ";
else
pageDiv = pageDiv + "<a href='javascript:"+js+"("+i+","+rows+");'>"+i+"</a> ";
}
page = (page==pages)?pages:(page+1);
pageDiv = pageDiv + "<a href='javascript:"+js+"("+page+","+rows+");'>下一页</a>";
//定义尾页连接
page = pages;
pageDiv = pageDiv + "<a href='javascript:"+js+"("+page+","+rows+");'>尾页</a>";
pageDiv = pageDiv + " 第"+page+"/"+pages+"页";
pageDiv = pageDiv + " 共"+total+"条记录";
pageDiv = pageDiv + "</div>";
return pageDiv;
}
测试效果
更多推荐
所有评论(0)