SSM-Vue前后端分离式项目开发
1、后端SSM项目搭建
1.1 项目基础设置
- 项目搭建前期所需的所有依赖,配置文件等,直接参考另一篇博客:SSM框架及项目搭建总结 - W-D-G - 博客园
1.2 数据库设计
- 用户表t_user
- 商品表t_product
- 商品类型表t_product_type
- 购物车表t_cart
- 订单表t_order
- 订单详情表t_orderinfo
1.3 编写后端代码
- 使用Mybatis逆向工程自动生成pojo、mapper、mapper.xml等项目所需代码
- 根据项目需求,编写业务逻辑层的接口,然后在编写对应接口的实现类
- 根据各个接口的实现类,来手动添加或修改逆向工程中没有自动生成的mapper接口和mapper.xml
- 如有问题,可参考博客:SSM框架开发-进阶案例 - W-D-G - 博客园
2、前端Vue项目搭建
-
创建一个基于webpack模板的项目
- vue init webpack 项目名
-
安装组件(插件)axios、vue-router、element-ui、vuex
-
npm install axios -s
-
npm install vue-router --save-dev
-
npm i element-ui -S
-
npm install vuex --save
-
-
安装依赖
- npm install(cnpm install)
说明:几种安装方式的区别
1.安装到项目目录node_module。不会添加任何依赖。(不会写入package.json)
npm install axios
2.安装到全局。磁盘目录为配置的npm config prefix处
npm install -g axios
3和4 一样.安装到项目目录node_modules。添加依赖(写入package.json)。添加依赖的作用是:比如项目上传到git中。其他成员下载项目时会直接下载依赖中有的插件
3.生产环境下载的包。
npm install -save axios
4.开发环境下载的包。 只在开发的模式下使用。
npm install -save-dev axios
-
引用各个组件
import Vue from 'vue' import ElementUI from 'element-ui' import 'element-ui/lib/theme-chalk/index.css'; import VueRouter from 'vue-router' import axios from 'axios' Vue.use(ElementUI); Vue.use(VueRouter); Vue.prototype.axios = axios;
-
配置路由router/index.js
点击查看代码import Vue from 'vue' import Router from 'vue-router' import ProductInfo from "../components/ProductInfo"; import Home from "../components/Home"; import Cart from "../components/Cart"; import Orders from "../components/Orders"; import Login from "../components/Login"; import Pay from "../components/Pay"; import CartForm from "../components/CartForm"; Vue.use(Router); export default new Router({ mode: 'history', routes: [ { path: '/home', name: 'Home', component: Home }, { path: '/productInfo', name: 'ProductInfo', component: ProductInfo }, { path: '/cart', name: 'Cart', component: Cart, children: [{ path: '/cartForm', name: 'CartForm', component: CartForm }] }, { path: '/orders', name: 'Orders', component: Orders }, { path: '/login', name: 'Login', component: Login }, { path: '/pay', name: 'Pay', component: Pay } ] });
2.1 登录页面搭建
点击查看代码<template>
<div class="login-box">
<el-form ref="form" status-icon :model="form" :rules="rules" label-width="80px">
<h3 class="login-title">欢迎登录</h3>
<el-form-item label="手机号码" prop="userTel">
<el-input v-model="form.userTel" type="number" placeholder="请输入手机号码"></el-input>
</el-form-item>
<el-form-item label="密码" prop="userPwd">
<el-input v-model="form.userPwd" type="password" placeholder="请输入密码"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="resetForm('form')">重置</el-button>
<el-button type="success" @click="onSubmit('form')">登录</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
export default {
name: "Login",
data() {
return {
form: {
userTel: '',
userPwd: ''
},
rules: {
userTel: [
{required: true, message: '请输入手机号码', trigger: 'blur'},
{min: 11, max: 11, message: '长度必须是11个数字', trigger: 'blur'}
],
userPwd: [
{required: true, message: '请输入密码', trigger: 'blur'},
{min: 6, max: 50, message: '长度在 6 到 50 个字符', trigger: 'blur'}
]
}
}
},
methods: {
onSubmit(formName) {
this.$refs[formName].validate((valid) => {
var vm = this;
if (valid) {
//表单验证成功,要发送登录请求
this.axios({
method: 'GET',
url: 'http://localhost:8090/user/login?userTel=' + vm.form.userTel + '&userPwd=' + vm.form.userPwd
}).then(function (resp) {
if (resp.data.result) {
var user = resp.data.data;
sessionStorage.setItem("isLogin", "true")
//往vuex里存放一个user对象
//先要有user对象
//再存到vuex里
vm.$store.dispatch('asyncUpdateUser', user);
//再在home.vue里获取vuex对象里的user对象的内容。
vm.$message({
message: "登录成功",
type: 'success'
});
setTimeout(function () {
vm.$router.push("/home");
}, 2000)
} else {
vm.$message.error("登录失败");
}
})
} else {
this.$message({
message: '电话号码或密码不能为空!',
type: 'warning'
});
return false;
}
});
},
resetForm(form) {
this.$refs[form].resetFields();
}
}
}
</script>
<style scoped>
.login-box {
width: 500px;
height: 300px;
border: 1px solid #DCDFE6;
margin: 150px auto;
padding: 20px 55px 20px 30px;
border-radius: 20px;
box-shadow: 0px 0px 20px #DCDFE6;
}
.login-title {
text-align: center;
margin-bottom: 40px;
}
.el-button{
margin: 15px 60px 0px 55px;
}
</style>
2.2 首页搭建
点击查看代码<template>
<div>
<el-container>
<el-row>
<el-col :span="12">
<div class="grid-content bg-purple-dark">
<div class="nav nav-1">
<el-link type="info">首页</el-link>
</div>
<div class="nav">
<el-link type="info">官网</el-link>
</div>
</div>
</el-col>
<el-col v-if="!islogin" :span="6">
<div class="grid-content bg-purple-dark">
<div class="nav nav-1">
<el-link type="info" @click="$router.push('/login')">请登录</el-link>
</div>
<div class="nav">
<el-link type="info">注册</el-link>
</div>
</div>
</el-col>
<el-col v-if="islogin" :span="6">
<div class="grid-content bg-purple-dark">
<div class="nav nav-1">
<el-link type="info"><span>欢迎你,{{username}}</span></el-link>
</div>
<div class="nav">
<el-link type="info" @click="$router.push('/logout')">注销</el-link>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="grid-content bg-purple-dark">
<div class="nav">
<el-link type="info">我的订单</el-link>
</div>
<div class="nav">
<el-link type="info">购物车</el-link>
</div>
</div>
</el-col>
</el-row>
<el-header height="80px">
<div class="grid-content bg-purple" align="left" style="float: left">
<img src="../assets/logo.png" style="width: 205px; height: 36px;margin: 25px 0px 0px 150px">
</div>
<div style="float: left; margin-top: 10px;width: 75%">
<div style="float: left; margin-left: 150px">商品名称:
<input v-model="proName" class="select select-input"/>
</div>
<div style="float: left; margin-left: 30px">
商品类型:<select v-model="selectedTypeId" class="select select-option">
<option v-for="option in options" v-bind:value="option.typeId">{{option.typeName}}</option>
</select>
价格区间:<input v-model="lprice" class="select select-input-price"/>-<input v-model="hprice"
class="select select-input-price"/>
<el-button type="primary" icon="el-icon-search"
@click="getList()"></el-button>
</div>
</div>
</el-header>
<el-main>
<div style="width: 99%;border: 1px solid #000;margin-bottom: 8px"></div>
<div class="block">
<el-carousel indicator-position="none" height="350px">
<el-carousel-item v-for="item in imgs" :key="item">
<img :src="item" style="width: 800px;height: 400px;">
</el-carousel-item>
</el-carousel>
</div>
<div style="width: 99%;border: 1px solid #000;margin-top: 8px"></div>
<div class="products">
<div v-for="pro in pros" class="product">
<img :src="pro.pimg"/><br/>
<p style="font-size: larger;">{{pro.pname}}</p>
<p style="font-size: larger;color: red;">¥{{pro.price}}</p>
<el-button type="primary" @click="getProInfo(pro.pid)">立即购买</el-button>
</div>
</div>
<div class="block" style="margin-bottom: 20px;margin-top: 20px">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page.sync="currentPage"
:page-sizes="[8,16,24,32]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="listTotal">
</el-pagination>
</div>
<div style="width: 99%;border: 1px solid #000000;"></div>
</el-main>
<el-footer height="420px">
<el-row>
<el-col :span="6">
<div class="footer-content">
<i class="el-icon-star-off" style="float: left;font-size: 40px;margin-top: 20px;margin-left: 45px"></i>
<div style="float:left; font-size: 25px;margin-top: 10px;margin-left: 10px">百强企业 品质保证</div>
</div>
</el-col>
<el-col :span="6">
<div class="footer-content">
<i class="el-icon-date" style="float: left;font-size: 40px;margin-top: 20px;margin-left: 45px"></i>
<div style="float:left; font-size: 25px;margin-top: 10px;margin-left: 10px">7天退货 15天换货</div>
</div>
</el-col>
<el-col :span="6">
<div class="footer-content">
<i class="el-icon-shopping-bag-2"
style="float: left;font-size: 40px;margin-top: 20px;margin-left: 45px"></i>
<div style="float:left; font-size: 25px;margin-top: 10px;margin-left: 10px">48元起免运费</div>
</div>
</el-col>
<el-col :span="6">
<div class="footer-content">
<i class="el-icon-location-information" style="float: left;font-size: 40px;margin-top: 20px;"></i>
<div style="float:left; font-size: 25px;margin-top: 10px;margin-left: 10px">2000家服务店 全国联保</div>
</div>
</el-col>
</el-row>
<el-row>
<el-col :span="3">
<div class="footer-content-1">
<span style="font-size: large">购物相关</span>
<span>购物指南</span>
<span>配送方式</span>
<span>支付方式</span>
<span>常见问题</span>
</div>
</el-col>
<el-col :span="3">
<div class="footer-content-1">
<span style="font-size: large">保修与退换货</span>
<span>保修政策</span>
<span>退换货政策</span>
<span>保修状态查询</span>
<span>配件防伪查询</span>
</div>
</el-col>
<el-col :span="3">
<div class="footer-content-1">
<span style="font-size: large;margin-left: 20px">维修与技术支持</span>
<span>服务店</span>
<span>预约维修</span>
<span>手机寄修</span>
<span>备件价格查询</span>
<span>上门服务</span>
</div>
</el-col>
<el-col :span="3">
<div class="footer-content-1">
<span style="font-size: large">特色服务</span>
<span>防伪查询</span>
<span>补购保障</span>
<span>以旧换新</span>
<span>补品包装</span>
</div>
</el-col>
<el-col :span="3">
<div class="footer-content-1">
<span style="font-size: large">关于我们</span>
<span>公司介绍</span>
<span>华为商城简介</span>
<span>华为零售店</span>
<span>商家中心</span>
<span>意见反馈</span>
</div>
</el-col>
<el-col :span="3">
<div class="footer-content-1">
<span style="font-size: large">友情链接</span>
<span>华为集团</span>
<span>华为CBG官网</span>
<span>花粉俱乐部</span>
<span>华为云</span>
<span>华为应用市场</span>
</div>
</el-col>
<el-col :span="6">
<div class="footer-content-1" style="line-height: 70px;">
<span style="padding-left: 90px;padding-top: 30px">950805</span>
<span style="margin-bottom: 20px">7x24小时客服热线(仅收市话费)</span>
<div style="border-radius: 40px;height: 40px;line-height: 40px;margin-left: 80px; width: 200px;background: #000000;color: #ffffff">
<i class="el-icon-headset"></i>在线客服
</div>
</div>
</el-col>
<el-col :span="24">
<div class="footer-content" style="height: 120px">
<el-col :span="2">
<div class="footer-content-2" style="height: 120px">
<img src="static/wLelYbpMVWbj9Xpaa5Fk.png" style="margin-top: 20px;height: 25px;margin-left: 10px;">
</div>
</el-col>
<el-col :span="16">
<div class="footer-content-2" style="padding-top: 10px;">
<span>华为集团 | 华为CBG官网 | 花粉俱乐部 | 华为应用市场 | HarmonyOS | 华为终端云空间 | 开发者联盟 | 华为商城手机版 | 网站地图</span><br/>
<a>隐私声明</a><a> 服务协议</a><a> COOKIES</a><a> Copyright © 2012-</a><a> 华为终端有限公司
版权所有 </a><a> 粤ICP备19015064号</a><a> | 粤公网安备 44190002003939号</a>
<br/><em>增值电信业务经营许可证:粤B2-20190762 | 备案主体编号:44201919072182 | 粤新出网备(2021)2号</em><br/>
<a>互联网药品信息服务资格证(粤)-非经营性-2020-0102 | 粤东食药监械经营备20203930</a>
</div>
</el-col>
<el-col :span="6">
<div class="footer-content-2">
<img src="static/20160226162415360.png" style="margin-top: 20px;height: 35px;margin-left: 120px;">
</div>
</el-col>
</div>
</el-col>
</el-row>
</el-footer>
</el-container>
</div>
</template>
<script>
import Qs from 'qs'
export default {
name: 'Home',
data() {
return {
proName: '',
selectedTypeId: '',
lprice: '',
hprice: '',
options: [{
typeId: 1,
typeName: "手机"
}],
imgs: [
"/static/pad.png",
"/static/computer.jpg",
"/static/huacp.png",
"/static/huaph.png"
],
pros: [{
tpId: 1,
pid: 1001,
pname: "",
price: 3333,
pimg: ""
}],
username: this.$store.getters.getUser.userNickname,
islogin: this.$store.getters.getUser == null ? false : true,
currentPage:1,//初始页
listTotal: 0,//数据总量
pageSize:8//每页多少条数据
}
},
created() {
this.getList();
this.getType();
},
methods: {
handleSizeChange: function (size) { // 下拉框选择分页的大小
this.pageSize = size;
this.getList();
},
handleCurrentChange: function(currentPage){ //点击跳转第几页
this.currentPage = currentPage;
this.getList();
},
getList:function() { // 获取商品列表
var vm = this;
var choice = {
proName: vm.proName,
selectedTypeId: vm.selectedTypeId,
lprice: vm.lprice,
hprice: vm.hprice,
pageNum: vm.currentPage,
pageSize:vm.pageSize
};
this.axios({
method: 'POST',
url: 'http://localhost:8090/product/list',
transformRequest: [function (data) {
return Qs.stringify(data)
}],
data: choice
}).then( function (resp) {
vm.pros = resp.data.list;
vm.listTotal = resp.data.total;
});
},
getProInfo(pid) {
var p = {
options: this.options,
pid: pid
};
this.$router.push({name: 'ProductInfo', params: p});
},
getType: function () { // 获取商品类型
var vm = this;
this.axios({
method: 'GET',
url: 'http://localhost:8090/productType/list'
}).then(function (resp) {
vm.options = resp.data;
// console.log(vm.options.typeName);
});
},
select() {
var vm = this;
var choice = {
proName: vm.proName,
selectedTypeId: vm.selectedTypeId,
lprice: vm.lprice,
hprice: vm.hprice,
};
console.log(choice);
}
}
}
</script>
<style scoped>
.el-header, .el-footer {
background-color: #ffffff;
color: #333;
text-align: center;
line-height: 60px;
}
.el-main {
color: #333;
text-align: center;
padding: 10px 0px 50px 0px;
}
.product {
display: inline-block;
width: 350px;
margin-top: 20px;
margin-bottom: 10px;
padding-bottom: 10px;
/*border-bottom: 1px solid red;*/
}
.product img {
width: 220px;
height: 280px;
}
.bg-purple-dark {
background: #000000;
}
.grid-content {
min-height: 36px;
height: 45px;
}
.nav {
float: left;
margin: 10px 0px 0px 30px;
}
.nav-1 {
margin-left: 200px;
}
.select {
border-radius: 5px;
border: #E9EEF3;
height: 35px;
border: 1px solid #000000;
}
.select-input {
width: 160px;
}
.select-option {
margin-right: 10px;
width: 125px;
}
.select-input-price {
width: 75px;
}
.footer-content {
height: 80px;
}
.footer-content-1 {
height: 220px;
}
.footer-content-1 span {
letter-spacing: 3px;
display: block;
text-align: left;
line-height: 40px;
margin-left: 40px;
height: 35px;
font-size: 16px;
}
.footer-content-2 {
height: 110px;
line-height: 24px;
text-align: left;
}
</style>
2.3 商品详情页面搭建
点击查看代码<template>
<div>
<el-container>
<el-row>
<el-col :span="12">
<div class="grid-content bg-purple-dark">
<div class="nav nav-1">
<el-link type="info">首页</el-link>
</div>
<div class="nav">
<el-link type="info">官网</el-link>
</div>
</div>
</el-col>
<el-col v-if="!islogin" :span="6">
<div class="grid-content bg-purple-dark">
<div class="nav nav-1">
<el-link type="info" @click="$router.push('/login')">请登录</el-link>
</div>
<div class="nav">
<el-link type="info">注册</el-link>
</div>
</div>
</el-col>
<el-col v-if="islogin" :span="6">
<div class="grid-content bg-purple-dark">
<div class="nav nav-1">
<el-link type="info"><span>欢迎你,{{username}}</span></el-link>
</div>
<div class="nav">
<el-link type="info" @click="$router.push('/logout')">注销</el-link>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="grid-content bg-purple-dark">
<div class="nav">
<el-link type="info">我的订单</el-link>
</div>
<div class="nav">
<el-link type="info">购物车</el-link>
</div>
</div>
</el-col>
</el-row>
<el-header height="80px">
<div class="grid-content bg-purple" align="left" style="float: left">
<img src="../assets/logo.png" style="width: 205px; height: 36px;margin: 25px 0px 0px 150px">
</div>
<div style="float: left; margin-top: 10px;width: 75%">
<div style="float: left; margin-left: 150px">商品名称:
<input v-model="proName" class="select select-input"/>
</div>
<div style="float: left; margin-left: 30px">
商品类型:<select v-model="selectedTypeId" class="select select-option">
<option v-for="option in options" v-bind:value="option.typeId">{{option.typeName}}</option>
</select>
价格区间:<input v-model="lprice" class="select select-input-price"/>-<input v-model="hprice"
class="select select-input-price"/>
<el-button type="primary" icon="el-icon-search"
@click="select()"></el-button>
</div>
</div>
</el-header>
<div style="width: 99%;border: 1px solid #000;margin-bottom: 8px"></div>
<el-container>
<el-aside width="550px">
<el-row>
<el-col :span="8">
<div class="bg-purple">
<img class="proimg" :src="pro.pimg">
</div>
</el-col>
</el-row>
</el-aside>
<el-main>
<div style="margin-left: 80px;line-height: 80px">
<div><h3>商品名称:{{pro.pname}}</h3></div>
<div><h3>商品价格:<span style="color: red;color: red">¥{{pro.price}}</span></h3></div>
<div><h3>商品数量:{{pcount}}</h3></div>
<div>
<el-input-number v-model="pcount" :step="1" :min="1"></el-input-number>
<el-button type="danger" @click="gtCart()">加入购物车</el-button>
</div>
</div>
</el-main>
</el-container>
</el-container>
</div>
</template>
<script>
export default {
name: "ProductInfo",
data() {
return {
pid: this.$route.params.pid,
pro: {
pimg: ''
},
options: this.$route.params.options,
selectedTypeId: '',
proName: '',
lprice: '',
hprice: '',
pcount: 1,
username: this.$store.getters.getUser.userNickname,
islogin: this.$store.getters.getUser == null ? false : true
}
},
created() {
this.getProduct();
},
methods: {
getProduct() {
var vm = this;
this.axios({
method: 'GET',
url: 'http://localhost:8090/product/getProductBypid?pid=' + vm.pid
}).then(function (resp) {
vm.pro = resp.data;
})
},
gtCart: function () {
var p = {
userId: this.$store.getters.getUser.userId,
pid: this.pro.pid,
pcount: this.pcount,
options: this.options
};
this.$router.push({name: 'Cart', params: p});
}
}
}
</script>
<style scoped>
.el-header, .el-footer {
color: #333;
text-align: center;
line-height: 60px;
}
.proimg {
width: 400px;
height: 500px;
}
.el-main {
color: #333;
text-align: left;
padding: 10px 0px 50px 0px;
}
.el-button {
margin-left: 30px;
}
.el-aside {
padding-left: 80px;
}
.bg-purple-dark {
background: #000000;
}
.grid-content {
min-height: 36px;
height: 45px;
}
.nav {
float: left;
margin: 10px 0px 0px 30px;
}
.nav-1 {
margin-left: 200px;
}
.select {
border-radius: 5px;
border: #E9EEF3;
height: 35px;
border: 1px solid #000000;
}
.select-input {
width: 160px;
}
.select-option {
margin-right: 10px;
width: 125px;
}
.select-input-price {
width: 75px;
}
</style>
2.4 购物车页面搭建
点击查看代码<template>
<el-container>
<el-row>
<el-col :span="12">
<div class="grid-content bg-purple-dark">
<div class="nav nav-1">
<el-link type="info">首页</el-link>
</div>
<div class="nav">
<el-link type="info">官网</el-link>
</div>
</div>
</el-col>
<el-col v-if="!islogin" :span="6">
<div class="grid-content bg-purple-dark">
<div class="nav nav-1">
<el-link type="info" @click="$router.push('/login')">请登录</el-link>
</div>
<div class="nav">
<el-link type="info">注册</el-link>
</div>
</div>
</el-col>
<el-col v-if="islogin" :span="6">
<div class="grid-content bg-purple-dark">
<div class="nav nav-1">
<el-link type="info"><span>欢迎你,{{username}}</span></el-link>
</div>
<div class="nav">
<el-link type="info" @click="$router.push('/logout')">注销</el-link>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="grid-content bg-purple-dark">
<div class="nav">
<el-link type="info">我的订单</el-link>
</div>
<div class="nav">
<el-link type="info">购物车</el-link>
</div>
</div>
</el-col>
</el-row>
<el-header height="80px">
<div class="grid-content bg-purple" align="left" style="float: left">
<img src="../assets/logo.png" style="width: 205px; height: 36px;margin: 25px 0px 0px 150px">
</div>
<div style="float: left; margin-top: 10px;width: 75%">
<div style="float: left; margin-left: 150px">商品名称:
<input v-model="proName" class="select select-input"/>
</div>
<div style="float: left; margin-left: 30px">
商品类型:<select v-model="selectedTypeId" class="select select-option">
<option v-for="option in options" v-bind:value="option.typeId">{{option.typeName}}</option>
</select>
价格区间:<input v-model="lprice" class="select select-input-price"/>-<input v-model="hprice"
class="select select-input-price"/>
<el-button type="primary" icon="el-icon-search"
@click="select()"></el-button>
</div>
</div>
</el-header>
<el-main>
<h2>我的购物车信息</h2>
<div align="center">
<el-table
ref="multipleTable"
:data="tableData"
tooltip-effect="dark"
style="width:820px"
:header-cell-style="{'text-align':'center'}"
:cell-style="{'text-align':'center'}"
@selection-change="handleSelectionChange">
<el-table-column
type="selection"
width="100">
</el-table-column>
<el-table-column
prop="pname"
label="商品名称"
width="300">
</el-table-column>
<el-table-column
prop="price"
label="商品价格"
width="200">
</el-table-column>
<el-table-column
prop="pcount"
label="商品数量"
width="200"
show-overflow-tooltip>
</el-table-column>
</el-table>
</div>
<div align="left">
<el-button class="el-button--success" @click="">管理(删除订单)</el-button>
<el-button class="el-button--danger" @click="open">结算(提交订单)</el-button>
</div>
<router-view></router-view>
</el-main>
</el-container>
</template>
<script>
export default {
name: "Cart",
data() {
return {
tableData: [{
pname: 'HUAWEI P30',
price: '6778',
pcount: 2
}],
multipleSelection: [],
userId: this.$route.params.userId,
pid: this.$route.params.pid,
pcount: this.$route.params.pcount,
totalMoney: 0,
options: this.$route.params.options,
selectedTypeId: '',
lprice: '',
hprice: '',
proName: '',
username: this.$store.getters.getUser.userNickname,
islogin: this.$store.getters.getUser == null ? false : true
}
},
created() {
this.getTableDate();
},
methods: {
handleSelectionChange(val) {
//当多选框变化是调用的函数
this.totalMoney = 0;
this.multipleSelection = val;
// console.log(this.multipleSelection)
this.multipleSelection.forEach(row => {
//获取选中的每一行的数据
// console.log(row);
this.totalMoney += row.price * row.pcount;
})
},
getTableDate() {
var vm = this;
this.axios({
method: 'GET',
url: 'http://localhost:8090/cart/addCart?userId=' + vm.userId + '&pid=' + vm.pid + '&pcount=' + vm.pcount
}).then(function (resp) {
console.log(resp.data);
vm.tableData = resp.data
})
},
open() { // 打开提交订单的表单
var p = {
uId: this.userId,
totalMoney: this.totalMoney,
pIds: [],
opt: this.options,
};
//获取选中的每一行的商品的id
var i = 0;
this.multipleSelection.forEach(row => {
p.pIds[i] = row.pid;
i++;
});
this.$router.push({name: 'CartForm', params: p});
}
}
}
</script>
<style scoped>
.el-header, .el-footer {
color: #333;
text-align: center;
line-height: 60px;
}
.bg-purple-dark {
background: #000000;
}
.grid-content {
min-height: 36px;
height: 45px;
}
.el-main {
color: #333;
text-align: center;
/*line-height: 560px;*/
/*height: 800px;*/
padding: 10px 0px 50px 0px;
}
.nav {
float: left;
margin: 10px 0px 0px 30px;
}
.nav-1 {
margin-left: 200px;
}
.select {
border-radius: 5px;
border: #E9EEF3;
height: 35px;
border: 1px solid #000000;
}
.select-input {
width: 160px;
}
.select-option {
margin-right: 10px;
width: 125px;
}
.select-input-price {
width: 75px;
}
.el-button--success {
margin: 30px 200px 30px 500px;
}
</style>
2.5 订单页面搭建
点击查看代码<template>
<el-container>
<el-row>
<el-col :span="12">
<div class="grid-content bg-purple-dark">
<div class="nav nav-1">
<el-link type="info">首页</el-link>
</div>
<div class="nav">
<el-link type="info">官网</el-link>
</div>
</div>
</el-col>
<el-col v-if="!islogin" :span="6">
<div class="grid-content bg-purple-dark">
<div class="nav nav-1">
<el-link type="info" @click="$router.push('/login')">请登录</el-link>
</div>
<div class="nav">
<el-link type="info">注册</el-link>
</div>
</div>
</el-col>
<el-col v-if="islogin" :span="6">
<div class="grid-content bg-purple-dark">
<div class="nav nav-1">
<el-link type="info"><span>欢迎你,{{username}}</span></el-link>
</div>
<div class="nav">
<el-link type="info" @click="$router.push('/logout')">注销</el-link>
</div>
</div>
</el-col>
<el-col :span="6">
<div class="grid-content bg-purple-dark">
<div class="nav">
<el-link type="info">我的订单</el-link>
</div>
<div class="nav">
<el-link type="info">购物车</el-link>
</div>
</div>
</el-col>
</el-row>
<el-header height="80px">
<div class="grid-content bg-purple" align="left" style="float: left">
<img src="../assets/logo.png" style="width: 205px; height: 36px;margin: 25px 0px 0px 150px">
</div>
<div style="float: left; margin-top: 10px;width: 75%">
<div style="float: left; margin-left: 150px">商品名称:
<input v-model="proName" class="select select-input"/>
</div>
<div style="float: left; margin-left: 30px">
商品类型:<select v-model="selectedTypeId" class="select select-option">
<option v-for="option in options" v-bind:value="option.typeId">{{option.typeName}}</option>
</select>
价格区间:<input v-model="lprice" class="select select-input-price"/>-<input v-model="hprice"
class="select select-input-price"/>
<el-button type="primary" icon="el-icon-search"
@click="select()"></el-button>
</div>
</div>
</el-header>
<el-main>
<div v-for="order in orders" align="center" style="border: 1px solid black;margin-bottom: 10px;">
<el-table
:data="order.products"
highlight-current-row
:header-cell-style="{'text-align':'center'}"
:cell-style="{'text-align':'center'}"
style="width: 98%">
<el-table-column type="expand">
<el-table
:data="order.products"
:header-cell-style="{'text-align':'center'}"
style="width: 95%">
<el-table-column label="商品名称" width="400">
<template slot-scope="scope">
<span style="margin-left: 10px;margin-left: 100px;">{{ scope.row.pname }}</span>
</template>
</el-table-column>
<el-table-column label="商品价格" width="200" align="center">
<template slot-scope="scope">
<span size="medium">{{ scope.row.price }}</span>
</template>
</el-table-column>
<el-table-column label="商品数量" width="200" align="center">
<template slot-scope="scope">
<span size="medium">{{ scope.row.pcount }}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="450" align="center">
<template slot-scope="scope">
<el-button
size="mini"
type="danger"
@click="handleDelete(scope.$index, scope.row)">删除</el-button>
<el-button
size="mini"
type="primary"
@click="pay(order)">支付</el-button>
</template>
</el-table-column>
</el-table>
</el-table-column>
<el-table-column :label="'订单创建时间:'+order.createdTime"/>
<el-table-column :label="'订单编号:'+order.orderId"/>
<el-table-column :label="'订单总金额:¥'+order.orderPrice"/>
<el-table-column label="订单支付"/>
</el-table>
</div>
</el-main>
</el-container>
</template>
<script>
export default {
name: "Orders",
data() {
return {
user: this.$store.getters.getUser,
payImgSrc: '',
orderId: '',
orders: [{
createTime: '',
order_id: '',
orderPrice: 4777,
products: [{
pname: '',
price: 0,
pcount: 0
}]
}],
falg: '',
selectedTypeId: '',
options: this.$route.params.op,
lprice: '',
hprice: '',
proName: '',
username: this.$store.getters.getUser.userNickname,
islogin: this.$store.getters.getUser == null ? false : true
}
},
created() {
this.getData();
},
methods: {
getData() {
var vm = this;
this.axios({
method: 'GET',
url: 'http://localhost:8090/order/list?userId=' + vm.user.userId
}).then(function (resp) {
vm.orders = resp.data;
console.log(vm.orders[0]["products"][0]);
});
},
pay(order) {
var d = {
orderId: order.orderId,
orderPrice: order.orderPrice
};
this.$router.push({name: 'Pay', params: d})
}
}
}
</script>
<style scoped>
.el-header {
background-color: #ffffff;
color: #333;
text-align: center;
line-height: 60px;
}
.bg-purple-dark {
background: #000000;
}
.grid-content {
min-height: 36px;
height: 45px;
}
.nav {
float: left;
margin: 10px 0px 0px 30px;
}
.nav-1 {
margin-left: 200px;
}
.select {
border-radius: 5px;
border: #E9EEF3;
height: 35px;
border: 1px solid #000000;
}
.select-input {
width: 160px;
}
.select-option {
margin-right: 10px;
width: 125px;
}
.select-input-price {
width: 75px;
}
</style>
2.6 解决VUEX中刷新数据不存在的问题
前端页面中要显示的当前登录的用户名,可通过后端接口得到,也可直接从浏览器中获取(登录成功后),此处介绍后者使用情况,在实现过程中如果遇到用户名刷新页面即丢失的情况,可按照如下步骤解决!
使用SessionStorage进行解决!
-
SessionStorage浏览器提供的用于会话管理的空间
-
如何操作这片空间,在js中:
- sessionStorage.setItem("键","值")
- sessionStorage.getItem("键"):值
- sessionStorage.clear() 清空
使用步骤:
-
在src文件夹下创建store/index.js
点击查看代码import Vue from 'vue' import Vuex from 'vuex' Vue.use(Vuex); // 全局 state 对象,用于保存所有组件的公共数据 const state = sessionStorage.getItem('state') ? JSON.parse(sessionStorage.getItem('state')) : { user: { username: '' } }; // 实时监听 state 值的最新状态,注意这里的 getters 可以理解为计算属性 const getters = { // 在组件中是通过 this.$store.getters.getUser 来获取 getUser(state) { return state.user; } }; // 定义改变 state 初始值的方法,这里是唯一可以改变 state 的地方,缺点是只能同步执行 const mutations = { // 在组件中是通过 this.$store.commit('updateUser', user); 方法来调用 mutations updateUser(state, user) { state.user = user; } }; // 定义触发 mutations 里函数的方法,可以异步执行 mutations 里的函数 const actions = { // 在组件中是通过 this.$store.dispatch('asyncUpdateUser', user); 来调用 actions asyncUpdateUser(context, user) { context.commit('updateUser', user); } }; export default new Vuex.Store({ state, getters, mutations, actions });
-
在main.js中添加如下配置
点击查看代码// 在跳转前执行 router.beforeEach((to, form, next) => { // 获取用户登录状态 let isLogin = sessionStorage.getItem('isLogin'); // 注销 if (to.path == '/logout') { // 清空 sessionStorage.clear(); // 跳转到登录 next({path: '/login'}); } // 如果请求的是登录页 else if (to.path == '/login') { if (isLogin != null) { // 跳转到首页 next({path: '/home'}); } } // 如果为非登录状态 else if (isLogin == null) { // 跳转到登录页 next({path: '/login'}); } // 下一个路由 next(); });
-
在登录Login.vue组件中添加
var user = resp.data.data; sessionStorage.setItem("isLogin", "true") //往vuex里存放一个user对象 //先要有user对象 //再存到vuex里 vm.$store.dispatch('asyncUpdateUser', user);
-
再在首页Home.vue组件里获取vuex对象里的user对象的内容
username: this.$store.getters.getUser.userNickname
3、前后端建立连接的桥梁--->接口文档的编写
注:访问密码---->123456