黑马后台管理系统是一个电商后台管理系统的前端项目,基于Vue+Element实现。 主要包括商品管理、订单管理、会员管理、促销管理、运营管理、内容管理、统计报表、财务管理、权限管理、设置等功能
此项目开发我用到的技术有:vue2+node.js+webapck element axios router vuex
项目选型
搭建登录注册页,权限管理,封装接口,vuex,路由配置,环境配置, 本地代理
主功能页面:按照各个页面业务需求进行开发
打包项目
代码整理,代码注释
这个项目大致分为了:登录,退出登录,用户管理,权限管理,商品管理,订单管理,数据统计7部分

实现用户登录功能的逻辑是: ①在登录页面输入账号和密码进行登录,将数据发送给服务器 ②服务器返回登录的结果,登录成功则返回数据中带有token ③客户端得到token并进行保存,后续的请求都需要将此token发送给服务器,服务器会验证token以保证用户身份。
首先在点击登录时候进行登陆的的表单验证

然后在request.js中添加请求拦截和响应拦截。在请求拦截中,会给请求头添加token字段,还有loading动画的开启。在响应拦截中,可以做一些loading动画的关闭,还有可以根据后端返回的状态码,做一些检验token是否有效或者过期的操作。接着就是做一些axios进行的api接口的封装,这里我用到了async,await封装请求接口函数,这样可以将异步操作同步化操作,代码更加友好。


在封装里处理token过期清除本地存储返回登录页。
跳转成功了我又去配置了路由守卫,判断是不是有token,有没有权力让他去进入主页面

在element-ui中也提供了相应的组件,在NavMenu导航菜单中可以找到相应的组件对应的区域
:router 开启路由模式,设置el-menu-item的index值 为路由标识
动态渲染:不同身份登录,权限控制
data中定义一个数组leftmenu来接收左侧菜单数据


调用接口,删除本地中的token,并跳转到登录页

添加编辑
展示:现有用户数量 GET
增加:用户名、密码、邮箱、手机,新增后重新加载页面 POST
删除:删除后重新加载页面 PUT
修改:DELETE 1.改基本信息:手机、邮箱 2.改角色:关系到权限
组件 面包屑、搜索框、表格、分页组件、switch状态转换
请求数据状态切换、分页、面包屑导航切换然后对添加和编辑的表单进行验证,然后为了优化项目
我把添加和编辑的封装到组件进行复用,使页面解构更清晰。

搜索功能的实现
将值利用绑定到queryInfo.query
分页!
@size-change: 监听pagesize改变的事件 @current-change: 监听页码值改变的事件 :current-page: 当前页 :page-sizes:一页的的信息条数 :page-size: 当前的页数 layout: 控制显示内容 :total:总共的信息条数

角色列表
添加角色(简单提交)
编辑、删除(简单slot-scope传参、delete请求)
分配角色(tag)
权限展示(表格展开行)
角色列表页面一个重点就是利用了element ui中的 table表格插件的展开行

分配权限也是利用利用了element ui中的 tree树形控件来完成的
<!-- 表格 -->
<el-table :data="list" border style="width: 100%">
<el-table-column type="expand">
<template v-slot="scope">
<!-- 当前角色权限渲染 -->
<el-row
v-for="(item, i1) in scope.row.children"
:key="item.id"
:class="[i1 === 0 ? '' : 'bdtop', 'vcenter']"
>
<el-col :span="6">
<!-- 一级 -->
<el-tag closable>{{ item.authName }}</el-tag>
</el-col>
<el-col :span="18">
<!-- 二级 -->
<el-row
v-for="(it, i2) in item.children"
:key="it.id"
:class="[i2 === 0 ? '' : 'bdtop', 'vcenter']"
>
<el-col>
<el-tag
type="success"
closable
@close="delRight(scope.row, it.id)"
>{{ it.authName }}</el-tag
>
</el-col>
<!-- 三级 -->
<el-col :span="18">
<el-tag
type="warning"
closable
v-for="i in it.children"
:key="i.id"
@close="delRight(scope.row, i.id)"
>{{ i.authName }}</el-tag
>
</el-col>
</el-row>
</el-col>
</el-row>
</template>
</el-table-column>
<el-table-column type="index" label="#"></el-table-column>
<el-table-column prop="roleName" label="角色名称" align="center">
</el-table-column>
<el-table-column prop="roleDesc" label="角色描述" align="center">
</el-table-column>
<el-table-column label="操作" align="center" width="300px">
<template slot-scope="scope">
<el-button
type="primary"
size="mini"
@click="handleEdit(scope.$index, scope.row)"
>编辑</el-button
>
<el-button
type="success"
size="mini"
@click="handleDelete(scope.row)"
>删除</el-button
>
<el-button type="warning" size="mini" @click="showfen(scope.row)"
>分配权限</el-button
>
</template>
展开所有的权限(树形结构自带的属性:default-expand-all) 显示:先勾选上拥有的三级权限(三层forEach,获得所有三级权限的集合,赋值给checklistArr) :default-checked-keys="checklistArr"


ref 绑定后方便使用他的事件
this.$refs.tree.getCheckedKeys() 返回目前被选中的节点的 key 所组成的数组 this.$refs.tree.getHalfCheckedKeys() 返回目前半选中的节点的 key 所组成的数组 data 是绑定的数据 []
show-checkbox 显示复选框
node-key 节点的key
default-expand-all 是否默认展开所有节点
default-checked-keys 默认勾选的节点的 key 的数组
props 配置选项
权限列表
重点在于权限等级可以利用插槽和v-if v-else-if来判断权限的等级

在商品管理页面又被分为了:商品分类 分类参数 商品列表三个页面
商品列表
添加编辑
分页、面包屑导航切换然后对添加和编辑的表单进行验证,然后为了优化项目
我把添加和编辑的封装到组件进行复用,使页面更清晰。

搜索功能的实现
将值利用绑定到queryInfo.query
分页 @size-change: 监听pagesize改变的事件 @current-change: 监听页码值改变的事件 :current-page: 当前页 :page-sizes:一页的的信息条数 :page-size: 当前的页数 layout: 控制显示内容 :total:总共的信息条数
上传图片 (Upload组件、百度Web Uploader)
请求上传接口,需要设置token(这里不是发axios请求)
:on-remove 文件列表移除文件时的钩子
on-success 文件上传成功时的钩子
headers 设置上传的请求头部
action 上传地址
on-preview 点击文件列表中已上传的文件时的钩子
list-type 文件列表的类型

分类参数
这一模块数据 分为了 动态参数和静态属性 所以分别发送不同的请求,获得数据保存在本地,再利用tabs组件进行渲染即可,添加,修改,删除功能
级联选择器 type=3 展示出三级分类
动态(涉及列表展开)、静态参数
查询名称、价格、重量、参数管理
添加商品详细描述(名称、价格、重点、数量、分类、参数、属性、图片)
步骤条组件+纵向tabs组件(需要包裹在el-form里)(并列关系)
上传图片
商品分类
在这个页面我们用了一个新的组件tree-table 树形表格 首先我们要下载表格vue-table-with-tree-grid插件,全局引入
show-index //序号 • align="center" //表格文字是否剧中 • width="220px" • index-text="#" // 设置序号的label属性 • :data="list" //表格所有数据 • :columns="columns" //设置属性

我认为添加分类是整个项目的及大难点之一,是一个三级联动的
options:数据源 props: //靶子对象 value: //选中的属性 • label: //显示的名称 • children: //嵌套的结构 • v-model: //选中数组 • @changed: //选择项发生变化时候 触发的函数



添加编辑
展示:现有用户数量 GET
增加:用户地址、手机,新增后重新加载页面 POST
删除:删除后重新加载页面 PUT
修改:DELETE 1.改基本信息:手机号,用户地址 2.改角色:关系到权限
组件 面包屑、搜索框、表格、分页组件、switch状态转换
请求数据状态切换、分页、面包屑导航切换然后对添加和编辑的表单进行验证,然后为了优化项目
我把添加和编辑的封装到组件进行复用,使页面解构更清晰。

搜索功能的实现
将值利用绑定到queryInfo.query
分页 @size-change: 监听pagesize改变的事件 @current-change: 监听页码值改变的事件 :current-page: 当前页 :page-sizes:一页的的信息条数 :page-size: 当前的页数 layout: 控制显示内容 :total:总共的信息条数
// 安装echarts库 npm install echarts -S
// 导入echarts接口 import echarts from ‘echarts’


【难点1】权限管理
1.创建vue实例的时候讲vue-router挂载,但这个时候vue-router挂载一些登录或者不用权限
的公共页面.
2.当用户登录后,获取用户的role,讲role和路由表每个页面的需要的权限作比较,生成最终用户,
可访问的路由表.
3.调用router.addRoutes添加用户可访问的路由.
4.使用vuex管理路由表,根据vuex中可访问的路由渲染侧边栏组件。
【难点2】三级权限展示,树形结构,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
}
]
}
]
}
]
}
],
}
<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>
【难点3】分配权限,树形结构el-tree 全选、半选(如何展示)
展开所有的权限(树形结构自带的属性:default-expand-all) 显示:先勾选上拥有的三级权限(三层forEach,获得所有三级权限的集合,赋值给checklistArr) :default-checked-keys="checklistArr" 提交:需要获取所有的一、二、三级权限的集合(全选+半选),传参修改

//显示
editRight(role) {
// checklist权限的集合,是个树形结构
this.checklist = role.children
this.currentRoleId = role.id
var tmpArr = []
this.checklist.forEach(item1 => {
var item2 = item1.children
item2.forEach(item2 => {
var item3 = item2.children
item3.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(',') })
}
【难点4】树形组件element-tree-grid在表格中的运用(组件选择、配置)
表格样式:树形结构 +【是否有效】【级别】【操作】字段; 组件选择:由于第一列的el-table-column要展示为树形结构,因此使用组件element-tree-grid,all props of el-table-column are supported; 在获取到三级商品分类后,element-tree-grid只需要绑定好对应的属性,即可显示。

<el-table :data="list" border style="width: 100%"> <el-table-column type="index" label="#" align="center"></el-table-column> <el-table-column prop="authName" label="权限名称" align="center"> </el-table-column> <el-table-column prop="path" label="路径" align="center"> </el-table-column> <el-table-column label="权限等级" align="center"> <template v-slot="scope"> <el-tag v-if="scope.row.level == 0">一级</el-tag> <el-tag type="success" v-else-if="scope.row.level == 1">二级</el-tag> <el-tag type="warning" v-else>三级</el-tag> </template> </el-table-column> </el-table>
【难点5】级联选择器-添加分类(理解接口type参数)
由于最细添加的是三级分类(或者添加一级、二级分类),因此级联选择器只用展示一、二级的父类,请求分类接口,type=2 value / v-model: 选中项绑定值,是一个数组 级联选择器的handleChange方法,能获取到最接近一层的父类参数分类id,配置级别和分类名称,组成一个obj作为参数发POST请求
<el-dialog @close="clearDefault" title="分配权限" :visible.sync="dialogVisible" width="30%" :before-close="handleClose" > <el-tree show-checkbox default-expand-all :default-checked-keys="defaultKeys" node-key="id" :data="rightstree" :props="Propslist" ref="treeData" ></el-tree>
【难点6】分类参数 – 只允许为三级分类设置参数
级联选择器 type=3 展示出三级分类
动态(涉及列表展开)、静态参数
如何限定只让第三级被选中:
handleChange () {
if (this.selectedOptions.length !== 3) {
this.$message.warning('商品只能添加到三级分类')
this.selectedOptions.length = 0
}
}
【难点7】什么时候渲染出参数,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.data
this.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.从头下手,到做一遍后,后面的几个模块比较相似,自己进行了实现
2.最大收获就是从拿到一个项目开始,梳理它的功能模块,然后各个模块再细分为单个功能例如添加,删除,修改等,然后逐个功能进行实现
3.在实现各个功能的时候,从老师那里学到了很多逻辑,包括思考问题的方式,比如这个项目,各个功能要做的大同小异,无非是拿到数据,进行处理,然后渲染,监听用户操作,修改数据,提交请求
4.还有就是之前没有怎么用过的 作用域插槽,层级选择器,树状结构,出现在项目中,
5.然后就是对于 axios拦截器的使用,比如登录时用到的request,在发起请求时为请求添加token,存储token,还有另一个 response,在获得数据时,添加loading效果;
6.然后就是帮助自己 复习了Vue-router,更加熟悉了路由的操作;
7.对Element-ui的使用更加熟练
8.还学会了封装全局的按钮鉴权,封装添加修改的的表单元素
我正在使用i18n从头开始构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在rubyonrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi
我安装了ruby版本管理器,并将RVM安装的ruby实现设置为默认值,这样'哪个ruby'显示'~/.rvm/ruby-1.8.6-p383/bin/ruby'但是当我在emacs中打开inf-ruby缓冲区时,它使用安装在/usr/bin中的ruby。有没有办法让emacs像shell一样尊重ruby的路径?谢谢! 最佳答案 我创建了一个emacs扩展来将rvm集成到emacs中。如果您有兴趣,可以在这里获取:http://github.com/senny/rvm.el
是否有简单的方法来更改默认ISO格式(yyyy-mm-dd)的ActiveAdmin日期过滤器显示格式? 最佳答案 您可以像这样为日期选择器提供额外的选项,而不是覆盖js:=f.input:my_date,as::datepicker,datepicker_options:{dateFormat:"mm/dd/yy"} 关于ruby-on-rails-事件管理员日期过滤器日期格式自定义,我们在StackOverflow上找到一个类似的问题: https://s
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
在应用开发中,有时候我们需要获取系统的设备信息,用于数据上报和行为分析。那在鸿蒙系统中,我们应该怎么去获取设备的系统信息呢,比如说获取手机的系统版本号、手机的制造商、手机型号等数据。1、获取方式这里分为两种情况,一种是设备信息的获取,一种是系统信息的获取。1.1、获取设备信息获取设备信息,鸿蒙的SDK包为我们提供了DeviceInfo类,通过该类的一些静态方法,可以获取设备信息,DeviceInfo类的包路径为:ohos.system.DeviceInfo.具体的方法如下:ModifierandTypeMethodDescriptionstatic StringgetAbiList()Obt
需求:要创建虚拟机,就需要给他提供一个虚拟的磁盘,我们就在/opt目录下创建一个10G大小的raw格式的虚拟磁盘CentOS-7-x86_64.raw命令格式:qemu-imgcreate-f磁盘格式磁盘名称磁盘大小qemu-imgcreate-f磁盘格式-o?1.创建磁盘qemu-imgcreate-fraw/opt/CentOS-7-x86_64.raw10G执行效果#ls/opt/CentOS-7-x86_64.raw2.安装虚拟机使用virt-install命令,基于我们提供的系统镜像和虚拟磁盘来创建一个虚拟机,另外在创建虚拟机之前,提前打开vnc客户端,在创建虚拟机的时候,通过vnc
Region是HBase数据管理的基本单位,region有一点像关系型数据的分区。region中存储这用户的真实数据,而为了管理这些数据,HBase使用了RegionSever来管理region。Region的结构hbaseregion的大小设置默认情况下,每个Table起初只有一个Region,随着数据的不断写入,Region会自动进行拆分。刚拆分时,两个子Region都位于当前的RegionServer,但处于负载均衡的考虑,HMaster有可能会将某个Region转移给其他的RegionServer。RegionSplit时机:当1个region中的某个Store下所有StoreFile
我是ruby的新手,我认为重新构建一个我用C#编写的简单聊天程序是个好主意。我正在使用Ruby2.0.0MRI(Matz的Ruby实现)。问题是我想在服务器运行时为简单的服务器命令提供I/O。这是从示例中获取的服务器。我添加了使用gets()获取输入的命令方法。我希望此方法在后台作为线程运行,但该线程正在阻塞另一个线程。require'socket'#Getsocketsfromstdlibserver=TCPServer.open(2000)#Sockettolistenonport2000defcommandsx=1whilex==1exitProgram=gets.chomp
我想用这两种语言中的任何一种(最好是ruby)制作一个窗口管理器。老实说,除了我需要加载某种X模块外,我不知道从哪里开始。因此,如果有人有线索,如果您能指出正确的方向,那就太好了。谢谢 最佳答案 XCB,X的下一代API使用XML格式定义X协议(protocol),并使用脚本生成特定语言绑定(bind)。它在概念上与SWIG类似,只是它描述的不是CAPI,而是X协议(protocol)。目前,C和Python存在绑定(bind)。理论上,Ruby端口只是编写一个从XML协议(protocol)定义语言到Ruby的翻译器的问题。生
因为我现在正在做一些时间测量,我想知道是否可以在不使用Benchmark类或命令行实用程序time的情况下测量用户时间或系统时间。使用Time类只显示挂钟时间,而不显示系统和用户时间,但是我正在寻找具有相同灵active的解决方案,例如time=TimeUtility.now#somecodeuser,system,real=TimeUtility.now-time原因是我有点不喜欢Benchmark,因为它不能只返回数字(编辑:我错了-它可以。请参阅下面的答案。)。当然,我可以解析输出,但感觉不对。*NIX系统的time实用程序也应该可以解决我的问题,但我想知道是否已经在Ruby中实