mirror of
https://github.com/jumpserver/lina.git
synced 2025-08-13 12:26:07 +00:00
Merge remote-tracking branch 'origin/master'
This commit is contained in:
commit
d90b01923b
@ -20,6 +20,7 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "0.18.1",
|
"axios": "0.18.1",
|
||||||
"deepmerge": "^4.2.2",
|
"deepmerge": "^4.2.2",
|
||||||
|
"echarts": "^4.7.0",
|
||||||
"element-ui": "2.13.0",
|
"element-ui": "2.13.0",
|
||||||
"eslint-plugin-html": "^6.0.0",
|
"eslint-plugin-html": "^6.0.0",
|
||||||
"jquery": "^3.5.0",
|
"jquery": "^3.5.0",
|
||||||
@ -44,6 +45,7 @@
|
|||||||
"vue": "2.6.10",
|
"vue": "2.6.10",
|
||||||
"vue-codemirror-lite": "^1.0.4",
|
"vue-codemirror-lite": "^1.0.4",
|
||||||
"vue-cookie": "^1.1.4",
|
"vue-cookie": "^1.1.4",
|
||||||
|
"vue-echarts": "^5.0.0-beta.0",
|
||||||
"vue-i18n": "^8.15.5",
|
"vue-i18n": "^8.15.5",
|
||||||
"vue-router": "3.0.6",
|
"vue-router": "3.0.6",
|
||||||
"vue-select": "^3.9.5",
|
"vue-select": "^3.9.5",
|
||||||
|
@ -7,8 +7,8 @@
|
|||||||
<slot />
|
<slot />
|
||||||
<div slot="footer" class="dialog-footer">
|
<div slot="footer" class="dialog-footer">
|
||||||
<slot name="footer">
|
<slot name="footer">
|
||||||
<el-button size="small" @click="onCancel">{{ $t('common.Cancel') }}</el-button>
|
<el-button v-if="showCancel" size="small" @click="onCancel">{{ cancelTitle }}</el-button>
|
||||||
<el-button type="primary" size="small" @click="onConfirm">{{ $t('common.Confirm') }}</el-button>
|
<el-button v-if="showConfirm" type="primary" size="small" @click="onConfirm">{{ confirmTitle }}</el-button>
|
||||||
</slot>
|
</slot>
|
||||||
</div>
|
</div>
|
||||||
</el-dialog>
|
</el-dialog>
|
||||||
@ -21,6 +21,26 @@ export default {
|
|||||||
title: {
|
title: {
|
||||||
type: String,
|
type: String,
|
||||||
default: 'Title'
|
default: 'Title'
|
||||||
|
},
|
||||||
|
showCancel: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
cancelTitle: {
|
||||||
|
type: String,
|
||||||
|
default() {
|
||||||
|
return this.$t('common.Cancel')
|
||||||
|
}
|
||||||
|
},
|
||||||
|
showConfirm: {
|
||||||
|
type: Boolean,
|
||||||
|
default: true
|
||||||
|
},
|
||||||
|
confirmTitle: {
|
||||||
|
type: String,
|
||||||
|
default() {
|
||||||
|
return this.$t('common.Confirm')
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
|
@ -1,8 +1,12 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-card :class="'ibox ' + type" shadow="never" v-bind="$attrs">
|
<el-card :class="'ibox ' + type" shadow="never" v-bind="$attrs">
|
||||||
|
<template #header>
|
||||||
|
<slot name="header">
|
||||||
<div v-if="title" slot="header" class="clearfix ibox-title">
|
<div v-if="title" slot="header" class="clearfix ibox-title">
|
||||||
<i v-if="fa" :class="'fa ' + fa" /> {{ title }}
|
<i v-if="fa" :class="'fa ' + fa" /> {{ title }}
|
||||||
</div>
|
</div>
|
||||||
|
</slot>
|
||||||
|
</template>
|
||||||
<slot />
|
<slot />
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog :title="$t('common.Export')" :visible.sync="showExportDialog" center @confirm="handleExportConfirm()" @cancel="handleExportCancel()">
|
<Dialog :title="$t('common.Export')" :visible.sync="showExportDialog" @confirm="handleExportConfirm()" @cancel="handleExportCancel()">
|
||||||
<el-form label-position="left" style="padding-left: 50px">
|
<el-form label-position="left" style="padding-left: 50px">
|
||||||
<el-form-item :label="this.$t('common.imExport.ExportRange')" :label-width="'100px'">
|
<el-form-item :label="this.$t('common.imExport.ExportRange')" :label-width="'100px'">
|
||||||
<el-radio v-model="exportOption" class="export-item" label="1">{{ this.$t('common.imExport.ExportAll') }}</el-radio>
|
<el-radio v-model="exportOption" class="export-item" label="1">{{ this.$t('common.imExport.ExportAll') }}</el-radio>
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<template>
|
<template>
|
||||||
<Dialog :title="$t('common.Import')" :visible.sync="showImportDialog" center @confirm="handleImportConfirm()" @cancel="handleImportCancel('import')">
|
<Dialog :title="$t('common.Import')" :visible.sync="showImportDialog" @confirm="handleImportConfirm" @cancel="handleImportCancel()">
|
||||||
<el-form label-position="left" style="padding-left: 50px">
|
<el-form label-position="left" style="padding-left: 50px">
|
||||||
<el-form-item :label="$t('common.Import' )" :label-width="'100px'">
|
<el-form-item :label="$t('common.Import' )" :label-width="'100px'">
|
||||||
<el-radio v-model="importOption" class="export-item" label="1">{{ this.$t('common.Create') }}</el-radio>
|
<el-radio v-model="importOption" class="export-item" label="1">{{ this.$t('common.Create') }}</el-radio>
|
||||||
<el-radio v-model="importOption" class="export-item" label="2">{{ this.$t('common.Update') }}</el-radio>
|
<el-radio v-model="importOption" class="export-item" label="2">{{ this.$t('common.Update') }}</el-radio>
|
||||||
<div>
|
<div style="line-height: 1.5">
|
||||||
<span v-if="importOption==='1'" class="el-upload__tip">
|
<span v-if="importOption==='1'" class="el-upload__tip">
|
||||||
{{ this.$t('common.imExport.downloadImportTemplateMsg') }}
|
{{ this.$t('common.imExport.downloadImportTemplateMsg') }}
|
||||||
<el-link type="success" :underline="false" :href="downloadImportTempUrl">{{ this.$t('common.Download') }}</el-link>
|
<el-link type="success" :underline="false" :href="downloadImportTempUrl">{{ this.$t('common.Download') }}</el-link>
|
||||||
@ -22,12 +22,20 @@
|
|||||||
:http-request="handleImport"
|
:http-request="handleImport"
|
||||||
list-type="text/csv"
|
list-type="text/csv"
|
||||||
:limit="1"
|
:limit="1"
|
||||||
|
:auto-upload="false"
|
||||||
|
:before-upload="beforeUpload"
|
||||||
>
|
>
|
||||||
<el-button size="mini" type="default">{{ this.$t('common.SelectFile') }}</el-button>
|
<el-button size="mini" type="default">{{ this.$t('common.SelectFile') }}</el-button>
|
||||||
<div slot="tip" class="el-upload__tip">{{ this.$t('common.imExport.onlyCSVFilesTips') }}</div>
|
<div slot="tip" :class="uploadHelpTextClass" style="line-height: 1.5">{{ this.$t('common.imExport.onlyCSVFilesTips') }}</div>
|
||||||
</el-upload>
|
</el-upload>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
<div v-if="errorMsg" class="error-msg error-results">
|
||||||
|
<ul v-if="typeof errorMsg === 'object'">
|
||||||
|
<li v-for="(item, index) in errorMsg" :key="item + '-' + index"> {{ item }}</li>
|
||||||
|
</ul>
|
||||||
|
<span v-else>{{ errorMsg }}</span>
|
||||||
|
</div>
|
||||||
</Dialog>
|
</Dialog>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -53,7 +61,9 @@ export default {
|
|||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
showImportDialog: false,
|
showImportDialog: false,
|
||||||
importOption: '1'
|
importOption: '1',
|
||||||
|
isCsv: true,
|
||||||
|
errorMsg: ''
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
@ -65,6 +75,13 @@ export default {
|
|||||||
},
|
},
|
||||||
downloadImportTempUrl() {
|
downloadImportTempUrl() {
|
||||||
return process.env.VUE_APP_BASE_API + this.url + '?format=csv&template=import&limit=1'
|
return process.env.VUE_APP_BASE_API + this.url + '?format=csv&template=import&limit=1'
|
||||||
|
},
|
||||||
|
uploadHelpTextClass() {
|
||||||
|
const cls = ['el-upload__tip']
|
||||||
|
if (!this.isCsv) {
|
||||||
|
cls.push('error-msg')
|
||||||
|
}
|
||||||
|
return cls
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
@ -77,22 +94,53 @@ export default {
|
|||||||
this.$axios.put(
|
this.$axios.put(
|
||||||
this.upLoadUrl,
|
this.upLoadUrl,
|
||||||
item.file,
|
item.file,
|
||||||
{ headers: { 'Content-Type': 'text/csv' }}
|
{ headers: { 'Content-Type': 'text/csv' }, disableFlashMsg: true }
|
||||||
).then((data) => {
|
).then((data) => {
|
||||||
const msg = this.$t('common.imExport.updateSuccessMsg', { count: data.length })
|
const msg = this.$t('common.imExport.updateSuccessMsg', { count: data.length })
|
||||||
this.$message.success(msg)
|
this.onSuccess(msg)
|
||||||
|
}).catch(error => {
|
||||||
|
this.catchError(error)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
performCreate(item) {
|
performCreate(item) {
|
||||||
this.$axios.post(
|
this.$axios.post(
|
||||||
this.upLoadUrl,
|
this.upLoadUrl,
|
||||||
item.file,
|
item.file,
|
||||||
{ headers: { 'Content-Type': 'text/csv' }}
|
{ headers: { 'Content-Type': 'text/csv' }, disableFlashMsg: true }
|
||||||
).then((data) => {
|
).then((data) => {
|
||||||
const msg = this.$t('common.imExport.createSuccessMsg', { count: data.length })
|
const msg = this.$t('common.imExport.createSuccessMsg', { count: data.length })
|
||||||
this.$message.success(msg)
|
this.onSuccess(msg)
|
||||||
|
}).catch(error => {
|
||||||
|
this.catchError(error)
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
catchError(error) {
|
||||||
|
this.$refs.upload.clearFiles()
|
||||||
|
if (error.response && error.response.status === 400) {
|
||||||
|
const errorData = error.response.data
|
||||||
|
const totalErrorMsg = []
|
||||||
|
errorData.forEach((value, index) => {
|
||||||
|
if (typeof value === 'string') {
|
||||||
|
totalErrorMsg.push(`line ${index}. ${value}`)
|
||||||
|
} else {
|
||||||
|
const errorMsg = [`line ${index}. `]
|
||||||
|
for (const [k, v] of Object.entries(value)) {
|
||||||
|
if (v) {
|
||||||
|
errorMsg.push(`${k}: ${v}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (errorMsg.length > 1) {
|
||||||
|
totalErrorMsg.push(errorMsg.join(' '))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
this.errorMsg = totalErrorMsg
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onSuccess(msg) {
|
||||||
|
this.errorMsg = ''
|
||||||
|
this.$message.success(msg)
|
||||||
|
},
|
||||||
downloadCsv(url) {
|
downloadCsv(url) {
|
||||||
const a = document.createElement('a')
|
const a = document.createElement('a')
|
||||||
a.href = url
|
a.href = url
|
||||||
@ -121,11 +169,24 @@ export default {
|
|||||||
},
|
},
|
||||||
handleImportCancel() {
|
handleImportCancel() {
|
||||||
this.showImportDialog = false
|
this.showImportDialog = false
|
||||||
|
},
|
||||||
|
beforeUpload(file) {
|
||||||
|
this.isCsv = _.endsWith(file.name, 'csv')
|
||||||
|
return this.isCsv
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang='less' scoped>
|
<style lang='scss' scoped>
|
||||||
|
@import "~@/styles/element-variables.scss";
|
||||||
|
.error-msg {
|
||||||
|
color: $--color-danger;
|
||||||
|
}
|
||||||
|
.error-msg.error-results {
|
||||||
|
background-color: #f3f3f4;
|
||||||
|
max-height: 200px;
|
||||||
|
overflow: auto
|
||||||
|
}
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,12 +1,21 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-card>
|
<el-card shadow="never">
|
||||||
<div slot="header">
|
<div slot="header" class="summary-header">
|
||||||
<span>卡片名称</span>
|
<span class="header-title">{{ title }}</span>
|
||||||
<span class="pull-right">卡片标签</span>
|
<span class="pull-right right-side">
|
||||||
</div>
|
<slot name="header-right">
|
||||||
<div>
|
<el-tag :type="rightSideLabel.type || 'success'" effect="dark" size="mini">{{ rightSideLabel.title }}</el-tag>
|
||||||
<span>卡片内容</span>
|
</slot>
|
||||||
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
<slot>
|
||||||
|
<h1 class="no-margins">
|
||||||
|
<a :href="body.link">
|
||||||
|
<span>{{ body.count }}</span>
|
||||||
|
</a>
|
||||||
|
</h1>
|
||||||
|
<small>{{ body.comment }}</small>
|
||||||
|
</slot>
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -14,12 +23,55 @@
|
|||||||
export default {
|
export default {
|
||||||
name: 'SummaryCard',
|
name: 'SummaryCard',
|
||||||
props: {
|
props: {
|
||||||
|
title: {
|
||||||
|
type: String,
|
||||||
|
default: ''
|
||||||
|
},
|
||||||
|
rightSideLabel: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style lang="scss" scoped>
|
||||||
.pull-right {
|
.pull-right {
|
||||||
float: right !important;
|
float: right !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.header-title {
|
||||||
|
font-size: 14px;
|
||||||
|
margin: 0 0 7px;
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
|
||||||
|
.right-side >>> .el-tag {
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 3px 8px;
|
||||||
|
text-shadow: none;
|
||||||
|
line-height: 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 30px;
|
||||||
|
font-weight: 100;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-card__body {
|
||||||
|
background-color: #ffffff;
|
||||||
|
color: inherit;
|
||||||
|
padding: 15px 20px 20px 20px !important;
|
||||||
|
border-color: #e7eaec;
|
||||||
|
border-image: none;
|
||||||
|
border-style: solid solid none;
|
||||||
|
border-width: 1px 0;
|
||||||
|
}
|
||||||
|
.no-margins {
|
||||||
|
margin: 0 !important;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,12 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<el-upload
|
<div>
|
||||||
v-bind="$attrs"
|
<input type="file" @change="Onchange">
|
||||||
@input="onInput"
|
<div v-if="tip !== ''">{{ tip }}</div>
|
||||||
v-on="$listeners"
|
<div>
|
||||||
>
|
<img :src="src" v-bind="$attrs">
|
||||||
<el-button size="small" type="primary">点击上传</el-button>
|
</div>
|
||||||
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
|
</div>
|
||||||
</el-upload>
|
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -15,16 +14,28 @@ export default {
|
|||||||
value: {
|
value: {
|
||||||
type: String,
|
type: String,
|
||||||
default: () => ''
|
default: () => ''
|
||||||
|
},
|
||||||
|
tip: {
|
||||||
|
type: String,
|
||||||
|
default: () => ''
|
||||||
|
}
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
src() {
|
||||||
|
return `${process.env.VUE_APP_BASE_API}${this.value}`
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
value(value) {
|
value(value) {
|
||||||
this.$emit('customEvent', value, 'message')
|
this.$emit('customEvent', value)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
onInput(val) {
|
onInput(val) {
|
||||||
this.$emit('input', 'my-input: ' + val)
|
this.$emit('input', 'upload-field: ' + val)
|
||||||
|
},
|
||||||
|
Onchange(e) {
|
||||||
|
this.$emit('fileChange', e.target.files[0])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -737,5 +737,20 @@
|
|||||||
"Assets": "",
|
"Assets": "",
|
||||||
"settings": {
|
"settings": {
|
||||||
"setting": ""
|
"setting": ""
|
||||||
|
},
|
||||||
|
"dashboard": {
|
||||||
|
"UsersTotal": "用户总数",
|
||||||
|
"AssetsTotal": "资产总数",
|
||||||
|
"OnlineUsers": "在线用户",
|
||||||
|
"OnlineSessions": "在线会话"
|
||||||
|
},
|
||||||
|
"xpack": {
|
||||||
|
"InterfaceSettings": "界面设置",
|
||||||
|
"loginTitle": "登录页面标题",
|
||||||
|
"loginImage": "登录页面图片",
|
||||||
|
"favicon": "网站图标",
|
||||||
|
"logoIndex": "管理页面logo",
|
||||||
|
"logoLogout": "退出页面logo",
|
||||||
|
"RestoreButton": "恢复默认"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,7 +8,7 @@ const getDefaultState = () => {
|
|||||||
const state = getDefaultState()
|
const state = getDefaultState()
|
||||||
|
|
||||||
const mutations = {
|
const mutations = {
|
||||||
setUrlMeta: (state, { url, meta }) => {
|
SET_URL_META: (state, { url, meta }) => {
|
||||||
state.metaMap[url] = meta
|
state.metaMap[url] = meta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -24,7 +24,7 @@ const actions = {
|
|||||||
}
|
}
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
optionUrlMeta(url).then(meta => {
|
optionUrlMeta(url).then(meta => {
|
||||||
commit('setUrlMeta', { url, meta })
|
commit('SET_URL_META', { url, meta })
|
||||||
resolve(meta)
|
resolve(meta)
|
||||||
}).catch(error => {
|
}).catch(error => {
|
||||||
reject(error)
|
reject(error)
|
||||||
|
@ -384,3 +384,20 @@ td .el-button.el-button--mini {
|
|||||||
padding-left: 10px;
|
padding-left: 10px;
|
||||||
padding-right: 14px;
|
padding-right: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.el-tag--dark.el-tag--info {
|
||||||
|
background-color: #23c6c8;
|
||||||
|
border-color: #23c6c8;
|
||||||
|
color: #fff;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #428bca !important;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tag--default.el-tag--dark {
|
||||||
|
background-color: #d1dade;
|
||||||
|
color: #5e5e5e;
|
||||||
|
border: none;
|
||||||
|
}
|
||||||
|
@ -71,3 +71,11 @@ div:focus {
|
|||||||
.el-tooltip__popper.is-light.help-tips div span {
|
.el-tooltip__popper.is-light.help-tips div span {
|
||||||
padding: 50px;
|
padding: 50px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.white-bg {
|
||||||
|
background-color: #ffffff;
|
||||||
|
}
|
||||||
|
|
||||||
|
.small, small {
|
||||||
|
font-size: 85%;
|
||||||
|
}
|
||||||
|
@ -75,11 +75,13 @@ service.interceptors.response.use(
|
|||||||
window.location = '/auth/login/'
|
window.location = '/auth/login/'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
if (!response.config.disableFlashMsg) {
|
||||||
Message({
|
Message({
|
||||||
message: error.message,
|
message: error.message,
|
||||||
type: 'error',
|
type: 'error',
|
||||||
duration: 5 * 1000
|
duration: 5 * 1000
|
||||||
})
|
})
|
||||||
|
}
|
||||||
return Promise.reject(error)
|
return Promise.reject(error)
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
71
src/views/dashboard/DatesLoginSummary/LoginActivePin.vue
Normal file
71
src/views/dashboard/DatesLoginSummary/LoginActivePin.vue
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
<template>
|
||||||
|
<div class="statistic-box">
|
||||||
|
<small>活跃用户资产占比</small>
|
||||||
|
<el-row :gutter="10">
|
||||||
|
<el-col :md="12" :sm="24">
|
||||||
|
<echarts :options="option" />
|
||||||
|
</el-col>
|
||||||
|
<el-col :md="12" :sm="24">
|
||||||
|
<echarts :options="option" />
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ECharts from 'vue-echarts'
|
||||||
|
import 'echarts/lib/chart/pie'
|
||||||
|
import 'echarts/lib/component/tooltip'
|
||||||
|
export default {
|
||||||
|
name: 'LoginActivePin',
|
||||||
|
components: { 'echarts': ECharts },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
option: {
|
||||||
|
legend: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
color: ['#1ab394', '#1C84C6', '#9CC3DA'],
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'item',
|
||||||
|
formatter: '{a} <br/>{b}: {c} ({d}%)'
|
||||||
|
},
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: '访问来源',
|
||||||
|
type: 'pie',
|
||||||
|
radius: ['50%', '70%'],
|
||||||
|
avoidLabelOverlap: false,
|
||||||
|
label: {
|
||||||
|
show: false,
|
||||||
|
position: 'center'
|
||||||
|
},
|
||||||
|
emphasis: {
|
||||||
|
label: {
|
||||||
|
show: true,
|
||||||
|
fontSize: '18',
|
||||||
|
fontWeight: 'bold'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
labelLine: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
data: [
|
||||||
|
{ value: 335, name: '直接访问' },
|
||||||
|
{ value: 310, name: '邮件营销' },
|
||||||
|
{ value: 234, name: '联盟广告' }
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.echarts {
|
||||||
|
width: 150px;
|
||||||
|
height: 250px;
|
||||||
|
}
|
||||||
|
</style>
|
167
src/views/dashboard/DatesLoginSummary/LoginMetric.vue
Normal file
167
src/views/dashboard/DatesLoginSummary/LoginMetric.vue
Normal file
@ -0,0 +1,167 @@
|
|||||||
|
<template>
|
||||||
|
<echarts :options="options" :autoresize="true" theme="light" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import ECharts from 'vue-echarts'
|
||||||
|
import 'echarts/lib/chart/line'
|
||||||
|
import 'echarts/lib/component/tooltip'
|
||||||
|
export default {
|
||||||
|
name: 'LoginMetric',
|
||||||
|
components: { 'echarts': ECharts },
|
||||||
|
data: function() {
|
||||||
|
return {
|
||||||
|
options: {
|
||||||
|
title: {
|
||||||
|
show: false
|
||||||
|
},
|
||||||
|
tooltip: {
|
||||||
|
trigger: 'axis',
|
||||||
|
axisPointer: {
|
||||||
|
type: 'cross',
|
||||||
|
label: {
|
||||||
|
backgroundColor: '#6a7985'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
legend: {
|
||||||
|
data: ['LoginCount', 'ActiveUser', 'ActiveAsset'],
|
||||||
|
formatter: function(name) {
|
||||||
|
const map = { LoginCount: '登录数量', ActiveUser: '用户', ActiveAsset: '资产' }
|
||||||
|
return map[name]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
grid: {
|
||||||
|
left: '3%',
|
||||||
|
right: '4%',
|
||||||
|
bottom: '3%',
|
||||||
|
containLabel: true
|
||||||
|
},
|
||||||
|
color: ['#1ab394', '#1C84C6', '#9CC3DA'],
|
||||||
|
xAxis: [
|
||||||
|
{
|
||||||
|
type: 'category',
|
||||||
|
boundaryGap: false,
|
||||||
|
data: [
|
||||||
|
'04-19', '04-20',
|
||||||
|
'04-21',
|
||||||
|
'04-22',
|
||||||
|
'04-23',
|
||||||
|
'04-24',
|
||||||
|
'04-25',
|
||||||
|
'04-26',
|
||||||
|
'04-27',
|
||||||
|
'04-28',
|
||||||
|
'04-29',
|
||||||
|
'04-30',
|
||||||
|
'05-01',
|
||||||
|
'05-02',
|
||||||
|
'05-03',
|
||||||
|
'05-04',
|
||||||
|
'05-05',
|
||||||
|
'05-06',
|
||||||
|
'05-07',
|
||||||
|
'05-09',
|
||||||
|
'05-11']
|
||||||
|
}
|
||||||
|
],
|
||||||
|
yAxis: [
|
||||||
|
{
|
||||||
|
type: 'value'
|
||||||
|
}
|
||||||
|
],
|
||||||
|
series: [
|
||||||
|
{
|
||||||
|
name: 'LoginCount',
|
||||||
|
type: 'line',
|
||||||
|
areaStyle: {},
|
||||||
|
smooth: true,
|
||||||
|
data: [20316,
|
||||||
|
35218,
|
||||||
|
12864,
|
||||||
|
37508,
|
||||||
|
11787,
|
||||||
|
37749,
|
||||||
|
28591,
|
||||||
|
28571,
|
||||||
|
8789,
|
||||||
|
11434,
|
||||||
|
2100,
|
||||||
|
35305,
|
||||||
|
27371,
|
||||||
|
5433,
|
||||||
|
59824,
|
||||||
|
69371,
|
||||||
|
11388,
|
||||||
|
101993,
|
||||||
|
26256,
|
||||||
|
0,
|
||||||
|
0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ActiveUser',
|
||||||
|
type: 'line',
|
||||||
|
areaStyle: {},
|
||||||
|
smooth: true,
|
||||||
|
data: [5079,
|
||||||
|
8804,
|
||||||
|
3216,
|
||||||
|
9377,
|
||||||
|
2946,
|
||||||
|
9437,
|
||||||
|
7147,
|
||||||
|
7143,
|
||||||
|
2197,
|
||||||
|
2857,
|
||||||
|
525,
|
||||||
|
8826,
|
||||||
|
6842,
|
||||||
|
905,
|
||||||
|
9970,
|
||||||
|
11562,
|
||||||
|
1898,
|
||||||
|
16999,
|
||||||
|
4376,
|
||||||
|
0,
|
||||||
|
0]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'ActiveAsset',
|
||||||
|
type: 'line',
|
||||||
|
areaStyle: {},
|
||||||
|
smooth: true,
|
||||||
|
data: [4323,
|
||||||
|
2079,
|
||||||
|
1666,
|
||||||
|
8837,
|
||||||
|
1417,
|
||||||
|
8567,
|
||||||
|
1492,
|
||||||
|
2969,
|
||||||
|
852,
|
||||||
|
690,
|
||||||
|
193,
|
||||||
|
2125,
|
||||||
|
5670,
|
||||||
|
127,
|
||||||
|
9148,
|
||||||
|
2237,
|
||||||
|
1685,
|
||||||
|
13882,
|
||||||
|
829,
|
||||||
|
0,
|
||||||
|
0]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.echarts {
|
||||||
|
width: 100%;
|
||||||
|
height: 300px;
|
||||||
|
}
|
||||||
|
</style>
|
101
src/views/dashboard/DatesLoginSummary/LoginTop.vue
Normal file
101
src/views/dashboard/DatesLoginSummary/LoginTop.vue
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
<template>
|
||||||
|
<div>
|
||||||
|
<small>过去一周, 共有 2 位用户登录 31 次资产.</small>
|
||||||
|
<ul class="list-group clear-list m-t">
|
||||||
|
<li v-for="(item, index) of summaryItems" :key="item.username" class="list-group-item fist-item">
|
||||||
|
<span class="pull-right">
|
||||||
|
{{ item.count }} 次/周
|
||||||
|
</span>
|
||||||
|
<el-tag effect="dark" size="small" :type="getLabelType(index)">{{ index + 1 }}</el-tag>
|
||||||
|
{{ item.username }}
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'LoginTop',
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
summaryItems: [
|
||||||
|
{
|
||||||
|
username: '周杰伦',
|
||||||
|
count: 42
|
||||||
|
},
|
||||||
|
{
|
||||||
|
username: '林俊杰',
|
||||||
|
count: 30
|
||||||
|
},
|
||||||
|
{
|
||||||
|
username: '蔡依林',
|
||||||
|
count: 28
|
||||||
|
},
|
||||||
|
{
|
||||||
|
username: '梁静茹',
|
||||||
|
count: 26
|
||||||
|
},
|
||||||
|
{
|
||||||
|
username: '孙燕姿',
|
||||||
|
count: 22
|
||||||
|
}
|
||||||
|
],
|
||||||
|
tabsType: ['success', 'info', 'primary', 'default', 'info']
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
getLabelType(index) {
|
||||||
|
return this.tabsType[index] || 'primary'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.m-t {
|
||||||
|
margin-top: 15px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group {
|
||||||
|
padding-left: 0;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group.clear-list .list-group-item {
|
||||||
|
border-top: 1px solid #e7eaec;
|
||||||
|
border-bottom: 0;
|
||||||
|
border-right: 0;
|
||||||
|
border-left: 0;
|
||||||
|
padding: 8px 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item:first-child {
|
||||||
|
border-top-left-radius: 4px;
|
||||||
|
border-top-right-radius: 4px;
|
||||||
|
border-top: none !important;
|
||||||
|
}
|
||||||
|
|
||||||
|
.list-group-item {
|
||||||
|
background-color: inherit;
|
||||||
|
border: 1px solid #e7eaec;
|
||||||
|
display: block;
|
||||||
|
margin-bottom: -1px;
|
||||||
|
padding: 8px 15px;
|
||||||
|
position: relative;
|
||||||
|
font-size: 13px;
|
||||||
|
line-height: 18px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-tag--small {
|
||||||
|
height: 24px;
|
||||||
|
font-size: 75%;
|
||||||
|
text-align: center;
|
||||||
|
white-space: nowrap;
|
||||||
|
vertical-align: baseline;
|
||||||
|
line-height: 16px;
|
||||||
|
margin-right: 10px;
|
||||||
|
font-weight: 600;
|
||||||
|
padding: 3px 8px;
|
||||||
|
text-shadow: none;
|
||||||
|
}
|
||||||
|
</style>
|
72
src/views/dashboard/DatesLoginSummary/index.vue
Normal file
72
src/views/dashboard/DatesLoginSummary/index.vue
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
<template>
|
||||||
|
<div class="white-bg dashboard-header">
|
||||||
|
<el-row>
|
||||||
|
<el-col :span="12">
|
||||||
|
<h2>登录汇总</h2>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="12">
|
||||||
|
<el-button-group style="float: right; padding: 0">
|
||||||
|
<el-button type="default" size="mini" :class="{ 'active': active === 'weekly'}" @click="changeDates('weekly')">Weekly</el-button>
|
||||||
|
<el-button type="default" size="mini" :class="{ 'active': active === 'monthly'}" @click="changeDates('monthly')">Monthly</el-button>
|
||||||
|
</el-button-group>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col :md="6" :sm="24">
|
||||||
|
<LoginTop />
|
||||||
|
</el-col>
|
||||||
|
<el-col :md="12" :sm="24">
|
||||||
|
<LoginMetric style="margin-top: -30px" heigth="300px" />
|
||||||
|
</el-col>
|
||||||
|
<el-col :md="6" :sm="24">
|
||||||
|
<LoginActivePin />
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import LoginTop from './LoginTop'
|
||||||
|
import LoginMetric from './LoginMetric'
|
||||||
|
import LoginActivePin from './LoginActivePin'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'DatesLoginSummary',
|
||||||
|
components: { LoginTop, LoginMetric, LoginActivePin },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
active: 'weekly'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
changeDates(type) {
|
||||||
|
this.active = type
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped>
|
||||||
|
.dashboard-header {
|
||||||
|
border-top: 0;
|
||||||
|
padding: 20px 20px 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin-top: 10px;
|
||||||
|
font-size: 26px;
|
||||||
|
font-weight: 100;
|
||||||
|
line-height: 1.1;
|
||||||
|
color: inherit;
|
||||||
|
}
|
||||||
|
|
||||||
|
.el-button--mini, .el-button--mini.is-round {
|
||||||
|
padding: 5px 10px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.active {
|
||||||
|
background-image: none;
|
||||||
|
border: 1px solid #d2d2d2;
|
||||||
|
-webkit-box-shadow: inset 0 3px 5px rgba(0,0,0,.125);
|
||||||
|
}
|
||||||
|
</style>
|
80
src/views/dashboard/ResourceSummary.vue
Normal file
80
src/views/dashboard/ResourceSummary.vue
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
<template>
|
||||||
|
<el-row :gutter="10">
|
||||||
|
<el-col v-for="item of summaryItems" :key="item.title" :md="6" :sm="12">
|
||||||
|
<SummaryCard :title="item.title" :right-side-label="item.rightSideLabel" :body="item.body" />
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { SummaryCard } from '@/components'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'ResourceSummary',
|
||||||
|
components: { SummaryCard },
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
summaryItems: [
|
||||||
|
{
|
||||||
|
title: this.$t('dashboard.UsersTotal'),
|
||||||
|
rightSideLabel: {
|
||||||
|
title: 'Users',
|
||||||
|
type: 'success'
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
link: '',
|
||||||
|
count: 10,
|
||||||
|
comment: 'All users'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: this.$t('dashboard.AssetsTotal'),
|
||||||
|
rightSideLabel: {
|
||||||
|
title: 'Assets',
|
||||||
|
type: 'info'
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
link: '',
|
||||||
|
count: 10,
|
||||||
|
comment: 'All assets'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: this.$t('dashboard.OnlineUsers'),
|
||||||
|
rightSideLabel: {
|
||||||
|
title: 'Online',
|
||||||
|
type: 'primary'
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
link: '',
|
||||||
|
count: 10,
|
||||||
|
comment: 'Online users'
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
title: this.$t('dashboard.OnlineSessions'),
|
||||||
|
rightSideLabel: {
|
||||||
|
title: 'Connected',
|
||||||
|
type: 'danger'
|
||||||
|
},
|
||||||
|
body: {
|
||||||
|
link: '',
|
||||||
|
count: 10,
|
||||||
|
comment: 'Online sessions'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.el-col {
|
||||||
|
margin-bottom: 25px;
|
||||||
|
&:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
@ -1,42 +1,27 @@
|
|||||||
<template>
|
<template>
|
||||||
<Page>
|
<Page>
|
||||||
<el-row :gutter="20">
|
<ResourceSummary />
|
||||||
<el-col :span="6"><SummaryCard /></el-col>
|
<DatesLoginSummary />
|
||||||
<el-col :span="6"><SummaryCard /></el-col>
|
|
||||||
<el-col :span="6"><SummaryCard /></el-col>
|
|
||||||
<el-col :span="6"><SummaryCard /></el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="20">
|
|
||||||
<el-col :span="4"><SummaryCard /></el-col>
|
|
||||||
<el-col :span="16"><SummaryCard /></el-col>
|
|
||||||
<el-col :span="4"><SummaryCard /></el-col>
|
|
||||||
</el-row>
|
|
||||||
<el-row :gutter="20">
|
|
||||||
<el-col :span="8"><SummaryCard /></el-col>
|
|
||||||
<el-col :span="8"><SummaryCard /></el-col>
|
|
||||||
<el-col :span="8"><SummaryCard /></el-col>
|
|
||||||
</el-row>
|
|
||||||
</Page>
|
</Page>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import Page from '@/layout/components/Page'
|
import { Page } from '@/layout/components'
|
||||||
import { SummaryCard } from '@/components'
|
import ResourceSummary from './ResourceSummary'
|
||||||
|
import DatesLoginSummary from './DatesLoginSummary'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'Dashboard',
|
name: 'Dashboard',
|
||||||
components: {
|
components: {
|
||||||
Page, SummaryCard
|
Page, DatesLoginSummary, ResourceSummary
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.el-row {
|
|
||||||
margin-bottom: 25px;
|
|
||||||
&:last-child {
|
|
||||||
margin-bottom: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
</style>
|
</style>
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="10">
|
||||||
<RunInfoCard type="primary" v-bind="RunSuccessConfig" />
|
<RunInfoCard type="primary" v-bind="RunSuccessConfig" />
|
||||||
<RunInfoCard type="info" style="margin-top: 15px" v-bind="RunFailedConfig" />
|
<RunInfoCard type="danger" style="margin-top: 15px" v-bind="RunFailedConfig" />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
@ -32,23 +32,18 @@ export default {
|
|||||||
RunSuccessConfig: {
|
RunSuccessConfig: {
|
||||||
icon: 'fa-info',
|
icon: 'fa-info',
|
||||||
title: this.$t('jobcenter.lastRunSuccessHosts'),
|
title: this.$t('jobcenter.lastRunSuccessHosts'),
|
||||||
content: [
|
content: {
|
||||||
{
|
|
||||||
hostname: 'linux',
|
hostname: 'linux',
|
||||||
result: 'api没有该数据,api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据'
|
result: 'api没有该数据,api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据'
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
},
|
||||||
RunFailedConfig: {
|
RunFailedConfig: {
|
||||||
icon: 'fa-info',
|
icon: 'fa-info',
|
||||||
title: this.$t('jobcenter.lastRunFailedHosts'),
|
title: this.$t('jobcenter.lastRunFailedHosts'),
|
||||||
headerColor: 'danger',
|
content: {
|
||||||
content: [
|
|
||||||
{
|
|
||||||
hostname: 'window',
|
hostname: 'window',
|
||||||
result: 'api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据'
|
result: 'api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据'
|
||||||
}
|
}
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
</el-col>
|
</el-col>
|
||||||
<el-col :span="10">
|
<el-col :span="10">
|
||||||
<RunInfoCard type="primary" v-bind="RunSuccessConfig" />
|
<RunInfoCard type="primary" v-bind="RunSuccessConfig" />
|
||||||
<RunInfoCard type="info" style="margin-top: 15px" v-bind="RunFailedConfig" />
|
<RunInfoCard type="danger" style="margin-top: 15px" v-bind="RunFailedConfig" />
|
||||||
</el-col>
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</template>
|
</template>
|
||||||
@ -32,23 +32,18 @@ export default {
|
|||||||
RunSuccessConfig: {
|
RunSuccessConfig: {
|
||||||
icon: 'fa-info',
|
icon: 'fa-info',
|
||||||
title: this.$t('jobcenter.lastRunSuccessHosts'),
|
title: this.$t('jobcenter.lastRunSuccessHosts'),
|
||||||
content: [
|
content: {
|
||||||
{
|
|
||||||
hostname: 'linux',
|
hostname: 'linux',
|
||||||
result: 'api没有该数据==api没有该数据api没有该数据api没有该数据api没有该数据'
|
result: 'api没有该数据==api没有该数据api没有该数据api没有该数据api没有该数据'
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
},
|
||||||
RunFailedConfig: {
|
RunFailedConfig: {
|
||||||
icon: 'fa-info',
|
icon: 'fa-info',
|
||||||
title: this.$t('jobcenter.lastRunFailedHosts'),
|
title: this.$t('jobcenter.lastRunFailedHosts'),
|
||||||
headerColor: 'danger',
|
content: {
|
||||||
content: [
|
hostname: 'linux',
|
||||||
{
|
result: 'api没有该数据==api没有该数据api没有该数据api没有该数据api没有该数据'
|
||||||
hostname: 'window',
|
|
||||||
result: 'api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据'
|
|
||||||
}
|
}
|
||||||
]
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -32,23 +32,18 @@ export default {
|
|||||||
RunSuccessConfig: {
|
RunSuccessConfig: {
|
||||||
icon: 'fa-info',
|
icon: 'fa-info',
|
||||||
title: this.$t('jobcenter.lastRunSuccessHosts'),
|
title: this.$t('jobcenter.lastRunSuccessHosts'),
|
||||||
content: [
|
content: {
|
||||||
{
|
|
||||||
hostname: 'linux',
|
hostname: 'linux',
|
||||||
result: 'api没有该数据==api没有该数据api没有该数据api没有该数据api没有该数据'
|
result: 'api没有该数据==api没有该数据api没有该数据api没有该数据api没有该数据'
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
},
|
||||||
RunFailedConfig: {
|
RunFailedConfig: {
|
||||||
icon: 'fa-info',
|
icon: 'fa-info',
|
||||||
title: this.$t('jobcenter.lastRunFailedHosts'),
|
title: this.$t('jobcenter.lastRunFailedHosts'),
|
||||||
headerColor: 'danger',
|
content: {
|
||||||
content: [
|
|
||||||
{
|
|
||||||
hostname: 'window',
|
hostname: 'window',
|
||||||
result: 'api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据'
|
result: 'api没有该数据api没有该数据api没有该数据api没有该数据api没有该数据'
|
||||||
}
|
}
|
||||||
]
|
|
||||||
},
|
},
|
||||||
taskData: {}
|
taskData: {}
|
||||||
}
|
}
|
||||||
|
@ -1,13 +1,11 @@
|
|||||||
<template>
|
<template>
|
||||||
<IBox :fa="icon" :type="type" :title="title" v-bind="$attrs">
|
<IBox :fa="icon" :type="type" :title="title" v-bind="$attrs">
|
||||||
<el-table class="el-table" style="width: 100%" :data="content" :show-header="false">
|
<table class="run-info">
|
||||||
<el-table-column width="150px" prop="hostname" />
|
<tr>
|
||||||
<el-table-column prop="result">
|
<td>{{ content.hostname }}</td>
|
||||||
<template slot-scope="scope">
|
<td>{{ content.result }}</td>
|
||||||
<span>{{ scope.row.result }}</span>
|
</tr>
|
||||||
</template>
|
</table>
|
||||||
</el-table-column>
|
|
||||||
</el-table>
|
|
||||||
</IBox>
|
</IBox>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
@ -29,8 +27,8 @@ export default {
|
|||||||
default: ''
|
default: ''
|
||||||
},
|
},
|
||||||
content: {
|
content: {
|
||||||
type: Array,
|
type: Object,
|
||||||
default: () => []
|
default: () => ({})
|
||||||
},
|
},
|
||||||
url: {
|
url: {
|
||||||
type: String,
|
type: String,
|
||||||
@ -45,5 +43,13 @@ export default {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style scoped>
|
<style scoped>
|
||||||
|
.run-info {
|
||||||
|
line-height: 1.43;
|
||||||
|
padding: 8px;
|
||||||
|
vertical-align: top;
|
||||||
|
font-size: 13px;
|
||||||
|
}
|
||||||
|
.run-info > tr:first-child > td:first-child {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<GenericTreeListPage :table-config="tableConfig" :tree-setting="treeSetting" />
|
<GenericTreeListPage :table-config="tableConfig" :tree-setting="treeSetting" :header-actions="headerActions" />
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@ -28,7 +28,28 @@ export default {
|
|||||||
],
|
],
|
||||||
columnsMeta: {
|
columnsMeta: {
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
headerActions: {
|
||||||
|
hasCreate: false,
|
||||||
|
hasBulkDelete: false,
|
||||||
|
hasImport: false,
|
||||||
|
hasRefresh: false,
|
||||||
|
extraActions: [
|
||||||
|
{
|
||||||
|
name: 'gather-user-tasks',
|
||||||
|
title: '收集用户任务',
|
||||||
|
type: 'primary',
|
||||||
|
has: true,
|
||||||
|
can: true,
|
||||||
|
callback: this.onGatherUserTasks
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
onGatherUserTasks() {
|
||||||
|
this.$router.push({ name: 'GatherUserTaskList' })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
46
src/views/xpack/GatheredUser/TaskCreateUpdate.vue
Normal file
46
src/views/xpack/GatheredUser/TaskCreateUpdate.vue
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
<template>
|
||||||
|
<GenericCreateUpdatePage v-bind="$data" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import { GenericCreateUpdatePage } from '@/layout/components'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
GenericCreateUpdatePage
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
fields: [
|
||||||
|
['收集用户任务', ['name', 'nodes', 'is_periodic', 'crontab', 'interval', 'comment']]
|
||||||
|
],
|
||||||
|
url: '/api/v1/xpack/gathered-user/tasks/',
|
||||||
|
fieldsMeta: {
|
||||||
|
nodes: {
|
||||||
|
el: {
|
||||||
|
multiple: true,
|
||||||
|
value: [],
|
||||||
|
ajax: {
|
||||||
|
url: '/api/v1/assets/nodes/',
|
||||||
|
processResults(data) {
|
||||||
|
const results = data.results.map((item) => {
|
||||||
|
return { label: item.name, value: item.id }
|
||||||
|
})
|
||||||
|
const more = !!data.next
|
||||||
|
return { results: results, pagination: more, total: data.count }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
'is_periodic': {
|
||||||
|
type: 'switch'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style lang="less" scoped>
|
||||||
|
</style>
|
35
src/views/xpack/GatheredUser/TaskList.vue
Normal file
35
src/views/xpack/GatheredUser/TaskList.vue
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
<template>
|
||||||
|
<GenericListPage :table-config="tableConfig" :header-actions="headerActions" />
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
import GenericListPage from '@/layout/components/GenericListPage'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
components: {
|
||||||
|
GenericListPage
|
||||||
|
},
|
||||||
|
data() {
|
||||||
|
return {
|
||||||
|
tableConfig: {
|
||||||
|
url: '/api/v1/xpack/gathered-user/tasks/',
|
||||||
|
columns: [
|
||||||
|
'name', 'nodes', 'periodic_display', 'executed_times', 'actions'
|
||||||
|
],
|
||||||
|
columnsMeta: {}
|
||||||
|
},
|
||||||
|
headerActions: {
|
||||||
|
hasBulkDelete: false,
|
||||||
|
hasImport: false,
|
||||||
|
hasRefresh: false,
|
||||||
|
hasExport: false,
|
||||||
|
createRoute: 'GatherUserTaskCreate'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
|
||||||
|
</style>
|
@ -1,11 +1,14 @@
|
|||||||
<template>
|
<template>
|
||||||
<TabPage :submenu="submenu" :active-menu="activemenu">
|
<TabPage :submenu="submenu" :active-menu="activeMenu">
|
||||||
<IBox>
|
<IBox v-if="!loading">
|
||||||
<GenericCreateUpdateForm
|
<GenericCreateUpdateForm
|
||||||
:fields="fields"
|
:fields="fields"
|
||||||
:url="url"
|
:url="url"
|
||||||
|
:initial="interfaceInfo"
|
||||||
:update-success-next-route="successUrl"
|
:update-success-next-route="successUrl"
|
||||||
:fields-meta="fieldsMeta"
|
:fields-meta="fieldsMeta"
|
||||||
|
:on-submit="submitForm"
|
||||||
|
:more-buttons="moreButtons"
|
||||||
/>
|
/>
|
||||||
</IBox>
|
</IBox>
|
||||||
</TabPage>
|
</TabPage>
|
||||||
@ -13,9 +16,9 @@
|
|||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { TabPage } from '@/layout/components'
|
import { TabPage } from '@/layout/components'
|
||||||
import { IBox } from '@/components'
|
import { IBox, UploadField } from '@/components'
|
||||||
import GenericCreateUpdateForm from '@/layout/components/GenericCreateUpdateForm'
|
import GenericCreateUpdateForm from '@/layout/components/GenericCreateUpdateForm'
|
||||||
import { UploadField } from '@/components'
|
import { getInterfaceInfo, postInterface, restoreInterface } from '@/views/xpack/api'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'InterfaceSettings',
|
name: 'InterfaceSettings',
|
||||||
@ -26,10 +29,13 @@ export default {
|
|||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
activemenu: 'interface',
|
loading: true,
|
||||||
|
files: {},
|
||||||
|
interfaceInfo: {},
|
||||||
|
activeMenu: 'interface',
|
||||||
submenu: [
|
submenu: [
|
||||||
{
|
{
|
||||||
title: 'interface-settings',
|
title: this.$t('xpack.InterfaceSettings'),
|
||||||
name: 'interface'
|
name: 'interface'
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@ -43,40 +49,112 @@ export default {
|
|||||||
],
|
],
|
||||||
fieldsMeta: {
|
fieldsMeta: {
|
||||||
login_title: {
|
login_title: {
|
||||||
label: 'login_title'
|
label: this.$t('xpack.loginTitle'),
|
||||||
|
helpText: '提示:将会显示在企业版用户登录页面(eg: 欢迎使用JumpServer开源堡垒机)'
|
||||||
},
|
},
|
||||||
login_image: {
|
login_image: {
|
||||||
label: 'login_image'
|
component: UploadField,
|
||||||
|
label: this.$t('xpack.loginImage'),
|
||||||
|
el: {
|
||||||
|
width: '10%',
|
||||||
|
height: '10%',
|
||||||
|
tip: '提示:将会显示在企业版用户登录页面(建议图片大小为: 492*472px)'
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
fileChange: ([value], updateForm) => {
|
||||||
|
console.log(value)
|
||||||
|
this.files['login_image'] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
favicon: {
|
favicon: {
|
||||||
label: 'favicon'
|
component: UploadField,
|
||||||
|
label: this.$t('xpack.favicon'),
|
||||||
|
el: {
|
||||||
|
width: '5%',
|
||||||
|
height: '5%',
|
||||||
|
tip: '提示:网站图标(建议图片大小为: 16px*16px)'
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
fileChange: ([value], updateForm) => {
|
||||||
|
this.files['favicon'] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
logo_index: {
|
logo_index: {
|
||||||
label: 'logo_index'
|
component: UploadField,
|
||||||
|
label: this.$t('xpack.logoIndex'),
|
||||||
|
el: {
|
||||||
|
width: '10%',
|
||||||
|
height: '10%',
|
||||||
|
tip: '提示:将会显示在管理页面左上方(建议图片大小为: 185px*55px)'
|
||||||
|
},
|
||||||
|
on: {
|
||||||
|
fileChange: ([value], updateForm) => {
|
||||||
|
this.files['logo_index'] = value
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
logo_logout: {
|
logo_logout: {
|
||||||
component: UploadField,
|
component: UploadField,
|
||||||
label: 'logo_logout',
|
label: this.$t('xpack.logoLogout'),
|
||||||
el: {
|
el: {
|
||||||
action: '/api/v1/xpack/interface/setting/',
|
width: '5%',
|
||||||
autoUpload: false,
|
height: '5%',
|
||||||
name: 'logo_logout',
|
tip: '提示:将会显示在企业版用户退出页面(建议图片大小为:82px*82px)'
|
||||||
onChange: function(file, fileList) {
|
|
||||||
console.log(file, fileList)
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
on: {
|
on: {
|
||||||
focus: ([event], updateForm) => {
|
fileChange: ([value], updateForm) => {
|
||||||
console.log(event.target.value) // output: input value
|
this.files['logo_logout'] = value
|
||||||
},
|
|
||||||
customEvent: ([value, msg], updateForm) => {
|
|
||||||
console.log(msg) // output: 'message'
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
url: '/api/v1/xpack/interface/setting'
|
url: '/api/v1/xpack/interface/setting',
|
||||||
|
moreButtons: [
|
||||||
|
{
|
||||||
|
title: this.$t('xpack.RestoreButton'),
|
||||||
|
callback: function(value, form) {
|
||||||
|
this.$confirm('您确定要恢复默认初始化吗?', '你确认吗?', {
|
||||||
|
confirmButtonText: '确定',
|
||||||
|
cancelButtonText: '取消',
|
||||||
|
type: 'warning'
|
||||||
|
}).then(() => {
|
||||||
|
restoreInterface().then(res => {
|
||||||
|
this.$message.success(res.success)
|
||||||
|
location.reload()
|
||||||
|
}).catch(errMsg => {
|
||||||
|
this.$message.error(errMsg.response.data.error)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}.bind(this)
|
||||||
}
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
mounted() {
|
||||||
|
getInterfaceInfo().then(data => {
|
||||||
|
this.interfaceInfo = data
|
||||||
|
this.loading = false
|
||||||
|
})
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
submitForm(values) {
|
||||||
|
const form = new FormData()
|
||||||
|
const ImageKeys = ['favicon', 'login_image', 'logo_logout', 'logo_index']
|
||||||
|
ImageKeys.forEach((value, index) => {
|
||||||
|
if (this.files[value] !== undefined) {
|
||||||
|
form.append(value, this.files[value])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
if (values['login_title'] !== undefined) {
|
||||||
|
form.append('login_title', values['login_title'])
|
||||||
|
}
|
||||||
|
postInterface(form).then(res => {
|
||||||
|
location.reload()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
25
src/views/xpack/api.js
Normal file
25
src/views/xpack/api.js
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
import request from '@/utils/request'
|
||||||
|
|
||||||
|
export function postInterface(formData) {
|
||||||
|
return request({
|
||||||
|
url: '/api/v1/xpack/interface/setting',
|
||||||
|
method: 'put',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'multipart/form-data'
|
||||||
|
},
|
||||||
|
data: formData
|
||||||
|
})
|
||||||
|
}
|
||||||
|
export function getInterfaceInfo() {
|
||||||
|
return request({
|
||||||
|
url: '/api/v1/xpack/interface/setting',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
export function restoreInterface() {
|
||||||
|
return request({
|
||||||
|
url: '/xpack/interface/restore/default',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import Layout from '@/layout/index'
|
import Layout from '@/layout/index'
|
||||||
|
import i18n from '@/i18n/i18n'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
path: '/xpack',
|
path: '/xpack',
|
||||||
@ -11,7 +12,7 @@ export default {
|
|||||||
path: 'interface-setting',
|
path: 'interface-setting',
|
||||||
component: () => import('@/views/xpack/InterfaceSettings.vue'),
|
component: () => import('@/views/xpack/InterfaceSettings.vue'),
|
||||||
name: 'InterfaceSetting',
|
name: 'InterfaceSetting',
|
||||||
meta: { title: 'InterfaceSetting' }
|
meta: { title: i18n.t('xpack.InterfaceSettings') }
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'license',
|
path: 'license',
|
||||||
@ -21,9 +22,30 @@ export default {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
path: 'gathered-users',
|
path: 'gathered-users',
|
||||||
component: () => import('@/views/xpack/GatherUser'),
|
component: () => import('@/views/xpack/GatheredUser/GatheredUserList'),
|
||||||
name: 'GatherUser',
|
name: 'GatherUserList',
|
||||||
meta: { title: 'GatherUser' }
|
meta: { title: 'GatherUserList' }
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'gathered-users/tasks',
|
||||||
|
component: () => import('@/views/xpack/GatheredUser/TaskList'),
|
||||||
|
name: 'GatherUserTaskList',
|
||||||
|
meta: { title: 'GatherUserTask' },
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'gathered-users/tasks/create',
|
||||||
|
component: () => import('@/views/xpack/GatheredUser/TaskCreateUpdate'),
|
||||||
|
name: 'GatherUserTaskCreate',
|
||||||
|
meta: { title: 'GatherUserTaskCreate', action: 'create' },
|
||||||
|
hidden: true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
path: 'gathered-users/tasks/update',
|
||||||
|
component: () => import('@/views/xpack/GatheredUser/TaskCreateUpdate'),
|
||||||
|
name: 'GatherUserTaskUpdate',
|
||||||
|
meta: { title: 'GatherUserTaskUpdate', action: 'update' },
|
||||||
|
hidden: true
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
31
yarn.lock
31
yarn.lock
@ -2689,6 +2689,11 @@ core-js@^2.4.0, core-js@^2.5.0, core-js@^2.5.7, core-js@^2.6.5:
|
|||||||
version "2.6.11"
|
version "2.6.11"
|
||||||
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
|
resolved "https://registry.yarnpkg.com/core-js/-/core-js-2.6.11.tgz#38831469f9922bded8ee21c9dc46985e0399308c"
|
||||||
|
|
||||||
|
core-js@^3.4.4:
|
||||||
|
version "3.6.5"
|
||||||
|
resolved "https://registry.npm.taobao.org/core-js/download/core-js-3.6.5.tgz#7395dc273af37fb2e50e9bd3d9fe841285231d1a"
|
||||||
|
integrity sha1-c5XcJzrzf7LlDpvT2f6EEoUjHRo=
|
||||||
|
|
||||||
core-util-is@1.0.2, core-util-is@~1.0.0:
|
core-util-is@1.0.2, core-util-is@~1.0.0:
|
||||||
version "1.0.2"
|
version "1.0.2"
|
||||||
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7"
|
||||||
@ -3331,6 +3336,13 @@ ecc-jsbn@~0.1.1:
|
|||||||
jsbn "~0.1.0"
|
jsbn "~0.1.0"
|
||||||
safer-buffer "^2.1.0"
|
safer-buffer "^2.1.0"
|
||||||
|
|
||||||
|
echarts@^4.7.0:
|
||||||
|
version "4.7.0"
|
||||||
|
resolved "https://registry.npm.taobao.org/echarts/download/echarts-4.7.0.tgz?cache=0&sync_timestamp=1584522755461&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fecharts%2Fdownload%2Fecharts-4.7.0.tgz#5b3875a4c2f91e3929425fabab9eace7e4098b3f"
|
||||||
|
integrity sha1-Wzh1pML5HjkpQl+rq56s5+QJiz8=
|
||||||
|
dependencies:
|
||||||
|
zrender "4.3.0"
|
||||||
|
|
||||||
editorconfig@^0.15.3:
|
editorconfig@^0.15.3:
|
||||||
version "0.15.3"
|
version "0.15.3"
|
||||||
resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5"
|
resolved "https://registry.yarnpkg.com/editorconfig/-/editorconfig-0.15.3.tgz#bef84c4e75fb8dcb0ce5cee8efd51c15999befc5"
|
||||||
@ -8187,6 +8199,11 @@ reselect@^3.0.1:
|
|||||||
version "3.0.1"
|
version "3.0.1"
|
||||||
resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147"
|
resolved "https://registry.yarnpkg.com/reselect/-/reselect-3.0.1.tgz#efdaa98ea7451324d092b2b2163a6a1d7a9a2147"
|
||||||
|
|
||||||
|
resize-detector@^0.1.10:
|
||||||
|
version "0.1.10"
|
||||||
|
resolved "https://registry.npm.taobao.org/resize-detector/download/resize-detector-0.1.10.tgz#1da3f961aa5f914ccbcfd3752d52fd45beeb692c"
|
||||||
|
integrity sha1-HaP5YapfkUzLz9N1LVL9Rb7raSw=
|
||||||
|
|
||||||
resize-observer-polyfill@^1.5.0:
|
resize-observer-polyfill@^1.5.0:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
|
resolved "https://registry.yarnpkg.com/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz#0e9020dd3d21024458d4ebd27e23e40269810464"
|
||||||
@ -9573,6 +9590,15 @@ vue-cookie@^1.1.4:
|
|||||||
dependencies:
|
dependencies:
|
||||||
tiny-cookie "^1.0"
|
tiny-cookie "^1.0"
|
||||||
|
|
||||||
|
vue-echarts@^5.0.0-beta.0:
|
||||||
|
version "5.0.0-beta.0"
|
||||||
|
resolved "https://registry.npm.taobao.org/vue-echarts/download/vue-echarts-5.0.0-beta.0.tgz#438dd4b0fc5ccea281709c1f7c6321b05352bdf4"
|
||||||
|
integrity sha1-Q43UsPxczqKBcJwffGMhsFNSvfQ=
|
||||||
|
dependencies:
|
||||||
|
core-js "^3.4.4"
|
||||||
|
lodash "^4.17.15"
|
||||||
|
resize-detector "^0.1.10"
|
||||||
|
|
||||||
vue-eslint-parser@^2.0.3:
|
vue-eslint-parser@^2.0.3:
|
||||||
version "2.0.3"
|
version "2.0.3"
|
||||||
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz#c268c96c6d94cfe3d938a5f7593959b0ca3360d1"
|
resolved "https://registry.yarnpkg.com/vue-eslint-parser/-/vue-eslint-parser-2.0.3.tgz#c268c96c6d94cfe3d938a5f7593959b0ca3360d1"
|
||||||
@ -10152,6 +10178,11 @@ yorkie@^2.0.0:
|
|||||||
normalize-path "^1.0.0"
|
normalize-path "^1.0.0"
|
||||||
strip-indent "^2.0.0"
|
strip-indent "^2.0.0"
|
||||||
|
|
||||||
|
zrender@4.3.0:
|
||||||
|
version "4.3.0"
|
||||||
|
resolved "https://registry.npm.taobao.org/zrender/download/zrender-4.3.0.tgz#9f056121b20bbae44414d287bf6a119ff7042661"
|
||||||
|
integrity sha1-nwVhIbILuuREFNKHv2oRn/cEJmE=
|
||||||
|
|
||||||
ztree@^3.5.24:
|
ztree@^3.5.24:
|
||||||
version "3.5.24"
|
version "3.5.24"
|
||||||
resolved "https://registry.yarnpkg.com/ztree/-/ztree-3.5.24.tgz#b63fe52981fdf2c329675cfd2772f0d147521ff1"
|
resolved "https://registry.yarnpkg.com/ztree/-/ztree-3.5.24.tgz#b63fe52981fdf2c329675cfd2772f0d147521ff1"
|
||||||
|
Loading…
Reference in New Issue
Block a user