完美对接avue

This commit is contained in:
smallwei 2018-03-21 17:10:35 +08:00
parent f53a1eb045
commit 5f06a00511
69 changed files with 2982 additions and 1752 deletions

View File

@ -1,6 +1,6 @@
// see http://vuejs-templates.github.io/webpack for documentation.
var path = require('path')
var baseUrl = 'http://218.70.11.118:7777';
module.exports = {
build: {
env: require('./prod.env'),
@ -30,17 +30,17 @@ module.exports = {
assetsPublicPath: '/',
proxyTable: {
'/auth': {
target: 'http://api.frps.shop',
target: baseUrl,
changeOrigin: true,
pathRewrite: {
'^/auth' : '/auth'
'^/auth': '/auth'
}
},
'/admin': {
target: 'http://api.frps.shop',
target: baseUrl,
changeOrigin: true,
pathRewrite: {
'^/admin' : '/admin'
'^/admin': '/admin'
}
}
},

View File

@ -27,6 +27,7 @@
"mockjs": "^1.0.1-beta3",
"vue": "2.5.2",
"vue-axios": "^2.0.2",
"vue-image-crop-upload": "^2.2.3",
"vue-router": "^3.0.0",
"vue-server-renderer": "2.5.2",
"vue-template-compiler": "2.5.2",

View File

@ -1,19 +1,7 @@
import { userTableData, roleTableData } from '@/mock/admin'
import { DIC } from '@/const/dic'
export const getUserData = (page) => {
return new Promise((resolve, reject) => {
resolve({ data: userTableData });
})
}
export const getRoleData = (page) => {
return new Promise((resolve, reject) => {
resolve({ data: roleTableData });
})
}
export const getDic = (type) => {
return new Promise((resolve, reject) => {
resolve({ data: DIC[type] });
resolve({ data: {} });
})
}

39
src/api/dept.js Normal file
View File

@ -0,0 +1,39 @@
import request from '@/router/axios'
export function fetchTree(query) {
return request({
url: '/admin/dept/tree',
method: 'get',
params: query
})
}
export function addObj(obj) {
return request({
url: '/admin/dept/',
method: 'post',
data: obj
})
}
export function getObj(id) {
return request({
url: '/admin/dept/' + id,
method: 'get'
})
}
export function delObj(id) {
return request({
url: '/admin/dept/' + id,
method: 'delete'
})
}
export function putObj(obj) {
return request({
url: '/admin/dept/',
method: 'put',
data: obj
})
}

46
src/api/dict.js Normal file
View File

@ -0,0 +1,46 @@
import request from '@/router/axios'
export function fetchList(query) {
return request({
url: '/admin/dict/dictPage',
method: 'get',
params: query
})
}
export function addObj(obj) {
return request({
url: '/admin/user/',
method: 'post',
data: obj
})
}
export function getObj(id) {
return request({
url: '/admin/user/' + id,
method: 'get'
})
}
export function delObj(row) {
return request({
url: '/admin/dict/' + row.id + '/' + row.type,
method: 'delete'
})
}
export function putObj(obj) {
return request({
url: '/admin/user/',
method: 'put',
data: obj
})
}
export function remote(type) {
return request({
url: '/admin/dict/type/' + type,
method: 'get'
})
}

39
src/api/log.js Normal file
View File

@ -0,0 +1,39 @@
import request from '@/router/axios'
export function fetchList(query) {
return request({
url: '/admin/log/logPage',
method: 'get',
params: query
})
}
export function delObj(id) {
return request({
url: '/admin/log/' + id,
method: 'delete'
})
}
export function addObj(obj) {
return request({
url: '/admin/user/',
method: 'post',
data: obj
})
}
export function getObj(id) {
return request({
url: '/admin/user/' + id,
method: 'get'
})
}
export function putObj(obj) {
return request({
url: '/admin/user/',
method: 'put',
data: obj
})
}

View File

@ -24,7 +24,7 @@ export const getUserInfo = () => {
export const logout = (accesstoken, refreshToken) => {
return request({
url: '/auth/removeToken',
url: '/auth/authentication/removeToken',
method: 'post',
params: { accesstoken, refreshToken }
})

View File

@ -4,4 +4,55 @@ export function GetMenu() {
url: '/admin/menu/getUserTree',
method: 'get'
})
}
}
export function fetchTree(query) {
return request({
url: '/admin/menu/tree',
method: 'get',
params: query
})
}
export function fetchAll() {
return request({
url: '/admin/menu/navMenu',
method: 'get'
})
}
export function fetchUserTree() {
return request({
url: '/admin/menu/userTree',
method: 'get'
})
}
export function addObj(obj) {
return request({
url: '/admin/menu/',
method: 'post',
data: obj
})
}
export function getObj(id) {
return request({
url: '/admin/menu/' + id,
method: 'get'
})
}
export function delObj(id) {
return request({
url: '/admin/menu/' + id,
method: 'delete'
})
}
export function putObj(obj) {
return request({
url: '/admin/menu/',
method: 'put',
data: obj
})
}

8
src/api/qiniu.js Normal file
View File

@ -0,0 +1,8 @@
import request from '@/router/axios'
export function getToken() {
return request({
url: '/zuul/admin/user/upload', // 假地址,自行替换
method: 'post'
})
}

79
src/api/role.js Normal file
View File

@ -0,0 +1,79 @@
import request from '@/router/axios'
export function roleList() {
return request({
url: '/admin/role/roleList',
method: 'get'
})
}
export function fetchList(query) {
return request({
url: '/admin/role/rolePage',
method: 'get',
params: query
})
}
export function deptRoleList(deptId) {
return request({
url: '/admin/role/roleList/' + deptId,
method: 'get'
})
}
export function getObj(id) {
return request({
url: '/admin/role/' + id,
method: 'get'
})
}
export function addObj(obj) {
return request({
url: '/admin/role/',
method: 'post',
data: obj
})
}
export function putObj(obj) {
return request({
url: '/admin/role/',
method: 'put',
data: obj
})
}
export function delObj(id) {
return request({
url: '/admin/role/' + id,
method: 'delete'
})
}
export function permissionUpd(roleId, menuIds) {
return request({
url: '/admin/role/roleMenuUpd',
method: 'put',
params: {
roleId: roleId,
menuIds: menuIds
}
})
}
export function fetchRoleTree(roleName) {
return request({
url: '/admin/menu/roleTree/' + roleName,
method: 'get'
})
}
export function fetchDeptTree(query) {
return request({
url: '/admin/dept/tree',
method: 'get',
params: query
})
}

40
src/api/user.js Normal file
View File

@ -0,0 +1,40 @@
import request from '@/router/axios'
export function fetchList(query) {
return request({
url: '/admin/user/userPage',
method: 'get',
params: query
})
}
export function addObj(obj) {
return request({
url: '/admin/user/',
method: 'post',
data: obj
})
}
export function getObj(id) {
return request({
url: '/admin/user/' + id,
method: 'get'
})
}
export function delObj(id) {
return request({
url: '/admin/user/' + id,
method: 'delete'
})
}
export function putObj(obj) {
return request({
url: '/admin/user',
method: 'put',
data: obj
})
}

View File

@ -1,111 +1,85 @@
<template>
<div class="crud-container pull-auto">
<!-- <div class="crud-header">
<!-- <div class="crud-header">
<el-button type="primary" @click="handleAdd" size="small"> </el-button>
<el-button @click="toggleSelection([tableData[1]])" size="small">切换第二选中状态</el-button>
<el-button @click="toggleSelection()" size="small">取消选择</el-button>
</div> -->
<el-table
:data="tableData"
ref="table"
style="width:100%;min-height:430px;"
:border="tableOption.border"
v-loading="tableLoading"
@selection-change="handleSelectionChange" >
<el-table :data="tableData" :height="tableOption.height" ref="table" style="width:99.5%;margin:0 auto;box-sizing:border-box;" :border="tableOption.border" v-loading="tableLoading" @selection-change="handleSelectionChange">
<!-- 选择框 -->
<template v-if="tableOption.selection">
<el-table-column
type="selection"
width="55">
</el-table-column>
<el-table-column type="selection" width="55">
</el-table-column>
</template>
<!-- 序号 -->
<template v-if="tableOption.index">
<el-table-column
type="index"
width="50">
<el-table-column type="index" width="50">
</el-table-column>
</template>
<!-- 循环列 -->
<template v-for="(column,index) in tableOption.column">
<el-table-column
:width="column.width"
:label="column.label"
:fixed="column.fixed"
:sortable="column.sortable" v-if="!column.hide">
<template slot-scope="scope">
<span v-if="!column.overHidden" v-html="handleDetail(scope.row,column)"></span>
<el-popover v-else trigger="hover" placement="top">
<p>{{column.label}}: {{ scope.row[column.prop]}}</p>
<div slot="reference" class="name-wrapper">
<span v-html="handleDetail(scope.row,column)" class="crud--overflow"></span>
</div>
</el-popover>
</template>
</el-table-column>
<el-table-column :width="column.width" :label="column.label" :fixed="column.fixed" :sortable="column.sortable" v-if="!column.hide">
<template slot-scope="scope">
<slot :row="scope.row" :dic="DIC[column.dicData]" :name="column.prop" v-if="column.solt"></slot>
<span v-else-if="!column.overHidden" v-html="handleDetail(scope.row,column)"></span>
<el-popover v-else trigger="hover" placement="top">
<p>{{column.label}}: {{ scope.row[column.prop]}}</p>
<div slot="reference" class="name-wrapper">
<span v-html="handleDetail(scope.row,column)" class="crud--overflow"></span>
</div>
</el-popover>
</template>
</el-table-column>
</template>
<el-table-column label="操作" :width="width">
<template slot-scope="scope" >
<template v-if="menu">
<el-button type="primary" icon="el-icon-edit" size="small" @click="handleEdit(scope.row,scope.$index)"> </el-button>
<el-button type="danger" icon="el-icon-delete" size="small" @click="handleDel(scope.row,scope.$index)"> </el-button>
</template>
<slot :row="scope.row"></slot>
<el-table-column label="操作" :width="width" v-if="tableOption.menu==undefined?true:tableOption.menu">
<template slot-scope="scope">
<template v-if="menu">
<el-button type="primary" icon="el-icon-edit" size="small" @click="handleEdit(scope.row,scope.$index)" v-if="tableOption.editBtn==undefined?true:tableOption.meeditBtnnu"> </el-button>
<el-button type="danger" icon="el-icon-delete" size="small" @click="handleDel(scope.row,scope.$index)" v-if="tableOption.delBtn==undefined?true:tableOption.delBtn"> </el-button>
</template>
<slot :row="scope.row" name="menu"></slot>
</template>
</el-table-column>
</el-table>
<el-pagination class="crud-pagination pull-right"
:current-page.sync="page.currentPage"
:background = "page.background?page.background:true"
:page-size="page.pageSize"
@current-change="handleCurrentChange"
layout="total, sizes, prev, pager, next, jumper"
:total="page.total"></el-pagination>
<el-dialog
:title="boxType==0?'新增':'编辑'"
:visible.sync="boxVisible"
width="50%" :before-close="boxhandleClose">
<el-pagination v-if="tableOption.page==undefined?true:tableOption.page" class="crud-pagination pull-right" :current-page.sync="page.currentPage" :background="page.background?page.background:true" :page-size="page.pageSize" @current-change="handleCurrentChange" layout="total, sizes, prev, pager, next, jumper" :total="page.total"></el-pagination>
<el-dialog :title="boxType==0?'新增':'编辑'" :visible.sync="boxVisible" width="50%" :before-close="boxhandleClose">
<el-form ref="tableForm" :model="tableForm" label-width="80px" :rules="tableFormRules">
<el-row :gutter="20" :span="24">
<el-row :gutter="20" :span="24">
<template v-for="(column,index) in tableOption.column">
<el-col :span="column.span||12">
<el-form-item :label="column.label" :prop="column.prop" v-if="!column.visdiplay">
<template v-if="column.type == 'select'">
<el-select v-model="tableForm[column.prop]" :placeholder="'请选择'+column.label">
<el-option
v-for="(item,index) in DIC[column.dicData]"
:key="index"
:label="item.label"
:value="item.value">
<el-select v-model="tableForm[column.prop]" :placeholder="'请选择'+column.label">
<el-option v-for="(item,index) in DIC[column.dicData]" :key="index" :label="item.label" :value="item.value">
</el-option>
</el-select>
</template>
<template v-if="column.type == 'radio'">
<el-radio v-for="(item,index) in DIC[column.dicData]" v-model="tableForm[column.prop]" :label="item.value" :key="index">{{item.label}}</el-radio>
<el-radio v-for="(item,index) in DIC[column.dicData]" v-model="tableForm[column.prop]" :label="item.value" :key="index">{{item.label}}</el-radio>
</template>
<template v-if="column.type == 'date'">
<el-date-picker v-model="tableForm[column.prop]" type="date" :placeholder="'请输入'+column.label"> </el-date-picker>
<el-date-picker v-model="tableForm[column.prop]" type="date" :placeholder="'请输入'+column.label"> </el-date-picker>
</template>
<template v-if="column.type == 'checkbox'">
<el-checkbox-group v-model="tableForm[column.prop]">
<el-checkbox v-for="(item,index) in DIC[column.dicData]" :label="item.value" :key="index">{{item.label}}</el-checkbox>
<el-checkbox-group v-model="tableForm[column.prop]">
<el-checkbox v-for="(item,index) in DIC[column.dicData]" :label="item.value" :key="index">{{item.label}}</el-checkbox>
</el-checkbox-group>
</template>
<template v-if="!column.type">
<el-input v-model="tableForm[column.prop]" :placeholder="'请输入'+column.label"></el-input>
<el-input v-model="tableForm[column.prop]" :placeholder="'请输入'+column.label"></el-input>
</template>
</el-form-item>
</el-col>
</el-col>
</template>
</el-row >
</el-row>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleUpdate" v-if="boxType==1"> </el-button>
<el-button type="primary" @click="handleSave" v-else> </el-button>
<el-button @click="boxVisible = false"> </el-button>
</span>
</el-dialog>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleUpdate" v-if="boxType==1"> </el-button>
<el-button type="primary" @click="handleSave" v-else> </el-button>
<el-button @click="boxVisible = false"> </el-button>
</span>
</el-dialog>
</div>
</template>
<script>
@ -141,11 +115,13 @@ export default {
beforeOpen: Function,
page: {
type: Object,
default: {
total: 0, //
currentPage: 0, //
pageSize: 10, //
background: true //
default() {
return {
total: 0, //
currentPage: 0, //
pageSize: 10, //
background: true //
};
}
},
tableLoading: {
@ -199,6 +175,9 @@ export default {
handleCurrentChange(val) {
this.$emit("handleCurrentChange", val);
},
findByvalue(dic, val) {
return findByvalue(dic, val);
},
//
toggleSelection(rows) {
if (rows) {
@ -217,13 +196,19 @@ export default {
//
handleDetail(row, column) {
let result = "";
if (column.type) {
result = findByvalue(this.DIC[column.dicData], row[column.prop]);
} else {
result = row[column.prop];
}
if (column.dataDetail) {
result = column.dataDetail(result);
if (column.type) {
result = findByvalue(this.DIC[column.dicData], row[column.prop]);
} else {
result = row[column.prop];
}
result = column.dataDetail(row);
} else {
if (column.type) {
result = findByvalue(this.DIC[column.dicData], row[column.prop]);
} else {
result = row[column.prop];
}
}
return result;
},

View File

@ -0,0 +1,103 @@
<template>
<div class="pull-auto">
<el-row :span="24">
<template v-for="item in data">
<el-col :span="span">
<div class="item" :style="{background:item.color}">
<div class="item-header">
<p>{{item.title}}</p>
<span>{{item.subtitle}}</span>
</div>
<div class="item-body">
<h2>{{item.count}}</h2>
</div>
<div class="item-footer">
<span>{{item.allcount}}</span>
<p>{{item.text}}</p>
</div>
<p class="item-tip">{{item.key}}</p>
</div>
</el-col>
</template>
</el-row>
</div>
</template>
<script>
export default {
name: "datashow",
data() {
return {
span: this.option.span || 6,
data: this.option.data || []
};
},
props: {
option: {
type: Object,
default: {}
}
}
};
</script>
<style lang="scss" scoped>
.item {
position: relative;
margin: 15px;
padding: 12px;
height: 144px;
border-radius: 4px;
box-sizing: border-box;
overflow: hidden;
color: #fff;
}
.item-header {
position: relative;
& > p {
margin: 0px;
font-size: 14px;
}
& > span {
position: absolute;
right: 0px;
top: 0px;
padding: 2px 8px;
border-radius: 4px;
font-size: 12px;
background: rgba(255, 255, 255, 0.3);
}
}
.item-body {
& > h2 {
margin: 0;
font-size: 32px;
line-height: 60px;
}
}
.item-footer {
line-height: 16px;
& > span {
font-size: 10px;
}
& > p {
margin: 0px;
font-size: 12px;
}
}
.item-tip {
display: flex;
align-items: center;
justify-content: center;
position: absolute;
width: 80px;
height: 80px;
bottom: 10px;
right: 10px;
border: 2px solid #fff;
border-radius: 100%;
font-size: 48px;
transform: rotate(-40deg);
opacity: 0.1;
}
</style>

View File

@ -0,0 +1,88 @@
<template>
<div class="pull-auto">
<el-row :span="24">
<template v-for="item,index in data">
<el-col :span="span">
<div class="item">
<img :src="item.src" class="item-img" />
<div class="item-text" :style="{color:colorText,backgroundColor:bgText}">
<h3>{{item.name}}</h3>
<p>{{item.text}}</p>
</div>
</div>
</el-col>
</template>
</el-row>
</div>
</template>
<script>
export default {
name: "cardData",
data() {
return {
span: this.option.span || 6,
data: this.option.data || [],
colorText: this.option.colorText || "#fff",
bgText: this.option.bgText || "#2e323f",
borderColor: this.option.borderColor || "#2e323f"
};
},
props: {
option: {
type: Object,
default: {}
}
},
created() {},
mounted() {},
watch: {},
computed: {},
methods: {}
};
</script>
<style lang="scss" scoped>
$height: 340px;
.item {
position: relative;
margin: 0 auto;
margin-bottom: 50px;
width: 230px;
height: $height;
overflow: hidden;
border-radius: 5px;
border-color: #fff;
border-width: 1px;
border-style: solid;
&:hover .item-text {
top: 0;
}
}
.item-img {
width: 100%;
background: red;
border-radius: 5px;
border-bottom-left-radius: 0;
border-bottom-right-radius: 0;
}
.item-text {
position: absolute;
top: 150px;
padding: 20px 15px;
width: 100%;
height: $height;
overflow: auto;
box-sizing: border-box;
border-radius: 5px;
border-top-left-radius: 0;
border-top-right-radius: 0;
opacity: 0.9;
transition: top 0.4s;
& > p {
font-size: 12px;
line-height: 25px;
text-indent: 2em;
}
}
</style>

View File

@ -0,0 +1,77 @@
<template>
<div class="pull-auto easyData-contailer">
<el-row :span="24">
<template v-for="item in data">
<el-col :span="span">
<div class="item" :class="[{'item--easy':discount}]">
<div class="item-icon" :style="{color:color}">
<i :class="item.icon"></i>
</div>
<div class="item-info">
<span>{{item.title}}</span>
<h3 :style="{color:color}">{{item.count}}</h3>
</div>
</div>
</el-col>
</template>
</el-row>
</div>
</template>
<script>
export default {
name: "easyData",
data() {
return {
span: this.option.span || 6,
data: this.option.data,
color: this.option.color || "rgb(63, 161, 255)",
discount: this.option.discount || false
};
},
props: {
option: {
type: Object,
default: {}
}
}
};
</script>
<style lang="scss" scoped>
.easyData-contailer {
}
.item {
display: flex;
align-items: center;
justify-content: space-between;
width: 80px;
margin: 0 auto;
}
.item-icon {
margin-top: 3px;
margin-right: 8px;
& > i {
font-size: 46px !important;
}
}
.item-info {
line-height: 25px;
& > span {
color: #999;
font-size: 12px;
}
}
.item--easy {
flex-direction: column;
& > .item-icon {
margin: 0;
}
& > .item-info {
margin-top: -15px;
& > span {
font-size: 14px;
}
}
}
</style>

View File

@ -12,13 +12,13 @@
let baseUrl = '';
let iconfontVersion = 'j0ic7mgvwddt2o6r';
let iconfontUrl = `//at.alicdn.com/t/font_567566_${iconfontVersion}.css`;
let iconfontVersion = ['567566_lgiis24af44bcsor', '599693_c3ju5pfa6altmx6r'];
let iconfontUrl = `//at.alicdn.com/t/font_$key.css`;
let codeUrl = `/admin/code`
if (process.env.NODE_ENV == 'development') {
baseUrl = `http://api.frps.shop`;
baseUrl = `http://218.70.11.118`;
} else if (process.env.NODE_ENV == 'production') {
baseUrl = `http://api.frps.shop`;
baseUrl = `http://218.70.11.118`;
}
export { baseUrl, iconfontUrl, codeUrl }
export { baseUrl, iconfontUrl, iconfontVersion, codeUrl }

View File

@ -1,54 +0,0 @@
export const userOption = {
border: true,
index: true,
selection: false,
dic: ['GRADE', 'STATE'],
column: [
{
label: "用户名",
prop: "username",
width: "150",
rules: [{ required: true, message: "请输入用户名", trigger: "blur" }]
},
{
label: "角色",
prop: "grade",
type: "checkbox",
dicData: 'GRADE'
},
{
label: "创建时间",
prop: "date",
type: "date",
visdiplay: true,
},
{
label: "状态",
prop: "state",
dataDetail: val => {
return `<span class="el-tag ${val == '有效' ? 'el-tag--success' : 'el-tag--danger'}">${val}</span>`;
},
type: "radio",
dicData: 'STATE'
}
]
};
export const roleOption = {
border: true,
index: true,
selection: false,
column: [
{
label: "角色名称",
prop: "name",
width: "150",
rules: [{ required: true, message: "请输入用户名", trigger: "blur" }]
},
{
label: "创建时间",
prop: "date",
visdiplay: true,
type: "date",
}
]
};

View File

@ -1,27 +0,0 @@
export const DIC = {
SEX: [{
label: '男',
value: 0
}, {
label: '女',
value: 1
}],
STATE: [{
label: '有效',
value: 0
}, {
label: '无效',
value: 1
}],
GRADE: [
{
label: "管理员",
value: 0
},
{
label: "二级管理员",
value: 1
}
]
}

View File

@ -1,39 +0,0 @@
export default {
dic: ['GRADE', 'SEX'],
column: [
{
label: "用户名",
prop: "username",
rules: [{ required: true, message: "请输入用户名", trigger: "blur" }]
},
{
label: "姓名",
prop: "name"
},
{
label: "类型",
prop: "type",
type: "select",
dicData: 'GRADE'
},
{
label: "性别",
prop: "sex",
type: "radio",
dicData: 'SEX'
},
{
label: "权限",
prop: "grade",
span: 24,
type: "checkbox",
dicData: 'GRADE'
},
{
label: "地址",
disabled: true,
span: 24,
prop: "address",
}
]
};

View File

@ -1,43 +0,0 @@
export default {
border: true,
index: true,
selection: true,
dic: ['GRADE', 'SEX'],
column: [
{
label: "用户名",
prop: "username",
width: "150",
dataDetail: val => {
return `<span class="el-tag el-tag--success">${val}</span>`;
},
rules: [{ required: true, message: "请输入用户名", trigger: "blur" }]
},
{
label: "姓名",
prop: "name"
},
{
label: "类型",
prop: "type",
dataDetail: val => {
return `<span class="el-tag">${val}</span>`;
},
type: "select",
dicData: 'GRADE'
},
{
label: "权限",
prop: "grade",
type: "checkbox",
dicData: 'GRADE'
},
{
label: "地址",
prop: "address",
width: "300",
span: 24,
overHidden: true
}
]
};

View File

@ -1,5 +1,6 @@
export default [
'Avue 是一个基于vue+vuex+vue-router快速后台管理模板采用token交互验证方式。',
'您可以 Avue 为基础不只限制于vue的页面你可以嵌入任意第三方网站基于iframe框架。',
'Avue 构建简单上手快,最大程度上帮助企业节省时间成本和费用开支。'
'是一个基于Spring Cloud、oAuth2.0开发基于Vue前后分离的开发平台',
' 是一个基于vue+vuex+vue-router快速后台管理系统采用token交互验证方式。',
'最大程度上帮助企业节省时间成本和费用开支。 ',
'QQ群23754102'
]

View File

@ -0,0 +1,49 @@
// Inspired by https://github.com/Inndy/vue-clipboard2
const Clipboard = require('clipboard')
if (!Clipboard) {
throw new Error('you shold npm install `clipboard` --save at first ')
}
export default {
bind(el, binding) {
if (binding.arg === 'success') {
el._v_clipboard_success = binding.value
} else if (binding.arg === 'error') {
el._v_clipboard_error = binding.value
} else {
const clipboard = new Clipboard(el, {
text() { return binding.value },
action() { return binding.arg === 'cut' ? 'cut' : 'copy' }
})
clipboard.on('success', e => {
const callback = el._v_clipboard_success
callback && callback(e) // eslint-disable-line
})
clipboard.on('error', e => {
const callback = el._v_clipboard_error
callback && callback(e) // eslint-disable-line
})
el._v_clipboard = clipboard
}
},
update(el, binding) {
if (binding.arg === 'success') {
el._v_clipboard_success = binding.value
} else if (binding.arg === 'error') {
el._v_clipboard_error = binding.value
} else {
el._v_clipboard.text = function() { return binding.value }
el._v_clipboard.action = function() { return binding.arg === 'cut' ? 'cut' : 'copy' }
}
},
unbind(el, binding) {
if (binding.arg === 'success') {
delete el._v_clipboard_success
} else if (binding.arg === 'error') {
delete el._v_clipboard_error
} else {
el._v_clipboard.destroy()
delete el._v_clipboard
}
}
}

View File

@ -0,0 +1,13 @@
import Clipboard from './clipboard'
const install = function(Vue) {
Vue.directive('Clipboard', Clipboard)
}
if (window.Vue) {
window.clipboard = Clipboard
Vue.use(install); // eslint-disable-line
}
Clipboard.install = install
export default Clipboard

91
src/directive/sticky.js Normal file
View File

@ -0,0 +1,91 @@
const vueSticky = {}
let listenAction
vueSticky.install = Vue => {
Vue.directive('sticky', {
inserted(el, binding) {
const params = binding.value || {}
const stickyTop = params.stickyTop || 0
const zIndex = params.zIndex || 1000
const elStyle = el.style
elStyle.position = '-webkit-sticky'
elStyle.position = 'sticky'
// if the browser support css stickyCurrently Safari, Firefox and Chrome Canary
// if (~elStyle.position.indexOf('sticky')) {
// elStyle.top = `${stickyTop}px`;
// elStyle.zIndex = zIndex;
// return
// }
const elHeight = el.getBoundingClientRect().height
const elWidth = el.getBoundingClientRect().width
elStyle.cssText = `top: ${stickyTop}px; z-index: ${zIndex}`
const parentElm = el.parentNode || document.documentElement
const placeholder = document.createElement('div')
placeholder.style.display = 'none'
placeholder.style.width = `${elWidth}px`
placeholder.style.height = `${elHeight}px`
parentElm.insertBefore(placeholder, el)
let active = false
const getScroll = (target, top) => {
const prop = top ? 'pageYOffset' : 'pageXOffset'
const method = top ? 'scrollTop' : 'scrollLeft'
let ret = target[prop]
if (typeof ret !== 'number') {
ret = window.document.documentElement[method]
}
return ret
}
const sticky = () => {
if (active) {
return
}
if (!elStyle.height) {
elStyle.height = `${el.offsetHeight}px`
}
elStyle.position = 'fixed'
elStyle.width = `${elWidth}px`
placeholder.style.display = 'inline-block'
active = true
}
const reset = () => {
if (!active) {
return
}
elStyle.position = ''
placeholder.style.display = 'none'
active = false
}
const check = () => {
const scrollTop = getScroll(window, true)
const offsetTop = el.getBoundingClientRect().top
if (offsetTop < stickyTop) {
sticky()
} else {
if (scrollTop < elHeight + stickyTop) {
reset()
}
}
}
listenAction = () => {
check()
}
window.addEventListener('scroll', listenAction)
},
unbind() {
window.removeEventListener('scroll', listenAction)
}
})
}
export default vueSticky

View File

@ -0,0 +1,13 @@
import waves from './waves'
const install = function(Vue) {
Vue.directive('waves', waves)
}
if (window.Vue) {
window.waves = waves
Vue.use(install); // eslint-disable-line
}
waves.install = install
export default waves

View File

@ -0,0 +1,26 @@
.waves-ripple {
position: absolute;
border-radius: 100%;
background-color: rgba(0, 0, 0, 0.15);
background-clip: padding-box;
pointer-events: none;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
-webkit-transform: scale(0);
-ms-transform: scale(0);
transform: scale(0);
opacity: 1;
}
.waves-ripple.z-active {
opacity: 0;
-webkit-transform: scale(2);
-ms-transform: scale(2);
transform: scale(2);
-webkit-transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
transition: opacity 1.2s ease-out, -webkit-transform 0.6s ease-out;
transition: opacity 1.2s ease-out, transform 0.6s ease-out;
transition: opacity 1.2s ease-out, transform 0.6s ease-out, -webkit-transform 0.6s ease-out;
}

View File

@ -0,0 +1,42 @@
import './waves.css'
export default{
bind(el, binding) {
el.addEventListener('click', e => {
const customOpts = Object.assign({}, binding.value)
const opts = Object.assign({
ele: el, // 波纹作用元素
type: 'hit', // hit点击位置扩散center中心点扩展
color: 'rgba(0, 0, 0, 0.15)' // 波纹颜色
}, customOpts)
const target = opts.ele
if (target) {
target.style.position = 'relative'
target.style.overflow = 'hidden'
const rect = target.getBoundingClientRect()
let ripple = target.querySelector('.waves-ripple')
if (!ripple) {
ripple = document.createElement('span')
ripple.className = 'waves-ripple'
ripple.style.height = ripple.style.width = Math.max(rect.width, rect.height) + 'px'
target.appendChild(ripple)
} else {
ripple.className = 'waves-ripple'
}
switch (opts.type) {
case 'center':
ripple.style.top = (rect.height / 2 - ripple.offsetHeight / 2) + 'px'
ripple.style.left = (rect.width / 2 - ripple.offsetWidth / 2) + 'px'
break
default:
ripple.style.top = (e.pageY - rect.top - ripple.offsetHeight / 2 - document.body.scrollTop) + 'px'
ripple.style.left = (e.pageX - rect.left - ripple.offsetWidth / 2 - document.body.scrollLeft) + 'px'
}
ripple.style.backgroundColor = opts.color
ripple.className = 'waves-ripple z-active'
return false
}
}, false)
}
}

View File

@ -9,7 +9,7 @@ import store from './store';
import ELEMENT from 'element-ui';
import { loadStyle } from './util/util'
import * as urls from '@/config/env';
import { iconfontUrl } from '@/config/env';
import { iconfontUrl, iconfontVersion } from '@/config/env';
import * as filters from './filters' // 全局filter
import './styles/common.scss';
Vue.use(ELEMENT)
@ -22,8 +22,10 @@ Object.keys(urls).forEach(key => {
Object.keys(filters).forEach(key => {
Vue.filter(key, filters[key])
})
iconfontVersion.forEach(ele => {
loadStyle(iconfontUrl.replace('$key', ele));
})
loadStyle(iconfontUrl);
Vue.config.productionTip = false;

View File

@ -1,123 +0,0 @@
<template>
<el-container class="menu-container pull-height">
<el-header class="menu-header">
<el-button-group>
<el-button type="primary" icon="el-icon-plus" size="small" @click.native="handleAdd" v-if="permission.sys_menu_btn_add">新增</el-button>
<el-button type="primary" icon="el-icon-edit" size="small" @click.native="handleEdit" v-if="permission.sys_menu_btn_edit">编辑</el-button>
<el-button type="primary" icon="el-icon-delete" size="small" @click.native="handleDel" v-if="permission.sys_menu_btn_del">删除</el-button>
</el-button-group>
</el-header>
<el-container>
<el-aside width="300px">
<el-tree
:data="menuAll"
node-key="id"
highlight-current
default-expand-all
:expand-on-click-node="false"
@node-click="handleNodeClick"></el-tree>
</el-aside>
<el-main>
<el-form ref="form" :model="form" label-width="80px">
<el-form-item label="父节点ID">
<el-input v-model="parentForm.id" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="父节点">
<el-input v-model="parentForm.label" :disabled="true"></el-input>
</el-form-item>
<el-form-item label="菜单名称">
<el-input v-model="form.label" :disabled="formGrade"></el-input>
</el-form-item>
<el-form-item label="菜单图标">
<el-input v-model="form.icon" :disabled="formGrade"></el-input>
</el-form-item>
<el-form-item label="菜单路径">
<el-input v-model="form.href" :disabled="formGrade"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleSubmit" :disabled="formGrade" v-if="formStatus=='add'">新增</el-button>
<el-button type="primary" @click="handleSubmit" :disabled="formGrade" v-if="formStatus=='edit'">修改</el-button>
</el-form-item>
</el-form>
</el-main>
</el-container>
</el-container>
</template>
<script>
import { mapGetters } from "vuex";
import { validatenull } from "@/util/validate";
import { findParent } from "@/util/util";
export default {
name: "menu",
data() {
return {
form: {},
obj: {},
parentForm: {},
formGrade: true,
formStatus: ""
};
},
created() {
this.$store.dispatch("GetMenuAll").then(data => {});
},
mounted() {},
computed: {
...mapGetters(["permission", "menuAll"])
},
props: [],
methods: {
handleNodeClick(data, checked, indeterminate) {
this.parentForm = Object.assign({}, findParent(this.menuAll, data.id));
this.formGrade = true;
this.formStatus = "";
this.obj = data;
this.form = data;
},
handleAdd() {
this.formGrade = false;
this.formStatus = "add";
this.form = {};
},
handleEdit() {
if (validatenull(this.obj)) {
this.$message({
showClose: true,
message: "请选择菜单",
type: "warning"
});
return false;
}
this.form = Object.assign({}, this.obj);
this.formStatus = "edit";
this.formGrade = false;
},
handleDel() {
this.$confirm(`是否确认删除序号为${this.form.label}`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.$message({
showClose: true,
message: "删除成功",
type: "success"
});
})
.catch(err => {});
},
handleSubmit() {}
}
};
</script>
<style lang="scss" scoped>
.menu-container {
padding: 0 20px;
}
.menu-header {
padding: 8px 0;
}
</style>

View File

@ -1,206 +0,0 @@
<template>
<div class="table-container pull-height">
<div class="table-header">
<el-button type="primary" @click="handleAdd" size="small" v-if="permission.sys_crud_btn_add"> </el-button>
</div>
<Crud
:tableOption="tableOption"
:tableData="tableData"
:tableLoading="tableLoading"
:page="page"
ref="crud"
width="290"
@handleSave="handleSave"
@handleUpdate="handleUpdate"
@handleDel="handleDel"
menu>
<template slot-scope="scope">
<el-button icon="el-icon-check" size="small" @click="handleGrade(scope.row,scope.$index)">权限</el-button>
</template>
</Crud>
<el-dialog
title="菜单"
:visible.sync="grade.box"
width="40%">
<el-tree
:data="menuAll"
:default-checked-keys="grade.check"
:default-expanded-keys="grade.check"
show-checkbox
node-key="id"
@check-change="handleGradeCheckChange">
</el-tree>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleGradeUpdate">更新</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import Crud from "@/components/crud/";
import { roleOption } from "@/const/adminTabelOption.js";
export default {
name: "role",
data() {
return {
tableOption: {}, //
tableData: [], //
tablePage: 1,
tableLoading: false,
tabelObj: {},
page: {
total: 0, //
currentPage: 1, //
pageSize: 10 //
},
grade: {
box: false,
check: []
}
};
},
created() {
//
this.tableOption = roleOption;
this.handleList();
},
watch: {},
mounted() {},
computed: {
...mapGetters(["permission", "menuAll"])
},
props: [],
methods: {
/**
* @title 权限更新
*
**/
handleGradeUpdate() {
this.tabelObj.check = [].concat(this.grade.check);
this.tabelObj = {};
this.grade.check = [];
this.grade.box = false;
},
/**
* @title 权限选择
*
**/
handleGradeCheckChange(data, checked, indeterminate) {
if (checked) {
this.grade.check.push(data.id);
} else {
this.grade.check.splice(this.grade.check.indexOf(data.id), 1);
}
},
/**
* @title 打开权限
*/
handleGrade(row, index) {
this.$store.dispatch("GetMenuAll").then(data => {
this.grade.box = true;
this.tabelObj = row;
this.grade.check = this.tabelObj.check;
});
},
/**
* @title 打开新增窗口
* @detail 调用crud的handleadd方法即可
*
**/
handleAdd() {
this.$refs.crud.handleAdd();
},
/**
* @title 获取数据
* @detail 赋值为tableData表格即可
*
**/
handleList() {
this.tableLoading = true;
this.$store
.dispatch("GetRoleData", { page: `${this.tablePage}` })
.then(data => {
setTimeout(() => {
this.tableData = data.tableData;
this.page = {
total: data.total,
pageSize: data.pageSize
};
this.tableLoading = false;
}, 1000);
});
},
/**
* @title 数据添加
* @param row 为当前的数据
* @param done 为表单关闭函数
*
**/
handleSave(row, done) {
this.tableData.push(row);
this.$message({
showClose: true,
message: "添加成功",
type: "success"
});
done();
},
/**
* @title 数据删除
* @param row 为当前的数据
* @param index 为当前更新数据的行数
*
**/
handleDel(row, index) {
this.$confirm(`是否确认删除序号为${row.name}`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.tableData.splice(index, 1);
this.$message({
showClose: true,
message: "删除成功",
type: "success"
});
})
.catch(err => {});
},
/**
* @title 数据更新
* @param row 为当前的数据
* @param index 为当前更新数据的行数
* @param done 为表单关闭函数
*
**/
handleUpdate(row, index, done) {
this.tableData.splice(index, 1, row);
this.$message({
showClose: true,
message: "修改成功",
type: "success"
});
done();
}
},
components: {
Crud
}
};
</script>
<style lang="scss" scoped>
.table-container {
padding: 8px 10px;
}
.table-header {
margin-bottom: 10px;
& > .el-button {
padding: 12px 25px;
}
}
</style>

View File

@ -1,157 +0,0 @@
<template>
<div class="table-container pull-height">
<div class="table-header">
<el-button type="primary" @click="handleAdd" size="small" v-if="permission.sys_crud_btn_add"> </el-button>
</div>
<Crud
:tableOption="tableOption"
:tableData="tableData"
:tableLoading="tableLoading"
:page="page"
ref="crud"
width="290"
@handleSave="handleSave"
@handleUpdate="handleUpdate"
@handleDel="handleDel"
menu>
</Crud>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import Crud from "@/components/crud/";
import { userOption } from "@/const/adminTabelOption.js";
export default {
name: "user",
data() {
return {
tableOption: {}, //
tableData: [], //
tablePage: 1,
tableLoading: false,
tabelObj: {},
page: {
total: 0, //
currentPage: 1, //
pageSize: 10 //
},
grade: {
box: false,
check: []
}
};
},
created() {
//
this.tableOption = userOption;
this.handleList();
},
watch: {},
mounted() {},
computed: {
...mapGetters(["permission", "menuAll"])
},
props: [],
methods: {
/**
* @title 打开新增窗口
* @detail 调用crud的handleadd方法即可
*
**/
handleAdd() {
this.$refs.crud.handleAdd();
},
/**
* @title 获取数据
* @detail 赋值为tableData表格即可
*
**/
handleList() {
this.tableLoading = true;
this.$store
.dispatch("GetUserData", { page: `${this.tablePage}` })
.then(data => {
setTimeout(() => {
this.tableData = data.tableData;
this.page = {
total: data.total,
pageSize: data.pageSize
};
this.tableLoading = false;
}, 1000);
});
},
/**
* @title 数据添加
* @param row 为当前的数据
* @param done 为表单关闭函数
*
**/
handleSave(row, done) {
this.tableData.push(row);
this.$message({
showClose: true,
message: "添加成功",
type: "success"
});
done();
},
/**
* @title 数据删除
* @param row 为当前的数据
* @param index 为当前更新数据的行数
*
**/
handleDel(row, index) {
this.$confirm(`是否确认删除序号为${row.name}`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.tableData.splice(index, 1);
this.$message({
showClose: true,
message: "删除成功",
type: "success"
});
})
.catch(err => {});
},
/**
* @title 数据更新
* @param row 为当前的数据
* @param index 为当前更新数据的行数
* @param done 为表单关闭函数
*
**/
handleUpdate(row, index, done) {
this.tableData.splice(index, 1, row);
this.$message({
showClose: true,
message: "修改成功",
type: "success"
});
done();
}
},
components: {
Crud
}
};
</script>
<style lang="scss" scoped>
.table-container {
padding: 8px 10px;
}
.table-header {
margin-bottom: 10px;
& > .el-button {
padding: 12px 25px;
}
}
</style>

View File

@ -1,67 +0,0 @@
<template>
<div class="errpage-container pull-chheight">
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>404错误页面</span>
</div>
<div class="error-box">
<errorPage404 class="error-page"></errorPage404>
<span class="error-text">/404当访问的页面不存在时会跳转到404页面您可以在浏览器地址栏中修改url为一个不存在的路径体验一下效果</span>
</div>
</el-card>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>403错误页面</span>
</div>
<div class="error-box">
<errorPage403 class="error-page"></errorPage403>
<span class="error-text">/403在当前登录用户不具有执行当前操作的权限时跳转到该页面您可以在ajax请求方法中判断返回的状态码为403时跳转到该页面</span>
</div>
</el-card>
<el-card class="box-card">
<div slot="header" class="clearfix">
<span>500错误页面</span>
</div>
<div class="error-box">
<errorPage500 class="error-page"></errorPage500>
<span class="error-text">/500当请求之后出现服务端错误时跳转到该页面您可以在ajax请求方法中判断返回的状态码为500时跳转到该页面</span>
</div>
</el-card>
</div>
</template>
<script>
import errorPage404 from "@/components/errorPage/404.vue";
import errorPage403 from "@/components/errorPage/403.vue";
import errorPage500 from "@/components/errorPage/500.vue";
export default {
name: "errPage",
data() {
return {};
},
created() {},
mounted() {},
computed: {},
props: [],
methods: {},
components: { errorPage404, errorPage403, errorPage500 }
};
</script>
<style lang="scss" scoped>
.error-page {
position: absolute;
top: 90px;
left: 150px;
transform: scale(0.4);
}
.error-text {
position: absolute;
top: 20px;
left: 340px;
}
.error-box {
position: relative;
height: 200px;
}
</style>

View File

@ -1,13 +0,0 @@
<template>
<div>
<!--error code-->
{{a.a}}
<!--error code-->
</div>
</template>
<script>
export default {
name: "errorTestA"
};
</script>

View File

@ -1,67 +0,0 @@
<template>
<div class="errlog-container pull-chheight">
<h5>
<el-tag>tip:</el-tag>&nbsp;vuexCLEAR_ALL_ERR
</h5>
<h5 v-if="errLog.length==0">
还没有错误日志了
你可以放开&nbsp;<el-tag type="danger">./src/page/errlog/index.vue中的errorA标签</el-tag>&nbsp;的组件即可测试<br />
</h5>
<!-- <errorA></errorA> -->
<div v-for="(err,index) in errLog" :key="index" class="errlog-list" v-else>
<p class="errlog-item"><el-tag type="info">地址</el-tag><span>{{err.url}}</span></p>
<p class="errlog-item"><el-tag type="danger">信息</el-tag><span>{{err.message}}</span></p>
<div class="errlog-info">
{{err.stack}}
</div>
</div>
</div>
</template>
<script>
import { mapState, mapGetters } from "vuex";
import errorA from "./errorTestA";
export default {
name: "errlog",
data() {
return {};
},
created() {},
mounted() {},
computed: {
...mapGetters(["errLog"])
},
props: [],
methods: {},
components: { errorA }
};
</script>
<style lang="scss" scoped>
.errlog-container {
padding: 15px;
}
.errlog-list {
& > .errlog-item {
height: 40px;
line-height: 40px;
& > span {
font-size: 14px;
}
& > .el-tag {
margin-right: 10px;
}
}
& > .errlog-info {
margin-top: 10px;
margin-bottom: 20px;
padding: 8px 10px;
background-color: #fff;
font-size: 12px;
border-style: solid;
border-width: 1px;
border-radius: 5px;
border-color: #ccc;
}
}
</style>

View File

@ -1,85 +0,0 @@
<template>
<div class="from-container pull-chheight">
<Form
:formOption="formOption"
:formSubmitText="formSubmitText"
@handleSubmit="handleSubmit"
></Form>
<el-button @click.native="formate" style="margin: 8px 0">格式化</el-button>
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 15}"
placeholder="请输入内容"
v-model="formJson">
</el-input>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import Form from "@/components/form/";
import formOption from "@/const/formOption";
export default {
name: "from",
data() {
return {
formJson: "",
formOption: formOption,
formSubmitText: "确定",
form: {}
};
},
created() {
this.formJson = JSON.stringify(formOption, null, 2);
},
watch: {},
mounted() {},
computed: {
...mapGetters(["permission"])
},
props: [],
methods: {
formate() {
let p = new Promise((resolve, reject) => {
resolve(JSON.parse(this.formJson));
});
p
.then(data => {
this.formOption = data;
this.formJson = JSON.stringify(data, null, 2);
this.$message({
message: "数据加载成功",
type: "success"
});
})
.catch(err => {
this.$message({
center: true,
dangerouslyUseHTMLString: true,
message: `JSON格式错误<br \>\n${err}`,
type: "error"
});
});
},
handleSubmit(form) {
if (form) {
this.form = form;
this.$message({
message: form,
type: "success"
});
} else {
}
}
},
components: {
Form
}
};
</script>
<style lang="scss" scoped>
.from-container {
padding: 8px 10px;
}
</style>

View File

@ -1,97 +0,0 @@
<template>
<div class="iconfon-container pull-height">
<h3 style="color:red;">修改./src/config/env.js中的iconfontVersion地址即可实时调用阿里云在线图标库</h3>
<ul class="icon-list">
<li><span><i class="icon-daohanglanmoshi02"></i><span class="icon-name">icon-daohanglanmoshi02</span></span></li>
<li><span><i class="icon-changyonglogo27"></i><span class="icon-name">icon-changyonglogo27</span></span></li>
<li><span><i class="icon-biaoge"></i><span class="icon-name">icon-biaoge</span></span></li>
<li><span><i class="icon-baidu1"></i><span class="icon-name">icon-baidu1</span></span></li>
<li><span><i class="icon-tubiao"></i><span class="icon-name">icon-tubiao</span></span></li>
<li><span><i class="icon-souhu"></i><span class="icon-name">icon-souhu</span></span></li>
<li><span><i class="icon-msnui-360"></i><span class="icon-name">icon-msnui-360</span></span></li>
<li><span><i class="icon-iframe"></i><span class="icon-name">icon-iframe</span></span></li>
<li><span><i class="icon-huanyingye"></i><span class="icon-name">icon-huanyingye</span></span></li>
<li><span><i class="icon-weixin"></i><span class="icon-name">icon-weixin</span></span></li>
<li><span><i class="icon-qq"></i><span class="icon-name">icon-qq</span></span></li>
<li><span><i class="icon-tuichu"></i><span class="icon-name">icon-tuichu</span></span></li>
<li><span><i class="icon-jiaoseguanli"></i><span class="icon-name">icon-jiaoseguanli</span></span></li>
<li><span><i class="icon-yonghuguanli"></i><span class="icon-name">icon-yonghuguanli</span></span></li>
<li><span><i class="icon-caidanguanli"></i><span class="icon-name">icon-caidanguanli</span></span></li>
</ul>
<img class="iconfon-explace" src="http://oetrwxnhv.bkt.clouddn.com/avue-iconfont.png" alt="">
</div>
</template>
<script>
export default {
name: "iconfont",
data() {
return {};
},
created() {},
mounted() {},
props: [],
methods: {},
components: {}
};
</script>
<style lang="scss" scoped>
.iconfon-container {
padding: 15px;
}
.iconfon-container > ul.icon-list {
margin: 15px auto;
overflow: hidden;
list-style: none;
padding: 0;
border: 1px solid #eaeefb;
border-radius: 4px;
}
.iconfon-container .content > ul:not(.timeline) {
margin: 10px 0;
padding: 0 0 0 20px;
font-size: 14px;
color: #5e6d82;
line-height: 2em;
}
.icon-list li {
float: left;
width: 16.66%;
text-align: center;
height: 120px;
line-height: 120px;
color: #666;
font-size: 13px;
transition: color 0.15s linear;
border-right: 1px solid #eee;
border-bottom: 1px solid #eee;
margin-right: -1px;
margin-bottom: -1px;
}
.icon-list li span {
display: inline-block;
line-height: normal;
vertical-align: middle;
font-family: Helvetica Neue, Helvetica, PingFang SC, Hiragino Sans GB,
Microsoft YaHei, SimSun, sans-serif;
color: #99a9bf;
}
.icon-list li i {
display: block;
font-size: 36px !important;
margin-bottom: 15px;
color: #606266;
}
.icon-list li .icon-name {
display: inline-block;
padding: 0 12px;
font-size: 12px !important;
height: 1em;
color: #606266;
}
.iconfon-explace {
width: 100%;
}
</style>

View File

@ -1,22 +1,27 @@
<template>
<div class="pull-height animated" :class="{'zoomOutUp': isLock}">
<Top></Top>
<div class="index">
<Sidebar class="left pull-chheight"></Sidebar>
<div class="right">
<Tags ref="nav" class="nav"></Tags>
<router-view class="main"></router-view>
</div>
</div>
</div>
<div class="pull-height animated" :class="{'zoomOutUp': isLock}">
<top></top>
<div class="index">
<sidebar class="left pull-chheight"></sidebar>
<div class="right">
<tags ref="nav" class="nav"></tags>
<router-view class="main pull-chheight"></router-view>
</div>
</div>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import Tags from "./tags";
import Top from "./top/";
import Sidebar from "./sidebar/";
import tags from "./tags";
import top from "./top/";
import sidebar from "./sidebar/";
export default {
components: {
top,
tags,
sidebar
},
name: "index",
data() {
return {};
@ -25,12 +30,7 @@ export default {
mounted() {},
computed: mapGetters(["isLock"]),
props: [],
methods: {},
components: {
Top,
Tags,
Sidebar
}
methods: {}
};
</script>
@ -43,13 +43,14 @@ export default {
min-height: 100%;
background: #fff;
overflow: hidden;
.left {
.left:not(.el-menu--collapse) {
width: 200px;
overflow-y: auto;
}
.right {
padding-top: 102px;
padding-top: 90px;
position: relative;
flex: 1;
overflow: auto;
box-sizing: border-box;
}
.main {

View File

@ -1,5 +1,5 @@
<template>
<el-menu unique-opened :default-active="tag.value" class="el-menu-vertical-demo" background-color="#495060" text-color="#c9cbd0" active-text-color="#409EFF" :collapse="isCollapse">
<el-menu unique-opened :default-active="nowTagValue" class="el-menu-vertical-demo" background-color="#495060" text-color="#c9cbd0" active-text-color="#fff" :collapse="isCollapse">
<sidebar-item :menu="menu" :show="!isCollapse"></sidebar-item>
</el-menu>
</template>
@ -7,6 +7,7 @@
<script>
import MENU from "@/mock/menu";
import { mapGetters } from "vuex";
import { setUrlPath } from "@/util/util";
import SidebarItem from "./sidebarItem";
export default {
@ -16,7 +17,12 @@ export default {
created() {
this.$store.dispatch("GetMenu").then(data => {});
},
computed: mapGetters(["menu", "tag", "isCollapse"]),
computed: {
...mapGetters(["menu", "tag", "isCollapse"]),
nowTagValue: function() {
return setUrlPath(this.$route);
}
},
mounted() {},
methods: {},
components: { SidebarItem }

View File

@ -1,7 +1,7 @@
<template>
<div class="menu-wrapper">
<template v-for="item in menu">
<el-menu-item v-if="item.children.length===0 " :index="item.component" @click="open(item)" :key="item.label">
<el-menu-item v-if="item.children.length===0 " :index="item.path" @click="open(item)" :key="item.label">
<i :class="item.icon"></i>
<span slot="title">{{item.label}}</span>
</el-menu-item>
@ -11,7 +11,7 @@
<span slot="title" :class="{display:!show}">{{item.label}}</span>
</template>
<template v-for="child in item.children">
<el-menu-item v-if="child.children.length==0" :index="child.component" @click="open(child)">
<el-menu-item v-if="child.children.length==0" :index="child.path" @click="open(child)">
<i :class="child.icon"></i>
<span slot="title">{{child.label}}</span>
</el-menu-item>
@ -40,10 +40,10 @@ export default {
mounted() {},
methods: {
open(item) {
this.$router.push({ path: resolveUrlPath(item.href) });
this.$router.push({ path: resolveUrlPath(item.path) });
this.$store.commit("ADD_TAG", {
label: item.label,
value: item.href
value: item.path
});
}
}

View File

@ -33,7 +33,8 @@
</div>
</template>
<script>
import { resolveUrlPath } from "@/util/util";
import { resolveUrlPath, setUrlPath } from "@/util/util";
import { baseUrl } from "@/config/env";
import { mapState, mapGetters } from "vuex";
import Breadcrumb from "./breadcrumb";
export default {
@ -77,11 +78,7 @@ export default {
computed: {
...mapGetters(["tagWel", "tagList", "isCollapse", "tag"]),
nowTagValue: function() {
const value = this.$route.query.src
? this.$route.query.src
: this.$route.path;
this.$store.commit("SET_TAG", value);
return value;
return setUrlPath(this.$route);
},
tagListNum: function() {
return this.tagList.length != 0;
@ -91,12 +88,14 @@ export default {
init() {
this.refsTag = this.$refs.tagsPageOpened;
setTimeout(() => {
this.refsTag.forEach((item, index) => {
if (this.tag.value === item.attributes.name.value) {
let tag = this.refsTag[index];
this.moveToView(tag);
}
});
if (this.refsTag) {
this.refsTag.forEach((item, index) => {
if (this.tag.value === item.attributes.name.value) {
let tag = this.refsTag[index];
this.moveToView(tag);
}
});
}
}, 1);
},
showCollapse() {

View File

@ -1,9 +1,11 @@
<template>
<div class="header">
<div class="header-button is-left">
<h3 style="letter-spacing: 1px;">Avue 通用管理系统快速开发框架</h3>
<top-logo></top-logo>
</div>
<h1 class="header-title"></h1>
<h1 class="header-title">
<!-- <topMenu></topMenu> -->
</h1>
<div class="header-button is-right">
<el-tooltip class="item" effect="dark" content="锁屏" placement="bottom">
<span class="header-item">
@ -43,9 +45,11 @@
<script>
import { mapState, mapGetters } from "vuex";
import { fullscreenToggel } from "@/util/util";
import topLogo from "./top-logo";
import topLock from "./top-lock";
import topMenu from "./top-menu";
export default {
components: { topLock },
components: { topLock, topLogo, topMenu },
name: "top",
data() {
return {};

View File

@ -0,0 +1,40 @@
<template>
<div class="pull-auto">
<div class="logo">
<span class="logo_title is-bold">Pig </span>
<span class="logo_subtitle"> 微服务快速开发框架</span>
</div>
</div>
</template>
<script>
export default {
name: "top-logo",
data() {
return {};
},
created() {},
computed: {},
methods: {}
};
</script>
<style scoped="scoped" lang="scss">
.logo {
display: flex;
align-items: center;
}
.logo_title {
padding: 0 8px 0 0;
color: #409eff;
line-height: 60px;
font-size: 28px;
font-style: italic;
&.is-bold {
font-weight: 700;
}
}
.logo_subtitle {
padding-top: 5px;
}
</style>

View File

@ -0,0 +1,65 @@
<template>
<div class="pull-auto top-menu">
<el-menu :default-active="activeIndex" mode="horizontal">
<template v-for="item in items">
<el-menu-item :index="item.parentId+''" @click.native="openMenu(item)">{{item.label}}</el-menu-item>
</template>
</el-menu>
</div>
</template>
<script>
import { resolveUrlPath } from "@/util/util";
import { mapState, mapGetters } from "vuex";
export default {
name: "top-menu",
data() {
return {
activeIndex: "0",
items: [
{
label: "首页",
href: "/wel/index",
parentId: 0
},
{
label: "设置",
parentId: 1
}
]
};
},
created() {},
computed: {
...mapGetters(["tagCurrent", "menu"])
},
methods: {
openMenu(item) {
this.$store.dispatch("GetMenu", item.parentId).then(data => {
this.$store.commit("DEL_ALL_TAG");
let tagCurrent = Object.assign([], this.tagCurrent);
tagCurrent[0] = {
label: item.label,
value: item.href
};
this.$store.commit("SET_TAG_CURRENT", tagCurrent);
this.$router.push({
path: resolveUrlPath(item.href ? item.href : this.menu[0].href)
});
this.$store.commit("ADD_TAG", {
label: item.label ? item.label : this.menu[0].label,
value: item.href ? item.href : this.menu[0].href
});
});
}
}
};
</script>
<style scoped="scoped" lang="scss">
.top-menu {
padding: 0 50px;
margin-top: -4px;
box-sizing: border-box;
}
</style>

View File

@ -14,6 +14,7 @@
</template>
<script>
import { mapGetters, mapState } from "vuex";
import { resolveUrlPath } from "@/util/util";
export default {
name: "lock",
data() {
@ -60,7 +61,7 @@ export default {
this.pass = true;
setTimeout(() => {
this.$store.commit("CLEAR_LOCK");
this.$router.push({ path: this.tag.value || "/" });
this.$router.push({ path: resolveUrlPath(this.tag.value || "/") });
}, 1000);
}
},

View File

@ -1,12 +1,16 @@
<template>
<div class="login-container pull-height pull-overflow" @keyup.enter.native="handleLogin">
<div class="login-container pull-height" @keyup.enter.native="handleLogin">
<div class="login-info text-white animated fadeInLeft">
<h2>Pig 微服务快速开发框架</h2>
<ul>
<li><i class="el-icon-check"></i> 是一个基于Spring CloudoAuth2.0开发基于Vue前后分离的开发平台</li>
<li><i class="el-icon-check"></i> 是一个基于vue+vuex+vue-router快速后台管理系统采用token交互验证方式</li>
<li><i class="el-icon-check"></i> 最大程度上帮助企业节省时间成本和费用开支 </li>
<li><i class="el-icon-check"></i> QQ群23754102 </li>
<h2 class="login-info-title">Pig 微服务快速开发框架</h2>
<ul class="login-info-list">
<li class="login-info-item">
<i class="el-icon-check"></i> 是一个基于Spring CloudoAuth2.0开发基于Vue前后分离的开发平台</li>
<li class="login-info-item">
<i class="el-icon-check"></i> 是一个基于vue+vuex+vue-router快速后台管理系统采用token交互验证方式</li>
<li class="login-info-item">
<i class="el-icon-check"></i> 最大程度上帮助企业节省时间成本和费用开支 </li>
<li class="login-info-item">
<i class="el-icon-check"></i> QQ群23754102 </li>
</ul>
</div>
<div class="login-border pull-height">
@ -18,7 +22,7 @@
<userLogin></userLogin>
</el-tab-pane>
<el-tab-pane label="短信验证码" name="code">
<codeLogin></codeLogin>
<codeLogin></codeLogin>
</el-tab-pane>
<el-tab-pane label="第三方授权登录" name="third">
<thirdLogin></thirdLogin>
@ -27,7 +31,7 @@
</div>
</div>
</div>
</div>
</template>
<script>
import userLogin from "./userlogin";
@ -77,10 +81,10 @@ export default {
.login-info {
padding-left: 60px;
}
.login-info > ul {
padding: 20px 0;
.login-info-title {
line-height: 90px;
}
.login-info > ul > li {
.login-info-item {
font-size: 14px;
}
.login-border {

View File

@ -1,63 +0,0 @@
<template>
<div class="pull-chheight role-container">
<el-card class="box-card">
<p>当前用户的权限值是有权限时(admin) 才可以看到菜单有这个页面</p>
<el-switch
v-model="roleSwitch"
active-color="#13ce66"
inactive-color="#ff4949"
active-value="admin"
active-text="有权限(admin)"
inactive-value="user"
inactive-text="无权限(user)" @change="handlechange">
</el-switch>
</el-card>
<el-card class="box-card" style="margin-top:20px;">
<p>当前用户的权限值是有权限时(admin) 才能看到全部按钮</p>
<el-button v-if="permission.sys_role_btn1">默认按钮</el-button>
<el-button type="primary" v-if="permission.sys_role_btn2">主要按钮</el-button>
<el-button type="success" v-if="permission.sys_role_btn3">成功按钮</el-button>
<el-button type="info" v-if="permission.sys_role_btn4">信息按钮</el-button>
<el-button type="warning" v-if="permission.sys_role_btn5">警告按钮</el-button>
<el-button type="danger" v-if="permission.sys_role_btn6">危险按钮</el-button>
</el-card>
</div>
</template>
<script>
import { mapGetters } from "vuex";
export default {
name: "role",
data() {
return {
roleSwitch: ""
};
},
created() {
this.roleSwitch = this.roles[0];
},
computed: {
...mapGetters(["roles", "permission"])
},
methods: {
handlechange(val) {
this.$store.commit("SET_ROLES", [val]);
if (val == "user") {
this.$store.commit("SET_PERMISSION", [
"sys_role_btn1",
"sys_role_btn2"
]);
} else if (val == "admin") {
this.$store.dispatch("GetUserInfo");
}
this.$store.dispatch("GetMenu");
}
}
};
</script>
<style scoped="scoped" lang="scss">
</style>

View File

@ -1,315 +0,0 @@
<template>
<div class="table-container pull-chheight">
<div class="table-header">
<el-button type="primary" @click="handleAdd" size="small" v-if="permission.sys_crud_btn_add"> </el-button>
<el-button type="success" @click="handleExport" size="small" v-if="permission.sys_crud_btn_export">导出excel</el-button>
<el-button @click="toggleSelection([tableData[1]])" size="small">切换第二选中状态</el-button>
<el-button @click="toggleSelection()" size="small">取消选择</el-button>
</div>
<Crud
:tableOption="tableOption"
:tableData="tableData"
:tableLoading="tableLoading"
:before-open="boxhandleOpen"
:before-close="boxhandleClose"
:page="page"
ref="crud"
width="290"
@handleSave="handleSave"
@handleUpdate="handleUpdate"
@handleDel="handleDel"
@handleCurrentChange="handleCurrentChange"
@handleSelectionChange="handleSelectionChange"
:menu="true">
<template slot-scope="scope">
<el-button icon="el-icon-check" size="small" @click="handleGrade(scope.row,scope.$index)">权限</el-button>
</template>
</Crud>
<el-button @click.native="formate" style="margin: 8px 0">格式化</el-button>
<el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 15}"
placeholder="请输入内容"
v-model="formJson">
</el-input>
<el-dialog
title="菜单"
:visible.sync="grade.box"
width="40%">
<el-tree
:data="menuAll"
:default-checked-keys="grade.check"
:default-expanded-keys="grade.check"
show-checkbox
node-key="id">
</el-tree>
<span slot="footer" class="dialog-footer">
<el-button type="primary" @click="handleGradeUpdate">更新</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import Crud from "@/components/crud/";
import tableOption from "@/const/tableOption";
export default {
name: "table",
data() {
return {
tableOption: tableOption, //
tableData: [], //
tablePage: 1,
tableLoading: false,
tabelObj: {},
formJson: "",
page: {
total: 0, //
currentPage: 1, //
pageSize: 10 //
},
grade: {
box: false,
check: []
}
};
},
created() {
this.formJson = JSON.stringify(tableOption, null, 2);
this.handleList();
},
watch: {},
mounted() {},
computed: {
...mapGetters(["permission", "menuAll"])
},
props: [],
methods: {
formate() {
let p = new Promise((resolve, reject) => {
resolve(JSON.parse(this.formJson));
});
p
.then(data => {
this.tableOption = data;
this.formJson = JSON.stringify(data, null, 2);
this.$message({
message: "数据加载成功",
type: "success"
});
})
.catch(err => {
this.$message({
center: true,
dangerouslyUseHTMLString: true,
message: `JSON格式错误<br \>\n${err}`,
type: "error"
});
});
},
/**
* @title 权限更新
*
**/
handleGradeUpdate() {
this.tabelObj.check = [].concat(this.grade.check);
this.tabelObj = {};
this.grade.check = [];
this.grade.box = false;
},
/**
* @title 权限选择
*
**/
handleGradeCheckChange(data, checked, indeterminate) {
if (checked) {
this.grade.check.push(data.id);
} else {
this.grade.check.splice(this.grade.check.indexOf(data.id), 1);
}
},
/**
* @title 打开权限
*/
handleGrade(row, index) {
this.$store.dispatch("GetMenuAll").then(data => {
this.grade.box = true;
this.tabelObj = row;
this.grade.check = this.tabelObj.check;
});
},
/**
* @title 导出excel
*
**/
handleExport() {
import("@/vendor/Export2Excel").then(excel => {
const tHeader = ["username", "name"];
const filterVal = ["username", "name"];
const list = this.tableData;
const data = this.formatJson(filterVal, list);
excel.export_json_to_excel(tHeader, data, this.filename);
});
},
formatJson(filterVal, jsonData) {
return jsonData.map(v =>
filterVal.map(j => {
if (j === "timestamp") {
return parseTime(v[j]);
} else {
return v[j];
}
})
);
},
/**
* @title 页面改变值
*
**/
handleCurrentChange(val) {
this.tablePage = val;
this.handleList();
},
/**
* @title 打开新增窗口
* @detail 调用crud的handleadd方法即可
*
**/
handleAdd() {
this.$refs.crud.handleAdd();
},
/**
* @title 选中第几行
* @param row 选中那几行数据
* @detail 调用crud的toggleSelection方法即可
*
**/
toggleSelection(row) {
this.$refs.crud.toggleSelection(row);
},
/**
* @title 获取数据
* @detail 赋值为tableData表格即可
*
**/
handleList() {
this.tableLoading = true;
this.$store
.dispatch("GetTableData", { page: `${this.tablePage}` })
.then(data => {
setTimeout(() => {
this.tableData = data.tableData;
this.page = {
total: data.total,
pageSize: data.pageSize
};
this.tableLoading = false;
}, 1000);
});
},
/**
* @title 当前选中的数据
* @param val 选中的值
*
**/
handleSelectionChange(val) {
this.$message({
showClose: true,
message: JSON.stringify(val),
type: "success"
});
},
/**
* @title 数据添加
* @param row 为当前的数据
* @param done 为表单关闭函数
*
**/
handleSave(row, done) {
this.tableData.push(row);
this.$message({
showClose: true,
message: "添加成功",
type: "success"
});
done();
},
/**
* @title 数据删除
* @param row 为当前的数据
* @param index 为当前更新数据的行数
*
**/
handleDel(row, index) {
this.$confirm(`是否确认删除序号为${row.name}`, "提示", {
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
})
.then(() => {
this.tableData.splice(index, 1);
this.$message({
showClose: true,
message: "删除成功",
type: "success"
});
})
.catch(err => {});
},
/**
* @title 数据更新
* @param row 为当前的数据
* @param index 为当前更新数据的行数
* @param done 为表单关闭函数
*
**/
handleUpdate(row, index, done) {
this.tableData.splice(index, 1, row);
this.$message({
showClose: true,
message: "修改成功",
type: "success"
});
done();
},
/**
* @title 表单关闭前处理
* @param done
*
**/
boxhandleClose(done) {
this.$message({
showClose: true,
message: "表单关闭前处理事件",
type: "success"
});
done();
},
boxhandleOpen(show) {
this.$message({
showClose: true,
message: "表单打开前处理事件",
type: "success"
});
show();
}
},
components: {
Crud
}
};
</script>
<style lang="scss" scoped>
.table-container {
padding: 8px 10px;
}
.table-header {
margin-bottom: 10px;
& > .el-button {
padding: 12px 25px;
}
}
</style>

View File

@ -1,14 +1,10 @@
<template>
<div class="app-main">
<div class="yun-content">
<div class="banner-sky"></div>
<div class="banner-text">
<h2>Pig 微服务快速开发框架</h2>
<span :class="['actor',{typeing:isText}]">{{text}}</span>
</div>
</div>
</div>
<div class="pull-chheight wel-contailer">
<div class="banner-text">
<h2>Pig 微服务快速开发框架</h2>
<span :class="['actor',{typeing:isText}]">{{text}}</span>
</div>
</div>
</template>
<script>
@ -84,27 +80,25 @@ export default {
</script>
<style scoped="scoped" lang="scss">
.yun-content {
background-color: #eee;
.wel-contailer {
position: relative;
}
.banner-sky {
position: absolute;
top: -100px;
bottom: -15px;
width: 100%;
height: 100%;
transform: skewY(-4deg);
transform-origin: center;
background-color: #fcfcfc;
}
.banner-text {
position: relative;
padding: 0 20px;
font-size: 20px;
text-align: center;
color: #333;
}
.banner-img {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0.8;
display: none;
}
.actor {
height: 250px;
overflow: hidden;

View File

@ -58,13 +58,13 @@ function findMenuParent(tagCurrent, tag, tagWel) {
} else {//其他操作
let currentPathObj = store.getters.menu.filter(item => {
if (item.children.length == 1) {
return item.children[0].href === tag.value;
return item.children[0].path === tag.value;
} else {
let i = 0;
let childArr = item.children;
let len = childArr.length;
while (i < len) {
if (childArr[i].href === tag.value) {
if (childArr[i].path === tag.value) {
return true;
}
i++;

View File

@ -1 +1 @@
module.exports = file => require(`../page/${file}.vue`)
module.exports = (path, file) => require(`../${path}/${file}.vue`)

View File

@ -7,7 +7,7 @@ import { getStore, getSessionStore, vaildUtil } from '@/util/yun'
import Myiframe from '@/components/iframe/iframe.vue'
import INDEX from '@/page/index/'
import Layout from '@/page/index/'
import errorPage404 from '@/components/errorPage/404.vue';
import errorPage403 from '@/components/errorPage/403.vue';
import errorPage500 from '@/components/errorPage/500.vue';
@ -31,8 +31,8 @@ export default new VueRouter({
},
});
export const asyncRouterMap = [
{ path: '/login', name: '登录页', component: _import('login/index') },
{ path: '/lock', name: '锁屏页', component: _import('lock/index') },
{ path: '/login', name: '登录页', component: _import('page', 'login/index') },
{ path: '/lock', name: '锁屏页', component: _import('page', 'lock/index') },
{ path: '*', redirect: '/404', hidden: true },
{ path: '/404', component: errorPage404, name: '404' },
{ path: '/403', component: errorPage403, name: '403' },
@ -44,7 +44,7 @@ export const asyncRouterMap = [
},
{
path: '/myiframe',
component: INDEX,
component: Layout,
redirect: '/myiframe',
children: [
{
@ -57,91 +57,32 @@ export const asyncRouterMap = [
}, {
path: '/wel',
component: INDEX,
component: Layout,
redirect: '/wel/index',
children: [
{
path: 'index',
name: '首页',
component: _import('wel')
}
]
}, {
path: '/role',
component: INDEX,
redirect: '/role/index',
children: [
{
path: 'index',
name: '权限测试页',
component: _import('role')
}
]
}, {
path: '/table',
component: INDEX,
redirect: '/table/index',
children: [
{
path: 'index',
name: '表格CRUD',
component: _import('table/index')
}
]
}, {
path: '/form',
component: INDEX,
redirect: '/form/index',
children: [
{
path: 'index',
name: '表单CRUD',
component: _import('form/index')
}
]
}, {
path: '/iconfont',
component: INDEX,
redirect: '/iconfont/index',
children: [
{
path: 'index',
name: '阿里图标',
component: _import('iconfont/index')
}
]
}, {
path: '/errlog',
component: INDEX,
redirect: '/errlog/index',
children: [
{
path: 'index',
name: '错误日志',
component: _import('errlog/index')
}, {
path: 'page',
name: '错误页面',
component: _import('errlog/errorPage')
component: _import('page', 'wel')
}
]
}, {
menuId: 1,
path: '/admin',
component: INDEX,
component: Layout,
name: '系统管理',
hidden: false,
redirect: '/admin/user',
meta: {
title: '系统管理',
},
children: [
{
path: 'user',
name: '用户管理',
component: _import('admin/user/index')
}, {
path: 'role',
name: '角色管理',
component: _import('admin/role/index')
}, {
path: 'menu',
name: '菜单管理',
component: _import('admin/menu/index')
}
{ menuId: 2, path: 'user', component: _import('views', 'admin/user/index'), name: '用户管理', meta: { title: '用户管理' } },
{ menuId: 3, path: 'menu', component: _import('views', 'admin/menu/index'), name: '菜单管理', meta: { title: '菜单管理' } },
{ menuId: 4, path: 'role', component: _import('views', 'admin/role/index'), name: '角色管理', meta: { title: '角色管理' } },
{ menuId: 5, path: 'dept', component: _import('views', 'admin/dept/index'), name: '部门管理', meta: { title: '部门管理' } },
{ menuId: 6, path: 'dict', component: _import('views', 'admin/dict/index'), name: '字典管理', meta: { title: '字典管理' } },
{ menuId: 7, path: 'log', component: _import('views', 'admin/log/index'), name: '日志管理', meta: { title: '日志管理' } }
]
}
},
]

View File

@ -3,7 +3,6 @@ import Vuex from 'vuex'
import user from './modules/user'
import common from './modules/common'
import tags from './modules/tags'
import admin from './modules/admin'
import errLog from './modules/errLog'
import getters from './getters'
@ -13,7 +12,6 @@ const store = new Vuex.Store({
user,
common,
errLog,
admin,
tags
},
getters,

View File

@ -1,30 +0,0 @@
import { getUserData, getRoleData } from '@/api/admin'
const user = {
state: {
},
actions: {
GetUserData({ commit, state, dispatch }, page) {
return new Promise((resolve, reject) => {
getUserData(page).then(res => {
const data = res.data;
resolve(data);
})
})
},
GetRoleData({ commit, state, dispatch }, page) {
return new Promise((resolve, reject) => {
getRoleData(page).then(res => {
const data = res.data;
resolve(data);
})
})
},
},
mutations: {
}
}
export default user

View File

@ -25,7 +25,7 @@ const navs = {
label: "首页",
value: "/wel/index"
},
tagCurrent: [{
tagCurrent: getStore({ name: 'tagCurrent' }) || [{
label: "首页",
value: "/wel/index"
}],
@ -36,7 +36,7 @@ const navs = {
mutations: {
ADD_TAG: (state, action) => {
state.tag = action;
setStore({ name: 'tag', content: state.tag, type: 'session' })
setStore({ name: 'tag', content: state.tag })
if (state.tagList.some(a => a.value === action.value)) return
state.tagList.push({
label: action.label,
@ -50,13 +50,12 @@ const navs = {
setStore({ name: 'tagCurrent', content: state.tagCurrent })
},
SET_TAG: (state, value) => {
for (const [i, v] of state.tagList.entries()) {
if (v.value === value) {
state.tag = state.tagList[i];
state.tagList.forEach((ele, num) => {
if (ele.value === value) {
state.tag = state.tagList[num];
setStore({ name: 'tag', content: state.tag })
break
}
}
});
},
DEL_ALL_TAG: (state, action) => {
state.tag = tagObj;
@ -65,28 +64,26 @@ const navs = {
removeStore({ name: 'tagList' });
},
DEL_TAG_OTHER: (state, action) => {
for (const [i, v] of state.tagList.entries()) {
if (v.value === state.tag.value) {
state.tagList = state.tagList.slice(i, i + 1)
state.tagList.forEach((ele, num) => {
if (ele.value === state.tag.value) {
state.tagList = state.tagList.slice(num, num + 1)
state.tag = state.tagList[0];
state.tagList[0].close = false;
setStore({ name: 'tag', content: state.tag })
setStore({ name: 'tagList', content: state.tagList })
break
}
}
})
},
DEL_TAG: (state, action) => {
for (const [i, a] of state.tagList.entries()) {
if (a.value === action.value) {
state.tagList.splice(i, 1)
state.tagList.forEach((ele, num) => {
if (ele.value === action.value) {
state.tagList.splice(num, 1)
state.tagList = setFistTag(state.tagList);
setStore({ name: 'tag', content: state.tagList, type: 'session' })
setStore({ name: 'tagList', content: state.tagList, type: 'session' })
break
}
}
})
},
}
}

View File

@ -182,3 +182,34 @@ table {
.text-white{
color: #fff;
}
.clearfix {
&:after {
visibility: hidden;
display: block;
font-size: 0;
content: " ";
clear: both;
height: 0;
}
}
//main-container全局样式
.app-main{
min-height: 100%
}
.filter-container {
padding-bottom: 10px;
.filter-item {
display: inline-block;
vertical-align: middle;
margin-bottom: 10px;
}
}
.app-container {
padding: 20px;
box-sizing: border-box;
}

View File

@ -7,6 +7,9 @@
font-size: 12px;
line-height: 28px;
}
.el-menu--popup{
padding: 0;
}
.el-select,.el-date-editor.el-input, .el-date-editor.el-input__inner{
width: 100%;
}

View File

@ -8,17 +8,16 @@
@mixin scrollBar {
&::-webkit-scrollbar-track-piece {
box-shadow: inset 0 0 6px rgba(0,0,0,0.3);
background-color: #fff;
}
&::-webkit-scrollbar {
width: 6px;
height: 6px;
background-color: #999;
width: 7px;
height: 7px;
background-color: #fff;
}
&::-webkit-scrollbar-thumb {
box-shadow: inset 0 0 6px rgba(0,0,0,.3);
&::-webkit-scrollbar-thumb {
border-radius: 5px;
background-color: #48576a;
background-color: hsla(220,4%,58%,.3);
}
}
@mixin radius($width,$size,$color){

View File

@ -1,14 +1,4 @@
.el-menu:not(.el-menu--collapse) {
width: 200px;
overflow-y: auto;
}
.el-menu{
border-right: 0;
.is-active{
color:#fff !important;
}
}
.hideSidebar {
.sidebar-container,.sidebar-container .el-menu {
width: 36px!important;

View File

@ -6,18 +6,17 @@
display: flex;
align-items: center;
padding: 0 16px;
height: 60px;
height: 50px;
}
.tags-breadcrumb-list{
padding: 0 25px;
}
.tags-box{
display: flex;
align-items: center;
position: relative;
box-sizing: border-box;
padding-right: 106px;
width: 100%;
height: 40px;
overflow:hidden;
background: #f0f0f0;
}
@ -28,16 +27,15 @@
transform: rotate(90deg);
}
.tags-list{
flex: 1;
position: relative;
padding: 0 16px;
}
.tag-scroll{
width: 200%;
position: absolute;
padding: 2px 10px;
overflow: visible;
white-space: nowrap;
transition: left .3s ease;
}
.tag-item-icon{
color: #eee;
font-size: 10px !important;
font-size: 11px !important;
}
.tag-item-icon.is-active{
color: $mainBg;
@ -69,8 +67,16 @@
opacity: .85;
}
.tags-menu{
margin-right: 5px;
position: absolute;
top:0;
right: 0;
display: flex;
align-items: center;
padding: 0 15px;
height: 96%;
box-sizing: border-box;
background-color: #fff;
box-shadow: -3px 0 15px 3px rgba(0, 0, 0, 0.1);
}
}
.contextmenu {

View File

@ -1,43 +1,43 @@
.header {
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
background-color: #fff;
border-bottom:2px solid $menuBg;
color: #333;
box-sizing: border-box;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
font-size: 18px;
height: 60px;
line-height: 1;
padding: 0 10px;
white-space: nowrap;
}
.header-title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: inherit;
font-weight: 400;
flex: 1;
}
.header-userImg{
margin: 0 3px 0 10px;
padding: 2px;
width: 35px;
height:35px;
border-radius: 100%;
box-sizing: border-box;
border:1px solid #eee;
}
.header-button {
display: flex;
align-items: center;
}
.header-button>.header-item{
margin-right: 12px;
}
-webkit-box-align: center;
-ms-flex-align: center;
align-items: center;
background-color: #fff;
border-bottom:2px solid $menuBg;
color: #333;
box-sizing: border-box;
display: -webkit-box;
display: -ms-flexbox;
display: flex;
font-size: 18px;
height: 60px;
line-height: 1;
padding: 0 10px;
white-space: nowrap;
}
.header-title {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
font-size: inherit;
font-weight: 400;
flex: 1;
}
.header-userImg{
margin: 0 3px 0 10px;
padding: 2px;
width: 35px;
height:35px;
border-radius: 100%;
box-sizing: border-box;
border:1px solid #eee;
}
.header-button {
display: flex;
align-items: center;
}
.header-button>.header-item{
margin-right: 12px;
}

View File

@ -1,6 +1,5 @@
import { validatenull } from './validate'
import { baseUrl } from '@/config/env'
/**
@ -80,14 +79,37 @@ export const findParent = (menu, id) => {
* 总体路由处理器
*/
export const resolveUrlPath = (url) => {
let reqUrl = url;
if (url.indexOf("http") != -1) {
if (url.indexOf("#") != -1 && url.indexOf("http") == -1) {
const port = reqUrl.substr(reqUrl.indexOf(':'));
reqUrl = `/myiframe/urlPath?src=${baseUrl}${port}${reqUrl.replace('#', '').replace(port, '')}`;
} else if (url.indexOf("http") != -1) {
reqUrl = `/myiframe/urlPath?src=${reqUrl}`;
} else {
reqUrl = `${reqUrl}`;
}
return reqUrl;
}
/**
* 总体路由设置器
*/
export const setUrlPath = ($route) => {
let value = "";
if ($route.query.src) {
value = $route.query.src;
if (value.indexOf(baseUrl) != -1) {
const port = value
.substr(value.lastIndexOf(":"))
.replace(value.substr(value.lastIndexOf("/")), "");
const path = value.replace(baseUrl + port, "");
value = "#" + path + port;
}
} else {
value = $route.path;
}
return value;
}
/**
* 动态插入css
*/

View File

@ -0,0 +1,205 @@
`<template>
<div class="app-container calendar-list-container">
<div class="filter-container">
<el-button-group>
<el-button type="primary" v-if="deptManager_btn_add" icon="plus" @click="handlerAdd">添加</el-button>
<el-button type="primary" v-if="deptManager_btn_edit" icon="edit" @click="handlerEdit">编辑</el-button>
<el-button type="primary" v-if="deptManager_btn_del" icon="delete" @click="handleDelete">删除</el-button>
</el-button-group>
</div>
<el-row>
<el-col :span="8" style='margin-top:15px;'>
<el-tree
class="filter-tree"
:data="treeData"
node-key="id"
highlight-current
:props="defaultProps"
:filter-node-method="filterNode"
@node-click="getNodeData"
default-expand-all
>
</el-tree>
</el-col>
<el-col :span="16" style='margin-top:15px;'>
<el-card class="box-card">
<el-form :label-position="labelPosition" label-width="80px" :model="form" ref="form">
<el-form-item label="父级节点" prop="parentId">
<el-input v-model="form.parentId" :disabled="formEdit" placeholder="请输入父级节点"></el-input>
</el-form-item>
<el-form-item label="节点编号" prop="parentId" v-if="formEdit">
<el-input v-model="form.deptId" :disabled="formEdit" placeholder="节点编号"></el-input>
</el-form-item>
<el-form-item label="部门名称" prop="name">
<el-input v-model="form.name" :disabled="formEdit" placeholder="请输入名称"></el-input>
</el-form-item>
<el-form-item label="排序" prop="orderNum">
<el-input v-model="form.orderNum" :disabled="formEdit" placeholder="请输入排序"></el-input>
</el-form-item>
<el-form-item v-if="formStatus == 'update'">
<el-button type="primary" @click="update">更新</el-button>
<el-button @click="onCancel">取消</el-button>
</el-form-item>
<el-form-item v-if="formStatus == 'create'">
<el-button type="primary" @click="create">保存</el-button>
<el-button @click="onCancel">取消</el-button>
</el-form-item>
</el-form>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import { fetchTree, getObj, addObj, delObj, putObj } from '@/api/dept'
import { mapGetters } from 'vuex'
export default {
name: 'menu',
data() {
return {
list: null,
total: null,
formEdit: true,
formAdd: true,
formStatus: '',
showElement: false,
typeOptions: ['0', '1'],
methodOptions: ['GET', 'POST', 'PUT', 'DELETE'],
listQuery: {
name: undefined
},
treeData: [],
defaultProps: {
children: 'children',
label: 'name'
},
labelPosition: 'right',
form: {
name: undefined,
orderNum: undefined,
parentId: undefined,
deptId: undefined
},
currentId: 0,
deptManager_btn_add: false,
deptManager_btn_edit: false,
deptManager_btn_del: false
}
},
filters: {
typeFilter(type) {
const typeMap = {
0: '菜单',
1: '按钮'
}
return typeMap[type]
}
},
created() {
this.getList()
this.deptManager_btn_add = this.permissions['sys_dept_add']
this.deptManager_btn_edit = this.permissions['sys_dept_edit']
this.deptManager_btn_del = this.permissions['sys_dept_del']
},
computed: {
...mapGetters([
'elements',
'permissions'
])
},
methods: {
getList() {
fetchTree(this.listQuery).then(response => {
this.treeData = response.data
})
},
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
getNodeData(data) {
if (!this.formEdit) {
this.formStatus = 'update'
}
getObj(data.id).then(response => {
this.form = response.data
})
this.currentId = data.id
this.showElement = true
},
handlerEdit() {
if (this.form.deptId) {
this.formEdit = false
this.formStatus = 'update'
}
},
handlerAdd() {
this.resetForm()
this.formEdit = false
this.formStatus = 'create'
},
handleDelete() {
this.$confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delObj(this.currentId).then(() => {
this.getList()
this.resetForm()
this.onCancel()
this.$notify({
title: '成功',
message: '删除成功',
type: 'success',
duration: 2000
})
})
})
},
update() {
putObj(this.form).then(() => {
this.getList()
this.$notify({
title: '成功',
message: '更新成功',
type: 'success',
duration: 2000
})
})
},
create() {
addObj(this.form).then(() => {
this.getList()
this.$notify({
title: '成功',
message: '创建成功',
type: 'success',
duration: 2000
})
})
},
onCancel() {
this.formEdit = true
this.formStatus = ''
},
resetForm() {
this.form = {
permission: undefined,
name: undefined,
menuId: undefined,
parentId: this.currentId,
url: undefined,
icon: undefined,
sort: undefined,
component: undefined,
type: undefined,
method: undefined
}
}
}
}
</script>

View File

@ -0,0 +1,230 @@
<template>
<div class="app-container calendar-list-container">
<div class="filter-container">
<el-button v-if="sys_dict_add" class="filter-item" style="margin-left: 10px;" @click="handleCreate" type="primary" icon="edit">添加
</el-button>
</div>
<el-table :key='tableKey' :data="list" v-loading="listLoading" element-loading-text="给我一点时间" border fit highlight-current-row style="width: 99%">
<el-table-column align="center" label="编号">
<template slot-scope="scope">
<span>{{ scope.row.id }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="数据值">
<template slot-scope="scope">
<span>{{ scope.row.value }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="标签名">
<template slot-scope="scope">
<span>{{ scope.row.label }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="类型">
<template slot-scope="scope">
<span>{{ scope.row.type }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="描述">
<template slot-scope="scope">
<span>{{ scope.row.description }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="排序">
<template slot-scope="scope">
<span>{{ scope.row.sort }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="创建时间">
<template slot-scope="scope">
<span>{{ scope.row.createTime | parseTime('{y}-{m}-{d}') }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="备注信息">
<template slot-scope="scope">
<span>{{ scope.row.remarks }}</span>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button v-if="sys_dict_upd" size="small" type="success" @click="handleUpdate(scope.row)">编辑
</el-button>
<el-button v-if="sys_dict_del" size="mini" type="danger" @click="handleDelete(scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
<div v-show="!listLoading" class="pagination-container">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page.sync="listQuery.page" :page-sizes="[10,20,30, 50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<el-form :model="form" :rules="rules" ref="form" label-width="100px">
<el-form-item label="编号" prop="username">
<el-input v-model="form.id" placeholder="编号"></el-input>
</el-form-item>
<el-form-item label="数据值" prop="username">
<el-input v-model="form.value" placeholder="数据值"></el-input>
</el-form-item>
<el-form-item label="标签名" prop="username">
<el-input v-model="form.label" placeholder="标签名"></el-input>
</el-form-item>
<el-form-item label="类型" prop="username">
<el-input v-model="form.type" placeholder="类型"></el-input>
</el-form-item>
<el-form-item label="描述" prop="username">
<el-input v-model="form.description" placeholder="描述"></el-input>
</el-form-item>
<el-form-item label="排序(升序)" prop="username">
<el-input v-model="form.sort" placeholder="排序(升序)"></el-input>
</el-form-item>
<el-form-item label="创建时间" prop="username">
<el-input v-model="form.createTime" placeholder="创建时间"></el-input>
</el-form-item>
<el-form-item label="备注信息" prop="username">
<el-input v-model="form.remarks" placeholder="备注信息"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancel('form')"> </el-button>
<el-button v-if="dialogStatus=='create'" type="primary" @click="create('form')"> </el-button>
<el-button v-else type="primary" @click="update('form')"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { fetchList, addObj, putObj, delObj } from "@/api/dict";
import waves from "@/directive/waves/index.js"; //
import { mapGetters } from "vuex";
export default {
name: "table_sys_dict",
directives: {
waves
},
data() {
return {
list: null,
total: null,
listLoading: true,
listQuery: {
page: 1,
limit: 20
},
rules: {},
form: {},
dialogFormVisible: false,
dialogStatus: "",
sys_dict_add: false,
sys_dict_upd: false,
sys_dict_del: false,
textMap: {
update: "编辑",
create: "创建"
},
tableKey: 0
};
},
computed: {
...mapGetters(["permissions"])
},
filters: {
statusFilter(status) {
const statusMap = {
0: "有效",
1: "无效"
};
return statusMap[status];
}
},
created() {
this.getList();
this.sys_dict_add = this.permissions["sys_dict_add"];
this.sys_dict_upd = this.permissions["sys_dict_upd"];
this.sys_dict_del = this.permissions["sys_dict_del"];
},
methods: {
getList() {
this.listLoading = true;
this.listQuery.orderByField = "create_time";
this.listQuery.isAsc = false;
fetchList(this.listQuery).then(response => {
this.list = response.data.records;
this.total = response.data.total;
this.listLoading = false;
});
},
handleSizeChange(val) {
this.listQuery.limit = val;
this.getList();
},
handleCurrentChange(val) {
this.listQuery.page = val;
this.getList();
},
handleDelete(row) {
delObj(row).then(response => {
this.dialogFormVisible = false;
this.getList();
this.$notify({
title: "成功",
message: "删除成功",
type: "success",
duration: 2000
});
});
},
handleCreate() {
this.dialogStatus = "create";
this.dialogFormVisible = true;
},
create(formName) {
const set = this.$refs;
set[formName].validate(valid => {
if (valid) {
addObj(this.form).then(() => {
this.dialogFormVisible = false;
this.getList();
this.$notify({
title: "成功",
message: "创建成功",
type: "success",
duration: 2000
});
});
} else {
return false;
}
});
},
cancel(formName) {
this.dialogFormVisible = false;
const set = this.$refs;
set[formName].resetFields();
},
update(formName) {
const set = this.$refs;
set[formName].validate(valid => {
if (valid) {
this.dialogFormVisible = false;
this.form.password = undefined;
putObj(this.form).then(() => {
this.dialogFormVisible = false;
this.getList();
this.$notify({
title: "成功",
message: "修改成功",
type: "success",
duration: 2000
});
});
} else {
return false;
}
});
}
}
};
</script>

View File

@ -0,0 +1,160 @@
<template>
<div class="app-container calendar-list-container">
<div class="filter-container">
<el-select v-model="listQuery.type" filterable placeholder="请选择">
<el-option v-for="item in dicts" :key="item.value" :label="item.label" :value="item.value">
</el-option>
</el-select>
<el-button class="filter-item" type="primary" v-waves icon="search" @click="handleFilter">搜索</el-button>
</div>
<el-table :key='tableKey' :data="list" v-loading="listLoading" element-loading-text="给我一点时间" border fit highlight-current-row style="width: 99%">
<el-table-column align="center" label="序号">
<template slot-scope="scope">
<span>{{Number(scope.row.id).toFixed()}}</span>
</template>
</el-table-column>
<el-table-column label="类型" align="center">
<template slot-scope="scope">
<span>
<el-button type="success" v-if="scope.row.type == 0">{{ scope.row.type | typeFilter }}</el-button>
<el-button type="danger" v-if="scope.row.type ==9">{{ scope.row.type | typeFilter }}</el-button>
</span>
</template>
</el-table-column>
<el-table-column label="请求接口" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{ scope.row.requestUri}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="IP地址">
<template slot-scope="scope">
<span>{{scope.row.remoteAddr}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="请求方式">
<template slot-scope="scope">
<span>{{scope.row.method}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="传入参数" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{scope.row.params}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="请求时间">
<template slot-scope="scope">
<span>{{scope.row.time}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="创建时间">
<template slot-scope="scope">
<span>{{scope.row.createTime | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
<el-table-column label="操作">
<template slot-scope="scope">
<el-button size="mini" type="danger" v-if="sys_log_del" @click="handleDelete(scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
<div v-show="!listLoading" class="pagination-container">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page.sync="listQuery.page" :page-sizes="[10,20,30, 50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
</div>
</template>
<script>
import { delObj, fetchList } from "@/api/log";
import { remote } from "@/api/dict";
import waves from "@/directive/waves/index.js"; //
import { mapGetters } from "vuex";
export default {
name: "table_log",
directives: {
waves
},
data() {
return {
list: null,
total: null,
sys_dict_add: false,
listLoading: true,
dicts: [],
listQuery: {
page: 1,
limit: 20,
type: undefined
},
tableKey: 0
};
},
computed: {
...mapGetters(["permissions"])
},
filters: {
typeFilter(type) {
const typeMap = {
0: "正常",
9: "异常"
};
return typeMap[type];
}
},
created() {
remote("log_type").then(response => {
this.dicts = response.data;
});
console.log(this.dicts);
this.getList();
this.sys_log_del = this.permissions["sys_log_del"];
},
methods: {
getList() {
this.listLoading = true;
this.listQuery.orderByField = "create_time";
this.listQuery.isAsc = false;
fetchList(this.listQuery).then(response => {
this.list = response.data.records;
this.total = response.data.total;
this.listLoading = false;
});
},
handleSizeChange(val) {
this.listQuery.limit = val;
this.getList();
},
handleCurrentChange(val) {
this.listQuery.page = val;
this.getList();
},
handleDelete(row) {
delObj(row.id).then(response => {
this.dialogFormVisible = false;
this.getList();
this.$notify({
title: "成功",
message: "删除成功",
type: "success",
duration: 2000
});
});
},
handleFilter() {
this.listQuery.page = 1;
this.getList();
}
}
};
</script>

View File

@ -0,0 +1,233 @@
<template>
<div class="app-container calendar-list-container">
<div class="filter-container">
<el-button-group>
<el-button type="primary" v-if="menuManager_btn_add" icon="plus" @click="handlerAdd">添加</el-button>
<el-button type="primary" v-if="menuManager_btn_edit" icon="edit" @click="handlerEdit">编辑</el-button>
<el-button type="primary" v-if="menuManager_btn_del" icon="delete" @click="handleDelete">删除</el-button>
</el-button-group>
</div>
<el-row>
<el-col :span="8" style='margin-top:15px;'>
<el-tree
class="filter-tree"
:data="treeData"
node-key="id"
highlight-current
:props="defaultProps"
:filter-node-method="filterNode"
@node-click="getNodeData"
default-expand-all
>
</el-tree>
</el-col>
<el-col :span="16" style='margin-top:15px;'>
<el-card class="box-card">
<el-form :label-position="labelPosition" label-width="80px" :model="form" ref="form">
<el-form-item label="父级节点" prop="parentId">
<el-input v-model="form.parentId" :disabled="formEdit" placeholder="请输入父级节点"></el-input>
</el-form-item>
<el-form-item label="节点ID" prop="parentId">
<el-input v-model="form.menuId" :disabled="formEdit" placeholder="请输入节点ID"></el-input>
</el-form-item>
<el-form-item label="标题" prop="name">
<el-input v-model="form.name" :disabled="formEdit" placeholder="请输入标题"></el-input>
</el-form-item>
<el-form-item label="权限标识" prop="permission">
<el-input v-model="form.permission" :disabled="formEdit" placeholder="请输入权限标识"></el-input>
</el-form-item>
<el-form-item label="图标" prop="icon">
<el-input v-model="form.icon" :disabled="formEdit" placeholder="请输入图标"></el-input>
</el-form-item>
<el-form-item label="资源路径" prop="url">
<el-input v-model="form.url" :disabled="formEdit" placeholder="请输入资源路径"></el-input>
</el-form-item>
<el-form-item label="请求方法" prop="method">
<el-select class="filter-item" v-model="form.method" :disabled="formEdit" placeholder="请输入资源请求类型">
<el-option v-for="item in methodOptions" :key="item" :label="item" :value="item"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="类型" prop="type">
<el-select class="filter-item" v-model="form.type" :disabled="formEdit" placeholder="请输入资源请求类型">
<el-option v-for="item in typeOptions" :key="item" :label="item | typeFilter" :value="item"> </el-option>
</el-select>
</el-form-item>
<el-form-item label="排序" prop="sort">
<el-input v-model="form.sort" :disabled="formEdit" placeholder="请输入排序"></el-input>
</el-form-item>
<el-form-item label="前端组件" prop="component">
<el-input v-model="form.component" :disabled="formEdit" placeholder="请输入描述"></el-input>
</el-form-item>
<el-form-item v-if="formStatus == 'update'">
<el-button type="primary" @click="update">更新</el-button>
<el-button @click="onCancel">取消</el-button>
</el-form-item>
<el-form-item v-if="formStatus == 'create'">
<el-button type="primary" @click="create">保存</el-button>
<el-button @click="onCancel">取消</el-button>
</el-form-item>
</el-form>
</el-card>
</el-col>
</el-row>
</div>
</template>
<script>
import { fetchTree, getObj, addObj, delObj, putObj } from '@/api/menu'
import { mapGetters } from 'vuex'
export default {
name: 'menu',
data() {
return {
list: null,
total: null,
formEdit: true,
formAdd: true,
formStatus: '',
showElement: false,
typeOptions: ['0', '1'],
methodOptions: ['GET', 'POST', 'PUT', 'DELETE'],
listQuery: {
name: undefined
},
treeData: [],
defaultProps: {
children: 'children',
label: 'name'
},
labelPosition: 'right',
form: {
permission: undefined,
name: undefined,
menuId: undefined,
parentId: undefined,
url: undefined,
icon: undefined,
sort: undefined,
component: undefined,
type: undefined,
method: undefined
},
currentId: -1,
menuManager_btn_add: false,
menuManager_btn_edit: false,
menuManager_btn_del: false
}
},
filters: {
typeFilter(type) {
const typeMap = {
0: '菜单',
1: '按钮'
}
return typeMap[type]
}
},
created() {
this.getList()
this.menuManager_btn_add = this.permissions['sys_menu_add']
this.menuManager_btn_edit = this.permissions['sys_menu_edit']
this.menuManager_btn_del = this.permissions['sys_menu_del']
},
computed: {
...mapGetters([
'elements',
'permissions'
])
},
methods: {
getList() {
fetchTree(this.listQuery).then(response => {
this.treeData = response.data
})
},
filterNode(value, data) {
if (!value) return true
return data.label.indexOf(value) !== -1
},
getNodeData(data) {
if (!this.formEdit) {
this.formStatus = 'update'
}
getObj(data.id).then(response => {
this.form = response.data
})
this.currentId = data.id
this.showElement = true
},
handlerEdit() {
if (this.form.menuId) {
this.formEdit = false
this.formStatus = 'update'
}
},
handlerAdd() {
this.resetForm()
this.formEdit = false
this.formStatus = 'create'
},
handleDelete() {
this.$confirm('此操作将永久删除, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
delObj(this.currentId).then(() => {
this.getList()
this.resetForm()
this.onCancel()
this.$notify({
title: '成功',
message: '删除成功',
type: 'success',
duration: 2000
})
})
})
},
update() {
putObj(this.form).then(() => {
this.getList()
this.$notify({
title: '成功',
message: '更新成功',
type: 'success',
duration: 2000
})
})
},
create() {
addObj(this.form).then(() => {
this.getList()
this.$notify({
title: '成功',
message: '创建成功',
type: 'success',
duration: 2000
})
})
},
onCancel() {
this.formEdit = true
this.formStatus = ''
},
resetForm() {
this.form = {
permission: undefined,
name: undefined,
menuId: undefined,
parentId: this.currentId,
url: undefined,
icon: undefined,
sort: undefined,
component: undefined,
type: undefined,
method: undefined
}
}
}
}
</script>

View File

@ -0,0 +1,344 @@
<template>
<div class="app-container calendar-list-container">
<div class="filter-container">
<el-button class="filter-item" style="margin-left: 10px;" @click="handleCreate" type="primary" icon="edit">添加
</el-button>
</div>
<el-table :key='tableKey' :data="list" v-loading="listLoading" element-loading-text="给我一点时间" border fit highlight-current-row style="width: 99%">
<el-table-column align="center" label="序号">
<template slot-scope="scope">
<span>{{scope.row.roleId}}</span>
</template>
</el-table-column>
<el-table-column label="角色名称">
<template slot-scope="scope">
<span>{{scope.row.roleName}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="角色标识">
<template slot-scope="scope">
<span>{{scope.row.roleCode}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="角色描述">
<template slot-scope="scope">
<span>{{scope.row.roleDesc }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="所属部门">
<template slot-scope="scope">
<span>{{scope.row.deptName }}</span>
</template>
</el-table-column>
<el-table-column align="center" label="创建时间">
<template slot-scope="scope">
<span>{{scope.row.createTime | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
<el-table-column label="操作" width="220">
<template slot-scope="scope">
<el-button size="mini" type="success" @click="handleUpdate(scope.row)">编辑
</el-button>
<el-button size="mini" type="danger" @click="handleDelete(scope.row)">删除
</el-button>
<el-button size="mini" type="info" plain @click="handlePermission(scope.row)">权限
</el-button>
</template>
</el-table-column>
</el-table>
<div v-show="!listLoading" class="pagination-container">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page.sync="listQuery.page" :page-sizes="[10,20,30, 50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<el-form :model="form" :rules="rules" ref="form" label-width="100px">
<el-form-item label="角色名称" prop="roleName">
<el-input v-model="form.roleName" placeholder="角色名称"></el-input>
</el-form-item>
<el-form-item label="角色标识" prop="roleCode">
<el-input v-model="form.roleCode" placeholder="角色标识"></el-input>
</el-form-item>
<el-form-item label="描述" prop="roleDesc">
<el-input v-model="form.roleDesc" placeholder="描述"></el-input>
</el-form-item>
<el-form-item label="所属部门" prop="roleDept">
<el-input v-model="form.deptName" placeholder="选择部门" @focus="handleDept()" readonly></el-input>
<el-input type="hidden" v-model="form.roleDeptId"></el-input>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancel('form')"> </el-button>
<el-button v-if="dialogStatus=='create'" type="primary" @click="create('form')"> </el-button>
<el-button v-else type="primary" @click="update('form')"> </el-button>
</div>
</el-dialog>
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogDeptVisible">
<el-tree class="filter-tree" :data="treeDeptData" :default-checked-keys="checkedKeys" check-strictly node-key="id" highlight-current ref="deptTree" @node-click="getNodeData" :props="defaultProps" :filter-node-method="filterNode" default-expand-all>
</el-tree>
</el-dialog>
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogPermissionVisible">
<el-tree class="filter-tree" :data="treeData" :default-checked-keys="checkedKeys" check-strictly node-key="id" highlight-current :props="defaultProps" show-checkbox ref="menuTree" :filter-node-method="filterNode" default-expand-all>
</el-tree>
<div slot="footer" class="dialog-footer">
<el-button type="primary" @click="updatePermession(roleId, roleCode)"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import {
fetchList,
getObj,
addObj,
putObj,
delObj,
permissionUpd,
fetchRoleTree,
fetchDeptTree
} from "@/api/role";
import { fetchTree } from "@/api/menu";
import waves from "@/directive/waves/index.js"; //
export default {
name: "table_role",
directives: {
waves
},
data() {
return {
treeData: [],
treeDeptData: [],
checkedKeys: [],
defaultProps: {
children: "children",
label: "name"
},
list: null,
total: null,
listLoading: true,
listQuery: {
page: 1,
limit: 20
},
form: {
roleName: undefined,
roleCode: undefined,
roleDesc: undefined,
deptName: undefined,
roleDeptId: undefined
},
roleId: undefined,
roleCode: undefined,
rules: {
roleName: [
{
required: true,
message: "角色名称",
trigger: "blur"
},
{
min: 3,
max: 20,
message: "长度在 3 到 20 个字符",
trigger: "blur"
}
],
roleCode: [
{
required: true,
message: "角色标识",
trigger: "blur"
},
{
min: 3,
max: 20,
message: "长度在 3 到 20 个字符",
trigger: "blur"
}
],
roleDesc: [
{
required: true,
message: "角色标识",
trigger: "blur"
},
{
min: 3,
max: 20,
message: "长度在 3 到 20 个字符",
trigger: "blur"
}
]
},
statusOptions: ["0", "1"],
rolesOptions: undefined,
dialogFormVisible: false,
dialogDeptVisible: false,
dialogPermissionVisible: false,
dialogStatus: "",
textMap: {
update: "编辑",
create: "创建",
permission: "分配权限"
},
tableKey: 0
};
},
created() {
this.getList();
},
methods: {
getList() {
this.listLoading = true;
fetchList(this.listQuery).then(response => {
this.list = response.data.records;
this.total = response.data.total;
this.listLoading = false;
});
},
handleSizeChange(val) {
this.listQuery.limit = val;
this.getList();
},
handleCurrentChange(val) {
this.listQuery.page = val;
this.getList();
},
handleCreate() {
this.resetTemp();
this.dialogStatus = "create";
this.dialogFormVisible = true;
},
handleUpdate(row) {
getObj(row.roleId).then(response => {
this.form = response.data;
this.form.deptName = row.deptName;
this.form.roleDeptId = row.roleDeptId;
this.dialogFormVisible = true;
this.dialogStatus = "update";
});
},
handlePermission(row) {
fetchRoleTree(row.roleCode).then(response => {
this.checkedKeys = response.data;
});
fetchTree().then(response => {
this.treeData = response.data;
this.dialogStatus = "permission";
this.dialogPermissionVisible = true;
this.roleId = row.roleId;
this.roleCode = row.roleCode;
});
},
handleDept() {
fetchDeptTree().then(response => {
this.treeDeptData = response.data;
this.dialogDeptVisible = true;
});
},
filterNode(value, data) {
if (!value) return true;
return data.label.indexOf(value) !== -1;
},
getNodeData(data) {
this.dialogDeptVisible = false;
this.form.roleDeptId = data.id;
this.form.deptName = data.name;
console.log(data);
},
handleDelete(row) {
delObj(row.roleId).then(response => {
this.dialogFormVisible = false;
this.getList();
this.$notify({
title: "成功",
message: "删除成功",
type: "success",
duration: 2000
});
});
},
create(formName) {
const set = this.$refs;
set[formName].validate(valid => {
if (valid) {
addObj(this.form).then(() => {
this.dialogFormVisible = false;
this.getList();
this.$notify({
title: "成功",
message: "创建成功",
type: "success",
duration: 2000
});
});
} else {
return false;
}
});
},
cancel(formName) {
this.dialogFormVisible = false;
this.$refs[formName].resetFields();
},
update(formName) {
const set = this.$refs;
set[formName].validate(valid => {
if (valid) {
this.dialogFormVisible = false;
putObj(this.form).then(() => {
this.dialogFormVisible = false;
this.getList();
this.$notify({
title: "成功",
message: "修改成功",
type: "success",
duration: 2000
});
});
} else {
return false;
}
});
},
updatePermession(roleId, roleCode) {
permissionUpd(roleId, this.$refs.menuTree.getCheckedKeys()).then(() => {
this.dialogPermissionVisible = false;
fetchTree().then(response => {
this.treeData = response.data;
});
fetchRoleTree(roleCode).then(response => {
this.checkedKeys = response.data;
});
this.$notify({
title: "成功",
message: "修改成功",
type: "success",
duration: 2000
});
});
},
resetTemp() {
this.form = {
id: undefined,
roleName: undefined,
roleCode: undefined,
roleDesc: undefined
};
}
}
};
</script>

View File

@ -0,0 +1,369 @@
<template>
<div class="app-container calendar-list-container">
<div class="filter-container">
<el-input @keyup.enter.native="handleFilter" style="width: 200px;" class="filter-item" placeholder="用户名" v-model="listQuery.username">
</el-input>
<el-button class="filter-item" type="primary" v-waves icon="search" @click="handleFilter">搜索</el-button>
<el-button v-if="sys_user_add" class="filter-item" style="margin-left: 10px;" @click="handleCreate" type="primary" icon="edit">添加</el-button>
</div>
<el-table :key='tableKey' :data="list" v-loading="listLoading" element-loading-text="给我一点时间" border fit highlight-current-row style="width: 99%">
<el-table-column align="center" label="序号">
<template slot-scope="scope">
<span>{{scope.row.userId}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="用户名">
<template slot-scope="scope">
<span>
<img v-if="scope.row.avatar" class="user-avatar" style="width: 20px; height: 20px; border-radius: 50%;" :src="scope.row.avatar+'?imageView2/1/w/20/h/20'"> {{scope.row.username}}
</span>
</template>
</el-table-column>
<el-table-column align="center" label="所属部门" show-overflow-tooltip>
<template slot-scope="scope">
<span>{{scope.row.deptName}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="角色">
<template slot-scope="scope">
<span>{{scope.row.roleList[0].roleDesc}}</span>
</template>
</el-table-column>
<el-table-column align="center" label="创建时间">
<template slot-scope="scope">
<span>{{scope.row.createTime | parseTime('{y}-{m}-{d} {h}:{i}')}}</span>
</template>
</el-table-column>
<el-table-column align="center" class-name="status-col" label="状态">
<template slot-scope="scope">
<el-tag>{{scope.row.delFlag | statusFilter}}</el-tag>
</template>
</el-table-column>
<el-table-column align="center" label="操作">
<template slot-scope="scope">
<el-button v-if="sys_user_upd" size="small" type="success" @click="handleUpdate(scope.row)">编辑
</el-button>
<el-button v-if="sys_user_del" size="small" type="danger" @click="deletes(scope.row)">删除
</el-button>
</template>
</el-table-column>
</el-table>
<div v-show="!listLoading" class="pagination-container">
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :current-page.sync="listQuery.page" :page-sizes="[10,20,30, 50]" :page-size="listQuery.limit" layout="total, sizes, prev, pager, next, jumper" :total="total">
</el-pagination>
</div>
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogDeptVisible">
<el-tree class="filter-tree" :data="treeDeptData" :default-checked-keys="checkedKeys" check-strictly node-key="id" highlight-current ref="deptTree" :props="defaultProps" @node-click="getNodeData" default-expand-all>
</el-tree>
</el-dialog>
<el-dialog :title="textMap[dialogStatus]" :visible.sync="dialogFormVisible">
<el-form :model="form" :rules="rules" ref="form" label-width="100px">
<el-form-item label="用户名" prop="username">
<el-input v-model="form.username" placeholder="请输用户名"></el-input>
</el-form-item>
<el-form-item v-if="dialogStatus == 'create'" label="密码" placeholder="请输入密码" prop="password">
<el-input type="password" v-model="form.password"></el-input>
</el-form-item>
<el-form-item label="所属部门" prop="deptName">
<el-input v-model="form.deptName" placeholder="选择部门" @focus="handleDept()" readonly></el-input>
<input type="hidden" v-model="form.deptId" />
</el-form-item>
<el-form-item label="角色" prop="role">
<el-select class="filter-item" v-model="role" placeholder="请选择">
<el-option v-for="item in rolesOptions" :key="item.roleId" :label="item.roleDesc" :value="item.roleId" :disabled="isDisabled[item.delFlag]">
<span style="float: left">{{ item.roleDesc }}</span>
<span style="float: right; color: #8492a6; font-size: 13px">{{ item.roleCode }}</span>
</el-option>
</el-select>
</el-form-item>
<el-form-item label="状态" v-if="dialogStatus == 'update' && sys_user_del " prop="delFlag">
<el-select class="filter-item" v-model="form.delFlag" placeholder="请选择">
<el-option v-for="item in statusOptions" :key="item" :label="item | statusFilter" :value="item"> </el-option>
</el-select>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="cancel('form')"> </el-button>
<el-button v-if="dialogStatus=='create'" type="primary" @click="create('form')"> </el-button>
<el-button v-else type="primary" @click="update('form')"> </el-button>
</div>
</el-dialog>
</div>
</template>
<script>
import { fetchList, getObj, addObj, putObj, delObj } from "@/api/user";
import { deptRoleList, fetchDeptTree } from "@/api/role";
import waves from "@/directive/waves/index.js"; //
// import { parseTime } from '@/utils'
import { mapGetters } from "vuex";
import ElRadioGroup from "element-ui/packages/radio/src/radio-group";
import ElOption from "element-ui/packages/select/src/option";
export default {
components: {
ElOption,
ElRadioGroup
},
name: "table_user",
directives: {
waves
},
data() {
return {
treeDeptData: [],
checkedKeys: [],
defaultProps: {
children: "children",
label: "name"
},
list: null,
total: null,
listLoading: true,
listQuery: {
page: 1,
limit: 20
},
role: undefined,
form: {
username: undefined,
password: undefined,
delFlag: undefined,
deptId: undefined
},
rules: {
username: [
{
required: true,
message: "请输入账户",
trigger: "blur"
},
{
min: 3,
max: 20,
message: "长度在 3 到 20 个字符",
trigger: "blur"
}
],
password: [
{
required: true,
message: "请输入密码",
trigger: "blur"
},
{
min: 5,
max: 20,
message: "长度在 5 到 20 个字符",
trigger: "blur"
}
],
deptId: [
{
required: true,
message: "请选择部门",
trigger: "blur"
}
],
role: [
{
required: true,
message: "请选择角色",
trigger: "blur"
}
]
},
statusOptions: ["0", "1"],
rolesOptions: [],
dialogFormVisible: false,
dialogDeptVisible: false,
userAdd: false,
userUpd: false,
userDel: false,
dialogStatus: "",
textMap: {
update: "编辑",
create: "创建"
},
isDisabled: {
0: false,
1: true
},
tableKey: 0
};
},
computed: {
...mapGetters(["permissions"])
},
filters: {
statusFilter(status) {
const statusMap = {
0: "有效",
1: "无效",
9: "锁定"
};
return statusMap[status];
}
},
created() {
this.getList();
this.sys_user_add = this.permissions["sys_user_add"];
this.sys_user_upd = this.permissions["sys_user_upd"];
this.sys_user_del = this.permissions["sys_user_del"];
},
methods: {
getList() {
this.listLoading = true;
this.listQuery.orderByField = "`user`.create_time";
this.listQuery.isAsc = false;
fetchList(this.listQuery).then(response => {
this.list = response.data.records;
this.total = response.data.total;
this.listLoading = false;
});
},
getNodeData(data) {
this.dialogDeptVisible = false;
this.form.deptId = data.id;
this.form.deptName = data.name;
deptRoleList(data.id).then(response => {
this.rolesOptions = response.data;
});
},
handleDept() {
fetchDeptTree().then(response => {
this.treeDeptData = response.data;
this.dialogDeptVisible = true;
});
},
handleFilter() {
this.listQuery.page = 1;
this.getList();
},
handleSizeChange(val) {
this.listQuery.limit = val;
this.getList();
},
handleCurrentChange(val) {
this.listQuery.page = val;
this.getList();
},
handleCreate() {
this.resetTemp();
this.dialogStatus = "create";
this.dialogFormVisible = true;
},
handleUpdate(row) {
getObj(row.userId).then(response => {
this.form = response.data;
this.role = row.roleList[0].roleId;
this.dialogFormVisible = true;
this.dialogStatus = "update";
deptRoleList(response.data.deptId).then(response => {
this.rolesOptions = response.data;
});
});
},
create(formName) {
const set = this.$refs;
this.form.role = this.role;
set[formName].validate(valid => {
if (valid) {
addObj(this.form).then(() => {
this.dialogFormVisible = false;
this.getList();
this.$notify({
title: "成功",
message: "创建成功",
type: "success",
duration: 2000
});
});
} else {
return false;
}
});
},
cancel(formName) {
this.dialogFormVisible = false;
this.$refs[formName].resetFields();
},
update(formName) {
const set = this.$refs;
this.form.role = this.role;
set[formName].validate(valid => {
if (valid) {
this.dialogFormVisible = false;
this.form.password = undefined;
putObj(this.form).then(() => {
this.dialogFormVisible = false;
this.getList();
this.$notify({
title: "成功",
message: "修改成功",
type: "success",
duration: 2000
});
});
} else {
return false;
}
});
},
deletes(row) {
this.$confirm(
"此操作将永久删除该用户(用户名:" + row.username + "), 是否继续?",
"提示",
{
confirmButtonText: "确定",
cancelButtonText: "取消",
type: "warning"
}
).then(() => {
delObj(row.userId)
.then(() => {
this.getList();
this.$notify({
title: "成功",
message: "删除成功",
type: "success",
duration: 2000
});
})
.cache(() => {
this.$notify({
title: "失败",
message: "删除失败",
type: "error",
duration: 2000
});
});
});
},
resetTemp() {
this.form = {
id: undefined,
username: "",
password: "",
role: undefined
};
}
}
};
</script>

View File

@ -0,0 +1,160 @@
<template>
<div class="app-container calendar-list-container">
<el-row>
<el-col :span="12">
<div class="grid-content bg-purple">
<el-form :model="ruleForm2" :rules="rules2" ref="ruleForm2" label-width="100px" class="demo-ruleForm">
<el-form-item label="用户名" prop="username">
<el-input type="text" :value="name" disabled></el-input>
</el-form-item>
<el-form-item label="原密码" prop="pass">
<el-input type="password" v-model="ruleForm2.password" auto-complete="off"></el-input>
</el-form-item>
<el-form-item label="密码" prop="pass">
<el-input type="password" v-model="ruleForm2.newpassword1" auto-complete="off"></el-input>
</el-form-item>
<el-form-item label="确认密码" prop="checkPass">
<el-input type="password" v-model="ruleForm2.newpassword2" auto-complete="off"></el-input>
</el-form-item>
<el-form-item label="头像">
<my-upload field="file" @crop-upload-success="cropUploadSuccess" v-model="show" :width="300" :height="300" url="/admin/user/upload" :headers="headers" img-format="png"></my-upload>
<img :src="avatar">
<el-button type="primary" @click="toggleShow" size="mini">选择
<i class="el-icon-upload el-icon--right"></i>
</el-button>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="submitForm('ruleForm2')">提交</el-button>
<el-button @click="resetForm('ruleForm2')">重置</el-button>
</el-form-item>
</el-form>
</div>
</el-col>
</el-row>
</div>
</template>
<script>
import { mapGetters } from "vuex";
import myUpload from "vue-image-crop-upload";
import { getToken } from "@/util/auth";
import ElFormItem from "element-ui/packages/form/src/form-item.vue";
import request from "@/router/axios";
export default {
components: {
ElFormItem,
"my-upload": myUpload
},
data() {
var validatePass = (rule, value, callback) => {
if (value === "") {
callback(new Error("请输入密码"));
} else if (value.length < 6) {
callback(new Error("密码不能小于6位"));
} else {
if (this.ruleForm2.newpassword1 !== "") {
this.$refs.ruleForm2.validateField("newpassword1");
}
callback();
}
};
var validatePass2 = (rule, value, callback) => {
if (value === "") {
callback(new Error("请再次输入密码"));
} else if (value !== this.ruleForm2.newpassword2) {
callback(new Error("两次输入密码不一致!"));
} else {
callback();
}
};
return {
fileList: [],
show: false,
headers: {
Authorization: "Bearer " + getToken()
},
ruleForm2: {
password: "",
newpassword1: "",
newpassword2: "",
avatar: ""
},
rules2: {
newpassword1: [{ validator: validatePass, trigger: "blur" }],
newpassword2: [{ validator: validatePass2, trigger: "blur" }]
}
};
},
computed: {
...mapGetters(["name", "avatar"])
},
methods: {
submitForm(formName) {
this.$refs[formName].validate(valid => {
if (valid) {
this.ruleForm2.avatar = this.avatar;
request({
url: "/admin/user/editInfo",
method: "put",
data: this.ruleForm2
})
.then(response => {
if (response) {
this.$notify({
title: "成功",
message: "修改成功",
type: "success",
duration: 2000
});
//
if (this.ruleForm2.newpassword1 !== "") {
this.$store.dispatch("LogOut").then(() => {
location.reload(); // vue-router bug
});
} else {
this.$router.push({ path: "/" });
}
} else {
this.$notify({
title: "失败",
message: response,
type: "fail",
duration: 2000
});
}
})
.catch(() => {
this.$notify({
title: "失败",
message: "修改失败",
type: "fail",
duration: 2000
});
});
} else {
return false;
}
});
},
resetForm(formName) {
this.$refs[formName].resetFields();
},
toggleShow() {
this.show = !this.show;
},
/**
* upload success
*
* [param] jsonData 服务器返回数据已进行json转码
* [param] field
*/
cropUploadSuccess(jsonData, field) {
console.log("-------- upload success --------");
this.$store.commit("SET_AVATAR", jsonData.filename);
}
}
};
</script>

View File

@ -0,0 +1,33 @@
<template>
<div class="dashboard-container">
<div class="dashboard-text">欢迎登录</div>
<div class="dashboard-text">用户名{{name}}</div>
<div class="dashboard-text">角色名<span v-for='role in roles' :key='role'>{{role}}</span></div>
</div>
</template>
<script>
import { mapGetters } from 'vuex'
export default {
name: 'dashboard',
computed: {
...mapGetters([
'name',
'roles'
])
}
}
</script>
<style rel="stylesheet/scss" lang="scss" scoped>
.dashboard {
&-container {
margin: 30px;
}
&-text {
font-size: 30px;
line-height: 46px;
}
}
</style>