一.后台搭建
使用 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'
}
);
}
}
