前端后台管理系统梳理

再梳理一遍
在这里插入图片描述

一、商品后台管理系统

1. 功能

1.1 服务端情况

  • 开启了CORS跨域支持
  • 需要授权的 API ,必须在请求头中使用 Authorization 字段提供token 令牌(axios拦截器)
  • baseUrl,接口地址:http://localhost:8888/api/private/v1/

token令牌在服务端生成,当登录成功时,post请求返回的用户信息里包含了这一元素:
在这里插入图片描述

1.1.1 axios发ajax请求

Axios:通过promise实现对ajax技术的一种封装,ajax只能访问同源的请求。axios并没有install 方法,所以是不能使用vue.use()方法的。为了不在每个文件都引用一次axios,将它改造成vue插件。

  1. npm安装
  2. axios发请求

1)使用

axios.get('/user?ID=12345').then(function (response) {console.log(response);}).catch(function (error) {console.log(error);});

2) 改造为vue插件
plugins/http.js

import axios from 'axios'
​
const httpHelper = {}
// 配置Vue插件
httpHelper.install = function fn (Vue) {axios.defaults.baseURL = 'http://127.0.0.1:8888/api/private/v1'Vue.prototype.$http = axios
}
​
export default httpHelper

main.js里安装插件

 import http from '@/plugins/http.js'
Vue.use(http)

1.1.2 拦截器 – 向服务端发请求需要token

httpAxios.install = function (Vue) {const instance = axios.create({baseURL: 'http://127.0.0.1:8888/api/private/v1'})
​instance.interceptors.request.use(function (config) {if (config.url.toLowerCase() !== 'login') {const token = sessionStorage.getItem('token')config.headers.Authorization = token}return config}, function (error) {return Promise.reject(error)})Vue.prototype.$http = instance
}

1.1.3 路由导航守卫 – 权限控制

路由的前置守卫 router.js

router.beforeEach((to, from, next) => {console.log(to, from)if (to.name === 'login') {next()} else {const token = sessionStorage.getItem('token')if (!token) {router.push({ 'name': 'login' })Message.warning('请先登录')return}next()}
})

1.1.4 使用async和await

handleLogin () {this.$http.post('login', this.formData).then((res) => {const data = res.dataconst {meta: {status, msg}} = dataif (status === 200) {const token = data.data.tokensessionStorage.setItem('token', token)this.$message.success(msg)} else {this.$message.error(msg)}})
}
async handleLogin () {const res = await this.$http.post('login', this.formData)const data = res.dataconst { meta: { status, msg } } = dataif (status === 200) {const token = data.data.tokensessionStorage.setItem('token', token)this.$message.success(msg)} else {this.$message.error(msg)}
}

外层方法使用async关键字(await最近的外层函数要加上async),发请求代码前加 await,省略.then
在这里插入图片描述

1.2 自定义组件

以自定义面包屑组件(子组件)为例,父组件(使用到面包屑的组件)向子组件传值。
子组件

<template><!-- 面包屑 --><el-breadcrumb separator="/"><el-breadcrumb-item :to="{ path: '/' }">首页</el-breadcrumb-item><el-breadcrumb-item>{{this.level1}}</el-breadcrumb-item><el-breadcrumb-item>{{this.level2}}</el-breadcrumb-item></el-breadcrumb>
</template>
​
<script>
export default {name: 'my-bread',props: ['level1', 'level2']
}
</script>

父组件

<my-bread level1='权限管理' level2='角色列表'></my-bread>

1.3 登录

  • 组件el-form 表单
  • :rules=“rules” 表单验证,show-password
  • 登录按钮的点击事件:
    1)表单验证是否通过
    2)通过设置token,跳转到主页
  • 头像:css设置水平居中
  • 全局监听enter键(把监听事件绑定到document上),当(that.$route.path === ‘/login’) && (e.keyCode === 13),触发登录方法

1.4 主页

  • 布局
  • 头部+左侧导航菜单+主体

1.4.1 头部,退出

  • 删除token sessionStorage.clear()
  • 跳转到登录页 this.$router.push({name: 'login'})

1.4.2 左侧菜单 – 权限控制

  • el-aside -> el-menu
  • :router 开启路由模式,设置el-menu-item的index值 为路由标识
  • 动态渲染:不同身份登录,权限控制

一级菜单和子菜单之间是并列关系,在知道有几级菜单的情况下,思考:如果不知道有几级菜单

<el-menu :unique-opened=true :router=true><el-submenu :index="item1.order.toString()" v-for="(item1,i) in menus" :key="item1.id"><template slot="title"><i :class="iconlist[i]"></i><span>{{item1.authName}}</span></template><el-menu-item :index="item2.path" v-for="item2 in item1.children" :key="item2.id"><i class="el-icon-menu"></i><span>{{item2.authName}}</span></el-menu-item></el-submenu>
</el-menu>

1.5 系统功能

1.5.1 用户管理 - 用户列表 - 增删改查

  • 展示:现有用户数量 GET
  • 增加:用户名、密码、邮箱、手机,新增后重新加载页面 POST
  • 删除:删除后重新加载页面 PUT
  • 修改:DELETE
    1)改基本信息:手机、邮箱
    2)改角色:关系到权限
  • 组件
    面包屑、搜索框、表格、分页组件、switch状态转换
1.5.1.1 显示、搜索的处理

显示
在created的时候,调用this.getUserList(),拿到res的数据,赋值给data里的userlist

const res = await this.$http.get(`users?query=${this.query}&pagenum=${this.pagenum}&pagesize=${this.pagesize}`)

搜索

<el-input @clear="getUserList"  v-model="query" clearable @keyup.enter.native="getUserList">

键盘抬起时/输入框清空时,依然是触发getUserList,该方法内部通过双向数据绑定的query进行传参查询,接口文档中,query参数可以为空,为空时显示全量信息。

1.5.1.2 slot-scope=“scope” 参数传递
 
<el-table-column label="用户状态"><template slot-scope="scope"><!-- scope.row就是当前绑定的数据对象 --><el-switch @change="handleSwitchChange(scope.row)" v-model="scope.row.mg_state" active-color="#13ce66"inactive-color="#ff4949"></el-switch></template>
</el-table-column>
1.5.1.3 添加完成,清空文本框
for (const key in this.formData) {this.formData[key] = ''
}
1.5.1.4 编辑用户,显示已有信息

编辑按钮所在行,通过slot-scope="scope"将被编辑用户信息传给方法editUser,通过初始化form(显示用户信息的el-form所绑定的内容)展示

editUser(user) {this.dialogFormVisibleEdit = truethis.form = user
}
<el-dialog title="编辑用户" :visible.sync="dialogFormVisibleEdit"><el-form :model="form"><el-form-item label="用户名" ><el-input v-model="form.username" disabled></el-input></el-form-item></el-form>
</el-dialog>
1.5.1.5 下拉框-显示当前用户角色
  1. select标签有多个option,有selected属性的option,会默认选中
  2. 被选中的option的value值就是select的value值,当选择了其他角色时,select的value值也会随之改变 => 获取当前编辑用户的角色id,双向绑定给select的value,既处理了显示,又处理了角色分配。
    在这里插入图片描述

1.5.2 权限管理 - 权限列表、角色列表

1.5.2.1 权限列表

一到三级权限的名词展示,可以作为后台的文档数据,不必作为一项功能

1.5.2.2 角色列表
  • 添加角色(简单提交)
  • 编辑、删除(简单slot-scope传参、delete请求)
  • 分配角色(tag)
  • 权限展示(表格展开行)
【难点1】 三级权限展示,树形结构,row、col的结构

请求角色列表的产物,因此数据包含在getRoleList的返回值里。
理解el-row和el-col的关系,两者包含成为一维。

在这里插入图片描述

<el-row :gutter="20"><el-col :span="6"><div class="grid-content bg-purple"></div></el-col><el-col :span="6"><div class="grid-content bg-purple"></div></el-col><el-col :span="6"><div class="grid-content bg-purple"></div></el-col><el-col :span="6"><div class="grid-content bg-purple"></div></el-col>
</el-row>
{"data": [{"id": 30,"roleName": "主管","roleDesc": "技术负责人","children": [{"id": 101,"authName": "商品管理","path": null,"children": [{"id": 104,"authName": "商品列表","path": null,"children": [{"id": 105,"authName": "添加商品","path": null}]}]}]}],
}

在这里插入图片描述
在这里插入图片描述

代码怎么写:

  • 先纵向看,有几个一级权限就应当v-for循环出几行
  • 再横向看,每个el-row里,拿一个el-col现实出当级权限,另一个el-col再作为一个整体来看(再看成一行两列)
<el-row v-for="(item1,i) in scope.row.children" :key="i" class="expand"><!-- 第一列中放一级标签 --><el-col :span="4"><!-- 可移除标签,这里展示一级标签,绑定取消权限方法 --><el-tag class="expand" closable @close="delRight(item1.id,scope.row)">{{item1.authName}}</el-tag></el-col><el-col :span="20"><!-- 第二列也是一行两列 --><el-row v-for="(item2,index) in item1.children" :key="index"><!-- 第二行第一列中放二级标签 --><el-col :span="4"><el-tag class="expand" type="success" closable @close="delRight(item2.id,scope.row)">{{item2.authName}}</el-tag></el-col><el-col :span="20"><el-tag class="expand" @close="delRight(item3.id,scope.row)" closable type="warning"v-for="(item3,indexInner) in item2.children" :key="indexInner">{{item3.authName}}</el-tag></el-col></el-row></el-col>
</el-row>
【难点2】 分配权限,树形结构el-tree 全选、半选(如何展示)

在这里插入图片描述

  • 展开所有的权限(树形结构自带的属性:default-expand-all
  • 显示:先勾选上拥有的三级权限(三层forEach,获得所有三级权限的集合,赋值给checklistArr
    :default-checked-keys="checklistArr"
  • 提交:需要获取所有的一、二、三级权限的集合(全选+半选),传参修改

显示:

editRight(role) {// checklist权限的集合,是个树形结构this.checklist = role.childrenthis.currentRoleId = role.idvar tmpArr = []this.checklist.forEach(item1 => {var item2 = item1.childrenitem2.forEach(item2 => {var item3 = item2.childrenitem3.forEach(item3 => {tmpArr.push(item3.id)})})})this.checklistArr = tmpArr
}

提交:

async confirmRole() {let arr1 = this.$refs.mytree.getCheckedKeys()let arr2 = this.$refs.mytree.getHalfCheckedKeys()let arr = [...arr1, ...arr2]const res = await this.$http.post(`roles/${this.currentRoleId}/rights`, { rids: arr.join(',') })
}

在这里插入图片描述

1.5.3 商品管理 - 列表、分类参数、商品分类

1.5.3.1 商品分类

分类接口设计:
重要参数type,type=2(返回一层、二层分类),type=3(返回前三层分类)
在这里插入图片描述

1.【难点3】树形组件element-tree-grid在表格中的运用(组件选择、配置)
  • 表格样式:树形结构 +【是否有效】【级别】【操作】字段;
  • 组件选择:由于第一列的el-table-column要展示为树形结构,因此使用组件element-tree-grid,all props of el-table-column are supported;
  • 在获取到三级商品分类后,element-tree-grid只需要绑定好对应的属性,即可显示。
    在这里插入图片描述
<el-tree-grid treeKey="cat_id" parentKey="cat_pid" levelKey="cat_level" childKey="children" prop="cat_name"label="分类名称">
</el-tree-grid>
2.【难点4】级联选择器-添加分类(理解接口type参数)
  • 由于最细添加的是三级分类(或者添加一级、二级分类),因此级联选择器只用展示一、二级的父类,请求分类接口,type=2
  • value / v-model: 选中项绑定值,是一个数组
  • 级联选择器的handleChange方法,能获取到最接近一层的父类参数分类id,配置级别和分类名称,组成一个obj作为参数发POST请求
      handleChange(value) {console.log(value);}

在这里插入图片描述

1.5.3.2 【难点5】分类参数 – 只允许为三级分类设置参数
  • 级联选择器 type=3 展示出三级分类
  • 动态(涉及列表展开)、静态参数

如何限定只让第三级被选中:

    handleChange () {if (this.selectedOptions.length !== 3) {this.$message.warning('商品只能添加到三级分类')this.selectedOptions.length = 0}}
1.5.3.3 【难点6】什么时候渲染出参数,tabs标签页改造

el-tab-pane里含了el-table–绑定dynamicAttrs el-button
在点击了级联选择器器之后,渲染出动、静态参数

async handleChange() {if (this.value.length === 3) {if (this.active === '1') {// 动态参数const res = await this.$http.get(`categories/${this.value[2]}/attributes?sel=many`)this.dynamicAttrs = res.data.datathis.dynamicAttrs.forEach((item) => {// 把attr_vals转为数组类型item.attr_vals = item.attr_vals.split(',')})} else if (this.active === '2') {const res1 = await this.$http.get(`categories/${this.value[2]}/attributes?sel=only`)this.staticAttrs = res1.data.data}}
}
1.5.3.4 【体现功能】商品列表 - 1000条数据

在这里插入图片描述

商品参数数据格式:
参数名–参数值(可能有多个)

    "data": [{"attr_id": 1,"attr_name": "cpu","cat_id": 22,"attr_sel": "only","attr_write": "manual","attr_vals": "2G","4G","8G"}],
  • 查询名称、价格、重量、参数管理
  • 添加商品详细描述(名称、价格、重点、数量、分类、参数、属性、图片)
  • 步骤条组件+纵向tabs组件(需要包裹在el-form里)(并列关系)
  • 上传图片(饿了么Upload组件、百度Web Uploader)
  • 富文本编辑器
  • 功能上的bug,商品列表不能显示图片(接口没返回这个字段)
  • bug2,数据库表设计时,时间字段长度太短,导致时间不正确,令人汗颜

在这里插入图片描述
在这里插入图片描述

改了表字段的数据类型,可能不是最合适,但是时间显示正常了。创建时间的时候,还是以1970位默认值。在这里插入图片描述
在这里插入图片描述

1. 上传图片 – 拓展,检测文件格式;性能

请求上传接口,需要设置token(这里不是发axios请求)

<el-upload 
action="http://47.xxx.1xx.7:8888/api/private/v1/upload" 
:headers="header" 
:on-remove="handleRemove" 
:on-success="handleSuccess" 
:file-list="fileList" 
list-type="picture"><el-button size="small" type="primary">点击上传</el-button><div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>header: {Authorization: sessionStorage.getItem('token')
}
2. 富文本编辑器组件 vue-quill-editor
<quill-editor v-model="form.goods_introduce"></quill-editor>

1.5.4 订单管理

1.5.5 数据统计

2. 框架选择 – vue

  1. 容易上手:react(JSX,学习成本),vue(模板):任何合乎规范的 HTML 都是合法的 Vue 模板。可以在单文件组件里完全控制 CSS,将其作为组件代码的一部分。
  2. vue-cli(核心插件)供了各种用途的模板。
  3. 体积:一个包含了 Vuex + Vue Router 的 Vue 项目 (gzip 之后 30kB) 相比使用了这些优化的 angular-cli 生成的默认项目尺寸 (~65KB) 还是要小得多。
  4. 当某个组件的状态发生变化时,系统能精确知晓哪个组件确实需要被重渲染。(组件的依赖是在渲染过程中自动追踪的)

3. 组件库

3.1 elementUI

3.1.1 vue-cli安装插件

vue create mypro
cd mypro
vue add element

这里选择的是按需引入:
在这里插入图片描述
观察项目文件夹中多了plugins-element.js
默认按需引入只引入了{Button组件} (可以减小体积),修改代码
在这里插入图片描述

3.1.2 echarts

4. 项目结构

在这里插入图片描述
一般脚手架都应当有以下的几个功能:

  • 自动化构建代码,比如打包、压缩、上传等功能
  • 本地开发与调试,并有热替换与热加载等功能
  • 本地接口数据模拟
  • css 模块化:拓展语言、预处理器saas、less(css 不是编程语言,所以不能声明变量、函数,不能做判断、循环和计算,也不能嵌套)
  • 检查并自动矫正不符合规范的代码,并优化代码格式

定义好项目的目录结构

  • 解耦:代码尽量去耦合,这样代码逻辑清晰,也容易扩展
  • 分块:按照功能对代码进行分块、分组,并能快捷的添加分块、分组
  • 编辑器友好:需要更新功能时,可以很快的定位到相关文件,并且这些文件应该是很靠近的,而不至于到处找文件

5. 亮点

  • 权限、商品分类涉及到多层级的树形结构
  • 权限控制

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/251294.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

操作系统 --- 使用套接字进行网络通信

一个套接字就是一个通信标识类型的数据结构,包含了通信目的的地址、通信使用的端口号、通信网络的传输协议、进程所在的网络地址,以及针对客户或服务器程序提供的不同系统调用等,是进程通信和网络通信的基本构件。套接字是为客户/服务器模型而设计的,通常分为以下两类: 1.基于…

构造器执行顺序

转载于:https://www.cnblogs.com/a6948076/p/8045801.html

Java08-java语法基础(七)构造方法

Java08-java语法基础&#xff08;七&#xff09;构造方法 一、构造方法 1、什么是构造方法&#xff1f; 构造方法&#xff08;类方法&#xff09;是一个方法名和类名相容的特殊的成员方法。 2、构造方法的作用&#xff1f; 当使用new关键字创建一个对象时&#xff0c;为新建对象…

安装mysql8.0.20,报错“找不到VCRUNTIME140_1.dll”

写在最前&#xff0c;指令集合 以管理员身份运行cmd mysql -uroot -p 【进入】mysql mysql > exit 【退出】 net stop mysql 【暂停】 net start mysql 【启动】 mysql -u root -p&#xff08;命令后输入临时密码&#xff0c;进入mysql&#xff09; ALTER USER USER() …

操作系统 --- 线程与进程的比较

如果说,在操作系统中引入进程的目的是为了使多个程序能并发执行,以提高资源利用率和系统吞吐量,那么在操作系统中再引入线程,则是为了减少程序在并发执行时所付出的时空开销,使OS(操作系统)具有更好的并发性… 我们再回顾一下进程的两个基本属性: 1.进程是一个可拥拥有资源的独…

24种吸引人的营销文章标题写法,总有一个适合你!

在如今信息爆炸的互联网时代下&#xff0c;如何提高提高文章的阅读(新闻稿、软文宣传稿、微信公众号)&#xff0c;成为从业者们共同研究的课题?首先你得有一个足够吸引的标题&#xff0c;尤其是定向推送的时候&#xff0c;这将是由一个质变带来量变的过程。小编虽然不提倡标题…

[js] 处理字符串换行造成的json解析失败

需求&#xff1a;从数据库某个字段取出字符串出来&#xff0c;转为json&#xff0c;结果发现报错为 解析失败&#xff0c;发现是因为取出的字符串换行导致&#xff0c;现在需要将字符串里面的换行替换为&#xff0c;使字符串可依成功解析成json对象。 技术&#xff1a;依靠repl…

使用mockjs模拟数据

一、安装 简单粗暴 npm install mockjs 二、引入 CommonJS引入 let Mock require(mockjs) let userInfo Mock.mock({data: {responseCode: 200,responseMessage: success,userMessage: {name: "cname",email: "email",msg: cparagraph(2)}} })或者ES…

angular --- ngDialog关闭当前层

今天做项目,使用ngDialog 弹出了一层,并且在弹出层上又弹出了第二层. 现在想点击确定按钮关闭第二层. 使用以前的ngDialog.close()会关闭掉全部ngDialog.open方法弹出来的层. 在网上查了一堆,找了好多,最后发现就一句话.$scope.closeThisDialog(); 注意, 要在controller:中传递…

lodash源码分析之compact中的遍历

小时候&#xff0c; 乡愁是一枚小小的邮票&#xff0c; 我在这头&#xff0c; 母亲在那头。 长大后&#xff0c;乡愁是一张窄窄的船票&#xff0c; 我在这头&#xff0c; 新娘在那头。 后来啊&#xff0c; 乡愁是一方矮矮的坟墓&#xff0c; 我在外头&#xff0c; 母亲在里头。…

[HAOI2008]移动玩具

这又是一道神奇的搜索题。。。只要记录每种状态。。。然后暴力判断这种状态往后一步的情况。。。 广搜出最优解即可。。。 呆码&#xff1a; #include<iostream> #include<cstdio> #include<queue> #include<cstring> using namespace std;int dx[5]{0…

javascript --- Sortable一个拖拽的接口

最近项目里面要实现需要实现一个拖拽功能,自己实现很麻烦,就在网上找到了一个封装好的sortable函数,github(https://github.com/SortableJS/Sortable). 首先是依赖的引入:(也可以自己下载源代码导入,方式很多呢) <body><!-- Latest compiled and minified CSS -->…

个人发展战略6天课

第一课 冰山模型 【知道自己为什么会不喜欢一份工作】 衡量和一个岗位是否匹配、匹配程度如何 从上到下的要素 知识技能&#xff08;30%&#xff09;特定领域 - 可以后天学习的&#xff0c;显性的、容易看出来的 和工作的关系&#xff1a; 工作中有陌生的内容&#xff0c;每天…

《Web全栈工程师的自我修养》

1. 什么是全栈工程师 Full-Stack Engineer Facaebook只招全栈工程师&#xff1f; Web开发流程 产品经理-->交互设计-->视觉设计-->开发&#xff08;前端、后端&#xff09;-->测试-->发布 流水线的优势 “各司其职”的弊端 工程师职责不清导致效率低工程师缺乏主…

div设置overflow-scroll滚动之后,jq获取其子元素的offset.top出现问题。

先上个图&#xff1a; 布局很简单&#xff0c;左右超过屏幕的部分自行滚动。 1. html <div class"ce-container"><div class"ce-leftBox">//左边的内容</div><div class"ce-rightBox">//右边的内容 </div…

javascript --- 利用Sortable实现一个可视化公式编辑器

Sortable的依赖引入和简单使用参见:https://blog.csdn.net/piano9425/article/details/90437182 先简单的介绍一下可视化公式编辑器的功能(样式没有调,毕竟每个人的需求都不一样): 首先会有2个需要计算的(我称为操作数)A_XiangRaoZuWenSheng和AYKZQ_CS,以及两个操作符ADD(加法…

使用uni-app搭建微信小程序

0 问题待解决 import { } 与否为什么要封装对齐问题每次重启项目&#xff0c;sitemap就会消失动态修改标题失效图片问题多多 &#xff1a;高度自适应 改成image固定高度&#xff0c;mode&#xff1a;aspectFill微信小程序文档b站视频链接后端接口文档 一、知识点 uni-app 是…

HttpTomcat

本节内容&#xff1a; Http协议Tomcat服务器下面开始的一系列内容都是JavaEE的内容&#xff0c;主要的内容见下图。JavaEE主要是做服务器端开发。 JavaEE全部规范&#xff1a;有13门技术&#xff0c;主要做web开发的需要学习servlet和jsp。其他技术&#xff0c;像EJB、 JNDI、J…

python---线程与进程

一 线程 1.1 概述 线程是操作系统能够进行运算调度的最小单位。它被包含在进程之中&#xff0c;是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流&#xff0c;一个进程中可以并发多个线程&#xff0c;每条线程并行执行不同的任务。 Threading用于提供线程相关…

jquery常见操作分享

参考: https://www.cnblogs.com/eager/p/7133270.html