Commit 7cfd8944 by dqjdda

merge 2.3dev

parents 5e4b4181 0fe86e60
{
"name": "eladmin",
"name": "eladmin-web",
"version": "2.2.0",
"license": "Apache-2.0",
"description": "eladmin 前端代码",
......@@ -22,7 +22,7 @@
"clipboard": "1.7.1",
"codemirror": "^5.38.0",
"connect": "3.6.6",
"echarts": "4.1.0",
"echarts": "^4.1.0",
"element-ui": "^2.12.0",
"file-saver": "1.3.8",
"js-cookie": "2.2.0",
......@@ -65,7 +65,7 @@
"file-loader": "1.1.11",
"friendly-errors-webpack-plugin": "1.7.0",
"happypack": "^5.0.1",
"html-webpack-plugin": "4.0.0-alpha",
"html-webpack-plugin": "^3.0.0",
"mini-css-extract-plugin": "0.4.1",
"node-notifier": "5.2.1",
"node-sass": "^4.7.2",
......@@ -88,11 +88,11 @@
"vue-loader": "15.3.0",
"vue-style-loader": "4.1.2",
"vue-template-compiler": "2.5.17",
"webpack": "4.16.5",
"webpack-bundle-analyzer": "3.3.2",
"webpack-cli": "3.1.0",
"webpack-dev-server": "3.3.1",
"webpack-merge": "4.1.4"
"webpack": "^4.41.2",
"webpack-bundle-analyzer": "^3.6.0",
"webpack-cli": "^3.3.9",
"webpack-dev-server": "^3.9.0",
"webpack-merge": "^4.2.2"
},
"engines": {
"node": ">= 6.0.0",
......
......@@ -30,3 +30,12 @@ export function edit(data) {
data
})
}
export function downloadDept(params) {
return request({
url: 'api/dept/download',
method: 'get',
params,
responseType: 'blob'
})
}
......@@ -22,3 +22,12 @@ export function edit(data) {
data
})
}
export function downloadDict(params) {
return request({
url: 'api/dict/download',
method: 'get',
params,
responseType: 'blob'
})
}
......@@ -35,3 +35,12 @@ export function edit(data) {
data
})
}
export function downloadJob(params) {
return request({
url: 'api/job/download',
method: 'get',
params,
responseType: 'blob'
})
}
......@@ -30,3 +30,12 @@ export function edit(data) {
data
})
}
export function downloadStorage(params) {
return request({
url: 'api/localStorage/download',
method: 'get',
params,
responseType: 'blob'
})
}
......@@ -6,3 +6,12 @@ export function getErrDetail(id) {
method: 'get'
})
}
export function downloadLog(params) {
return request({
url: 'api/logs/download',
method: 'get',
params,
responseType: 'blob'
})
}
......@@ -22,7 +22,14 @@ export function getInfo() {
export function getCodeImg() {
return request({
url: 'auth/vCode',
url: 'auth/code',
method: 'get'
})
}
export function logout() {
return request({
url: 'auth/logout',
method: 'delete'
})
}
......@@ -37,3 +37,12 @@ export function edit(data) {
data
})
}
export function downloadMenu(params) {
return request({
url: 'api/menus/download',
method: 'get',
params,
responseType: 'blob'
})
}
import request from '@/utils/request'
export function del(key) {
return request({
url: 'auth/online/' + key,
method: 'delete'
})
}
export function downloadOnline(params) {
return request({
url: 'auth/online/download',
method: 'get',
params,
responseType: 'blob'
})
}
import request from '@/utils/request'
// 获取所有的权限树
export function getPermissionTree() {
return request({
url: 'api/permissions/tree',
method: 'get'
})
}
export function add(data) {
return request({
url: 'api/permissions',
method: 'post',
data
})
}
export function del(id) {
return request({
url: 'api/permissions/' + id,
method: 'delete'
})
}
export function edit(data) {
return request({
url: 'api/permissions',
method: 'put',
data
})
}
......@@ -14,3 +14,12 @@ export function delAll(ids) {
data: ids
})
}
export function downloadPicture(params) {
return request({
url: 'api/pictures/download',
method: 'get',
params,
responseType: 'blob'
})
}
......@@ -2,14 +2,14 @@ import request from '@/utils/request'
export function get() {
return request({
url: 'api/qiNiuConfig',
url: 'api/qiNiuContent/config',
method: 'get'
})
}
export function update(data) {
return request({
url: 'api/qiNiuConfig',
url: 'api/qiNiuContent/config',
data,
method: 'put'
})
......@@ -43,3 +43,12 @@ export function delAll(ids) {
data: ids
})
}
export function downloadQiNiu(params) {
return request({
url: 'api/qiNiuContent/download/list',
method: 'get',
params,
responseType: 'blob'
})
}
......@@ -33,3 +33,12 @@ export function edit(data) {
data
})
}
export function downloadRedis(params) {
return request({
url: 'api/redis/download',
method: 'get',
params,
responseType: 'blob'
})
}
......@@ -60,3 +60,12 @@ export function editMenu(data) {
data
})
}
export function downloadRole(params) {
return request({
url: 'api/roles/download',
method: 'get',
params,
responseType: 'blob'
})
}
......@@ -36,3 +36,21 @@ export function execution(id) {
method: 'put'
})
}
export function downloadJobs(params) {
return request({
url: 'api/jobs/download',
method: 'get',
params,
responseType: 'blob'
})
}
export function downloadLogs(params) {
return request({
url: 'api/jobs/download/log',
method: 'get',
params,
responseType: 'blob'
})
}
......@@ -7,10 +7,12 @@ export function add(data) {
data
})
}
export function downloadUser() {
export function downloadUser(params) {
return request({
url: 'api/users/download',
method: 'get',
params,
responseType: 'blob'
})
}
......@@ -49,4 +51,3 @@ export function updateEmail(code, data) {
data
})
}
import Vue from 'vue'
import { get as getDictDetail } from '@/api/dictDetail'
export default class Dict {
constructor(dict) {
this.dict = dict
}
async init(names, completeCallback) {
if (names === undefined || name === null) {
throw new Error('need Dict names')
}
const ps = []
names.forEach(n => {
Vue.set(this.dict.dict, n, {})
Vue.set(this.dict.label, n, {})
Vue.set(this.dict, n, [])
ps.push(getDictDetail(n).then(data => {
this.dict[n].splice(0, 0, ...data.content)
data.content.forEach(d => {
Vue.set(this.dict.dict[n], d.value, d)
Vue.set(this.dict.label[n], d.value, d.label)
})
}))
})
await Promise.all(ps)
completeCallback()
}
}
import Dict from './Dict'
const install = function(Vue) {
Vue.mixin({
data() {
if (this.$options.dicts instanceof Array) {
const dict = {
dict: {},
label: {}
}
return {
dict
}
}
return {}
},
created() {
if (this.$options.dicts instanceof Array) {
new Dict(this.dict).init(this.$options.dicts, () => {
this.$nextTick(() => {
this.$emit('dictReady')
})
})
}
}
})
}
export default { install }
<template>
<a href="https://github.com/elunez/eladmin" target="_blank">
<svg id="icon-github" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" class="icon svg" viewBox="0 0 1025 1024" width="100%" height="100%"><path d="M512.032 831.904c-19.168 0-38.304-9.92-58.144-29.76-7.808-7.808-7.808-20.48 0-28.288s20.48-7.808 28.288 0c12.192 12.224 21.984 18.144 29.856 18.144s17.664-5.92 29.856-18.144c7.808-7.808 20.48-7.808 28.288 0s7.808 20.48 0 28.288c-19.84 19.84-38.976 29.76-58.144 29.76zM0.032 525.504c0 49.888 4.256 95.136 12.8 135.68s20.544 75.744 36 105.536c15.456 29.792 35.008 55.904 58.656 78.336s49.344 40.928 77.056 55.456c27.744 14.528 59.456 26.304 95.2 35.264s72.096 15.264 109.056 18.848 77.696 5.376 122.144 5.376c44.448 0 85.248-1.792 122.4-5.376s73.6-9.856 109.344-18.848c35.744-8.96 67.552-20.736 95.456-35.264s53.792-33.024 77.6-55.456c23.808-22.432 43.456-48.544 58.944-78.336s27.552-64.96 36.256-105.536c8.704-40.576 13.056-85.792 13.056-135.68 0-89.376-27.744-166.368-83.2-230.976 3.2-8.608 5.952-18.496 8.256-29.6s4.544-26.816 6.656-47.104c2.144-20.288 1.344-43.712-2.4-70.272s-10.752-53.664-21.056-81.312l-8-1.632c-5.344-1.088-14.048-0.704-26.144 1.088s-26.208 5.024-42.4 9.696c-16.192 4.672-37.056 13.92-62.656 27.744s-52.608 31.328-81.056 52.512c-48.352-14.72-115.008-30.112-200-30.112s-151.808 15.392-200.544 30.112c-28.448-21.184-55.552-38.592-81.344-52.224s-46.4-22.976-61.856-28c-15.456-5.024-29.792-8.256-42.944-9.696s-21.6-1.888-25.344-1.344c-3.744 0.544-6.496 1.152-8.256 1.888-10.304 27.648-17.408 54.752-21.344 81.312s-4.8 49.888-2.656 69.984c2.144 20.096 4.448 35.904 6.944 47.392s5.344 21.344 8.544 29.6c-55.456 64.256-83.2 141.248-83.2 230.976zM136.576 639.392c0-58.016 21.344-110.624 64-157.856 12.8-14.4 27.648-25.312 44.544-32.704s36.096-11.616 57.6-12.608 42.048-0.8 61.6 0.608c19.552 1.408 43.744 3.296 72.544 5.696s53.696 3.616 74.656 3.616c20.96 0 45.856-1.184 74.656-3.616s52.992-4.288 72.544-5.696c19.552-1.408 40.096-1.6 61.6-0.608s40.8 5.216 57.856 12.608c17.056 7.392 32 18.304 44.8 32.704 42.656 47.232 64 99.84 64 157.856 0 34.016-3.552 64.32-10.656 90.944s-16.096 48.928-26.944 66.912c-10.848 18.016-26.048 33.216-45.6 45.632s-38.496 22.016-56.8 28.8c-18.304 6.784-41.952 12.096-70.944 15.904s-54.944 6.112-77.856 6.912c-22.944 0.8-51.808 1.216-86.656 1.216s-63.648-0.416-86.4-1.216c-22.752-0.8-48.608-3.104-77.6-6.912s-52.608-9.12-70.944-15.904c-18.304-6.816-37.248-16.416-56.8-28.8s-34.752-27.616-45.6-45.632c-10.848-18.016-19.84-40.32-26.944-66.912s-10.656-56.928-10.656-90.944zM256.032 608c0-53.024 28.64-96 64-96s64 42.976 64 96c0 53.024-28.64 96-64 96s-64-42.976-64-96zM640.032 608c0-53.024 28.64-96 64-96s64 42.976 64 96c0 53.024-28.64 96-64 96s-64-42.976-64-96z" p-id="1450"/></svg>
</a>
</template>
<script>
export default {
name: 'Github'
}
</script>
<style scoped>
.svg {
display: inline-block;
cursor: pointer;
fill: #5a5e66;;
width: 20px;
height: 20px;
vertical-align: 10px;
}
</style>
/**
* @Author: jianglei
* @Date: 2017-10-12 12:06:49
*/
'use strict'
import Vue from 'vue'
export default function treeToArray(data, expandAll, parent = null, level = null) {
let tmp = []
Array.from(data).forEach(function(record) {
if (record._expanded === undefined) {
Vue.set(record, '_expanded', expandAll)
}
let _level = 1
if (level !== undefined && level !== null) {
_level = level + 1
}
Vue.set(record, '_level', _level)
// 如果有父元素
if (parent) {
Vue.set(record, 'parent', parent)
}
tmp.push(record)
if (record.children && record.children.length > 0) {
const children = treeToArray(record.children, expandAll, record, _level)
tmp = tmp.concat(children)
}
})
return tmp
}
<template>
<el-table :data="formatData" :row-style="showRow" v-bind="$attrs">
<el-table-column v-if="columns.length===0" width="150">
<template slot-scope="scope">
<span v-for="space in scope.row._level" :key="space" class="ms-tree-space"/>
<span v-if="iconShow(0,scope.row)" class="tree-ctrl" @click="toggleExpanded(scope.$index)">
<i v-if="!scope.row._expanded" class="el-icon-plus"/>
<i v-else class="el-icon-minus"/>
</span>
{{ scope.$index }}
</template>
</el-table-column>
<el-table-column v-for="(column, index) in columns" v-else :key="column.value" :label="column.text" :width="column.width">
<template slot-scope="scope">
<!-- Todo -->
<!-- eslint-disable-next-line vue/no-confusing-v-for-v-if -->
<span v-for="space in scope.row._level" v-if="index === 0" :key="space" class="ms-tree-space"/>
<span v-if="iconShow(index,scope.row)" class="tree-ctrl" @click="toggleExpanded(scope.$index)">
<i v-if="!scope.row._expanded" class="el-icon-plus"/>
<i v-else class="el-icon-minus"/>
</span>
{{ scope.row[column.value] }}
</template>
</el-table-column>
<slot/>
</el-table>
</template>
<script>
/**
Auth: Lei.j1ang
Created: 2018/1/19-13:59
*/
import treeToArray from './eval'
export default {
name: 'TreeTable',
props: {
/* eslint-disable */
data: {
type: [Array, Object],
required: true
},
columns: {
type: Array,
default: () => []
},
evalFunc: Function,
evalArgs: Array,
expandAll: {
type: Boolean,
default: false
}
},
computed: {
// 格式化数据源
formatData: function() {
let tmp
if (!Array.isArray(this.data)) {
tmp = [this.data]
} else {
tmp = this.data
}
const func = this.evalFunc || treeToArray
const args = this.evalArgs ? Array.concat([tmp, this.expandAll], this.evalArgs) : [tmp, this.expandAll]
return func.apply(null, args)
}
},
methods: {
showRow: function(row) {
const show = (row.row.parent ? (row.row.parent._expanded && row.row.parent._show) : true)
row.row._show = show
return show ? 'animation:treeTableShow 1s;-webkit-animation:treeTableShow 1s;' : 'display:none;'
},
// 切换下级是否展开
toggleExpanded: function(trIndex) {
const record = this.formatData[trIndex]
record._expanded = !record._expanded
},
// 图标显示
iconShow(index, record) {
return (index === 0 && record.children && record.children.length > 0)
}
}
}
</script>
<style rel="stylesheet/css">
@keyframes treeTableShow {
from {opacity: 0;}
to {opacity: 1;}
}
@-webkit-keyframes treeTableShow {
from {opacity: 0;}
to {opacity: 1;}
}
</style>
<style lang="scss" rel="stylesheet/scss" scoped>
$color-blue: #2196F3;
$space-width: 18px;
.ms-tree-space {
position: relative;
top: 1px;
display: inline-block;
font-style: normal;
font-weight: 400;
line-height: 1;
width: $space-width;
height: 14px;
&::before {
content: ""
}
}
.processContainer{
width: 100%;
height: 100%;
}
table td {
line-height: 26px;
}
.tree-ctrl{
position: relative;
cursor: pointer;
color: $color-blue;
margin-left: -$space-width;
}
</style>
## 写在前面
此组件仅提供一个创建TreeTable的解决思路
## prop说明
#### *data*
**必填**
原始数据,要求是一个数组或者对象
```javascript
[{
key1: value1,
key2: value2,
children: [{
key1: value1
},
{
key1: value1
}]
},
{
key1: value1
}]
```
或者
```javascript
{
key1: value1,
key2: value2,
children: [{
key1: value1
},
{
key1: value1
}]
}
```
#### columns
列属性,要求是一个数组
1. text: 显示在表头的文字
2. value: 对应data的key。treeTable将显示相应的value
3. width: 每列的宽度,为一个数字(可选)
如果你想要每个字段都有自定义的样式或者嵌套其他组件,columns可不提供,直接像在el-table一样写即可,如果没有自定义内容,提供columns将更加的便捷方便
如果你有几个字段是需要自定义的,几个不需要,那么可以将不需要自定义的字段放入columns,将需要自定义的内容放入到slot中,详情见后文
```javascript
[{
value:string,
text:string,
width:number
},{
value:string,
text:string,
width:number
}]
```
#### expandAll
是否默认全部展开,boolean值,默认为false
#### evalFunc
解析函数,function,非必须
如果不提供,将使用默认的[evalFunc](./eval.js)
如果提供了evalFunc,那么会用提供的evalFunc去解析data,并返回treeTable渲染所需要的值。如何编写一个evalFunc,请参考[*eval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/components/TreeTable/eval.js)[*customEval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/table/treeTable/customEval.js)
#### evalArgs
解析函数的参数,是一个数组
**请注意,自定义的解析函数参数第一个为this.data,第二个参数为, this.expandAll,你不需要在evalArgs填写。一定记住,这两个参数是强制性的,并且位置不可颠倒** *this.data为需要解析的数据,this.expandAll为是否默认展开*
如你的解析函数需要的参数为`(this.data, this.expandAll,1,2,3,4)`,那么你只需要将`[1,2,3,4]`赋值给`evalArgs`就可以了
如果你的解析函数参数只有`(this.data, this.expandAll)`,那么就可以不用填写evalArgs了
具体可参考[*customEval.js*](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/table/treeTable/customEval.js)的函数参数和[customTreeTable](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/table/treeTable/customTreeTable.vue)`evalArgs`属性值
## slot
这是一个自定义列的插槽。
默认情况下,treeTable只有一行行展示数据的功能。但是一般情况下,我们会要给行加上一个操作按钮或者根据当行数据展示不同的样式,这时我们就需要自定义列了。请参考[customTreeTable](https://github.com/PanJiaChen/vue-element-admin/blob/master/src/views/table/treeTable/customTreeTable.vue)[实例效果](https://panjiachen.github.io/vue-element-admin/#/table/tree-table)
`slot``columns属性`可同时存在,columns里面的数据列会在slot自定义列的左边展示
## 其他
如果有其他的需求,请参考[el-table](http://element-cn.eleme.io/#/en-US/component/table)的api自行修改index.vue
<svg width="128" height="100" xmlns="http://www.w3.org/2000/svg"><path d="M27.429 63.638c0-2.508-.893-4.65-2.679-6.424-1.786-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.465 2.662-1.785 1.774-2.678 3.916-2.678 6.424 0 2.508.893 4.65 2.678 6.424 1.786 1.775 3.94 2.662 6.465 2.662 2.524 0 4.678-.887 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm13.714-31.801c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM71.714 65.98l7.215-27.116c.285-1.23.107-2.378-.536-3.443-.643-1.064-1.56-1.762-2.75-2.094-1.19-.33-2.333-.177-3.429.462-1.095.639-1.81 1.573-2.143 2.804l-7.214 27.116c-2.857.237-5.405 1.266-7.643 3.088-2.238 1.822-3.738 4.152-4.5 6.992-.952 3.644-.476 7.098 1.429 10.364 1.905 3.265 4.69 5.37 8.357 6.317 3.667.947 7.143.474 10.429-1.42 3.285-1.892 5.404-4.66 6.357-8.305.762-2.84.619-5.607-.429-8.305-1.047-2.697-2.762-4.85-5.143-6.46zm47.143-2.342c0-2.508-.893-4.65-2.678-6.424-1.786-1.775-3.94-2.662-6.465-2.662-2.524 0-4.678.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.786 1.775 3.94 2.662 6.464 2.662 2.524 0 4.679-.887 6.465-2.662 1.785-1.775 2.678-3.916 2.678-6.424zm-45.714-45.43c0-2.509-.893-4.65-2.679-6.425C68.68 10.01 66.524 9.122 64 9.122c-2.524 0-4.679.887-6.464 2.661-1.786 1.775-2.679 3.916-2.679 6.425 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zm32 13.629c0-2.508-.893-4.65-2.679-6.424-1.785-1.775-3.94-2.662-6.464-2.662-2.524 0-4.679.887-6.464 2.662-1.786 1.774-2.679 3.916-2.679 6.424 0 2.508.893 4.65 2.679 6.424 1.785 1.774 3.94 2.662 6.464 2.662 2.524 0 4.679-.888 6.464-2.662 1.786-1.775 2.679-3.916 2.679-6.424zM128 63.638c0 12.351-3.357 23.78-10.071 34.286-.905 1.372-2.19 2.058-3.858 2.058H13.93c-1.667 0-2.953-.686-3.858-2.058C3.357 87.465 0 76.037 0 63.638c0-8.613 1.69-16.847 5.071-24.703C8.452 31.08 13 24.312 18.714 18.634c5.715-5.68 12.524-10.199 20.429-13.559C47.048 1.715 55.333.035 64 .035c8.667 0 16.952 1.68 24.857 5.04 7.905 3.36 14.714 7.88 20.429 13.559 5.714 5.678 10.262 12.446 13.643 20.301 3.38 7.856 5.071 16.09 5.071 24.703z"/></svg>
\ No newline at end of file
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1572170050760" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5149" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400"><defs><style type="text/css"></style></defs><path d="M219.428571 658.285714q0-30.285714-21.428571-51.714285T146.285714 585.142857t-51.714285 21.428572T73.142857 658.285714t21.428572 51.714286T146.285714 731.428571t51.714286-21.428571T219.428571 658.285714z m109.714286-256q0-30.285714-21.428571-51.714285T256 329.142857t-51.714286 21.428572T182.857143 402.285714t21.428571 51.714286T256 475.428571t51.714286-21.428571T329.142857 402.285714z m244.571429 274.857143l57.714285-218.285714q3.428571-14.857143-4.285714-27.714286T605.142857 414.285714t-27.428571 3.714286-17.142857 22.571429l-57.714286 218.285714q-34.285714 2.857143-61.142857 24.857143t-36 56.285714q-11.428571 44 11.428571 83.428571t66.857143 50.857143 83.428571-11.428571 50.857143-66.857143q9.142857-34.285714-3.428571-66.857143t-41.142857-52z m377.142857-18.857143q0-30.285714-21.428572-51.714285T877.714286 585.142857t-51.714286 21.428572-21.428571 51.714285 21.428571 51.714286 51.714286 21.428571 51.714285-21.428571 21.428572-51.714286z m-365.714286-365.714285q0-30.285714-21.428571-51.714286T512 219.428571t-51.714286 21.428572T438.857143 292.571429t21.428571 51.714285T512 365.714286t51.714286-21.428572T585.142857 292.571429z m256 109.714285q0-30.285714-21.428571-51.714285T768 329.142857t-51.714286 21.428572T694.857143 402.285714t21.428571 51.714286T768 475.428571t51.714286-21.428571T841.142857 402.285714z m182.857143 256q0 149.142857-80.571429 276-10.857143 16.571429-30.857142 16.571429H111.428571q-20 0-30.857142-16.571429Q0 808 0 658.285714q0-104 40.571429-198.857143t109.142857-163.428571 163.428571-109.142857 198.857143-40.571429 198.857143 40.571429 163.428571 109.142857 109.142857 163.428571 40.571429 198.857143z" p-id="5150" fill="#bfbfbf"></path></svg>
\ No newline at end of file
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="4695" t="1543827393750" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css">@font-face{font-family:rbicon;src:url(chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2) format(&quot;woff2&quot;);font-weight:400;font-style:normal}</style></defs><path d="M64 64V640H896V64H64zM0 0h960v704H0V0z" p-id="4696"/><path d="M192 896H768v64H192zM448 640H512v256h-64z" p-id="4697"/><path d="M479.232 561.604267l309.9904-348.330667-47.803733-42.5472-259.566934 291.669333L303.957333 240.008533 163.208533 438.6048l52.224 37.009067 91.6224-129.28z" p-id="4698"/></svg>
\ No newline at end of file
<<<<<<< HEAD
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200" class="icon" p-id="4695" t="1543827393750" version="1.1" viewBox="0 0 1024 1024"><defs><style type="text/css">@font-face{font-family:rbicon;src:url(chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2) format(&quot;woff2&quot;);font-weight:400;font-style:normal}</style></defs><path d="M64 64V640H896V64H64zM0 0h960v704H0V0z" p-id="4696"/><path d="M192 896H768v64H192zM448 640H512v256h-64z" p-id="4697"/><path d="M479.232 561.604267l309.9904-348.330667-47.803733-42.5472-259.566934 291.669333L303.957333 240.008533 163.208533 438.6048l52.224 37.009067 91.6224-129.28z" p-id="4698"/></svg>
=======
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1572170613674" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12819" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400"><defs><style type="text/css"></style></defs><path d="M932 848H120V148c0-15.5-12.5-28-28-28s-28 12.5-28 28v700c0 30.9 25.1 56 56 56h812c15.5 0 28-12.5 28-28s-12.5-28-28-28z" p-id="12820" fill="#bfbfbf"></path><path d="M204 652h66.7c21.3 0 40.5-11.8 50.1-31l26.6-53.4 54.9 82.3c10.5 15.8 27.9 25 46.5 25 2.1 0 4.3-0.2 6.4-0.4 21-2.4 38.7-16.2 46.1-36L625.6 307l133.3 311c8.9 20.6 29 33.9 51.5 33.9H876c15.5 0 28-12.5 28-28s-12.5-28-28-28h-65.5L677.2 285c-8.9-20.7-28.9-33.9-51.4-33.9h-1.4c-23 0.5-43 14.8-51.1 36.3L449 619l-55-82.4c-11.2-16.8-30-26-50-24.8-20.1 1.3-37.6 12.8-46.6 30.8L270.7 596H204c-15.5 0-28 12.5-28 28s12.5 28 28 28z" p-id="12821" fill="#bfbfbf"></path></svg>
>>>>>>> 2.3dev
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="211.719" height="200" class="icon" p-id="10233" t="1543827724451" version="1.1" viewBox="0 0 1084 1024"><defs><style type="text/css">@font-face{font-family:rbicon;src:url(chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2) format(&quot;woff2&quot;);font-weight:400;font-style:normal}</style></defs><path fill="#bfbfbf" d="M1080.09609 434.500756c-4.216302-23.731757-26.9241-47.945376-50.595623-53.185637l-17.648235-4.095836a175.940257 175.940257 0 0 1-101.612877-80.832531 177.807476 177.807476 0 0 1-18.732427-129.801867l5.541425-16.684509c7.10748-23.129428-2.108151-54.992624-20.599646-70.833873 0 0-16.624276-14.094495-63.244529-41.199293-46.800951-26.984332-66.858502-34.513443-66.858502-34.513443-22.76803-8.372371-54.631227-0.361397-71.255503 17.407304l-12.287509 13.251234a173.470708 173.470708 0 0 1-120.465769 48.065842A174.13327 174.13327 0 0 1 421.329029 33.590675L409.583617 20.761071C393.140039 2.99237 361.096144-4.898138 338.267881 3.353767c0 0-20.358715 7.529111-67.099434 34.513443-46.800951 27.34573-63.244529 41.440225-63.244529 41.440225-18.431263 15.66055-27.646894 47.222582-20.539413 70.592941l5.059562 16.865207a178.048407 178.048407 0 0 1-18.672194 129.621169 174.916297 174.916297 0 0 1-102.275439 81.073463l-17.045906 3.854904c-23.310126 5.42096-46.258856 29.333415-50.595623 53.185637 0 0-3.854905 21.382674-3.854905 75.712737 0 54.330062 3.854905 75.712736 3.854905 75.712736 4.216302 23.972688 26.9241 47.945376 50.595623 53.185637l16.624276 3.854905a174.253736 174.253736 0 0 1 102.395904 81.314394c23.310126 40.837896 28.911785 87.337683 18.732427 129.801867l-4.81863 16.443578c-7.10748 23.129428 2.108151 54.992624 20.599646 70.833872 0 0 16.624276 14.094495 63.244529 41.199293 46.800951 27.104798 66.918735 34.513443 66.918735 34.513443 22.707798 8.372371 54.631227 0.361397 71.255503-17.407303l11.624947-12.588673a175.096996 175.096996 0 0 1 242.256662 0.120465l11.624947 12.648906c16.383345 17.708468 48.427239 25.598976 71.255503 17.347071 0 0 20.358715-7.529111 67.159666-34.513443 46.740719-27.104798 63.124063-41.199293 63.124064-41.199293 18.491496-15.600317 27.707127-47.463513 20.599646-70.833873l-5.059562-17.106139a176.723284 176.723284 0 0 1 18.672194-129.139305 176.060722 176.060722 0 0 1 102.395904-81.314394l16.68451-3.854905c23.310126-5.42096 46.258856-29.333415 50.595623-53.185637 0 0 3.854905-21.382674 3.854904-75.712737-0.240932-54.330062-4.095836-75.833202-4.095836-75.833202z m-537.819428 293.334149c-119.261112 0-216.175824-97.336342-216.175824-217.621412a216.657687 216.657687 0 0 1 216.236057-217.320249c119.200879 0 216.115591 97.276109 216.11559 217.56118-0.240932 120.044139-96.974945 217.320248-216.175823 217.320249z" p-id="10234"/></svg>
\ No newline at end of file
<<<<<<< HEAD
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="211.719" height="200" class="icon" p-id="10233" t="1543827724451" version="1.1" viewBox="0 0 1084 1024"><defs><style type="text/css">@font-face{font-family:rbicon;src:url(chrome-extension://dipiagiiohfljcicegpgffpbnjmgjcnf/fonts/rbicon.woff2) format(&quot;woff2&quot;);font-weight:400;font-style:normal}</style></defs><path fill="#bfbfbf" d="M1080.09609 434.500756c-4.216302-23.731757-26.9241-47.945376-50.595623-53.185637l-17.648235-4.095836a175.940257 175.940257 0 0 1-101.612877-80.832531 177.807476 177.807476 0 0 1-18.732427-129.801867l5.541425-16.684509c7.10748-23.129428-2.108151-54.992624-20.599646-70.833873 0 0-16.624276-14.094495-63.244529-41.199293-46.800951-26.984332-66.858502-34.513443-66.858502-34.513443-22.76803-8.372371-54.631227-0.361397-71.255503 17.407304l-12.287509 13.251234a173.470708 173.470708 0 0 1-120.465769 48.065842A174.13327 174.13327 0 0 1 421.329029 33.590675L409.583617 20.761071C393.140039 2.99237 361.096144-4.898138 338.267881 3.353767c0 0-20.358715 7.529111-67.099434 34.513443-46.800951 27.34573-63.244529 41.440225-63.244529 41.440225-18.431263 15.66055-27.646894 47.222582-20.539413 70.592941l5.059562 16.865207a178.048407 178.048407 0 0 1-18.672194 129.621169 174.916297 174.916297 0 0 1-102.275439 81.073463l-17.045906 3.854904c-23.310126 5.42096-46.258856 29.333415-50.595623 53.185637 0 0-3.854905 21.382674-3.854905 75.712737 0 54.330062 3.854905 75.712736 3.854905 75.712736 4.216302 23.972688 26.9241 47.945376 50.595623 53.185637l16.624276 3.854905a174.253736 174.253736 0 0 1 102.395904 81.314394c23.310126 40.837896 28.911785 87.337683 18.732427 129.801867l-4.81863 16.443578c-7.10748 23.129428 2.108151 54.992624 20.599646 70.833872 0 0 16.624276 14.094495 63.244529 41.199293 46.800951 27.104798 66.918735 34.513443 66.918735 34.513443 22.707798 8.372371 54.631227 0.361397 71.255503-17.407303l11.624947-12.588673a175.096996 175.096996 0 0 1 242.256662 0.120465l11.624947 12.648906c16.383345 17.708468 48.427239 25.598976 71.255503 17.347071 0 0 20.358715-7.529111 67.159666-34.513443 46.740719-27.104798 63.124063-41.199293 63.124064-41.199293 18.491496-15.600317 27.707127-47.463513 20.599646-70.833873l-5.059562-17.106139a176.723284 176.723284 0 0 1 18.672194-129.139305 176.060722 176.060722 0 0 1 102.395904-81.314394l16.68451-3.854905c23.310126-5.42096 46.258856-29.333415 50.595623-53.185637 0 0 3.854905-21.382674 3.854904-75.712737-0.240932-54.330062-4.095836-75.833202-4.095836-75.833202z m-537.819428 293.334149c-119.261112 0-216.175824-97.336342-216.175824-217.621412a216.657687 216.657687 0 0 1 216.236057-217.320249c119.200879 0 216.115591 97.276109 216.11559 217.56118-0.240932 120.044139-96.974945 217.320248-216.175823 217.320249z" p-id="10234"/></svg>
=======
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1572170574070" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="12584" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400"><defs><style type="text/css"></style></defs><path d="M921.6 102.4H102.4a68.266667 68.266667 0 0 0-68.266667 68.266667v546.133333a68.266667 68.266667 0 0 0 68.266667 68.266667h375.466667v68.266666h-136.533334a34.133333 34.133333 0 0 0 0 68.266667h341.333334a34.133333 34.133333 0 0 0 0-68.266667h-136.533334v-68.266666h375.466667a68.266667 68.266667 0 0 0 68.266667-68.266667V170.666667a68.266667 68.266667 0 0 0-68.266667-68.266667z m0 68.266667v443.733333H102.4V170.666667zM102.4 716.8v-34.133333h819.2v34.133333z" p-id="12585" fill="#bfbfbf"></path><path d="M204.8 546.133333a32.085333 32.085333 0 0 0 18.773333-5.802666L409.6 415.744l152.234667 91.477333a34.133333 34.133333 0 0 0 37.205333 0l238.933333-170.666666a34.133333 34.133333 0 1 0-39.594666-55.296L580.266667 437.248l-151.552-91.136a34.133333 34.133333 0 0 0-36.181334 0l-204.8 136.533333A34.133333 34.133333 0 0 0 204.8 546.133333z" p-id="12586" fill="#bfbfbf"></path></svg>
>>>>>>> 2.3dev
......@@ -5,6 +5,11 @@
<div class="right-menu">
<template v-if="device!=='mobile'">
<el-tooltip content="源码地址" effect="dark" placement="bottom">
<Github class="screenfull right-menu-item"/>
</el-tooltip>
</template>
<template v-if="device!=='mobile'">
<el-tooltip content="全屏" effect="dark" placement="bottom">
<screenfull class="screenfull right-menu-item"/>
</el-tooltip>
......@@ -46,12 +51,14 @@ import { mapGetters } from 'vuex'
import Breadcrumb from '@/components/Breadcrumb'
import Hamburger from '@/components/Hamburger'
import Screenfull from '@/components/Screenfull'
import Github from '@/components/Github'
import Avatar from '@/assets/avatar/avatar.png'
export default {
components: {
Breadcrumb,
Hamburger,
Screenfull
Screenfull,
Github
},
data() {
return {
......
......@@ -10,22 +10,24 @@ import '@/styles/index.scss' // global css
import App from './App'
import router from './router/routers'
import permission from './components/permission'
import permission from './components/Permission'
import dict from './components/Dict'
import store from './store'
import '@/icons' // icon
import './router/index' // permission control
// import Router from 'vue-router'
import Router from 'vue-router'
Vue.use(mavonEditor)
Vue.use(permission)
Vue.use(dict)
Vue.use(ElementUI, { locale })
Vue.config.productionTip = false
// const routerPush = Router.prototype.push
// Router.prototype.push = function push(location) {
// return routerPush.call(this, location).catch(error => error)
// }
const routerPush = Router.prototype.push
Router.prototype.push = function push(location) {
return routerPush.call(this, location).catch(error => error)
}
require('babel-polyfill')
new Vue({
......
......@@ -3,7 +3,7 @@ import { initData } from '@/api/data'
export default {
data() {
return {
loading: true, data: [], page: 0, size: 10, total: 0, url: '', params: {}, query: {}, time: 170, isAdd: false
loading: true, data: [], page: 0, size: 10, total: 0, url: '', params: {}, query: {}, time: 50, isAdd: false, downloadLoading: false
}
},
methods: {
......
import { login, getInfo } from '@/api/login'
import { login, getInfo, logout } from '@/api/login'
import { getToken, setToken, removeToken } from '@/utils/auth'
import { decrypt } from '@/utils/rsaEncrypt'
......@@ -63,10 +63,13 @@ const user = {
// 登出
LogOut({ commit }) {
return new Promise((resolve, reject) => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
resolve()
logout().then(res => {
logOut(commit)
resolve()
}).catch(error => {
logOut(commit)
reject(error)
})
})
},
......@@ -78,6 +81,12 @@ const user = {
}
}
export const logOut = (commit) => {
commit('SET_TOKEN', '')
commit('SET_ROLES', [])
removeToken()
}
export const setUserInfo = (res, commit) => {
// 如果没有任何权限,则赋予一个默认的权限,避免请求死循环
if (res.roles.length === 0) {
......
......@@ -3,13 +3,13 @@
.main-container {
min-height: 100%;
transition: margin-left .28s;
margin-left: 180px;
margin-left: 195px;
position: relative;
}
// 侧边栏
.sidebar-container {
transition: width 0.28s;
width: 180px !important;
width: 195px !important;
height: 100%;
position: fixed;
font-size: 0px;
......@@ -90,14 +90,14 @@
}
.sidebar-container .nest-menu .el-submenu>.el-submenu__title,
.sidebar-container .el-submenu .el-menu-item {
min-width: 180px !important;
min-width: 195px !important;
background-color: $subMenuBg !important;
&:hover {
background-color: $menuHover !important;
}
}
.el-menu--collapse .el-menu .el-submenu {
min-width: 180px !important;
min-width: 195px !important;
}
//适配移动端
......@@ -107,12 +107,12 @@
}
.sidebar-container {
transition: transform .28s;
width: 180px !important;
width: 195px !important;
}
&.hideSidebar {
.sidebar-container {
transition-duration: 0.3s;
transform: translate3d(-180px, 0, 0);
transform: translate3d(-195px, 0, 0);
}
}
}
......
......@@ -9,7 +9,7 @@ $menuHover:#263445;
$subMenuBg:#1f2d3d;
$subMenuHover:#001528;
$sideBarWidth: 180px;
$sideBarWidth: 193px;
$hideSidebarWidth: 38px;
......
......@@ -81,7 +81,7 @@ service.interceptors.response.use(
if (errorMsg !== undefined) {
Notification.error({
title: errorMsg,
duration: 2500
duration: 3000
})
}
}
......
<template>
<div>
<el-button type="primary" size="mini" @click="toGen">生成代码</el-button>
<el-dialog :visible.sync="dialog" :close-on-click-modal="false" :before-close="cancel" title="代码生成配置" append-to-body width="850px">
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="78px">
<el-dialog :visible.sync="dialog" :close-on-click-modal="false" :before-close="cancel" title="代码生成配置" append-to-body width="880px">
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="90px">
<el-form-item label="模块名称" prop="moduleName">
<el-input v-model="form.moduleName"/>
</el-form-item>
......
......@@ -79,7 +79,7 @@ export default {
methods: {
getCode() {
getCodeImg().then(res => {
this.codeUrl = 'data:image/gif;base64,' + res.img
this.codeUrl = res.img
this.loginForm.uuid = res.uuid
})
},
......@@ -155,7 +155,7 @@ export default {
.login-form {
border-radius: 6px;
background: #ffffff;
width: 400px;
width: 385px;
padding: 25px 25px 5px 25px;
.el-input {
height: 38px;
......
......@@ -3,12 +3,23 @@
<Search :query="query"/>
<!--表格渲染-->
<el-table v-loading="loading" :data="data" size="small" style="width: 100%;">
<el-table-column type="expand">
<template slot-scope="props">
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item label="请求方法">
<span>{{ props.row.method }}</span>
</el-form-item>
<el-form-item label="请求参数">
<span>{{ props.row.params }}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column prop="username" label="用户名"/>
<el-table-column prop="requestIp" label="IP"/>
<el-table-column :show-overflow-tooltip="true" prop="address" label="IP来源"/>
<el-table-column prop="description" label="描述"/>
<el-table-column :show-overflow-tooltip="true" prop="method" label="方法名称"/>
<el-table-column :show-overflow-tooltip="true" prop="params" label="参数"/>
<el-table-column prop="browser" label="浏览器"/>
<el-table-column prop="createTime" label="创建日期">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
......@@ -21,9 +32,9 @@
</el-table-column>
</el-table>
<el-dialog :visible.sync="dialog" title="异常详情" append-to-body top="0" width="85%">
<span>
<pre>
{{ errorInfo }}
</span>
</pre>
</el-dialog>
<!--分页组件-->
<el-pagination
......@@ -64,6 +75,11 @@ export default {
const value = query.value
this.params = { page: this.page, size: this.size, sort: sort }
if (value) { this.params['blurry'] = value }
this.params['logType'] = 'ERROR'
if (query.date) {
this.params['startTime'] = query.date[0]
this.params['endTime'] = query.date[1]
}
return true
},
info(id) {
......@@ -76,6 +92,21 @@ export default {
}
</script>
<style scoped>
<style>
.demo-table-expand {
font-size: 0;
}
.demo-table-expand label {
width: 70px;
color: #99a9bf;
}
.demo-table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 100%;
}
.demo-table-expand .el-form-item__content {
font-size: 12px;
}
</style>
......@@ -3,12 +3,23 @@
<Search :query="query"/>
<!--表格渲染-->
<el-table v-loading="loading" :data="data" size="small" style="width: 100%;">
<el-table-column type="expand">
<template slot-scope="props">
<el-form label-position="left" inline class="demo-table-expand">
<el-form-item label="请求方法">
<span>{{ props.row.method }}</span>
</el-form-item>
<el-form-item label="请求参数">
<span>{{ props.row.params }}</span>
</el-form-item>
</el-form>
</template>
</el-table-column>
<el-table-column prop="username" label="用户名"/>
<el-table-column prop="requestIp" label="IP"/>
<el-table-column :show-overflow-tooltip="true" prop="address" label="IP来源"/>
<el-table-column prop="description" label="描述"/>
<el-table-column :show-overflow-tooltip="true" prop="method" label="方法名称"/>
<el-table-column :show-overflow-tooltip="true" prop="params" label="参数"/>
<el-table-column prop="browser" label="浏览器"/>
<el-table-column prop="time" label="请求耗时" align="center">
<template slot-scope="scope">
<el-tag v-if="scope.row.time <= 300">{{ scope.row.time }}ms</el-tag>
......@@ -55,12 +66,32 @@ export default {
const value = query.value
this.params = { page: this.page, size: this.size, sort: sort }
if (value) { this.params['blurry'] = value }
this.params['logType'] = 'INFO'
if (query.date) {
this.params['startTime'] = query.date[0]
this.params['endTime'] = query.date[1]
}
return true
}
}
}
</script>
<style scoped>
<style>
.demo-table-expand {
font-size: 0;
}
.demo-table-expand label {
width: 70px;
color: #99a9bf;
}
.demo-table-expand .el-form-item {
margin-right: 0;
margin-bottom: 0;
width: 100%;
}
.demo-table-expand .el-form-item__content {
font-size: 12px;
}
</style>
<template>
<div class="head-container">
<el-input v-model="query.value" clearable placeholder="请输入你要搜索的内容" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-date-picker
v-model="query.date"
type="daterange"
range-separator=":"
class="el-range-editor--small filter-item"
style="height: 30.5px;width: 220px"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"/>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="$parent.toQuery">搜索</el-button>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-download"
@click="download">导出</el-button>
</div>
</div>
</template>
<script>
import { downloadFile } from '@/utils/index'
import { downloadLog } from '@/api/log'
export default {
props: {
query: {
type: Object,
required: true
}
},
data() {
return {
downloadLoading: false
}
},
methods: {
download() {
this.$parent.beforeInit()
this.downloadLoading = true
downloadLog(this.$parent.params).then(result => {
downloadFile(result, '系统日志列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
</script>
<template>
<div class="app-container">
<div class="head-container">
<el-input v-model="query.value" clearable placeholder="全表模糊搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-download"
@click="download">导出</el-button>
</div>
</div>
<!--表格渲染-->
<el-table v-loading="loading" :data="data" size="small" style="width: 100%;">
<el-table-column prop="userName" label="用户名"/>
<el-table-column prop="job" label="岗位"/>
<el-table-column prop="ip" label="登录IP"/>
<el-table-column :show-overflow-tooltip="true" prop="address" label="登录地点"/>
<el-table-column prop="browser" label="浏览器"/>
<el-table-column prop="loginTime" label="登录时间">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.loginTime) }}</span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="操作" width="100px">
<template slot-scope="scope">
<el-popover
v-permission="['admin']"
:ref="scope.$index"
placement="top"
width="180">
<p>确定踢出该用户吗?</p>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="$refs[scope.$index].doClose()">取消</el-button>
<el-button :loading="delLoading" type="primary" size="mini" @click="subDelete(scope.$index, scope.row.key)">确定</el-button>
</div>
<el-button slot="reference" size="mini" type="text">踢出</el-button>
</el-popover>
</template>
</el-table-column>
</el-table>
<!--分页组件-->
<el-pagination
:total="total"
:current-page="page + 1"
style="margin-top: 8px;"
layout="total, prev, pager, next, sizes"
@size-change="sizeChange"
@current-change="pageChange"/>
</div>
</template>
<script>
import initData from '@/mixins/initData'
import { parseTime, downloadFile } from '@/utils/index'
import { del, downloadOnline } from '@/api/online'
export default {
name: 'OnlineUser',
mixins: [initData],
data() {
return {
delLoading: false
}
},
created() {
this.$nextTick(() => {
this.init()
})
},
methods: {
parseTime,
beforeInit() {
this.url = 'auth/online'
this.params = { page: this.page, size: this.size }
if (this.query.value) { this.params['filter'] = this.query.value }
return true
},
subDelete(index, key) {
this.delLoading = true
del(key).then(res => {
this.delLoading = false
this.$refs[index].doClose()
this.dleChangePage()
this.init()
this.$notify({
title: '踢出成功',
type: 'success',
duration: 2500
})
}).catch(err => {
this.delLoading = false
this.$refs[index].doClose()
console.log(err.response.data.message)
})
},
download() {
this.beforeInit()
this.downloadLoading = true
downloadOnline(this.params).then(result => {
downloadFile(result, '在线用户列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
</script>
......@@ -7,16 +7,21 @@
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<div style="display: inline-block;">
<!-- 清空缓存 -->
<el-button v-permission="['ADMIN','REDIS_ALL','REDIS_DELETE']" :loading="deleteAllLoading" type="warning" size="mini" class="filter-item" icon="el-icon-delete" @click="deleteAll">清空缓存</el-button>
<el-button v-permission="['admin','redis:del']" :loading="deleteAllLoading" type="danger" size="mini" class="filter-item" icon="el-icon-delete" @click="deleteAll">清空</el-button>
</div>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-download"
@click="download">导出</el-button>
</div>
</div>
<!--表格渲染-->
<el-table v-loading="loading" :data="data" size="small" style="width: 100%;">
<el-table-column label="序号" width="80" align="center">
<template slot-scope="scope">
<div>{{ scope.$index + 1 }}</div>
</template>
</el-table-column>
<el-table-column :show-overflow-tooltip="true" prop="key" label="KEY"/>
<el-table-column prop="value" label="VALUE">
<template slot-scope="scope">
......@@ -25,10 +30,10 @@
</div>
</template>
</el-table-column>
<el-table-column v-if="checkPermission(['ADMIN','REDIS_ALL','REDIS_EDIT','REDIS_DELETE'])" label="操作" width="130px" align="center" fixed="right">
<el-table-column v-if="checkPermission(['admin','redis:del'])" label="操作" width="130px" align="center" fixed="right">
<template slot-scope="scope">
<el-popover
v-permission="['ADMIN','REDIS_ALL','REDIS_DELETE']"
v-permission="['admin','redis:del']"
:ref="scope.$index"
placement="top"
width="180">
......@@ -56,7 +61,8 @@
<script>
import checkPermission from '@/utils/permission' // 权限判断函数
import initData from '@/mixins/initData'
import { del, delAll } from '@/api/redis'
import { del, delAll, downloadRedis } from '@/api/redis'
import { downloadFile } from '@/utils/index'
export default {
name: 'Redis',
mixins: [initData],
......@@ -115,6 +121,16 @@ export default {
this.deleteAllLoading = false
})
})
},
download() {
this.beforeInit()
this.downloadLoading = true
downloadRedis(this.params).then(result => {
downloadFile(result, '缓存列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
......
......@@ -3,7 +3,7 @@
</template>
<script>
import { mapGetters } from 'vuex'
import elFrame from '@/components/iframe/index'
import elFrame from '@/components/Iframe/index'
export default {
name: 'Sql',
components: { elFrame },
......
......@@ -4,12 +4,21 @@
<div class="head-container">
<!-- 搜索 -->
<el-input v-model="query.value" clearable placeholder="输入部门名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-date-picker
v-model="query.date"
type="daterange"
range-separator=":"
class="el-range-editor--small filter-item"
style="height: 30.5px;width: 220px"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"/>
<el-select v-model="query.enabled" clearable placeholder="状态" class="filter-item" style="width: 90px" @change="toQuery">
<el-option v-for="item in enabledTypeOptions" :key="item.key" :label="item.display_name" :value="item.key"/>
</el-select>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<!-- 新增 -->
<div v-permission="['ADMIN','DEPT_ALL','DEPT_CREATE']" style="display: inline-block;margin: 0px 2px;">
<div v-permission="['admin','dept:add']" style="display: inline-block;margin: 0px 2px;">
<el-button
class="filter-item"
size="mini"
......@@ -17,25 +26,30 @@
icon="el-icon-plus"
@click="add">新增</el-button>
</div>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
class="filter-item"
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-more"
@click="changeExpand">{{ expand ? '折叠' : '展开' }}</el-button>
<eForm ref="form" :is-add="true" :dicts="dicts"/>
icon="el-icon-download"
@click="download">导出</el-button>
</div>
</div>
<!--表单组件-->
<eForm ref="form" :is-add="isAdd" :dicts="dicts"/>
<eForm ref="form" :is-add="isAdd" :dicts="dict.dept_status"/>
<!--表格渲染-->
<tree-table v-loading="loading" :expand-all="expand" :data="data" :columns="columns" size="small">
<el-table v-loading="loading" :tree-props="{children: 'children', hasChildren: 'hasChildren'}" :default-expand-all="expand" :data="data" row-key="id" size="small">
<el-table-column label="名称" prop="name"/>
<el-table-column label="状态" align="center">
<template slot-scope="scope">
<div v-for="item in dicts" :key="item.id">
<el-tag v-if="scope.row.enabled.toString() === item.value" :type="scope.row.enabled ? '' : 'info'">{{ item.label }}</el-tag>
</div>
<el-switch
v-model="scope.row.enabled"
:disabled="scope.row.id == 1"
active-color="#409EFF"
inactive-color="#F56C6C"
@change="changeEnabled(scope.row, scope.row.enabled,)"/>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建日期">
......@@ -43,11 +57,11 @@
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column v-if="checkPermission(['ADMIN','DEPT_ALL','DEPT_EDIT','DEPT_DELETE'])" label="操作" width="130px" align="center" fixed="right">
<el-table-column v-if="checkPermission(['admin','dept:edit','dept:del'])" label="操作" width="130px" align="center" fixed="right">
<template slot-scope="scope">
<el-button v-permission="['ADMIN','DEPT_ALL','DEPT_EDIT']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-button v-permission="['admin','dept:edit']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-popover
v-permission="['ADMIN','DEPT_ALL','DEPT_DELETE']"
v-permission="['admin','dept:del']"
:ref="scope.row.id"
placement="top"
width="180">
......@@ -60,30 +74,24 @@
</el-popover>
</template>
</el-table-column>
</tree-table>
</el-table>
</div>
</template>
<script>
import treeTable from '@/components/TreeTable'
import checkPermission from '@/utils/permission'
import initData from '@/mixins/initData'
import initDict from '@/mixins/initDict'
import { del } from '@/api/dept'
import { parseTime } from '@/utils/index'
import { del, edit, downloadDept } from '@/api/dept'
import { parseTime, downloadFile } from '@/utils/index'
import eForm from './form'
export default {
name: 'Dept',
components: { eForm, treeTable },
mixins: [initData, initDict],
components: { eForm },
mixins: [initData],
// 设置数据字典
dicts: ['dept_status'],
data() {
return {
columns: [
{
text: '名称',
value: 'name'
}
],
enabledTypeOptions: [
{ key: 'true', display_name: '正常' },
{ key: 'false', display_name: '禁用' }
......@@ -94,8 +102,6 @@ export default {
created() {
this.$nextTick(() => {
this.init()
// 加载数据字典
this.getDict('dept_status')
})
},
methods: {
......@@ -109,6 +115,10 @@ export default {
const value = query.value
const enabled = query.enabled
if (value) { this.params['name'] = value }
if (query.date) {
this.params['startTime'] = query.date[0]
this.params['endTime'] = query.date[1]
}
if (enabled !== '' && enabled !== null) { this.params['enabled'] = enabled }
return true
},
......@@ -137,7 +147,6 @@ export default {
},
changeExpand() {
this.expand = !this.expand
this.init()
},
edit(data) {
this.isAdd = false
......@@ -151,6 +160,37 @@ export default {
enabled: data.enabled.toString()
}
_this.dialog = true
},
// 改变状态
changeEnabled(data, val) {
this.$confirm('此操作将 "' + this.dict.label.dept_status[val] + '" ' + data.name + '部门, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
edit(data).then(res => {
this.$notify({
title: this.dict.label.dept_status[val] + '成功',
type: 'success',
duration: 2500
})
}).catch(err => {
data.enabled = !data.enabled
console.log(err.response.data.message)
})
}).catch(() => {
data.enabled = !data.enabled
})
},
download() {
this.beforeInit()
this.downloadLoading = true
downloadDept(this.params).then(result => {
downloadFile(result, '部门列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
......
......@@ -8,7 +8,7 @@
<div slot="header" class="clearfix">
<span>字典列表</span>
<el-button
v-permission="['ADMIN','DICT_ALL','DICT_CREATE']"
v-permission="['admin','dict:add']"
class="filter-item"
size="mini"
style="float: right;padding: 4px 10px"
......@@ -21,16 +21,26 @@
<!-- 搜索 -->
<el-input v-model="query.value" clearable placeholder="输入名称或者描述搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-download"
@click="download">导出</el-button>
</div>
</div>
<!--表格渲染-->
<el-table v-loading="loading" :data="data" size="small" highlight-current-row style="width: 100%;" @current-change="handleCurrentChange">
<el-table-column :show-overflow-tooltip="true" prop="name" label="名称"/>
<el-table-column :show-overflow-tooltip="true" prop="remark" label="描述"/>
<el-table-column v-if="checkPermission(['ADMIN','DICT_ALL','DICT_EDIT','DICT_DELETE'])" label="操作" width="130px" align="center" fixed="right">
<el-table-column v-if="checkPermission(['admin','dict:edit','dict:del'])" label="操作" width="130px" align="center" fixed="right">
<template slot-scope="scope">
<el-button v-permission="['ADMIN','DICT_ALL','DICT_EDIT']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-button v-permission="['admin','dict:edit']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-popover
v-permission="['ADMIN','DICT_ALL','DICT_DELETE']"
v-permission="['admin','dict:del']"
:ref="scope.row.id"
placement="top"
width="180">
......@@ -59,7 +69,7 @@
<div slot="header" class="clearfix">
<span>字典详情</span>
<el-button
v-if="checkPermission(['ADMIN','DICT_ALL','DICT_CREATE']) && this.$refs.dictDetail && this.$refs.dictDetail.dictName"
v-if="checkPermission(['admin','dict:add']) && this.$refs.dictDetail && this.$refs.dictDetail.dictName"
class="filter-item"
size="mini"
style="float: right;padding: 4px 10px"
......@@ -77,8 +87,9 @@
<script>
import checkPermission from '@/utils/permission'
import initData from '@/mixins/initData'
import { del } from '@/api/dict'
import { del, downloadDict } from '@/api/dict'
import dictDetail from '../dictDetail/index'
import { downloadFile } from '@/utils/index'
import eForm from './form'
export default {
name: 'Dict',
......@@ -147,6 +158,16 @@ export default {
remark: data.remark
}
_this.dialog = true
},
download() {
this.beforeInit()
this.downloadLoading = true
downloadDict(this.params).then(result => {
downloadFile(result, '字典列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
......
......@@ -22,11 +22,11 @@
<el-table-column prop="label" label="字典标签"/>
<el-table-column prop="value" label="字典值"/>
<el-table-column prop="sort" label="排序"/>
<el-table-column v-if="checkPermission(['ADMIN','DICT_ALL','DICT_EDIT','DICT_DELETE'])" label="操作" width="130px" align="center" fixed="right">
<el-table-column v-if="checkPermission(['admin','dict:edit','dict:del'])" label="操作" width="130px" align="center" fixed="right">
<template slot-scope="scope">
<el-button v-permission="['ADMIN','DICT_ALL','DICT_EDIT']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-button v-permission="['admin','dict:edit']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-popover
v-permission="['ADMIN','DICT_ALL','DICT_DELETE']"
v-permission="['admin','dict:del']"
:ref="scope.row.id"
placement="top"
width="180">
......
......@@ -4,12 +4,21 @@
<div class="head-container">
<!-- 搜索 -->
<el-input v-model="query.value" clearable placeholder="输入岗位名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-date-picker
v-model="query.date"
type="daterange"
range-separator=":"
class="el-range-editor--small filter-item"
style="height: 30.5px;width: 220px"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"/>
<el-select v-model="query.enabled" clearable placeholder="状态" class="filter-item" style="width: 90px" @change="toQuery">
<el-option v-for="item in enabledTypeOptions" :key="item.key" :label="item.display_name" :value="item.key"/>
</el-select>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<!-- 新增 -->
<div v-permission="['ADMIN','USERJOB_ALL','USERJOB_CREATE']" style="display: inline-block;margin: 0px 2px;">
<div v-permission="['admin','job:add']" style="display: inline-block;margin: 0px 2px;">
<el-button
class="filter-item"
size="mini"
......@@ -17,9 +26,19 @@
icon="el-icon-plus"
@click="add">新增</el-button>
</div>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-download"
@click="download">导出</el-button>
</div>
</div>
<!--表单组件-->
<eForm ref="form" :is-add="isAdd" :dicts="dicts"/>
<eForm ref="form" :is-add="isAdd" :dicts="dict.job_status"/>
<!--表格渲染-->
<el-table v-loading="loading" :data="data" size="small" style="width: 100%;">
<el-table-column prop="name" label="名称"/>
......@@ -35,9 +54,11 @@
</el-table-column>
<el-table-column label="状态" align="center">
<template slot-scope="scope">
<div v-for="item in dicts" :key="item.id">
<el-tag v-if="scope.row.enabled.toString() === item.value" :type="scope.row.enabled ? '' : 'info'">{{ item.label }}</el-tag>
</div>
<el-switch
v-model="scope.row.enabled"
active-color="#409EFF"
inactive-color="#F56C6C"
@change="changeEnabled(scope.row, scope.row.enabled,)"/>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建日期">
......@@ -45,11 +66,11 @@
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column v-if="checkPermission(['ADMIN','USERJOB_ALL','USERJOB_EDIT','USERJOB_DELETE'])" label="操作" width="130px" align="center" fixed="right">
<el-table-column v-if="checkPermission(['admin','job:edit','job:del'])" label="操作" width="130px" align="center" fixed="right">
<template slot-scope="scope">
<el-button v-permission="['ADMIN','USERJOB_ALL','USERJOB_EDIT']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-button v-permission="['admin','job:edit']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-popover
v-permission="['ADMIN','USERJOB_ALL','USERJOB_DELETE']"
v-permission="['admin','job:del']"
:ref="scope.row.id"
placement="top"
width="180">
......@@ -77,14 +98,15 @@
<script>
import checkPermission from '@/utils/permission'
import initData from '@/mixins/initData'
import initDict from '@/mixins/initDict'
import { del } from '@/api/job'
import { parseTime } from '@/utils/index'
import { del, edit, downloadJob } from '@/api/job'
import { parseTime, downloadFile } from '@/utils/index'
import eForm from './form'
export default {
name: 'Job',
components: { eForm },
mixins: [initData, initDict],
mixins: [initData],
// 设置数据字典
dicts: ['job_status'],
data() {
return {
delLoading: false,
......@@ -97,8 +119,6 @@ export default {
created() {
this.$nextTick(() => {
this.init()
// 加载数据字典
this.getDict('job_status')
})
},
methods: {
......@@ -112,6 +132,10 @@ export default {
const value = query.value
const enabled = query.enabled
if (value) { this.params['name'] = value }
if (query.date) {
this.params['startTime'] = query.date[0]
this.params['endTime'] = query.date[1]
}
if (enabled !== '' && enabled !== null) { this.params['enabled'] = enabled }
return true
},
......@@ -152,6 +176,37 @@ export default {
}
_this.deptId = data.dept.id
_this.dialog = true
},
// 改变状态
changeEnabled(data, val) {
this.$confirm('此操作将 "' + this.dict.label.job_status[val] + '" ' + data.name + '岗位, 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
edit(data).then(res => {
this.$notify({
title: this.dict.label.job_status[val] + '成功',
type: 'success',
duration: 2500
})
}).catch(err => {
data.enabled = !data.enabled
console.log(err.response.data.message)
})
}).catch(() => {
data.enabled = !data.enabled
})
},
download() {
this.beforeInit()
this.downloadLoading = true
downloadJob(this.params).then(result => {
downloadFile(result, '岗位列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
......
<template>
<el-dialog :visible.sync="dialog" :close-on-click-modal="false" :before-close="cancel" :title="isAdd ? '新增菜单' : '编辑菜单'" append-to-body width="585px">
<el-dialog :visible.sync="dialog" :close-on-click-modal="false" :before-close="cancel" :title="isAdd ? '新增菜单' : '编辑菜单'" append-to-body width="580px">
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="80px">
<el-form-item label="菜单图标">
<el-form-item label="菜单类型">
<el-radio-group v-model="form.type" size="mini" style="width: 178px">
<el-radio-button label="0">目录</el-radio-button>
<el-radio-button label="1">菜单</el-radio-button>
<el-radio-button label="2">按钮</el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item v-show="form.type.toString() !== '2'" label="菜单图标">
<el-popover
placement="bottom-start"
width="450"
......@@ -14,38 +21,44 @@
</el-input>
</el-popover>
</el-form-item>
<el-form-item label="菜单名称" prop="name">
<el-input v-model="form.name" placeholder="名称" style="width: 450px;"/>
</el-form-item>
<el-form-item label="内部菜单">
<el-form-item v-show="form.type.toString() === '1'" label="外链菜单">
<el-radio-group v-model="form.iframe" size="mini">
<el-radio-button label="false"></el-radio-button>
<el-radio-button label="true"></el-radio-button>
<el-radio-button label="true"></el-radio-button>
<el-radio-button label="false"></el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="是否缓存">
<el-form-item v-show="form.type.toString() === '1'" label="菜单缓存">
<el-radio-group v-model="form.cache" size="mini">
<el-radio-button label="true"></el-radio-button>
<el-radio-button label="false"></el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="是否隐藏">
<el-form-item v-show="form.type.toString() === '1'" label="菜单可见">
<el-radio-group v-model="form.hidden" size="mini">
<el-radio-button label="true"></el-radio-button>
<el-radio-button label="false"></el-radio-button>
</el-radio-group>
</el-form-item>
<el-form-item label="菜单排序" prop="sort">
<el-input-number v-model.number="form.sort" :min="0" :max="999" controls-position="right" style="width: 177px;"/>
<el-form-item v-show="form.type.toString() !== '2'" label="菜单标题" prop="name">
<el-input v-model="form.name" :style=" form.type.toString() === '0' ? 'width: 450px' : 'width: 178px'" placeholder="菜单标题"/>
</el-form-item>
<el-form-item label="链接地址" prop="path">
<el-input v-model="form.path" placeholder="链接地址" style="width: 177px;"/>
<el-form-item v-show="form.type.toString() === '2'" label="按钮名称">
<el-input v-model="form.name" placeholder="按钮名称" style="width: 178px;"/>
</el-form-item>
<el-form-item v-if="form.iframe === 'false'" label="组件路径">
<el-input v-model="form.component" placeholder="菜单路径"/>
<el-form-item v-show="form.type.toString() !== '0'" label="权限标识">
<el-input :disabled="form.iframe === 'true'" v-model="form.permission" placeholder="权限标识" style="width: 178px;"/>
</el-form-item>
<el-form-item v-if="form.iframe === 'false'" label="组件名称">
<el-input v-model="form.componentName" placeholder="匹配组件内Name字段"/>
<el-form-item v-if="form.type.toString() !== '2'" label="路由地址" prop="path">
<el-input v-model="form.path" placeholder="路由地址" style="width: 178px;"/>
</el-form-item>
<el-form-item label="菜单排序">
<el-input-number v-model.number="form.sort" :min="0" :max="999" controls-position="right" style="width: 178px;"/>
</el-form-item>
<el-form-item v-show="form.iframe === 'false' && form.type.toString() === '1'" label="组件名称">
<el-input v-model="form.componentName" style="width: 178px;" placeholder="匹配组件内Name字段"/>
</el-form-item>
<el-form-item v-show="form.iframe === 'false' && form.type.toString() === '1'" label="组件路径">
<el-input v-model="form.component" style="width: 178px;" placeholder="组件路径"/>
</el-form-item>
<el-form-item label="上级类目">
<treeselect v-model="form.pid" :options="menus" style="width: 450px;" placeholder="选择上级类目" />
......@@ -74,14 +87,11 @@ export default {
data() {
return {
loading: false, dialog: false, menus: [],
form: { name: '', sort: 999, path: '', component: '', componentName: '', iframe: 'false', roles: [], pid: 0, icon: '', cache: false, hidden: false },
form: { name: '', sort: 999, path: '', component: '', componentName: '', iframe: 'false', roles: [], pid: 0, icon: '', cache: false, hidden: false, type: 0, permission: '' },
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' }
],
sort: [
{ required: true, message: '请输入序号', trigger: 'blur', type: 'number' }
],
path: [
{ required: true, message: '请输入地址', trigger: 'blur' }
]
......@@ -114,9 +124,8 @@ export default {
})
this.loading = false
this.$parent.init()
}).catch(err => {
}).catch(() => {
this.loading = false
console.log(err.response.data.message)
})
},
doEdit() {
......@@ -129,15 +138,14 @@ export default {
})
this.loading = false
this.$parent.init()
}).catch(err => {
}).catch(() => {
this.loading = false
console.log(err.response.data.message)
})
},
resetForm() {
this.dialog = false
this.$refs['form'].resetFields()
this.form = { name: '', sort: 999, path: '', component: '', componentName: '', iframe: 'false', roles: [], pid: 0, icon: '', cache: false, hidden: false }
this.form = { name: '', sort: 999, path: '', component: '', componentName: '', iframe: 'false', roles: [], pid: 0, icon: '', cache: false, hidden: false, type: 0, permission: '' }
},
selected(name) {
this.form.icon = name
......
......@@ -4,9 +4,18 @@
<div class="head-container">
<!-- 搜索 -->
<el-input v-model="query.value" clearable placeholder="模糊搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-date-picker
v-model="query.date"
type="daterange"
range-separator=":"
class="el-range-editor--small filter-item"
style="height: 30.5px;width: 220px"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"/>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<!-- 新增 -->
<div v-permission="['ADMIN','MENU_ALL','MENU_CREATE']" style="display: inline-block;margin: 0px 2px;">
<div v-permission="['admin','menu:add']" style="display: inline-block;margin: 0px 2px;">
<el-button
class="filter-item"
size="mini"
......@@ -14,20 +23,22 @@
icon="el-icon-plus"
@click="add">新增</el-button>
</div>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
class="filter-item"
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-more"
@click="changExpand">{{ expand ? '折叠' : '展开' }}</el-button>
<eForm ref="form" :is-add="true"/>
icon="el-icon-download"
@click="download">导出</el-button>
</div>
</div>
<!--表单组件-->
<eForm ref="form" :is-add="isAdd"/>
<!--表格渲染-->
<tree-table v-loading="loading" :data="data" :expand-all="expand" :columns="columns" :height="height" size="small">
<el-table v-loading="loading" :data="data" :tree-props="{children: 'children', hasChildren: 'hasChildren'}" :default-expand-all="expand" row-key="id" size="small">
<el-table-column :show-overflow-tooltip="true" label="菜单名称" width="125px" prop="name"/>
<el-table-column prop="icon" label="图标" align="center" width="60px">
<template slot-scope="scope">
<svg-icon :icon-class="scope.row.icon" />
......@@ -35,28 +46,29 @@
</el-table-column>
<el-table-column prop="sort" align="center" label="排序">
<template slot-scope="scope">
<el-tag>{{ scope.row.sort }}</el-tag>
{{ scope.row.sort }}
</template>
</el-table-column>
<el-table-column :show-overflow-tooltip="true" prop="path" label="链接地址"/>
<el-table-column :show-overflow-tooltip="true" prop="componentName" label="组件名称"/>
<el-table-column :show-overflow-tooltip="true" prop="component" label="组件路径" width="130px"/>
<el-table-column prop="iframe" label="内部菜单">
<el-table-column :show-overflow-tooltip="true" prop="path" label="路由地址"/>
<el-table-column :show-overflow-tooltip="true" prop="permission" label="权限标识"/>
<!--<el-table-column :show-overflow-tooltip="true" prop="componentName" label="组件名称"/>-->
<el-table-column :show-overflow-tooltip="true" prop="component" label="组件路径"/>
<el-table-column prop="iframe" label="外链" width="75px">
<template slot-scope="scope">
<span v-if="!scope.row.iframe"></span>
<span v-if="scope.row.iframe"></span>
<span v-else></span>
</template>
</el-table-column>
<el-table-column prop="iframe" label="是否缓存">
<el-table-column prop="iframe" label="缓存" width="75px">
<template slot-scope="scope">
<span v-if="scope.row.cache"></span>
<span v-else></span>
</template>
</el-table-column>
<el-table-column prop="iframe" label="是否隐藏">
<el-table-column prop="iframe" label="可见" width="75px">
<template slot-scope="scope">
<span v-if="scope.row.hidden"></span>
<span v-else></span>
<span v-if="scope.row.hidden"></span>
<span v-else></span>
</template>
</el-table-column>
<el-table-column prop="createTime" label="创建日期" width="135px">
......@@ -64,11 +76,11 @@
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column v-if="checkPermission(['ADMIN','MENU_ALL','MENU_EDIT','MENU_DELETE'])" label="操作" width="130px" align="center" fixed="right">
<el-table-column v-if="checkPermission(['admin','menu:edit','menu:del'])" label="操作" width="130px" align="center" fixed="right">
<template slot-scope="scope">
<el-button v-permission="['ADMIN','MENU_ALL','MENU_EDIT']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-button v-permission="['admin','menu:edit']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-popover
v-permission="['ADMIN','MENU_ALL','MENU_DELETE']"
v-permission="['admin','menu:del']"
:ref="scope.row.id"
placement="top"
width="200">
......@@ -81,36 +93,27 @@
</el-popover>
</template>
</el-table-column>
</tree-table>
</el-table>
</div>
</template>
<script>
import checkPermission from '@/utils/permission' // 权限判断函数
import treeTable from '@/components/TreeTable'
import initData from '@/mixins/initData'
import { del } from '@/api/menu'
import { parseTime } from '@/utils/index'
import { del, downloadMenu } from '@/api/menu'
import { parseTime, downloadFile } from '@/utils/index'
import eForm from './form'
export default {
name: 'Menu',
components: { treeTable, eForm },
components: { eForm },
mixins: [initData],
data() {
return {
columns: [
{
text: '名称',
value: 'name',
width: 140
}
],
delLoading: false, expand: true, height: 625
delLoading: false, expand: false
}
},
created() {
this.$nextTick(() => {
this.height = document.documentElement.clientHeight - 200
this.init()
})
},
......@@ -124,6 +127,10 @@ export default {
const value = query.value
this.params = { page: this.page, size: this.size, sort: sort }
if (value) { this.params['blurry'] = value }
if (query.date) {
this.params['startTime'] = query.date[0]
this.params['endTime'] = query.date[1]
}
return true
},
subDelete(id) {
......@@ -152,12 +159,22 @@ export default {
this.isAdd = false
const _this = this.$refs.form
_this.getMenus()
_this.form = { id: data.id, component: data.component, componentName: data.componentName, name: data.name, sort: data.sort, pid: data.pid, path: data.path, iframe: data.iframe.toString(), roles: [], icon: data.icon, cache: data.cache, hidden: data.hidden }
_this.form = { id: data.id, component: data.component, componentName: data.componentName, name: data.name, sort: data.sort, pid: data.pid, path: data.path, iframe: data.iframe.toString(), roles: [], icon: data.icon, cache: data.cache, hidden: data.hidden, type: data.type, permission: data.permission }
_this.dialog = true
},
changExpand() {
this.expand = !this.expand
this.init()
},
download() {
this.beforeInit()
this.downloadLoading = true
downloadMenu(this.params).then(result => {
downloadFile(result, '菜单列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
......
<template>
<el-dialog :visible.sync="dialog" :close-on-click-modal="false" :before-close="cancel" :title="isAdd ? '新增权限' : '编辑权限'" append-to-body width="500px">
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="80px">
<el-form-item label="名称" prop="name">
<el-input v-model="form.name" style="width: 360px;"/>
</el-form-item>
<el-form-item label="别名" prop="alias">
<el-input v-model="form.alias" style="width: 360px;"/>
</el-form-item>
<el-form-item style="margin-bottom: 0px;" label="上级类目">
<treeselect v-model="form.pid" :options="permissions" style="width: 360px;" placeholder="选择上级类目" />
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button type="text" @click="cancel">取消</el-button>
<el-button :loading="loading" type="primary" @click="doSubmit">确认</el-button>
</div>
</el-dialog>
</template>
<script>
import { add, edit, getPermissionTree } from '@/api/permission'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
export default {
components: { Treeselect },
props: {
isAdd: {
type: Boolean,
required: true
}
},
data() {
return {
loading: false, dialog: false, permissions: [],
form: { name: '', alias: '', pid: 0 },
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' }
],
alias: [
{ required: true, message: '请输入别名', trigger: 'blur' }
]
}
}
},
methods: {
cancel() {
this.resetForm()
},
doSubmit() {
this.$refs['form'].validate((valid) => {
if (valid) {
this.loading = true
if (this.isAdd) {
this.doAdd()
} else this.doEdit()
} else {
return false
}
})
},
doAdd() {
add(this.form).then(res => {
this.resetForm()
this.$notify({
title: '添加成功',
type: 'success',
duration: 2500
})
this.loading = false
this.$parent.init()
}).catch(err => {
this.loading = false
console.log(err.response.data.message)
})
},
doEdit() {
edit(this.form).then(res => {
this.resetForm()
this.$notify({
title: '修改成功',
type: 'success',
duration: 2500
})
this.loading = false
this.$parent.init()
}).catch(err => {
this.loading = false
console.log(err.response.data.message)
})
},
resetForm() {
this.dialog = false
this.$refs['form'].resetFields()
this.form = { name: '', alias: '', pid: 0 }
},
getPermissions() {
getPermissionTree().then(res => {
this.permissions = []
const permission = { id: 0, label: '顶级类目', children: [] }
permission.children = res
this.permissions.push(permission)
})
}
}
}
</script>
<style scoped>
</style>
<template>
<div class="app-container">
<!--工具栏-->
<div class="head-container">
<!-- 搜索 -->
<el-input v-model="query.value" clearable placeholder="输入名称或者别名搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<!-- 新增 -->
<div v-permission="['ADMIN','PERMISSION_ALL','PERMISSION_CREATE']" style="display: inline-block;margin: 0px 2px 0px">
<el-button
class="filter-item"
size="mini"
type="primary"
icon="el-icon-plus"
@click="add">新增</el-button>
</div>
<div style="display: inline-block;">
<el-button
class="filter-item"
size="mini"
type="warning"
icon="el-icon-more"
@click="changeExpand">{{ expand ? '折叠' : '展开' }}</el-button>
<eForm ref="form" :is-add="true"/>
</div>
</div>
<!--表单组件-->
<eForm ref="form" :is-add="isAdd"/>
<!--表格渲染-->
<tree-table v-loading="loading" :data="data" :expand-all="expand" :height="height" :columns="columns" size="small">
<el-table-column prop="createTime" label="创建日期">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column v-if="checkPermission(['ADMIN','PERMISSION_ALL','PERMISSION_EDIT','PERMISSION_DELETE'])" label="操作" width="130px" align="center" fixed="right">
<template slot-scope="scope">
<el-button v-permission="['ADMIN','PERMISSION_ALL','PERMISSION_EDIT']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-popover
v-permission="['ADMIN','PERMISSION_ALL','PERMISSION_DELETE']"
:ref="scope.row.id"
placement="top"
width="200">
<p>确定删除吗,如果存在下级节点则一并删除,此操作不能撤销!</p>
<div style="text-align: right; margin: 0">
<el-button size="mini" type="text" @click="$refs[scope.row.id].doClose()">取消</el-button>
<el-button :loading="delLoading" type="primary" size="mini" @click="subDelete(scope.row.id)">确定</el-button>
</div>
<el-button slot="reference" type="danger" icon="el-icon-delete" size="mini"/>
</el-popover>
</template>
</el-table-column>
</tree-table>
</div>
</template>
<script>
import checkPermission from '@/utils/permission' // 权限判断函数
import treeTable from '@/components/TreeTable'
import initData from '@/mixins/initData'
import { del } from '@/api/permission'
import { parseTime } from '@/utils/index'
import eForm from './form'
export default {
name: 'Permission',
components: { treeTable, eForm },
mixins: [initData],
data() {
return {
columns: [
{
text: '名称',
value: 'name'
},
{
text: '别名',
value: 'alias'
}
],
delLoading: false, expand: true, height: 625
}
},
created() {
this.$nextTick(() => {
this.height = document.documentElement.clientHeight - 200
this.init()
})
},
methods: {
parseTime,
checkPermission,
beforeInit() {
this.url = 'api/permissions'
const sort = 'id,desc'
const query = this.query
const value = query.value
this.params = { page: this.page, size: this.size, sort: sort }
if (value) { this.params['blurry'] = value }
return true
},
subDelete(id) {
this.delLoading = true
del(id).then(res => {
this.delLoading = false
this.$refs[id].doClose()
this.init()
this.$notify({
title: '删除成功',
type: 'success',
duration: 2500
})
}).catch(err => {
this.delLoading = false
this.$refs[id].doClose()
console.log(err.response.data.message)
})
},
add() {
this.isAdd = true
this.$refs.form.getPermissions()
this.$refs.form.dialog = true
},
edit(data) {
this.isAdd = false
const _this = this.$refs.form
_this.getPermissions()
_this.form = { id: data.id, name: data.name, alias: data.alias, pid: data.pid }
_this.dialog = true
},
changeExpand() {
this.expand = !this.expand
this.init()
}
}
}
</script>
<style scoped>
</style>
<template>
<el-dialog :visible.sync="dialog" :close-on-click-modal="false" :before-close="cancel" :title="isAdd ? '新增角色' : '编辑角色'" append-to-body width="500px">
<el-form ref="form" :model="form" :rules="rules" size="small" label-width="80px">
<el-dialog :visible.sync="dialog" :close-on-click-modal="false" :before-close="cancel" :title="isAdd ? '新增角色' : '编辑角色'" append-to-body width="520px">
<el-form ref="form" :inline="true" :model="form" :rules="rules" size="small" label-width="80px">
<el-form-item label="角色名称" prop="name">
<el-input v-model="form.name" style="width: 370px;"/>
<el-input v-model="form.name" style="width: 145px;"/>
</el-form-item>
<el-form-item label="角色级别" prop="sort">
<el-input-number v-model.number="form.level" :min="1" controls-position="right" style="width: 370px;"/>
<el-form-item label="角色权限" prop="permission">
<el-input v-model="form.permission" style="width: 145px;"/>
</el-form-item>
<el-form-item label="数据范围">
<el-select v-model="form.dataScope" style="width: 370px" placeholder="请选择数据范围" @change="changeScope">
<el-select v-model="form.dataScope" style="width: 145px" placeholder="请选择数据范围" @change="changeScope">
<el-option
v-for="item in dateScopes"
:key="item"
......@@ -16,11 +16,14 @@
:value="item"/>
</el-select>
</el-form-item>
<el-form-item label="角色级别" prop="sort">
<el-input-number v-model.number="form.level" :min="1" controls-position="right" style="width: 145px;"/>
</el-form-item>
<el-form-item v-if="form.dataScope === '自定义'" label="数据权限">
<treeselect v-model="deptIds" :options="depts" multiple style="width: 370px" placeholder="请选择" />
<treeselect v-model="deptIds" :options="depts" multiple style="width: 380px" placeholder="请选择" />
</el-form-item>
<el-form-item label="描述信息">
<el-input v-model="form.remark" style="width: 370px;" rows="5" type="textarea"/>
<el-input v-model="form.remark" style="width: 380px;" rows="5" type="textarea"/>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
......@@ -47,10 +50,13 @@ export default {
return {
dateScopes: ['全部', '本级', '自定义'],
loading: false, dialog: false, depts: [], deptIds: [],
form: { name: '', depts: [], remark: '', dataScope: '本级', level: 3 },
form: { name: '', depts: [], remark: '', dataScope: '本级', level: 3, permission: '' },
rules: {
name: [
{ required: true, message: '请输入名称', trigger: 'blur' }
],
permission: [
{ required: true, message: '请输入权限', trigger: 'blur' }
]
}
}
......@@ -119,7 +125,7 @@ export default {
resetForm() {
this.dialog = false
this.$refs['form'].resetFields()
this.form = { name: '', depts: [], remark: '', dataScope: '本级', level: 3 }
this.form = { name: '', depts: [], remark: '', dataScope: '本级', level: 3, permission: '' }
},
getDepts() {
getDepts({ enabled: true }).then(res => {
......
......@@ -4,9 +4,18 @@
<div class="head-container">
<!-- 搜索 -->
<el-input v-model="query.value" clearable placeholder="输入任务名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-date-picker
v-model="query.date"
type="daterange"
range-separator=":"
class="el-range-editor--small filter-item"
style="height: 30.5px;width: 220px"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"/>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<!-- 新增 -->
<div v-permission="['ADMIN','JOB_ALL','JOB_CREATE']" style="display: inline-block;margin: 0px 2px;">
<div v-permission="['admin','timing:add']" style="display: inline-block;margin: 0px 2px;">
<el-button
class="filter-item"
size="mini"
......@@ -14,14 +23,24 @@
icon="el-icon-plus"
@click="dialog = true;isAdd = true">新增</el-button>
</div>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-download"
@click="download">导出</el-button>
</div>
<!-- 任务日志 -->
<div v-permission="['ADMIN','JOB_ALL','JOB_SELECT']" style="display: inline-block;">
<div style="display: inline-block;">
<el-button
class="filter-item"
size="mini"
type="warning"
type="info"
icon="el-icon-tickets"
@click="doLog">执行日志</el-button>
@click="doLog">日志</el-button>
<Log ref="log"/>
</div>
</div>
......@@ -69,20 +88,20 @@
</template>
</el-table-column>
<el-table-column :show-overflow-tooltip="true" prop="remark" label="描述"/>
<el-table-column :show-overflow-tooltip="true" prop="updateTime" label="更新日期">
<el-table-column :show-overflow-tooltip="true" prop="createTime" label="创建日期">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.updateTime) }}</span>
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column v-if="checkPermission(['ADMIN','JOB_ALL','JOB_EDIT','JOB_DELETE'])" label="操作" width="180px" align="center" fixed="right">
<el-table-column v-if="checkPermission(['admin','timing:edit','timing:del'])" label="操作" width="180px" align="center" fixed="right">
<template slot-scope="scope">
<el-button v-permission="['ADMIN','JOB_ALL','JOB_EDIT']" size="mini" style="margin-right: 3px;" type="text" @click="edit(scope.row)">编辑</el-button>
<el-button v-permission="['ADMIN','JOB_ALL','JOB_EDIT']" style="margin-left: -2px" type="text" size="mini" @click="execute(scope.row.id)">执行</el-button>
<el-button v-permission="['ADMIN','JOB_ALL','JOB_EDIT']" style="margin-left: 3px" type="text" size="mini" @click="updateStatus(scope.row.id,scope.row.isPause ? '恢复' : '暂停')">
<el-button v-permission="['admin','timing:edit']" size="mini" style="margin-right: 3px;" type="text" @click="edit(scope.row)">编辑</el-button>
<el-button v-permission="['admin','timing:edit']" style="margin-left: -2px" type="text" size="mini" @click="execute(scope.row.id)">执行</el-button>
<el-button v-permission="['admin',,'timing:edit']" style="margin-left: 3px" type="text" size="mini" @click="updateStatus(scope.row.id,scope.row.isPause ? '恢复' : '暂停')">
{{ scope.row.isPause ? '恢复' : '暂停' }}
</el-button>
<el-popover
v-permission="['ADMIN','JOB_ALL','JOB_DELETE']"
v-permission="['admin','timing:del']"
:ref="scope.row.id"
placement="top"
width="200">
......@@ -110,8 +129,8 @@
<script>
import checkPermission from '@/utils/permission'
import initData from '@/mixins/initData'
import { del, updateIsPause, execution, add, edit } from '@/api/timing'
import { parseTime } from '@/utils/index'
import { del, updateIsPause, execution, add, edit, downloadJobs } from '@/api/timing'
import { parseTime, downloadFile } from '@/utils/index'
import Log from './log'
export default {
name: 'Timing',
......@@ -153,6 +172,10 @@ export default {
const value = query.value
this.params = { page: this.page, size: this.size, sort: sort }
if (value) { this.params['jobName'] = value }
if (query.date) {
this.params['startTime'] = query.date[0]
this.params['endTime'] = query.date[1]
}
return true
},
execute(id) {
......@@ -258,6 +281,16 @@ export default {
this.isAdd = false
this.form = { id: data.id, jobName: data.jobName, beanName: data.beanName, methodName: data.methodName, params: data.params, cronExpression: data.cronExpression, isPause: data.isPause.toString(), remark: data.remark }
this.dialog = true
},
download() {
this.beforeInit()
this.downloadLoading = true
downloadJobs(this.params).then(result => {
downloadFile(result, '任务列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
......
......@@ -3,10 +3,29 @@
<!-- 搜索 -->
<div class="head-container">
<el-input v-model="query.value" clearable placeholder="输入任务名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-date-picker
v-model="query.date"
type="daterange"
range-separator=":"
class="el-range-editor--small filter-item"
style="height: 30.5px;width: 220px"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"/>
<el-select v-model="query.isSuccess" placeholder="日志状态" clearable class="filter-item" style="width: 110px" @change="toQuery">
<el-option v-for="item in enabledTypeOptions" :key="item.key" :label="item.display_name" :value="item.key"/>
</el-select>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-download"
@click="download">导出</el-button>
</div>
</div>
<!--表格渲染-->
<el-table v-loading="loading" :data="data" size="small" style="width: 100%;margin-top: -10px;">
......@@ -52,7 +71,8 @@
<script>
import checkPermission from '@/utils/permission'
import initData from '@/mixins/initData'
import { parseTime } from '@/utils/index'
import { downloadLogs } from '@/api/timing'
import { parseTime, downloadFile } from '@/utils/index'
export default {
mixins: [initData],
data() {
......@@ -78,7 +98,7 @@ export default {
this.doInit()
},
beforeInit() {
this.url = 'api/jobLogs'
this.url = 'api/jobs/logs'
const sort = 'id,desc'
const query = this.query
const value = query.value
......@@ -86,12 +106,26 @@ export default {
this.size = 6
this.params = { page: this.page, size: this.size, sort: sort }
if (value) { this.params['jobName'] = value }
if (query.date) {
this.params['startTime'] = query.date[0]
this.params['endTime'] = query.date[1]
}
if (isSuccess !== '' && isSuccess !== null) { this.params['isSuccess'] = isSuccess }
return true
},
info(errorInfo) {
this.errorInfo = errorInfo
this.errorDialog = true
},
download() {
this.beforeInit()
this.downloadLoading = true
downloadLogs(this.params).then(result => {
downloadFile(result, '任务日志列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
......
......@@ -46,6 +46,7 @@
<el-table-column prop="description" label="行为"/>
<el-table-column prop="requestIp" label="IP"/>
<el-table-column :show-overflow-tooltip="true" prop="address" label="IP来源"/>
<el-table-column prop="browser" label="浏览器"/>
<el-table-column prop="time" label="请求耗时" align="center">
<template slot-scope="scope">
<el-tag v-if="scope.row.time <= 300">{{ scope.row.time }}ms</el-tag>
......
<template>
<div class="app-container">
<!--form 组件-->
<eForm ref="form" :is-add="isAdd" :dicts="dicts"/>
<eForm ref="form" :is-add="isAdd" :dicts="dict.user_status"/>
<el-row :gutter="20">
<!--部门数据-->
<el-col :xs="9" :sm="6" :md="4" :lg="4" :xl="4">
......@@ -16,12 +16,21 @@
<div class="head-container">
<!-- 搜索 -->
<el-input v-model="query.blurry" clearable placeholder="输入名称或者邮箱搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-date-picker
v-model="query.date"
type="daterange"
range-separator=":"
class="el-range-editor--small filter-item"
style="height: 30.5px;width: 220px"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"/>
<el-select v-model="query.enabled" clearable placeholder="状态" class="filter-item" style="width: 90px" @change="toQuery">
<el-option v-for="item in enabledTypeOptions" :key="item.key" :label="item.display_name" :value="item.key"/>
</el-select>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<!-- 新增 -->
<div v-permission="['ADMIN','USER_ALL','USER_CREATE']" style="display: inline-block;margin: 0px 2px;">
<div v-permission="['admin','user:add']" style="display: inline-block;margin: 0px 2px;">
<el-button
class="filter-item"
size="mini"
......@@ -32,7 +41,6 @@
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
v-permission="['ADMIN','USER_ALL','USER_SELECT']"
:loading="downloadLoading"
size="mini"
class="filter-item"
......@@ -53,9 +61,11 @@
</el-table-column>
<el-table-column label="状态" align="center">
<template slot-scope="scope">
<div v-for="item in dicts" :key="item.id">
<el-tag v-if="scope.row.enabled.toString() === item.value" :type="scope.row.enabled ? '' : 'info'">{{ item.label }}</el-tag>
</div>
<el-switch
v-model="scope.row.enabled"
active-color="#409EFF"
inactive-color="#F56C6C"
@change="changeEnabled(scope.row, scope.row.enabled,)"/>
</template>
</el-table-column>
<el-table-column :show-overflow-tooltip="true" prop="createTime" label="创建日期">
......@@ -63,11 +73,11 @@
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column v-if="checkPermission(['ADMIN','USER_ALL','USER_EDIT','USER_DELETE'])" label="操作" width="125" align="center" fixed="right">
<el-table-column v-if="checkPermission(['admin','user:edit','user:del'])" label="操作" width="125" align="center" fixed="right">
<template slot-scope="scope">
<el-button v-permission="['ADMIN','USER_ALL','USER_EDIT']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-button v-permission="['admin','user:edit']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-popover
v-permission="['ADMIN','USER_ALL','USER_DELETE']"
v-permission="['admin','user:del']"
:ref="scope.row.id"
placement="top"
width="180">
......@@ -97,15 +107,16 @@
<script>
import checkPermission from '@/utils/permission'
import initData from '@/mixins/initData'
import initDict from '@/mixins/initDict'
import { del, downloadUser } from '@/api/user'
import { del, downloadUser, edit } from '@/api/user'
import { getDepts } from '@/api/dept'
import { parseTime, downloadFile } from '@/utils/index'
import eForm from './form'
export default {
name: 'User',
components: { eForm },
mixins: [initData, initDict],
mixins: [initData],
// 设置数据字典
dicts: ['user_status'],
data() {
return {
height: document.documentElement.clientHeight - 180 + 'px;', isAdd: false,
......@@ -114,7 +125,6 @@ export default {
children: 'children',
label: 'name'
},
downloadLoading: false,
enabledTypeOptions: [
{ key: 'true', display_name: '激活' },
{ key: 'false', display_name: '锁定' }
......@@ -125,8 +135,6 @@ export default {
this.getDeptDatas()
this.$nextTick(() => {
this.init()
// 加载数据字典
this.getDict('user_status')
})
},
mounted: function() {
......@@ -146,9 +154,24 @@ export default {
const enabled = query.enabled
this.params = { page: this.page, size: this.size, sort: sort, deptId: this.deptId }
if (blurry) { this.params['blurry'] = blurry }
if (query.date) {
this.params['startTime'] = query.date[0]
this.params['endTime'] = query.date[1]
}
if (enabled !== '' && enabled !== null) { this.params['enabled'] = enabled }
return true
},
// 导出
download() {
this.beforeInit()
this.downloadLoading = true
downloadUser(this.params).then(result => {
downloadFile(result, '用户列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
},
subDelete(id) {
this.delLoading = true
del(id).then(res => {
......@@ -190,16 +213,6 @@ export default {
this.$refs.form.getRoleLevel()
this.$refs.form.dialog = true
},
// 导出
download() {
this.downloadLoading = true
downloadUser().then(result => {
downloadFile(result, '用户列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
},
// 数据转换
formatJson(filterVal, jsonData) {
return jsonData.map(v => filterVal.map(j => {
......@@ -227,6 +240,27 @@ export default {
_this.jobId = data.job.id
_this.getJobs(_this.deptId)
_this.dialog = true
},
// 改变状态
changeEnabled(data, val) {
this.$confirm('此操作将 "' + this.dict.label.user_status[val] + '" ' + data.username + ', 是否继续?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
edit(data).then(res => {
this.$notify({
title: this.dict.label.user_status[val] + '成功',
type: 'success',
duration: 2500
})
}).catch(err => {
data.enabled = !data.enabled
console.log(err.response.data.message)
})
}).catch(() => {
data.enabled = !data.enabled
})
}
}
}
......
......@@ -4,18 +4,27 @@
<div class="head-container">
<!--搜索-->
<el-input v-model="query.filename" clearable placeholder="输入文件名" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-date-picker
v-model="query.date"
type="daterange"
range-separator=":"
class="el-range-editor--small filter-item"
style="height: 30.5px;width: 220px"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"/>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<!-- 上传 -->
<div style="display: inline-block;margin: 0px 2px;">
<el-button
v-permission="['ADMIN','PICTURE_ALL','PICTURE_UPLOAD']"
v-permission="['admin','pictures:add']"
class="filter-item"
size="mini"
type="primary"
icon="el-icon-upload"
@click="dialog = true">上传图片</el-button>
</div>
<div v-permission="['ADMIN','PICTURE_ALL','PICTURE_DELETE']" style="display: inline-block;">
<div v-permission="['admin','pictures:del']" style="display: inline-block;">
<el-button
:loading="delAllLoading"
:disabled="data.length === 0 || $refs.table.selection.length === 0"
......@@ -25,6 +34,16 @@
icon="el-icon-delete"
@click="open">删除</el-button>
</div>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-download"
@click="download">导出</el-button>
</div>
</div>
<!--上传图片-->
<el-dialog :visible.sync="dialog" :close-on-click-modal="false" append-to-body width="600px" @close="doSubmit">
......@@ -64,7 +83,7 @@
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column v-if="checkPermission(['ADMIN','PICTURE_ALL','PICTURE_DELETE'])" label="操作" width="100px" align="center" fixed="right">
<el-table-column v-if="checkPermission(['admin','pictures:del'])" label="操作" width="100px" align="center" fixed="right">
<template slot-scope="scope">
<el-popover
:ref="scope.row.id"
......@@ -94,16 +113,16 @@
<script>
import checkPermission from '@/utils/permission' // 权限判断函数
import initData from '@/mixins/initData'
import { parseTime } from '@/utils/index'
import { parseTime, downloadFile } from '@/utils/index'
import { mapGetters } from 'vuex'
import { del, delAll } from '@/api/picture'
import { del, delAll, downloadPicture } from '@/api/picture'
import { getToken } from '@/utils/auth'
export default {
name: 'Pictures',
mixins: [initData],
data() {
return {
delLoading: false, downloadLoading: false,
delLoading: false,
delAllLoading: false,
headers: {
'Authorization': 'Bearer ' + getToken()
......@@ -135,6 +154,10 @@ export default {
const filename = query.filename
this.params = { page: this.page, size: this.size, sort: sort }
if (filename) { this.params[filename] = filename }
if (query.date) {
this.params['startTime'] = query.date[0]
this.params['endTime'] = query.date[1]
}
return true
},
subDelete(id) {
......@@ -218,6 +241,16 @@ export default {
type: 'error',
duration: 2500
})
},
download() {
this.beforeInit()
this.downloadLoading = true
downloadPicture(this.params).then(result => {
downloadFile(result, '图片列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
......
......@@ -3,18 +3,21 @@
<!--工具栏-->
<div class="head-container">
<!-- 搜索 -->
<el-input
v-model="query.value"
clearable
placeholder="输入内容模糊搜索"
style="width: 200px;"
class="filter-item"
@keyup.enter.native="toQuery"/>
<el-input v-model="query.value" clearable placeholder="输入内容模糊搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-date-picker
v-model="query.date"
type="daterange"
range-separator=":"
class="el-range-editor--small filter-item"
style="height: 30.5px;width: 220px"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"/>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<!-- 新增 -->
<div style="display: inline-block;margin: 0px 2px;">
<el-button
v-permission="['ADMIN','LOCALSTORAGE_ALL','LOCALSTORAGE_CREATE']"
v-permission="['admin','storage:add']"
class="filter-item"
size="mini"
type="primary"
......@@ -25,6 +28,7 @@
<!-- 多选删除 -->
<div style="display: inline-block;margin: 0px 2px;">
<el-button
v-permission="['admin','storage:del']"
:loading="delAllLoading"
:disabled="data.length === 0 || $refs.table.selection.length === 0"
class="filter-item"
......@@ -34,13 +38,23 @@
@click="open">删除
</el-button>
</div>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-download"
@click="download">导出</el-button>
</div>
</div>
<!--表单组件-->
<eForm ref="form" :is-add="isAdd"/>
<!--表格渲染-->
<el-table v-loading="loading" ref="table" :data="data" size="small" style="width: 100%;">
<el-table-column type="selection" width="55"/>
<el-table-column :show-overflow-tooltip="true" prop="name" label="文件名">
<el-table-column prop="name" width="150px" label="文件名">
<template slot-scope="scope">
<el-popover
:content="'file/' + scope.row.type + '/' + scope.row.realName"
......@@ -48,28 +62,33 @@
title="路径"
width="200"
trigger="hover">
<el-link
<a
slot="reference"
:underline="false"
:href="baseApi + '/file/' + scope.row.type + '/' + scope.row.realName"
target="_blank"
type="primary">{{ scope.row.name }}
</el-link>
class="el-link--primary"
style="word-break:keep-all;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;color: #1890ff;font-size: 13px;"
target="_blank">
{{ scope.row.name }}
</a>
</el-popover>
</template>
</el-table-column>
<el-table-column prop="suffix" label="文件类型"/>
<el-table-column prop="type" label="类别"/>
<el-table-column prop="path" label="预览">
<el-table-column prop="path" label="预览图">
<template slot-scope="{row}">
<el-image
:src=" baseApi + '/file/' + row.type + '/' + row.realName"
:preview-src-list="[baseApi + '/file/' + row.type + '/' + row.realName]"
fit="contain"
lazy
style="width: 60px; height: 40px"/>
class="el-avatar">
<div slot="error">
<i class="el-icon-document"/>
</div>
</el-image>
</template>
</el-table-column>
<el-table-column prop="suffix" label="文件类型"/>
<el-table-column prop="type" label="类别"/>
<el-table-column prop="size" label="大小"/>
<el-table-column prop="operate" label="操作人"/>
<el-table-column prop="createTime" label="创建日期">
......@@ -77,25 +96,11 @@
<span>{{ parseTime(scope.row.createTime) }}</span>
</template>
</el-table-column>
<el-table-column prop="updateTime" label="修改日期">
<el-table-column v-if="checkPermission(['admin','storage:edit','storage:del'])" label="操作" width="150px" align="center">
<template slot-scope="scope">
<span>{{ parseTime(scope.row.updateTime) }}</span>
</template>
</el-table-column>
<el-table-column
v-if="checkPermission(['ADMIN','LOCALSTORAGE_ALL','LOCALSTORAGE_EDIT','LOCALSTORAGE_DELETE'])"
label="操作"
width="150px"
align="center">
<template slot-scope="scope">
<el-button
v-permission="['ADMIN','LOCALSTORAGE_ALL','LOCALSTORAGE_EDIT']"
size="mini"
type="primary"
icon="el-icon-edit"
@click="edit(scope.row)"/>
<el-button v-permission="['admin','storage:edit']" size="mini" type="primary" icon="el-icon-edit" @click="edit(scope.row)"/>
<el-popover
v-permission="['ADMIN','LOCALSTORAGE_ALL','LOCALSTORAGE_DELETE']"
v-permission="['admin','storage:del']"
:ref="scope.row.id"
placement="top"
width="180">
......@@ -125,10 +130,9 @@
import { mapGetters } from 'vuex'
import checkPermission from '@/utils/permission'
import initData from '@/mixins/initData'
import { del, delAll } from '@/api/localStorage'
import { parseTime } from '@/utils/index'
import { del, delAll, downloadStorage } from '@/api/localStorage'
import { parseTime, downloadFile } from '@/utils/index'
import eForm from './form'
export default {
components: { eForm },
mixins: [initData],
......@@ -162,8 +166,10 @@ export default {
this.params = { page: this.page, size: this.size, sort: sort }
const query = this.query
const value = query.value
if (value) {
this.params['blurry'] = value
if (value) { this.params['blurry'] = value }
if (query.date) {
this.params['startTime'] = query.date[0]
this.params['endTime'] = query.date[1]
}
return true
},
......@@ -227,11 +233,23 @@ export default {
}).then(() => {
this.doDelete()
})
},
download() {
this.beforeInit()
this.downloadLoading = true
downloadStorage(this.params).then(result => {
downloadFile(result, '文件列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
</script>
<style scoped>
/deep/ .el-image__error, .el-image__placeholder{
background: none;
}
</style>
......@@ -6,6 +6,15 @@
<div class="head-container">
<!-- 搜索 -->
<el-input v-model="query.value" clearable placeholder="输入文件名称搜索" style="width: 200px;" class="filter-item" @keyup.enter.native="toQuery"/>
<el-date-picker
v-model="query.date"
type="daterange"
range-separator=":"
class="el-range-editor--small filter-item"
style="height: 30.5px;width: 220px"
value-format="yyyy-MM-dd HH:mm:ss"
start-placeholder="开始日期"
end-placeholder="结束日期"/>
<el-button class="filter-item" size="mini" type="success" icon="el-icon-search" @click="toQuery">搜索</el-button>
<!-- 上传 -->
<div style="display: inline-block;margin: 0px 2px;">
......@@ -33,6 +42,16 @@
icon="el-icon-delete"
@click="open">删除</el-button>
</div>
<!-- 导出 -->
<div style="display: inline-block;">
<el-button
:loading="downloadLoading"
size="mini"
class="filter-item"
type="warning"
icon="el-icon-download"
@click="downloadList">导出</el-button>
</div>
<!-- 文件上传 -->
<el-dialog :visible.sync="dialog" :close-on-click-modal="false" append-to-body width="500px" @close="doSubmit">
<el-upload
......@@ -98,8 +117,8 @@
<script>
import initData from '@/mixins/initData'
import { del, download, sync, delAll } from '@/api/qiniu'
import { parseTime } from '@/utils/index'
import { del, download, sync, delAll, downloadQiNiu } from '@/api/qiniu'
import { parseTime, downloadFile } from '@/utils/index'
import { mapGetters } from 'vuex'
import { getToken } from '@/utils/auth'
import eForm from './form'
......@@ -139,6 +158,10 @@ export default {
const value = query.value
this.params = { page: this.page, size: this.size, sort: sort }
if (value) { this.params['key'] = value }
if (query.date) {
this.params['startTime'] = query.date[0]
this.params['endTime'] = query.date[1]
}
return true
},
doConfig() {
......@@ -257,6 +280,16 @@ export default {
}).then(() => {
this.doDelete()
})
},
downloadList() {
this.beforeInit()
this.downloadLoading = true
downloadQiNiu(this.params).then(result => {
downloadFile(result, '七牛云文件列表', 'xlsx')
this.downloadLoading = false
}).catch(() => {
this.downloadLoading = false
})
}
}
}
......
......@@ -3,7 +3,7 @@
</template>
<script>
import { mapGetters } from 'vuex'
import elFrame from '@/components/iframe/index'
import elFrame from '@/components/Iframe/index'
export default {
name: 'Swagger',
components: { elFrame },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment