1.电商业务概述

客户使用的业务服务:PC端,小程序,移动web,移动app
管理员使用的业务服务:PC后台管理端。
PC后台管理端的功能:管理用户账号(登录,退出,用户管理,权限管理),商品管理(商品分类,分类参数,商品信息,订单),数据统计
电商后台管理系统采用前后端分离的开发模式
前端项目是基于Vue的SPA(单页应用程序)项目

前端技术栈:Vue,Vue-Router,Vuex,Element-UI,Axios,Echarts
后端技术栈:Node.js,Express,Jwt(模拟session),MySQL,Sequelize(操作数据库的框架)

2.项目初始化

A.安装Vue脚手架
B.通过脚手架创建项目 命令:vue ui
C.配置路由、Vuex
D.配置Element-UI:在插件中安装,搜索vue-cli-plugin-element
E.配置Axios:在依赖中安装,搜索axios(运行依赖)
F.初始化git
G.将本地项目托管到github或者gitee(码云)中

3.码云相关操作

A.注册登录码云账号

B.安装git
在Windows上使用Git,可以从Git官网直接下载安装程序进行安装。
测试命令:git --version

C.点击网站右上角“登录”,登录码云,并进行账号设置

D.在本地创建公钥:在终端运行:ssh-keygen -t rsa -C “xxx@xxx.com”

E.找到公钥地址:
Your identification has been saved in /c/Users/My/.ssh/id_rsa.
Your public key has been saved in /c/Users/My/.ssh/id_rsa.pub.
当我们创建公钥完毕之后,请注意打印出来的信息“Your public key has been saved in”
/c/Users/My/.ssh/id_rsa.pub : c盘下面的Users下面的My下面的.ssh下面的id_rsa.pub就是我们创建好的公钥了

E.打开id_rsa.pub文件,复制文件中的所有代码,点击码云中的SSH公钥,将生成的公钥复制到公钥中


G.测试公钥:打开终端,输入命令
ssh -T git@gitee.com

H.将本地代码托管到码云中
点击码云右上角的+号->新建仓库

I.进行git配置:

打开项目所在位置的终端,进行git仓库关联

4.配置后台项目

A.安装mysql数据库,并导入创建数据库(mydb),执行mydb.sql文件

打开MySQL命令行,执行以下代码:

mysql> create database mydb;          # 创建数据库
mysql> use mydb;                     # 使用已创建的数据库
mysql> source /Vue电商项目相关资料/vue_api_server/db/mydb.sql            # 导入备份数据库

B.安装nodeJS,配置后台项目,从终端打开后台项目vue_api_server
然后在终端中输入命令安装项目依赖包:npm install
启动项目命令:node app.js
C.安装postman,使用postman测试api接口
postman下载路径:
https://www.postman.com/downloads/?utm_source=postman-home

5.实现登录功能

A.登录状态保持
如果服务器和客户端同源,建议可以使用cookie或者session来保持登录状态
如果客户端和服务器跨域了,建议使用token进行维持登录状态。
B.登录逻辑:
在登录页面输入账号和密码进行登录,将数据发送给服务器
服务器返回登录的结果,登录成功则返回数据中带有token
客户端得到token并进行保存,后续的请求都需要将此token发送给服务器,服务器会验证token以保证用户身份。

接口管理

封装axios实例 —— request.js

在项目src目录下新建utils文件夹,然后在其中新建 request.js文件。 需要什么就配什么!

// 1.引入axios
// 2.axios.create方法创建实例
// 3.使用实例对象创建请求拦截器
// 4.使用实例创建响应拦截器
// 5.export抛出实例对象
import axios from 'axios'
// import store from '@/store'
// 1. 创建新的axios实例
const request = axios.create({// 公共接口--这里注意后面会讲baseURL: 'http://127.0.0.1:8888/api/private/v1/',// 超时时间 单位是ms,这里设置了3s的超时时间timeout: 3 * 1000
})
// request拦截器
request.interceptors.request.use(config => {// 发请求前做的一些处理,数据转化,配置请求头,设置token,设置loading等,根据需求去添加config.data = JSON.stringify(config.data) // 数据转化,也可以使用qs转换config.headers = {'Content-Type': 'application/json' // 配置请求头}// 注意使用token的时候需要用localStorage方法来获取const token = localStorage.getItem('token') // 这里取token之前,你肯定需要先拿到token,存一下if (token) {config.headers.Authorization = token // 如果要求携带在请求头中}return config}, error => {Promise.reject(error)})// response拦截器
request.interceptors.response.use(response => {// 接收到响应数据并成功后的一些共有的处理,关闭loading等return response
}, error => {/* 接收到异常响应的处理开始 */if (error && error.response) {// 1.公共错误处理// 2.根据响应码具体处理switch (error.response.status) {case 400:error.message = '错误请求'breakcase 401:error.message = '未授权,请重新登录'breakcase 403:error.message = '拒绝访问'breakcase 404:error.message = '请求错误,未找到该资源'// window.location.href = '/NotFound'breakcase 405:error.message = '请求方法未允许'breakcase 408:error.message = '请求超时'breakcase 500:error.message = '服务器端出错'breakcase 501:error.message = '网络未实现'breakcase 502:error.message = '网络错误'breakcase 503:error.message = '服务不可用'breakcase 504:error.message = '网络超时'breakcase 505:error.message = 'http版本不支持该请求'breakdefault:error.message = `连接错误${error.response.status}`}} else {// 超时处理if (JSON.stringify(error).includes('timeout')) {this.$message.error('服务器响应超时,请刷新当前页')}error.message = '连接服务器失败'}this.$message.error(error.message)/* 处理结束 */// 如果不需要错误处理,以上的处理过程都可省略return Promise.resolve(error.response)
})export default request

封装请求——http.js

在项目src目录下的utils文件夹中新建 http.js文件。

/*    http.js    */
// 导入封装好的axios实例
import request from './request'const http = {/*** methods: 请求* @param url 请求地址* @param params 请求参数*/get (url, params) {const config = {method: 'get',url: url}if (params) {config.params = params}return request(config)},post (url, params) {const config = {method: 'post',url: url}if (params) {config.data = params}return request(config)},put (url, params) {const config = {method: 'put',url: url}if (params) {config.params = params}return request(config)},delete (url, params) {const config = {method: 'delete',url: url}if (params) {config.params = params}return request(config)}
}
// 导出/*    http.js    */
// 导入封装好的axios实例
import request from './request'const http = {/*** methods: 请求* @param url 请求地址* @param params 请求参数*/get (url, params) {const config = {method: 'get',url: url}if (params) {config.params = params}return request(config)},post (url, data) {const config = {method: 'post',url: url}if (data) {config.data = data}console.log(config)return request(config)},put (url, data) {const config = {method: 'put',url: url}if (params) {config.data = data}return request(config)},delete (url, params) {const config = {method: 'delete',url: url}if (params) {config.params = params}return request(config)}
}
// 导出
export default http

封装API——用于发送请求

在项目src目录下新建api文件夹,以用户登录为案例,然后在其中新建 user.js文件

import http from '../utils/http.js'
// post请求
export function login (params) {return http.post('login', params)
}

添加新分支login,在login分支中开发当前项目vue_shop:
打开vue_shop终端,使用git status确定当前项目状态。
确定当前工作目录是干净的之后,创建一个分支进行开发,开发完毕之后将其合并到master
git checkout -b login
然后查看新创建的分支:git branch
确定我们正在使用login分支进行开发

然后执行vue ui命令打开ui界面,然后运行serve,运行app查看当前项目效果

登录组件

打开项目的src目录,点击main.js文件(入口文件)进行更改

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import './plugins/element.js'import store from './store'Vue.config.productionTip = falsenew Vue({router,store,render: h => h(App)
}).$mount('#app')

再打开App.vue(根组件),将根组件的内容进行操作梳理(template中留下根节点,script中留下默认导出,去掉组件,style中去掉所有样式)

<template><div id="app"><router-view></router-view></div>
</template><script>
export default {name: 'app'
}
</script><style>
</style>

再打开router.js(路由),将routes数组中的路由规则清除,然后将views删除,将components中的helloworld.vue删除

import Vue from 'vue'
import Router from 'vue-router'Vue.use(Router)export default new Router({routes: []
})

在components文件夹中新建Login.vue组件,添加template,script,style标签,style标签中的scoped可以防止组件之间的样式冲突,没有scoped则样式是全局的

<template><div class="login_container"></div>
</template><script>
export default {}
</script><style lang="scss" scoped>
.login_container {background-color: #2b5b6b;height: 100%;
}</style>

在router.js中导入组件并设置规则
在App.vue中添加路由占位符

const router = new Router({routes: [{ path: '/', redirect: '/login' },{ path: '/login', component: Login }]
})

当我们给Login.vue中的内容添加样式的时候,会报错“缺少sass-loader”,需要配置sass加载器(开发依赖),安装sass(开发依赖)

cnpm install sass-loader@10.1.1
cnpm i node-sass@4.14.1 // 安装
// 如果node-sass安装失败,也可以直接在package.json中写上版本号,删除node_modules文件夹,重新npm i即可

然后需要添加公共样式,安装normalize.css

npm install normalize.css -S

在main.js中我们引入normalize.css样式:import 'normalize.css/normalize.css'
然后Login.vue中的根元素也需要设置撑满全屏(height:100%)
最终Login.vue文件中的代码如下

<template><div><!-- 背景动画 --><ul class="bg-bubbles"><li v-for="(item, index) in bubbles" :key="index"></li></ul><!-- 登录卡片 --><el-card class="box-card"><h2>登录</h2><!-- 登录表单 --><el-form :model="loginForm" :rules="rules" ref="LoginFormRef"><!-- 用户名 --><el-form-item prop="username"><el-input v-model="loginForm.username" prefix-icon="el-icon-user"></el-input></el-form-item><!-- 密码 --><el-form-item prop="password"><el-input type="password" v-model="loginForm.password" prefix-icon="el-icon-lock"></el-input></el-form-item><el-form-item class="btns"><el-button type="primary" @click="submitLogin('LoginFormRef')">登录</el-button><el-button type="info" @click="resetLogin('LoginFormRef')">重置</el-button></el-form-item></el-form></el-card></div>
</template><script>import {login} from '@/api/user'export default {data() {return {// 数据绑定bubbles: [], // 背景样式loginForm: {username: '',password: ''},// 表单验证规则rules: {username: [{required: true,message: '*请输入用户名',trigger: 'blur'},{min: 3,max: 10,message: '*用户名长度在3到10个字符',trigger: 'blur'}],password: [{required: true,message: '*请输入密码',trigger: 'blur'},{min: 6,max: 18,message: '*密码长度在6到18个字符',trigger: 'blur'}]}}},created() {this.bubbles.length = 10},methods: {submitLogin(LoginFormRef) { // 提交表单// 点击登录的时候先调用validate方法验证表单内容是否有误this.$refs.LoginFormRef.validate(valid => {if (valid) {login(this.loginForm).then(res => {if (res.data.meta.status !== 200) {return this.$message.error(res.data.meta.msg)}// 保存token,存储到localStorage以及vuex中this.$store.commit('login', res.data.data.token)this.$message.success(res.data.meta.msg)// 导航至/homethis.$router.push('/home').catch(() => {})}).catch(err => {console.log(err)})} else {this.$message.error('登录失败')}})},resetLogin(LoginFormRef) { // 重置表单// this=>当前组件对象,其中的属性$refs包含了设置的表单refthis.$refs[LoginFormRef].resetFields()}}}
</script><style lang="scss" scoped>.bg-bubbles {background-image: linear-gradient(to bottom right, rgb(41, 174, 165), rgb(3, 234, 167));margin: 0px;position: absolute;width: 97%;height: 100%;overflow: hidden;li {position: absolute;// bottom 的设置是为了营造出气泡从页面底部冒出的效果;bottom: -100px;// 默认的气泡大小;width: 40px;height: 40px;background-color: rgba(255, 255, 255, 0.3);list-style: none;// 使用自定义动画使气泡渐现、上升、下降和翻滚;animation: square 15s infinite;transition-timing-function: linear;// 分别设置每个气泡不同的位置、大小、透明度和速度,以显得有层次感;&:nth-child(1) {left: 5%;}&:nth-child(2) {left: 10%;width: 90px;height: 90px;animation-delay: 2s;animation-duration: 7s;}&:nth-child(3) {left: 15%;animation-delay: 4s;}&:nth-child(4) {left: 30%;width: 60px;height: 60px;animation-duration: 8s;background-color: rgba(255, 255, 255, 0.3);}&:nth-child(5) {left: 60%;}&:nth-child(6) {right: 10%;width: 120px;height: 120px;animation-delay: 3s;background-color: rgba(255, 255, 255, 0.2);}&:nth-child(7) {left: 22%;width: 160px;height: 160px;animation-delay: 2s;}&:nth-child(8) {left: 75%;width: 20px;height: 20px;animation-delay: 4s;animation-duration: 15s;}&:nth-child(9) {left: 25%;width: 100px;height: 100px;animation-delay: 2s;animation-duration: 12s;background-color: rgba(255, 255, 255, 0.3);}&:nth-child(10) {right: 15%;width: 80px;height: 80px;animation-delay: 5s;}}// 自定义 square 动画;@keyframes square {0% {opacity: 0.5;transform: translateY(0px) rotate(45deg);}25% {opacity: 0.75;transform: translateY(-400px) rotate(90deg)}50% {opacity: 1;transform: translateY(-800px) rotate(135deg);}100% {opacity: 0;transform: translateX(-150px) rotate(180deg);}}}.box-card {width: 360px;position: absolute;top: 25%;left: 34%;padding: 0 20px;background-color: #fff;opacity: 0.8;}.btns {display: flex;justify-content: flex-end;}
</style>

其中我们有用到一下内容,需要进行进一步处理:
A.添加element-ui的表单组件
在plugins文件夹中打开element.js文件,进行elementui的按需导入

import { Form, FormItem } from 'element-ui'
import { Input } from 'element-ui'
import { Button } from 'element-ui'
import { Icon } from 'element-ui'
import { Card } from 'element-ui'Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
Vue.use(Button)
Vue.use(Icon)
Vue.use(Card)

B.添加表单验证的步骤
1).给添加属性:rules=“rules”,rules是一堆验证规则,定义在script、中
2).在script中添加rules:

export default{ data(){return{......, rules: {username: [{ required: true, message: '*请输入用户名', trigger: 'blur' },{ min: 3, max: 10, message: '*用户名长度在3到10个字符', trigger: 'blur' }],password: [{ required: true, message: '*请输入密码', trigger: 'blur' },{ min: 6, max: 18, message: '*密码长度在6到18个字符', trigger: 'blur' }]}......

3).通过的prop属性设置验证规则
5.配置弹窗提示:
在plugins文件夹中打开element.js文件,进行elementui的按需导入
import {Message} from ‘element-ui’
进行全局挂载:Vue.prototype.$message = Message;
在login.vue组件中编写弹窗代码:this.$message.error(‘登录失败’)

通过状态管理保存token(登录状态)

A.登录成功之后,需要将后台返回的token保存通过状态管理保存token(登录状态)操作完毕之后,需要跳转到/home

export default {state: {token: '' // 定义token},mutations: {login: function(state, token) {state.token = tokenlocalStorage.setItem('token', token) // 保存token},logout: function(state) {localStorage.removeItem('token') // 删除token}}
}

修改stroe目录下的index.js文件,添加user模块

import Vue from 'vue'
import Vuex from 'vuex'
import user from '@/store/modules/user.js'Vue.use(Vuex)export default new Vuex.Store({state: {},mutations: {},actions: {},modules: {user}
})
      submitLogin(LoginFormRef) { // 提交表单// 点击登录的时候先调用validate方法验证表单内容是否有误this.$refs.LoginFormRef.validate(valid => {if (valid) {login(this.loginForm).then(res => {if (res.data.meta.status !== 200) {return this.$message.error(res.data.meta.msg)}// 保存token,存储到localStorage以及vuex中this.$store.commit('login', res.data.data.token)this.$message.success(res.data.meta.msg)// 导航至/homethis.$router.push('/home').catch(() => {})}).catch(err => {console.log(err)})} else {this.$message.error('登录失败')}})

添加一个组件Home.vue,并为之添加规则

<template><div>this is home<el-button type="info" @click="logout"> 退出 </el-button></div>
</template><script>
export default {methods: {logout() {sessionStorage.clear()this.$router.push('/login')}}
}
</script>
<style lang="scss" scoped>
</style>

添加路由规则

const routes = [{ path: '/', redirect: '/login' },{path: '/login',name: 'login',component: Login},{path: '/home',name: 'home',component: Home}
]

添加路由守卫

如果用户没有登录,不能访问/home,如果用户通过url地址直接访问,则强制跳转到登录页面
打开router.js

import Vue from 'vue'
import VueRouter from 'vue-router'
import Login from '@/views/Login.vue'
import Home from '@/views/Home.vue'Vue.use(VueRouter)const routes = [{ path: '/', redirect: '/login' },{path: '/login',name: 'login',component: Login},{path: '/home',name: 'home',component: Home}
]const router = new VueRouter({routes
})
// 挂载路由导航守卫,to表示将要访问的路径,from表示从哪里来,next是下一个要做的操作
router.beforeEach((to, from, next) => {if (to.path === '/login') {return next()}// 获取tokenconst token = localStorage.getItem('token')console.log(token)if (!token) {return next('/login')}next()
})export default router

实现退出功能

在Home组件中添加一个退出功能按钮,给退出按钮添加点击事件,添加事件处理代码如下:

export default {methods:{logout(){window.sessionStorage.clear();this.$router.push('/login');}}
}

补充

A.处理ESLint警告
打开脚手架面板,查看警告信息

默认情况下,ESLint和vscode格式化工具有冲突,需要添加配置文件解决冲突。
在项目根目录添加 .prettierrc 文件

{"semi":false,"singleQuote":true
}

打开.eslintrc.js文件,禁用对 space-before-function-paren 的检查:

  rules: {'no-console': process.env.NODE_ENV === 'production' ? 'error' : 'off','no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off','space-before-function-paren' : 0},

B.合并按需导入的element-ui

import Vue from 'vue'
import { Form, FormItem, Input, Button, Icon, Card, Message } from 'element-ui'Vue.use(Form)
Vue.use(FormItem)
Vue.use(Input)
Vue.use(Button)
Vue.use(Icon)
Vue.use(Card)Vue.prototype.$message = Message

将代码提交到码云

新建一个项目终端,输入命令‘git status’查看修改过的与新增的文件内容
将所有文件添加到暂存区:git add .
将所有代码提交到本地仓库:git commit -m “添加登录功能以及/home的基本结构”
查看当前分支: git branch 发现所有代码都被提交到了login分支
将login分支代码合并到master主分支,先切换到master:git checkout master
在master分支进行代码合并:git merge login
将本地的master推送到远端的码云:git push
推送本地的子分支到码云,先切换到子分支:git checkout 分支名
然后推送到码云:git push -u origin 远端分支名

Vue+ElementUI电商项目(一)相关推荐

  1. 前端学习之vue+element-ui电商项目(九)订单管理

    文章目录 0. 准备工作 1.界面样式 1.1 界面布局 1.2 导航区 2.订单数据列表 2.1 界面样式 2.2 数据添加 2.3 方法实现 3.分页区 3.1 界面样式 3.2 数据添加 3.3 ...

  2. 前端学习之vue+element-ui电商项目(八)商品信息添加

    文章目录 0. 准备工作 1.界面样式 1.1 界面布局 1.2 导航区视图 2.卡片视图区域 2.1 警示条 2.1.1 步骤条 3. 卡片视图的表单 3.1 tab 栏框架 3.1.2 tab 栏 ...

  3. vue.js电商项目--美丽购物街day01首页制作

    vue.js电商项目--美丽购物街day01 首页效果如图 划分目录结构 vue.config.js配置文件别名 App.vue文件 router文件下的index.js 封装网络请求 Home.vu ...

  4. [Vue]实战---电商项目(项目的概述及初始化)【一】

    项目实战 项目目录 项目概述 项目初始化 登录/退出功能 主页布局 用户管理模块 权限管理模块 分类管理模块 参数管理模块 商品管理模块 订单管理模块 数据统计模块 项目概述 电商项目基本业务概述 电 ...

  5. 【VUE项目】VUE+ElementUI电商后台管理系统

    电商后台管理系统 项目来源:https://www.bilibili.com/video/BV1x64y1S7S7?p=191&spm_id_from=333.1007.top_right_b ...

  6. 【vue】【开源】vue开源电商项目hello-mall嗨喽商城

    开源地址 https://github.com/zengxiaochao/hello-mall 觉得还行的小伙伴麻烦给个star,鼓励一下,非常感谢. hello-mall嗨喽商城 基于Vue+Ele ...

  7. Vue+Element-UI 电商后台管理系统详细总结

    一.概述 基于 Vue 和 Element-UI 的电商后台管理系统 1.1 实现功能 用户登录/退出 用户管理 用户列表 实现用户的增删改查.分页查询以及分配角色功能 权限管理 角色列表 实现角色的 ...

  8. Java项目:网上电商项目(前后端分离+java+vue+Springboot+ssm+mysql+maven+redis)

    源码获取:博客首页 "资源" 里下载! 一.项目简述 本系统功能包括: 一款基于Springboot+Vue的电商项目,前后端分离项目,前台后台都有,前台商品展示购买,购物车分类, ...

  9. Vue实战项,基于Element-UI 电商管理系统源代码,含项目部署指南

    电商项目基本业务概述 根据不同的应用场景,电商系统一般都提供了 PC 端.移动 APP.移动 Web.微信小程序等多种终端访问方式,我们主要是实现PC后台管理系统. 1.2 电商后台管理系统的功能 电 ...

最新文章

  1. 蚂蚁金服 CTO 程立登台新加坡 Money 20/20 Asia,传递技术让世界更平等的愿景
  2. 【220】◀▶ IDL 数组操作函数说明
  3. 线程池模式比较-------ICE线程池模型------L/F领导者跟随者模式
  4. 转向语句 goto语句
  5. 各linux版本比较
  6. C语言输出百分号%的方法和示例
  7. python读取xml文件有哪些方法_深入解读Python 解析xml的几种方式
  8. MySQL复制 自动监控脚本
  9. python生活中的小问题_python日常注意小知识集锦
  10. 计算机数值方法知识点,数值分析 全部 知识点.docx
  11. 360服务器linux版,360浏览器Linux版
  12. Python快速下载M3U8电影
  13. 微信开发者工具小技巧——快速打开微信程序API文档。
  14. [转]oracle性能调优之--Oracle 10g AWR 配置
  15. 机器学习kaggle案例:沃尔玛招聘 - 商店销售预测
  16. 群晖NAS 7.X 搭建个人博客网站并发布公网 1/8
  17. D2D D3D12 渲染视频帧思路及实现
  18. PIL库 : 居中对齐写入文本(英文 / 中文)
  19. 使用 微信JS-SDK 拍照 或者获取 相册 图片并展示
  20. js中exec()函数的使用

热门文章

  1. 比python更快制作大数据图表展示的平台
  2. ms08_067复现(windows sever 2003 英文/中文版系统)
  3. 洛咕 P3645 [APIO2015]雅加达的摩天楼
  4. 【教学类-24-01】20230306《数字火车-升序1-9取5填空1》(中班《玩具总动员》)
  5. 六石编程学:抄代码是个技术活,大多数人不传抄
  6. 6年之痒的小米智能电视,真的能扛起AIoT的大旗?
  7. Struts2 s:property标签的escapeHtml属性
  8. 一线大厂程序员谈回长沙感受:这不是退路,而是新的开始
  9. 一周一论文(翻译)——[ICDCS 15] DRS: 在快速流下实时计算分析的动态资源调度系统
  10. 2023(吉林)功能性农业·农业大健康大会春耕示范基地授牌启动