一.后台搭建
使用 vue-admin-template 来快速搭建后台管理,它包含了 Element UI & axios & iconfont & permission control & lint,这些搭建后台必要的东西。
Element是(饿了么团队)基于MVVM框架Vue开源出来的一套前端ui组件。官网: element-ui
1.快速搭建
若用vue官网提供的脚手架需要写跟多代码,比如登录界面、主界面菜单等。可以使用 vue-admin-template ,在此基础上开发,而且github上配有详细的模板说明,这样可以节省开发时间。
- 下载vue-admin-template(vue 2.0)进行解压
在命令提示符切换到该目录,输入命令安装所有依赖:
cnpm install
运行
npm run dev
2.工程结构
目录名称 | 存储内容 |
---|---|
build | 构建工程相关脚本 |
config | 配置相关 |
src | 工程源码 |
static | 静态资源 |
src/api | 访问后端API |
src/utils | 工具类 |
src/views | 路由组件 |
src/router | 路由 |
3.项目初始化
- 关闭语法规范性检查
修改config/index.js : useEslint = false - 国际化设置
修改main.js :
import locale from 'element‐ui/lib/locale/lang/en' --> import locale from 'elemen‐ui/lib/locale/lang/zh‐CN' 与easy-mock对接
修改config下dev.env.js中BASE_API为easy-mock的Base URL,easy-mock最好部署到服务器上BASE_API: '"http://192.168.91.136:7300/mock/5af314a4c612520d0d7650c7"',
easy-mock添加登录认证模拟数据
地址: /user/login
提交方式:post
内容:{ "code": 20000, "data": { "token": "admin" } }
添加返回用户信息url模拟数据
地址:/user/info
提交方式:get
内容:{ "code": 20000, "data": { "roles": ["admin"], "role": ["admin"], "name": "admin", "avatar": "https://wpimg.wallstcn.com/f778738c‐e4f8‐4870‐b634‐56703b4acafe.gif" } }
4.更改标题与菜单
- 修改index.html的标题为“后台管理系统”,修改后浏览器自动刷新。
修改src/router下的index.js中constantRouterMap的内容
export const constantRoutes = [ { path: '/login', component: () => import('@/views/login/index'), hidden: true }, { path: '/404', component: () => import('@/views/404'), hidden: true }, { path: '/', component: Layout, // redirect: '/dashboard', redirect: '/hostmanager/server', //登录后重定向到服务器信息页面 children: [{ path: 'dashboard', name: 'Dashboard', component: () => import('@/views/dashboard/index'), meta: { title: 'Dashboard', icon: 'dashboard' } }] }, { path: '/hostmanager', component: Layout, redirect: '/hostmanager/list', name: 'hostmanager', meta: { title: '主机管理', icon: 'example' }, children: [ { path: 'server', name: 'Server', component: () => import('@/views/server/index'), meta: { title: '服务器信息', icon: 'form' } }, { path: 'list', name: 'List', component: () => import('@/views/list/index'), meta: { title: '主机列表', icon: 'table' } }, { path: 'task', name: 'Task', component: () => import('@/views/task/index'), meta: { title: '任务控制', icon: 'tree' } } ] }, { path: '/testqueue', component: Layout, children: [ { path: 'index', name: 'testQueue', component: () => import('@/views/queue/index'), meta: { title: '测试队列', icon: 'form' } } ] }, { path: '/taskmanager', component: Layout, meta: { title: '任务管理', icon: 'example' }, children: [ { path: 'list', name: 'taskList', component: () => import('@/views/taskList/index'), meta: { title: '任务列表', icon: 'form' } }, { path: 'detail', name: 'taskDetail', component: () => import('@/views/taskDetail/index'), meta: { title: '任务清单', icon: 'form' } }, { path: 'create', name: 'taskCreate', component: () => import('@/views/taskCreate/index'), meta: { title: '新建任务', icon: 'form' } }, ] }, // 404 page must be placed at the end !!! { path: '*', redirect: '/404', hidden: true } ]
二.element-ui使用
1.表格组件
<el-table :data="list" border style="width: 100%;"> <el-table-column prop="id" label="活动ID" min-width="1"></el-table-column> <el-table-column prop="name" label="活动名称" min-width="1"></el-table-column> <el-table-column prop="address" label="活动地址" min-width="1"></el-table-column> <el-table-column prop="starttime" label="开始日期" min-width="1"></el-table-column> <el-table-column label="操作" min-width="1"> <template slot-scope="scope"> <el-button type="text" size="small" @click="handleEdit(scope.row.id)">修改</el-button> <el-button type="text" size="small" @click="handleDelete(scope.row.id)">删除</el-button> </template> </el-table-column> </el-table> <script> import gatheringApi from '@/api/gathering' export default { data(){ return { list:[] } }, created(){ this.fetchData(); }, methods:{ fetchData(){ gatheringApi.getList().then(response => { this.list=response.data }); } } } </script>
当没有使用template模板页时,一般加上prop属性,若有template时,可以为:
<el-table-column label="主机名" min-width="2"> <template slot-scope="scope">{{scope.row.name}}</template> </el-table-column> <el-table-column label="操作" min-width="3"> <template slot-scope="scope"> <el-button type="primary" size="small" @click="findTask(scope.$index,scope.row)">查看</el-button> <el-button type="info" size="small" :disabled="scope.row.status !== '空闲'" @click="createTask(scope.$index,scope.row)">新建</el-button> </template> </el-table-column>
slot-scope用于指定当前行的上下文。使用scope.row可以获取行对象。
table组件的属性:
参数 | 说明 | 类型 |
---|---|---|
data | 显示的数据 | array |
table-column组件的属性:
参数 | 说明 | 类型 |
---|---|---|
label | 显示的标题 | string |
prop | 对应列内容的字段名 | string |
width | 对应列的宽度 | number |
min-width | 按比例显示宽度 | number |
官方文档:table组件
2.分页组件
<el‐table :data="list" border style="width: 100%"></el-table> <el-pagination @size-change="fetchDate" @current-change="fetchDate" :current-page="currentPage" :page-sizes="[10,20,30,50]" :page-size="pageSize" layout="sizes, prev, pager, next, jumper, ->, total, slot" :total="total"> </el-pagination> <script> import gatheringApi from '@/api/gathering' export default { data(){ return { list:[], total:0,//总记录数 currentPage:1,//当前页 pageSize:10,//每页大小 searchMap: {}//查询表单绑定变量 } }, created(){ this.fetchData(); }, methods:{ fetchData(){ gatheringApi.search(this.currentPage,this.pageSize,this.searchMap).then(response =>{ this.list=response.data.rows this.total=response.data.total }); } } } </script>
上面的分页方式是数据量比较大是传currentPage, pageSize给后端,由后端来实现分页;
数据量比较小时由前端实现分页,如下:
<el-table border :data="list.slice((currentPage-1)*pageSize, currentPage*pageSize)" style="width: 100%;margin-top: 20px;"></el-table> <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page="currentPage" :page-size="pageSize" layout="sizes, prev, pager, next, jumper, ->, total" :total="list.length"> </el-pagination> <script> export default { data() { return { list: [], currentPage: 1, pageSize: 10, } }, methods: { // 分页相关函数 handleSizeChange(val){ console.log(`每页${val}条`) this.pageSize = val }, handleCurrentChange(val){ console.log(`当前页:${val}`) this.currentPage = val }, } } </script>
pagination的常用属性:
参数 | 说明 | 类型 | 可选值 | 默认值 |
---|---|---|---|---|
page-size | 每页显示条目个数 | number | - | 10 |
total | 总条目数 | number | - | - |
current-page | 当前页数,支持.sync修饰符 | number | - | 1 |
layout | 组件布局 | string | sizes,prev,pager,next,jumper,->,total,slot | prev,pager,next,jumper, ->, total |
pages-sizes | 每页显示个数选择器的选项设置 | number[] | - | [10,20,30,40,50,100] |
pagination的常用事件:
事件名称 | 说明 | 回调参数· |
---|---|---|
size-changer | pageSize改变时会触发 | 每页条数 |
current-change | currentPage改变时会触发 | 当前页 |
官网链接:pagination组件
3.表单组件
在分页列表的基础上实现条件查询功能
<!-- 行内表单:用于查询条件 --> <el-form :inline="true"> <el-form-item label="活动名称"> <el-input v-model="searchMap.name" placeholder="活动名称"></el-input> </el-form-item> <el-form-item label="活动日期"> <el-date-picker type="date" v-model="searchMap.startdate" placeholder="选择开始日期" ></el-date-picker> <el-date-picker type="date" v-model="searchMap.enddate" placeholder="选择结束日期" ></el-date-picker> </el-form-item> <el-button type="primary" @click="fetchDate">查询</el-button> <el-button type="primary" @click="handleEdit('')">新增</el-button> </el-form> <!-- 对话框表单 --> <el-dialog title="活动编辑" :visible.sync="addDialogVisible"> <el-form label-width="80px"> <el-form-item label="活动名称"> <el-input v-model="pojo.name" placeholder="活动名称"></el-input> </el-form-item> <el-form-item label="开始日期"> <el-date-picker type="date" v-model="pojo.starttime" placeholder="开始日期"></el-date-picker> </el-form-item> <el-form-item label="活动详情"> <el-input type="textarea" v-model="pojo.detail" :rows="2" placeholder="活动详情"></el-input> </el-form-item> <el-form-item label="是否可见"> <el-switch v-model="pojo.state" active-color="#13ce66" inactive-color="#ff4949" active-value="1" inactive-value="0"></el-switch> </el-form-item> <el-form-item> <el-button type="primary" @click="handerSave">保存</el-button> <el-button @click="addDialogVisible=false">关闭</el-button> </el-form-item> </el-form> </el-dialog>
form(表单)组件官方文档:form组件
input(文本框)组件官方文档:input组件
date-picker(日期框)组件官方文档:DatePicker组件
switch(开关)组件官方文档:switch组件
注意:input组件中多行文本框设置
4.对话框组件
<el-dialog title="新建任务" :visible.sync="addDialogVisible" width="37%"> </el-dialog> <script> data(){ ...... addDialogVisible: false // 对话框是否显示 } </script>
属性title为对话框标题,visible为是否显示。变量addDialogVisible用于控制对话框的显示,点击按钮将dialogFormVisible = true即可打开对话框。
dialog(对话框)组件官方文档:dialog组件
5.下拉选组件
<el‐form‐item label="城市"> <el‐select v‐model="pojo.city" placeholder="请选择"> <el‐option v‐for="item in cityList" :key="item.id" :label="item.name" :value="item.id"> </el‐option> </el‐select> </el‐form‐item> <script> import cityApi from '@/api/city' export default { data(){ return { cityList: [] } }, created() { cityApi.getList().then(response =>{ this.cityList = response.data }) } } </script>
select(下拉选)组件官方文档:select组件
6.消息提示组件
this.$message({ message: response.message, type: (response.flag?'success':'error') }); // 或者 this.$message.success('请求成功!');
message(消息提示)组件官方文档:message组件
7.关于尺寸介绍
默认尺寸是最大的,其次中等、小、超小
button按钮
size:medium / small / mini
input输入框
size:medium / small / mini
select选择器
size:medium / small / mini
form表单
label-width:表单域标签的宽度
size:medium / small / mini (用于控制该表单域下组件的尺寸)
table表格
size:medium / small / mini
三.vue中使用element-ui示例
对活动管理的查询、分页、条件查询,增加,修改,删除等。采用的easy-mock的模拟接口。
gathering.vue
<template> <div> <br/> <el-form :inline="true"> <el-form-item label="活动名称"> <el-input v-model="searchMap.name" placeholder="活动名称"></el-input> </el-form-item> <el-form-item label="活动日期"> <el-date-picker type="date" v-model="searchMap.startdate" placeholder="选择开始日期" ></el-date-picker> <el-date-picker type="date" v-model="searchMap.enddate" placeholder="选择结束日期" ></el-date-picker> </el-form-item> <el-button type="primary" @click="fetchDate">查询</el-button> <el-button type="primary" @click="handleEdit('')">新增</el-button> </el-form> <el-table :data="list" border style="width: 100%;"> <el-table-column prop="id" label="活动ID" min-width="1"></el-table-column> <el-table-column prop="name" label="活动名称" min-width="1"></el-table-column> <el-table-column prop="address" label="活动地址" min-width="1"></el-table-column> <el-table-column prop="starttime" label="开始日期" min-width="1"></el-table-column> <el-table-column label="操作" min-width="1"> <template slot-scope="scope"> <el-button type="text" size="small" @click="handleEdit(scope.row.id)">修改</el-button> <el-button type="text" size="small" @click="handleDelete(scope.row.id)">删除</el-button> </template> </el-table-column> </el-table> <el-pagination @size-change="fetchDate" @current-change="fetchDate" :current-page="currentPage" :page-sizes="[10,20,30,50]" :page-size="pageSize" layout="sizes, prev, pager, next, jumper, ->, total, slot" :total="total"> </el-pagination> <el-dialog title="活动编辑" :visible.sync="addDialogVisible"> <el-form label-width="80px"> <el-form-item label="活动名称"> <el-input v-model="pojo.name" placeholder="活动名称"></el-input> </el-form-item> <el-form-item label="开始日期"> <el-date-picker type="date" v-model="pojo.starttime" placeholder="开始日期"></el-date-picker> </el-form-item> <el-form-item label="活动详情"> <el-input type="textarea" v-model="pojo.detail" :rows="2" placeholder="活动详情"></el-input> </el-form-item> <el-form-item label="选择城市"> <el-select v-model="pojo.city" placeholder="请选择"> <el-option v-for="item in cityList" :key="item.id" :value="item.id" :label="item.name"></el-option> </el-select> </el-form-item> <el-form-item label="是否可见"> <el-switch v-model="pojo.state" active-color="#13ce66" inactive-color="#ff4949" active-value="1" inactive-value="0"></el-switch> </el-form-item> <el-form-item> <el-button type="primary" @click="handerSave">保存</el-button> <el-button @click="addDialogVisible=false">关闭</el-button> </el-form-item> </el-form> </el-dialog> </div> </template> <script> import gatheringApi from '@/api/gathering' import cityApi from '@/api/city' export default { data(){ return { list: [], // 当前活动列表 // 分页初始化 currentPage: 1, // 当前页 pageSize: 20, // 每页条数,默认是10 searchMap: {}, //查询条件 total: 0, // 总条数 // 对话框 addDialogVisible: false, pojo: {}, // 对话框表单数据对象 // 城市下拉选列表 cityList: [], //城市列表 id: '', // 当前编辑的id } }, created() { this.fetchDate(); cityApi.getList().then(res => { this.cityList = res.data; console.log(res.data) }) }, methods: { // 分页根据条件获取列表数据 fetchDate(){ gatheringApi.search(this.currentPage, this.pageSize, this.searchMap).then(res => { this.list = res.data.rows; // 当前页面列表 this.total = res.data.total; // 总条数 console.log(res.data.rows) }).catch(err => { alert('请求失败!') }) }, // 新增或修改 handleEdit(id){ this.id = id; // 标准是新增还是修改 this.addDialogVisible = true; // 打开窗口 if (id){ // 修改 // 调用查询 gatheringApi.findById(id).then(response => { this.pojo = response.data; }) } else { // 新增 this.pojo = {} // 清空表单 } }, // 保存 handerSave(){ gatheringApi.updateById(this.id,this.pojo).then(res => { this.$message({ message: res.message, type: (res.flag? 'success':'error'), }); if (res.flag){ //添加成功 this.fetchDate(); } }); this.addDialogVisible = false; //关闭对话框 }, handleDelete(id){ this.$confirm('确定要删除此条记录吗','提示',{ confirmButtonText: '确定', cancelButtonText: '取消', type: 'warning' }).then(() => { gatheringApi.deleteById(id).then(res => { this.$message({ message: res.message, type: (res.flag? 'success':'error') }); if (res.flag){ this.fetchDate(); // 刷新数据 } }); }).catch(() => {}); } }, } </script> <style> </style>
gathering.js
import request from '@/utils/request' const group_name = 'gathering' const api_name = 'gathering' export default { getList() { // 获取所有 return request( { url: `/${group_name}/${api_name}`, method: 'get' } ); }, search(page, size, searchMap){ // 分页 return request( { url: `/${group_name}/${api_name}/search/${page}/${size}`, method: 'post', data: searchMap } ); }, save(pojo){ // 新增对话框保存 return request( { url: `/${group_name}/${api_name}`, method: 'post', data: pojo } ) }, findById(id){ // 根据id查询 return request({ url: `/${group_name}/${api_name}/${id}`, method: 'get' }); }, updateById(id,pojo){ if (id == null || id == ''){ return this.save(); }; return request({ url: `/${group_name}/${api_name}/${id}`, method: 'put', data: pojo }); }, deleteById(id){ return request({ url: `/${group_name}/${api_name}/${id}`, method: 'delete' }); } }
city.js
import request from "@/utils/request" export default { getList(){ return request( { url:'/base/city', method:'get' } ); } }