mirror of
https://github.com/apache/cloudstack.git
synced 2025-10-26 08:42:29 +01:00
src: codebase wide cleanup and refactorings
Signed-off-by: Rohit Yadav <rohit.yadav@shapeblue.com>
This commit is contained in:
parent
7dad796113
commit
8b196ed56c
@ -1,102 +0,0 @@
|
||||
<template>
|
||||
<span>
|
||||
{{ lastTime | format }}
|
||||
</span>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
function fixedZero (val) {
|
||||
return val * 1 < 10 ? `0${val}` : val
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'CountDown',
|
||||
props: {
|
||||
format: {
|
||||
type: Function,
|
||||
default: undefined
|
||||
},
|
||||
target: {
|
||||
type: [Date, Number],
|
||||
required: true
|
||||
},
|
||||
onEnd: {
|
||||
type: Function,
|
||||
default: () => ({})
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
dateTime: '0',
|
||||
originTargetTime: 0,
|
||||
lastTime: 0,
|
||||
timer: 0,
|
||||
interval: 1000
|
||||
}
|
||||
},
|
||||
filters: {
|
||||
format (time) {
|
||||
const hours = 60 * 60 * 1000
|
||||
const minutes = 60 * 1000
|
||||
|
||||
const h = Math.floor(time / hours)
|
||||
const m = Math.floor((time - h * hours) / minutes)
|
||||
const s = Math.floor((time - h * hours - m * minutes) / 1000)
|
||||
return `${fixedZero(h)}:${fixedZero(m)}:${fixedZero(s)}`
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.initTime()
|
||||
this.tick()
|
||||
},
|
||||
methods: {
|
||||
initTime () {
|
||||
let lastTime = 0
|
||||
let targetTime = 0
|
||||
this.originTargetTime = this.target
|
||||
try {
|
||||
if (Object.prototype.toString.call(this.target) === '[object Date]') {
|
||||
targetTime = this.target
|
||||
} else {
|
||||
targetTime = new Date(this.target).getTime()
|
||||
}
|
||||
} catch (e) {
|
||||
throw new Error('invalid target prop')
|
||||
}
|
||||
|
||||
lastTime = targetTime - new Date().getTime()
|
||||
|
||||
this.lastTime = lastTime < 0 ? 0 : lastTime
|
||||
},
|
||||
tick () {
|
||||
const { onEnd } = this
|
||||
|
||||
this.timer = setTimeout(() => {
|
||||
if (this.lastTime < this.interval) {
|
||||
clearTimeout(this.timer)
|
||||
this.lastTime = 0
|
||||
if (typeof onEnd === 'function') {
|
||||
onEnd()
|
||||
}
|
||||
} else {
|
||||
this.lastTime -= this.interval
|
||||
this.tick()
|
||||
}
|
||||
}, this.interval)
|
||||
}
|
||||
},
|
||||
beforeUpdate () {
|
||||
if (this.originTargetTime !== this.target) {
|
||||
this.initTime()
|
||||
}
|
||||
},
|
||||
beforeDestroy () {
|
||||
clearTimeout(this.timer)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
|
||||
</style>
|
||||
@ -1,3 +0,0 @@
|
||||
import CountDown from './CountDown'
|
||||
|
||||
export default CountDown
|
||||
@ -1,64 +0,0 @@
|
||||
<script>
|
||||
import Tooltip from 'ant-design-vue/es/tooltip'
|
||||
import { cutStrByFullLength, getStrFullLength } from '@/components/_util/util'
|
||||
/*
|
||||
const isSupportLineClamp = document.body.style.webkitLineClamp !== undefined;
|
||||
|
||||
const TooltipOverlayStyle = {
|
||||
overflowWrap: 'break-word',
|
||||
wordWrap: 'break-word',
|
||||
};
|
||||
*/
|
||||
|
||||
export default {
|
||||
name: 'Ellipsis',
|
||||
components: {
|
||||
Tooltip
|
||||
},
|
||||
props: {
|
||||
prefixCls: {
|
||||
type: String,
|
||||
default: 'ant-pro-ellipsis'
|
||||
},
|
||||
tooltip: {
|
||||
type: Boolean
|
||||
},
|
||||
length: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
lines: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
fullWidthRecognition: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
getStrDom (str, fullLength) {
|
||||
return (
|
||||
<span>{ cutStrByFullLength(str, this.length) + (fullLength > this.length ? '...' : '') }</span>
|
||||
)
|
||||
},
|
||||
getTooltip (fullStr, fullLength) {
|
||||
return (
|
||||
<Tooltip>
|
||||
<template slot="title">{ fullStr }</template>
|
||||
{ this.getStrDom(fullStr, fullLength) }
|
||||
</Tooltip>
|
||||
)
|
||||
}
|
||||
},
|
||||
render () {
|
||||
const { tooltip, length } = this.$props
|
||||
const str = this.$slots.default.map(vNode => vNode.text).join('')
|
||||
const fullLength = getStrFullLength(str)
|
||||
const strDom = tooltip && fullLength > length ? this.getTooltip(str, fullLength) : this.getStrDom(str, fullLength)
|
||||
return (
|
||||
strDom
|
||||
)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -1,3 +0,0 @@
|
||||
import Ellipsis from './Ellipsis'
|
||||
|
||||
export default Ellipsis
|
||||
@ -1,57 +0,0 @@
|
||||
<template>
|
||||
<div class="footer-toolbar">
|
||||
<div class="footer-toolbar-left">
|
||||
<slot name="extra">{{ extra }}</slot>
|
||||
</div>
|
||||
<div class="footer-toolbar-right">
|
||||
<slot></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'FooterToolBar',
|
||||
props: {
|
||||
prefixCls: {
|
||||
type: String,
|
||||
default: 'reduced'
|
||||
},
|
||||
extra: {
|
||||
type: [String, Object],
|
||||
default: ''
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.footer-toolbar {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.03);
|
||||
background: #fff;
|
||||
border-top: 1px solid #e8e8e8;
|
||||
padding: 0 24px;
|
||||
z-index: 9;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
&-left {
|
||||
float: left;
|
||||
}
|
||||
|
||||
&-right {
|
||||
float: right;
|
||||
}
|
||||
|
||||
}
|
||||
</style>
|
||||
@ -1,4 +0,0 @@
|
||||
import FooterToolBar from './FooterToolBar'
|
||||
import './index.less'
|
||||
|
||||
export default FooterToolBar
|
||||
@ -1,23 +0,0 @@
|
||||
@import "../../style/variables/prefixes";
|
||||
|
||||
@footer-toolbar-prefix-cls: ~"@{ant-pro-prefix}-footer-toolbar";
|
||||
|
||||
.@{footer-toolbar-prefix-cls} {
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
box-shadow: 0 -1px 2px rgba(0, 0, 0, 0.03);
|
||||
background: #fff;
|
||||
border-top: 1px solid #e8e8e8;
|
||||
padding: 0 24px;
|
||||
z-index: 9;
|
||||
|
||||
&:after {
|
||||
content: "";
|
||||
display: block;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
@ -1,106 +0,0 @@
|
||||
<template>
|
||||
<div :class="[prefixCls]">
|
||||
<slot name="subtitle">
|
||||
<div :class="[`${prefixCls}-subtitle`]">{{ typeof subTitle === 'string' ? subTitle : subTitle() }}</div>
|
||||
</slot>
|
||||
<div class="number-info-value">
|
||||
<span>{{ total }}</span>
|
||||
<span class="sub-total">
|
||||
{{ subTotal }}
|
||||
<icon :type="`caret-${status}`" />
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Icon from 'ant-design-vue/es/icon'
|
||||
|
||||
export default {
|
||||
name: 'NumberInfo',
|
||||
props: {
|
||||
prefixCls: {
|
||||
type: String,
|
||||
default: 'number-info'
|
||||
},
|
||||
total: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
subTotal: {
|
||||
type: Number,
|
||||
required: true
|
||||
},
|
||||
subTitle: {
|
||||
type: [String, Function],
|
||||
default: ''
|
||||
},
|
||||
status: {
|
||||
type: String,
|
||||
default: 'up'
|
||||
}
|
||||
},
|
||||
components: {
|
||||
Icon
|
||||
},
|
||||
data () {
|
||||
return {}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import '~ant-design-vue/lib/style/themes/default';
|
||||
|
||||
.number-info {
|
||||
|
||||
.number-info-subtitle {
|
||||
color: @text-color-secondary;
|
||||
font-size: @font-size-base;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.number-info-value {
|
||||
margin-top: 4px;
|
||||
font-size: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
white-space: nowrap;
|
||||
|
||||
& > span {
|
||||
color: @heading-color;
|
||||
display: inline-block;
|
||||
line-height: 32px;
|
||||
height: 32px;
|
||||
font-size: 24px;
|
||||
margin-right: 32px;
|
||||
}
|
||||
|
||||
.sub-total {
|
||||
color: @text-color-secondary;
|
||||
font-size: @font-size-lg;
|
||||
vertical-align: top;
|
||||
margin-right: 0;
|
||||
i {
|
||||
font-size: 12px;
|
||||
transform: scale(0.82);
|
||||
margin-left: 4px;
|
||||
}
|
||||
:global {
|
||||
.anticon-caret-up {
|
||||
color: @red-6;
|
||||
}
|
||||
.anticon-caret-down {
|
||||
color: @green-6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,3 +0,0 @@
|
||||
import NumberInfo from './NumberInfo'
|
||||
|
||||
export default NumberInfo
|
||||
@ -1,56 +0,0 @@
|
||||
@import '~ant-design-vue/lib/style/themes/default';
|
||||
@import '../../style/variables/prefixes';
|
||||
|
||||
@numberInfo-prefix-cls: ~"@{ant-pro-prefix}-number-info";
|
||||
|
||||
.@{numberInfo-prefix-cls} {
|
||||
|
||||
.ant-pro-number-info-subtitle {
|
||||
color: @text-color-secondary;
|
||||
font-size: @font-size-base;
|
||||
height: 22px;
|
||||
line-height: 22px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.number-info-value {
|
||||
margin-top: 4px;
|
||||
font-size: 0;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
word-break: break-all;
|
||||
white-space: nowrap;
|
||||
|
||||
& > span {
|
||||
color: @heading-color;
|
||||
display: inline-block;
|
||||
line-height: 32px;
|
||||
height: 32px;
|
||||
font-size: 24px;
|
||||
margin-right: 32px;
|
||||
}
|
||||
|
||||
.sub-total {
|
||||
color: @text-color-secondary;
|
||||
font-size: @font-size-lg;
|
||||
vertical-align: top;
|
||||
margin-right: 0;
|
||||
i {
|
||||
font-size: 12px;
|
||||
transform: scale(0.82);
|
||||
margin-left: 4px;
|
||||
}
|
||||
:global {
|
||||
.anticon-caret-up {
|
||||
color: @red-6;
|
||||
}
|
||||
.anticon-caret-down {
|
||||
color: @green-6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,90 +0,0 @@
|
||||
<template>
|
||||
<div class="result">
|
||||
<div>
|
||||
<a-icon :class="{ 'icon': true, 'success': isSuccess, 'error': !isSuccess }" :type="isSuccess ? 'check-circle' : 'close-circle'"/>
|
||||
</div>
|
||||
<div class="title" v-if="title">{{ title }}</div>
|
||||
<div class="description" v-if="description">{{ description }}</div>
|
||||
<div class="content" v-if="content">
|
||||
<slot></slot>
|
||||
</div>
|
||||
<div class="action">
|
||||
<slot name="action"></slot>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Result',
|
||||
props: {
|
||||
isSuccess: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
description: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
content: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.result {
|
||||
text-align: center;
|
||||
width: 72%;
|
||||
margin: 0 auto;
|
||||
padding: 24px 0 8px;
|
||||
|
||||
.icon {
|
||||
font-size: 72px;
|
||||
line-height: 72px;
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.success {
|
||||
color: #52c41a;
|
||||
}
|
||||
.error {
|
||||
color: red;
|
||||
}
|
||||
.title {
|
||||
font-size: 24px;
|
||||
color: rgba(0, 0, 0, .85);
|
||||
font-weight: 500;
|
||||
line-height: 32px;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
.description {
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
color: rgba(0, 0, 0, 0.45);
|
||||
margin-bottom: 24px;
|
||||
}
|
||||
.content {
|
||||
background: #fafafa;
|
||||
padding: 24px 40px;
|
||||
border-radius: 2px;
|
||||
text-align: left;
|
||||
}
|
||||
.action {
|
||||
margin-top: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
.mobile {
|
||||
.result {
|
||||
width: 100%;
|
||||
margin: 0 auto;
|
||||
padding: unset;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,2 +0,0 @@
|
||||
import Result from './Result.vue'
|
||||
export default Result
|
||||
@ -1,124 +0,0 @@
|
||||
import { Menu, Icon, Input } from 'ant-design-vue'
|
||||
|
||||
const { Item, ItemGroup, SubMenu } = Menu
|
||||
const { Search } = Input
|
||||
|
||||
export default {
|
||||
name: 'Tree',
|
||||
props: {
|
||||
dataSource: {
|
||||
type: Array,
|
||||
required: true
|
||||
},
|
||||
openKeys: {
|
||||
type: Array,
|
||||
default: () => []
|
||||
},
|
||||
search: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.localOpenKeys = this.openKeys.slice(0)
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
localOpenKeys: []
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handlePlus (item) {
|
||||
this.$emit('add', item)
|
||||
},
|
||||
handleTitleClick (...args) {
|
||||
this.$emit('titleClick', { args })
|
||||
},
|
||||
|
||||
renderSearch () {
|
||||
return (
|
||||
<Search
|
||||
placeholder="input search text"
|
||||
style="width: 100%; margin-bottom: 1rem"
|
||||
/>
|
||||
)
|
||||
},
|
||||
renderIcon (icon) {
|
||||
return icon && (<Icon type={icon} />) || null
|
||||
},
|
||||
renderMenuItem (item) {
|
||||
return (
|
||||
<Item key={item.key}>
|
||||
{ this.renderIcon(item.icon) }
|
||||
{ item.title }
|
||||
<a class="btn" style="width: 20px;z-index:1300" {...{ on: { click: () => this.handlePlus(item) } }}><a-icon type="plus"/></a>
|
||||
</Item>
|
||||
)
|
||||
},
|
||||
renderItem (item) {
|
||||
return item.children ? this.renderSubItem(item, item.key) : this.renderMenuItem(item, item.key)
|
||||
},
|
||||
renderItemGroup (item) {
|
||||
const childrenItems = item.children.map(o => {
|
||||
return this.renderItem(o, o.key)
|
||||
})
|
||||
|
||||
return (
|
||||
<ItemGroup key={item.key}>
|
||||
<template slot="title">
|
||||
<span>{ item.title }</span>
|
||||
<a-dropdown>
|
||||
<a class="btn"><a-icon type="ellipsis" /></a>
|
||||
<a-menu slot="overlay">
|
||||
<a-menu-item key="1">新增</a-menu-item>
|
||||
<a-menu-item key="2">合并</a-menu-item>
|
||||
<a-menu-item key="3">移除</a-menu-item>
|
||||
</a-menu>
|
||||
</a-dropdown>
|
||||
</template>
|
||||
{ childrenItems }
|
||||
</ItemGroup>
|
||||
)
|
||||
},
|
||||
renderSubItem (item, key) {
|
||||
const childrenItems = item.children && item.children.map(o => {
|
||||
return this.renderItem(o, o.key)
|
||||
})
|
||||
|
||||
const title = (
|
||||
<span slot="title">
|
||||
{ this.renderIcon(item.icon) }
|
||||
<span>{ item.title }</span>
|
||||
</span>
|
||||
)
|
||||
|
||||
if (item.group) {
|
||||
return this.renderItemGroup(item)
|
||||
}
|
||||
// titleClick={this.handleTitleClick(item)}
|
||||
return (
|
||||
<SubMenu key={key}>
|
||||
{ title }
|
||||
{ childrenItems }
|
||||
</SubMenu>
|
||||
)
|
||||
}
|
||||
},
|
||||
render () {
|
||||
const { dataSource, search } = this.$props
|
||||
|
||||
// this.localOpenKeys = openKeys.slice(0)
|
||||
const list = dataSource.map(item => {
|
||||
return this.renderItem(item)
|
||||
})
|
||||
|
||||
return (
|
||||
<div class="tree-wrapper">
|
||||
{ search ? this.renderSearch() : null }
|
||||
<Menu mode="inline" class="custom-tree" {...{ on: { click: item => this.$emit('click', item), 'update:openKeys': val => { this.localOpenKeys = val } } }} openKeys={this.localOpenKeys}>
|
||||
{ list }
|
||||
</Menu>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
<template>
|
||||
<div class="trend" :class="[ reverseColor && 'reverse-color' ]">
|
||||
<span>
|
||||
<slot name="term"></slot>
|
||||
<span class="item-text">
|
||||
<slot></slot>
|
||||
</span>
|
||||
</span>
|
||||
<span :class="[flag]"><a-icon :type="`caret-${flag}`"/></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Trend',
|
||||
props: {
|
||||
prefixCls: {
|
||||
type: String,
|
||||
default: 'ant-pro-trend'
|
||||
},
|
||||
flag: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
reverseColor: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import "~ant-design-vue/lib/style/themes/default";
|
||||
.trend {
|
||||
display: inline-block;
|
||||
font-size: @font-size-base;
|
||||
line-height: 22px;
|
||||
|
||||
.up,
|
||||
.down {
|
||||
margin-left: 4px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
|
||||
i {
|
||||
font-size: 12px;
|
||||
transform: scale(0.83);
|
||||
}
|
||||
}
|
||||
|
||||
.item-text {
|
||||
display: inline-block;
|
||||
margin-left: 8px;
|
||||
color: rgba(0,0,0,.85);
|
||||
}
|
||||
|
||||
.up {
|
||||
color: @red-6;
|
||||
}
|
||||
.down {
|
||||
color: @green-6;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
&.reverse-color .up {
|
||||
color: @green-6;
|
||||
}
|
||||
&.reverse-color .down {
|
||||
color: @red-6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,3 +0,0 @@
|
||||
import Trend from './Trend.vue'
|
||||
|
||||
export default Trend
|
||||
@ -1,43 +0,0 @@
|
||||
@import '~ant-design-vue/lib/style/themes/default';
|
||||
@import '../../style/variables/prefixes';
|
||||
|
||||
@trend-prefix-cls: ~"@{ant-pro-prefix}-trend";
|
||||
|
||||
.@{trend-prefix-cls} {
|
||||
display: inline-block;
|
||||
font-size: @font-size-base;
|
||||
line-height: 22px;
|
||||
|
||||
.up,
|
||||
.down {
|
||||
margin-left: 4px;
|
||||
position: relative;
|
||||
top: 1px;
|
||||
|
||||
i {
|
||||
font-size: 12px;
|
||||
transform: scale(0.83);
|
||||
}
|
||||
}
|
||||
|
||||
.item-text {
|
||||
display: inline-block;
|
||||
margin-left: 8px;
|
||||
color: rgba(0,0,0,.85);
|
||||
}
|
||||
|
||||
.up {
|
||||
color: @red-6;
|
||||
}
|
||||
.down {
|
||||
color: @green-6;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
&.reverse-color .up {
|
||||
color: @green-6;
|
||||
}
|
||||
&.reverse-color .down {
|
||||
color: @red-6;
|
||||
}
|
||||
}
|
||||
@ -1,32 +0,0 @@
|
||||
/**
|
||||
* components util
|
||||
*/
|
||||
|
||||
export function filterEmpty (children = []) {
|
||||
return children.filter(c => c.tag || (c.text && c.text.trim() !== ''))
|
||||
}
|
||||
|
||||
export const getStrFullLength = (str = '') =>
|
||||
str.split('').reduce((pre, cur) => {
|
||||
const charCode = cur.charCodeAt(0)
|
||||
if (charCode >= 0 && charCode <= 128) {
|
||||
return pre + 1
|
||||
}
|
||||
return pre + 2
|
||||
}, 0)
|
||||
|
||||
export const cutStrByFullLength = (str = '', maxLength) => {
|
||||
let showLength = 0
|
||||
return str.split('').reduce((pre, cur) => {
|
||||
const charCode = cur.charCodeAt(0)
|
||||
if (charCode >= 0 && charCode <= 128) {
|
||||
showLength += 1
|
||||
} else {
|
||||
showLength += 2
|
||||
}
|
||||
if (showLength <= maxLength) {
|
||||
return pre + cur
|
||||
}
|
||||
return pre
|
||||
}, '')
|
||||
}
|
||||
@ -1,73 +0,0 @@
|
||||
<template>
|
||||
<div class="bar-wrapper">
|
||||
<h4 class="bar-headline">{{ title }}</h4>
|
||||
<v-chart
|
||||
class="bar-chart"
|
||||
:data="data"
|
||||
:forceFit="true">
|
||||
<v-tooltip />
|
||||
<v-axis />
|
||||
<v-bar position="x*y"/>
|
||||
</v-chart>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const data = []
|
||||
for (let i = 0; i < 12; i += 1) {
|
||||
data.push({
|
||||
x: `${i + 1}X`,
|
||||
y: Math.floor(Math.random() * 1000) + 200
|
||||
})
|
||||
}
|
||||
const tooltip = [
|
||||
'x*y',
|
||||
(x, y) => ({
|
||||
name: x,
|
||||
value: y
|
||||
})
|
||||
]
|
||||
const scale = [{
|
||||
dataKey: 'x',
|
||||
min: 2
|
||||
}, {
|
||||
dataKey: 'y',
|
||||
title: 'Data',
|
||||
min: 1,
|
||||
max: 22
|
||||
}]
|
||||
|
||||
export default {
|
||||
name: 'Bar',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
data,
|
||||
scale,
|
||||
tooltip
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.bar {
|
||||
&-wrapper {
|
||||
padding: 0 0 32px 32px;
|
||||
}
|
||||
|
||||
&-headline {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
&-chart {
|
||||
height: 254px;
|
||||
padding: 0 0 40px 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,76 +0,0 @@
|
||||
<template>
|
||||
<div>
|
||||
<v-chart
|
||||
class="liquid-chart"
|
||||
:forceFit="true"
|
||||
:height="height"
|
||||
:width="width"
|
||||
:data="data"
|
||||
:scale="scale">
|
||||
<v-tooltip />
|
||||
<v-interval
|
||||
:shape="['liquid-fill-gauge']"
|
||||
position="transfer*value"
|
||||
color=""
|
||||
class="liquid-interval"
|
||||
:v-style="{
|
||||
lineWidth: 10
|
||||
}"
|
||||
:tooltip="[
|
||||
'transfer*value',
|
||||
(transfer, value) => {
|
||||
return {
|
||||
name: transfer,
|
||||
value,
|
||||
};
|
||||
},
|
||||
]"
|
||||
></v-interval>
|
||||
<v-guide
|
||||
class="liquid-guide"
|
||||
v-for="(row, index) in data"
|
||||
:key="index"
|
||||
type="text"
|
||||
:top="true"
|
||||
:position="{
|
||||
gender: row.transfer,
|
||||
value: 45
|
||||
}"
|
||||
:content="row.value + '%'"
|
||||
/>
|
||||
</v-chart>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Liquid',
|
||||
props: {
|
||||
height: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
width: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.liquid {
|
||||
&-graph {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
&-interval {
|
||||
opacity: 0.75;
|
||||
}
|
||||
|
||||
&-guide {
|
||||
text-align: 'center';
|
||||
opacity: 0.75;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,73 +0,0 @@
|
||||
<template>
|
||||
<div class="mini-area-wrapper">
|
||||
<div class="mini-area-wrapper2">
|
||||
<v-chart class="mini-area-chart" :force-fit="true" :data="data">
|
||||
<v-tooltip />
|
||||
<v-smooth-area position="x*y" />
|
||||
</v-chart>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
const data = []
|
||||
const beginDay = new Date().getTime()
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
data.push({
|
||||
x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
|
||||
y: Math.round(Math.random() * 10)
|
||||
})
|
||||
}
|
||||
|
||||
const tooltip = [
|
||||
'x*y',
|
||||
(x, y) => ({
|
||||
name: x,
|
||||
value: y
|
||||
})
|
||||
]
|
||||
|
||||
const scale = [{
|
||||
dataKey: 'x',
|
||||
min: 2
|
||||
}, {
|
||||
dataKey: 'y',
|
||||
title: '时间',
|
||||
min: 1,
|
||||
max: 22
|
||||
}]
|
||||
|
||||
export default {
|
||||
name: 'MiniArea',
|
||||
data () {
|
||||
return {
|
||||
data,
|
||||
tooltip,
|
||||
scale
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.mini-area {
|
||||
&-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-wrapper2 {
|
||||
position: absolute;
|
||||
bottom: -28px;
|
||||
width: 100%;
|
||||
height: 46px;
|
||||
}
|
||||
|
||||
&-chart {
|
||||
padding: 36px 0 18px 0;
|
||||
height: 100px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,73 +0,0 @@
|
||||
<template>
|
||||
<div class="mini-bar-wrapper">
|
||||
<div class="mini-bar-wrapper2">
|
||||
<v-chart class="mini-bar-chart" :force-fit="true" :data="data">
|
||||
<v-tooltip />
|
||||
<v-bar position="x*y" />
|
||||
</v-chart>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import moment from 'moment'
|
||||
const data = []
|
||||
const beginDay = new Date().getTime()
|
||||
|
||||
for (let i = 0; i < 10; i++) {
|
||||
data.push({
|
||||
x: moment(new Date(beginDay + 1000 * 60 * 60 * 24 * i)).format('YYYY-MM-DD'),
|
||||
y: Math.round(Math.random() * 10)
|
||||
})
|
||||
}
|
||||
|
||||
const tooltip = [
|
||||
'x*y',
|
||||
(x, y) => ({
|
||||
name: x,
|
||||
value: y
|
||||
})
|
||||
]
|
||||
|
||||
const scale = [{
|
||||
dataKey: 'x',
|
||||
min: 2
|
||||
}, {
|
||||
dataKey: 'y',
|
||||
title: '时间',
|
||||
min: 1,
|
||||
max: 22
|
||||
}]
|
||||
|
||||
export default {
|
||||
name: 'MiniArea',
|
||||
data () {
|
||||
return {
|
||||
data,
|
||||
tooltip,
|
||||
scale
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.mini-bar {
|
||||
&-wrapper {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-wrapper2 {
|
||||
position: absolute;
|
||||
bottom: -28px;
|
||||
width: 100%;
|
||||
height: 46px;
|
||||
}
|
||||
|
||||
&-chart {
|
||||
padding: 36px 0 18px 0;
|
||||
height: 100px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,93 +0,0 @@
|
||||
<template>
|
||||
<div class="mini-progress-wrapper">
|
||||
<div class="mini-progress-target target" :style="{ left: target + '%'}">
|
||||
<span class="mini-progress-background"/>
|
||||
<span class="mini-progress-background2"/>
|
||||
</div>
|
||||
<div class="mini-progress-wrapper-inner">
|
||||
<div class="mini-progress-progress"></div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'MiniProgress',
|
||||
props: {
|
||||
target: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
height: {
|
||||
type: String,
|
||||
default: '10px'
|
||||
},
|
||||
color: {
|
||||
type: String,
|
||||
default: '#13C2C2'
|
||||
},
|
||||
percentage: {
|
||||
type: Number,
|
||||
default: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
@import "~ant-design-vue/lib/style/themes/default";
|
||||
|
||||
.mini-progress {
|
||||
&-wrapper {
|
||||
padding: 5px 0;
|
||||
position: relative;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&-wrapper-inner {
|
||||
background-color: #f5f5f5;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
&-target {
|
||||
left: 0;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&-background {
|
||||
background-color: @cyan-6;
|
||||
border-radius: 100px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 4px;
|
||||
width: 2px;
|
||||
}
|
||||
|
||||
&-background2 {
|
||||
background-color: @cyan-6;
|
||||
border-radius: 100px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 4px;
|
||||
width: 2px;
|
||||
top: auto;
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
&-progress {
|
||||
background-color: @cyan-6;
|
||||
width: 0%;
|
||||
height: 0;
|
||||
|
||||
transition: all .4s cubic-bezier(.08, .82, .17, 1) 0s;
|
||||
border-radius: 1px 0 0 1px;
|
||||
background-color: #1890ff;
|
||||
width: 0;
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,73 +0,0 @@
|
||||
<template>
|
||||
<v-chart class="radar-chart" :forceFit="true" :data="data" :scale="scale">
|
||||
<v-tooltip></v-tooltip>
|
||||
<v-axis :dataKey="axis1Opts.dataKey" :line="axis1Opts.line" :tickLine="axis1Opts.tickLine" :grid="axis1Opts.grid" />
|
||||
<v-axis :dataKey="axis2Opts.dataKey" :line="axis2Opts.line" :tickLine="axis2Opts.tickLine" :grid="axis2Opts.grid" />
|
||||
<v-legend dataKey="user" marker="circle" :offset="30" />
|
||||
<v-coord type="polar" radius="0.8" />
|
||||
<v-line position="item*score" color="user" :size="2" />
|
||||
<v-point position="item*score" color="user" :size="4" shape="circle" />
|
||||
</v-chart>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const axis1Opts = {
|
||||
dataKey: 'item',
|
||||
line: null,
|
||||
tickLine: null,
|
||||
grid: {
|
||||
lineStyle: {
|
||||
lineDash: null
|
||||
},
|
||||
hideFirstLine: false
|
||||
}
|
||||
}
|
||||
const axis2Opts = {
|
||||
dataKey: 'score',
|
||||
line: null,
|
||||
tickLine: null,
|
||||
grid: {
|
||||
type: 'polygon',
|
||||
lineStyle: {
|
||||
lineDash: null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const scale = [
|
||||
{
|
||||
dataKey: 'score',
|
||||
min: 0,
|
||||
max: 80
|
||||
}, {
|
||||
dataKey: 'user',
|
||||
alias: 'Alias'
|
||||
}
|
||||
]
|
||||
|
||||
export default {
|
||||
name: 'Radar',
|
||||
props: {
|
||||
data: {
|
||||
type: Array,
|
||||
default: null
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
axis1Opts,
|
||||
axis2Opts,
|
||||
scale
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.radar {
|
||||
&-chart {
|
||||
height: 400px;
|
||||
padding: 20 20 95 20;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,74 +0,0 @@
|
||||
<template>
|
||||
<div class="rank-list-wrapper">
|
||||
<h4>{{ title }}</h4>
|
||||
<ul class="rank-list-list">
|
||||
<li class="rank-list-item" :key="index" v-for="(item, index) in list">
|
||||
<span class="rank-list-index" :class="index < 3 ? 'is-active' : null">{{ index + 1 }}</span>
|
||||
<span class="rank-list-name">{{ item.name }}</span>
|
||||
<span class="rank-list-total">{{ item.total }}</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'RankList',
|
||||
// ['title', 'list']
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
list: {
|
||||
type: Array,
|
||||
default: null
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.rank-list {
|
||||
margin: 25px 0 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
&-wrapper {
|
||||
padding: 0 32px 32px 72px;
|
||||
|
||||
.mobile & {
|
||||
padding-left: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
&-item {
|
||||
margin-top: 16px;
|
||||
color: rgba(0, 0, 0, .65);
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
&-index {
|
||||
background-color: #f5f5f5;
|
||||
border-radius: 20px;
|
||||
display: inline-block;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
margin-right: 24px;
|
||||
height: 20px;
|
||||
line-height: 20px;
|
||||
width: 20px;
|
||||
text-align: center;
|
||||
|
||||
&.is-active {
|
||||
background-color: #314659;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
&-total {
|
||||
float: right;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,81 +0,0 @@
|
||||
<template>
|
||||
<div class="transfer-bar-wrapper">
|
||||
<h4 class="transfer-bar-headline">{{ title }}</h4>
|
||||
<v-chart
|
||||
class="transfer-bar-chart"
|
||||
:data="data"
|
||||
:scale="scale"
|
||||
:forceFit="true"
|
||||
>
|
||||
<v-tooltip />
|
||||
<v-axis />
|
||||
<v-bar position="x*y"/>
|
||||
</v-chart>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
const tooltip = [
|
||||
'x*y',
|
||||
(x, y) => ({
|
||||
name: x,
|
||||
value: y
|
||||
})
|
||||
]
|
||||
const scale = [{
|
||||
dataKey: 'x',
|
||||
title: '日期(天)',
|
||||
alias: '日期(天)',
|
||||
min: 2
|
||||
}, {
|
||||
dataKey: 'y',
|
||||
title: 'Title',
|
||||
alias: 'Alias',
|
||||
min: 1
|
||||
}]
|
||||
|
||||
export default {
|
||||
name: 'Bar',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
data: [],
|
||||
scale,
|
||||
tooltip
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.getMonthBar()
|
||||
},
|
||||
methods: {
|
||||
getMonthBar () {
|
||||
this.$http.get('/analysis/month-bar')
|
||||
.then(res => {
|
||||
this.data = res.result
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.c-transfer-bar {
|
||||
&-wrapper {
|
||||
padding: 0 0 32px 32px;
|
||||
}
|
||||
|
||||
&-headline {
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
&-chart {
|
||||
height: 254px;
|
||||
padding: 0 0 40px 50px;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,86 +0,0 @@
|
||||
<template class="trend">
|
||||
<div class="trend-wrapper chart-trend">
|
||||
{{ term }}
|
||||
<span class="trend-rate">{{ rate }}%</span>
|
||||
<span class="trend-icon " :class="[trend]"><a-icon :type="'caret-' + trend"/></span>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Trend',
|
||||
props: {
|
||||
term: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: true
|
||||
},
|
||||
percentage: {
|
||||
type: Number,
|
||||
default: null
|
||||
},
|
||||
type: {
|
||||
type: Boolean,
|
||||
default: null
|
||||
},
|
||||
target: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
value: {
|
||||
type: Number,
|
||||
default: 0
|
||||
},
|
||||
fixed: {
|
||||
type: Number,
|
||||
default: 2
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
trend: this.type && 'up' || 'down',
|
||||
rate: this.percentage
|
||||
}
|
||||
},
|
||||
created () {
|
||||
const type = this.type === null ? this.value >= this.target : this.type
|
||||
this.trend = type ? 'up' : 'down'
|
||||
this.rate = (this.percentage === null ? Math.abs(this.value - this.target) * 100 / this.target : this.percentage).toFixed(this.fixed)
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.trend {
|
||||
&-wrapper {
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
}
|
||||
|
||||
&-icon {
|
||||
font-size: 12px;
|
||||
|
||||
&.up,
|
||||
&.down {
|
||||
margin-left: 4px;
|
||||
position: relative;
|
||||
|
||||
i {
|
||||
font-size: 12px;
|
||||
transform: scale(.83);
|
||||
}
|
||||
}
|
||||
|
||||
&.up {
|
||||
color: #f5222d;
|
||||
top: 1px;
|
||||
}
|
||||
|
||||
&.down {
|
||||
color: #52c41a;
|
||||
top: -1px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,10 +0,0 @@
|
||||
.antv-chart-mini {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
|
||||
.chart-wrapper {
|
||||
position: absolute;
|
||||
bottom: -28px;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
@ -6,7 +6,7 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ProjectMenu from '../tools/ProjectMenu'
|
||||
import ProjectMenu from './ProjectMenu'
|
||||
|
||||
export default {
|
||||
name: 'Logo',
|
||||
@ -1,46 +0,0 @@
|
||||
// chart
|
||||
import Bar from '@/components/chart/Bar'
|
||||
import ChartCard from '@/components/chart/ChartCard'
|
||||
import Liquid from '@/components/chart/Liquid'
|
||||
import MiniArea from '@/components/chart/MiniArea'
|
||||
import MiniBar from '@/components/chart/MiniBar'
|
||||
import MiniProgress from '@/components/chart/MiniProgress'
|
||||
import Radar from '@/components/chart/Radar'
|
||||
import RankList from '@/components/chart/RankList'
|
||||
import TransferBar from '@/components/chart/TransferBar'
|
||||
|
||||
// pro components
|
||||
import AvatarList from '@/components/AvatarList'
|
||||
import CountDown from '@/components/CountDown'
|
||||
import Ellipsis from '@/components/Ellipsis'
|
||||
import FooterToolbar from '@/components/FooterToolbar'
|
||||
import NumberInfo from '@/components/NumberInfo'
|
||||
import DetailList from '@/components/tools/DetailList'
|
||||
import Tree from '@/components/Tree/Tree'
|
||||
import Trend from '@/components/Trend'
|
||||
import STable from '@/components/table'
|
||||
import MultiTab from '@/components/MultiTab'
|
||||
import Result from '@/components/Result'
|
||||
|
||||
export {
|
||||
AvatarList,
|
||||
Bar,
|
||||
ChartCard,
|
||||
Liquid,
|
||||
MiniArea,
|
||||
MiniBar,
|
||||
MiniProgress,
|
||||
Radar,
|
||||
RankList,
|
||||
TransferBar,
|
||||
Trend,
|
||||
CountDown,
|
||||
Ellipsis,
|
||||
FooterToolbar,
|
||||
NumberInfo,
|
||||
DetailList,
|
||||
Tree,
|
||||
STable,
|
||||
MultiTab,
|
||||
Result
|
||||
}
|
||||
@ -18,7 +18,7 @@
|
||||
|
||||
<script>
|
||||
import ALayoutSider from 'ant-design-vue/es/layout/Sider'
|
||||
import Logo from '../tools/Logo'
|
||||
import Logo from '../header/Logo'
|
||||
import SMenu from './index'
|
||||
import { mixin, mixinDevice } from '@/utils/mixin.js'
|
||||
|
||||
|
||||
@ -40,9 +40,9 @@
|
||||
|
||||
<script>
|
||||
import Breadcrumb from '@/components/widgets/Breadcrumb'
|
||||
import Logo from '../tools/Logo'
|
||||
import Logo from '../header/Logo'
|
||||
import SMenu from '../menu/'
|
||||
import UserMenu from '../tools/UserMenu'
|
||||
import UserMenu from '../header/UserMenu'
|
||||
|
||||
import { mixin } from '@/utils/mixin.js'
|
||||
|
||||
|
||||
@ -1,256 +0,0 @@
|
||||
import T from 'ant-design-vue/es/table/Table'
|
||||
import get from 'lodash.get'
|
||||
|
||||
export default {
|
||||
data () {
|
||||
return {
|
||||
needTotalList: [],
|
||||
|
||||
selectedRows: [],
|
||||
selectedRowKeys: [],
|
||||
|
||||
localLoading: false,
|
||||
localDataSource: [],
|
||||
localPagination: Object.assign({}, T.props.pagination)
|
||||
}
|
||||
},
|
||||
props: Object.assign({}, T.props, {
|
||||
rowKey: {
|
||||
type: [String, Function],
|
||||
default: 'id'
|
||||
},
|
||||
data: {
|
||||
type: Function,
|
||||
required: true
|
||||
},
|
||||
pageNum: {
|
||||
type: Number,
|
||||
default: 1
|
||||
},
|
||||
pageSize: {
|
||||
type: Number,
|
||||
default: 10
|
||||
},
|
||||
showSizeChanger: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'default'
|
||||
},
|
||||
/**
|
||||
* {
|
||||
* show: true,
|
||||
* clear: Function
|
||||
* }
|
||||
*/
|
||||
alert: {
|
||||
type: [Object, Boolean],
|
||||
default: null
|
||||
},
|
||||
rowSelection: {
|
||||
type: Object,
|
||||
default: null
|
||||
},
|
||||
/** @Deprecated */
|
||||
showAlertInfo: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
showPagination: {
|
||||
type: String,
|
||||
default: 'auto'
|
||||
}
|
||||
}),
|
||||
watch: {
|
||||
'localPagination.current' (val) {
|
||||
this.$router.push({
|
||||
name: this.$route.name,
|
||||
params: Object.assign({}, this.$route.params, {
|
||||
pageNo: val
|
||||
})
|
||||
})
|
||||
},
|
||||
pageNum (val) {
|
||||
Object.assign(this.localPagination, {
|
||||
current: val
|
||||
})
|
||||
},
|
||||
pageSize (val) {
|
||||
Object.assign(this.localPagination, {
|
||||
pageSize: val
|
||||
})
|
||||
},
|
||||
showSizeChanger (val) {
|
||||
Object.assign(this.localPagination, {
|
||||
showSizeChanger: val
|
||||
})
|
||||
}
|
||||
},
|
||||
created () {
|
||||
this.localPagination = ['auto', true].includes(this.showPagination) && Object.assign({}, this.localPagination, {
|
||||
current: this.pageNum,
|
||||
pageSize: this.pageSize,
|
||||
showSizeChanger: this.showSizeChanger
|
||||
})
|
||||
this.needTotalList = this.initTotalList(this.columns)
|
||||
this.loadData()
|
||||
},
|
||||
methods: {
|
||||
refresh (bool = false) {
|
||||
bool && (this.localPagination = Object.assign({}, {
|
||||
current: 1, pageSize: this.pageSize
|
||||
}))
|
||||
this.loadData()
|
||||
},
|
||||
loadData (pagination, filters, sorter) {
|
||||
this.localLoading = true
|
||||
const parameter = Object.assign({
|
||||
pageNo: (pagination && pagination.current) ||
|
||||
this.localPagination.current,
|
||||
pageSize: (pagination && pagination.pageSize) ||
|
||||
this.localPagination.pageSize
|
||||
},
|
||||
(sorter && sorter.field && {
|
||||
sortField: sorter.field
|
||||
}) || {},
|
||||
(sorter && sorter.order && {
|
||||
sortOrder: sorter.order
|
||||
}) || {}, {
|
||||
...filters
|
||||
}
|
||||
)
|
||||
const result = this.data(parameter)
|
||||
// eslint-disable-next-line
|
||||
if (result instanceof Promise || '[object Promise]' === result.toString()) {
|
||||
result.then(r => {
|
||||
this.localPagination = Object.assign({}, this.localPagination, {
|
||||
current: r.pageNo, // 返回结果中的当前分页数
|
||||
total: r.totalCount, // 返回结果中的总记录数
|
||||
showSizeChanger: this.showSizeChanger,
|
||||
pageSize: (pagination && pagination.pageSize) ||
|
||||
this.localPagination.pageSize
|
||||
})
|
||||
if (r.data.length === 0 && this.localPagination.current !== 1) {
|
||||
this.localPagination.current--
|
||||
this.loadData()
|
||||
return
|
||||
}
|
||||
|
||||
!r.totalCount && ['auto', false].includes(this.showPagination) && (this.localPagination = false)
|
||||
this.localDataSource = r.data
|
||||
this.localLoading = false
|
||||
})
|
||||
}
|
||||
},
|
||||
initTotalList (columns) {
|
||||
const totalList = []
|
||||
columns && columns instanceof Array && columns.forEach(column => {
|
||||
if (column.needTotal) {
|
||||
totalList.push({
|
||||
...column,
|
||||
total: 0
|
||||
})
|
||||
}
|
||||
})
|
||||
return totalList
|
||||
},
|
||||
updateSelect (selectedRowKeys, selectedRows) {
|
||||
this.selectedRows = selectedRows
|
||||
this.selectedRowKeys = selectedRowKeys
|
||||
const list = this.needTotalList
|
||||
this.needTotalList = list.map(item => {
|
||||
return {
|
||||
...item,
|
||||
total: selectedRows.reduce((sum, val) => {
|
||||
const total = sum + parseInt(get(val, item.dataIndex))
|
||||
return isNaN(total) ? 0 : total
|
||||
}, 0)
|
||||
}
|
||||
})
|
||||
},
|
||||
clearSelected () {
|
||||
if (this.rowSelection) {
|
||||
this.rowSelection.onChange([], [])
|
||||
this.updateSelect([], [])
|
||||
}
|
||||
},
|
||||
renderClear (callback) {
|
||||
if (this.selectedRowKeys.length <= 0) return null
|
||||
return (
|
||||
<a style="margin-left: 24px" onClick={() => {
|
||||
callback()
|
||||
this.clearSelected()
|
||||
}}>清空</a>
|
||||
)
|
||||
},
|
||||
renderAlert () {
|
||||
const needTotalItems = this.needTotalList.map((item) => {
|
||||
return (<span style="margin-right: 12px">
|
||||
{item.title}总计 <a style="font-weight: 600">{!item.customRender ? item.total : item.customRender(item.total)}</a>
|
||||
</span>)
|
||||
})
|
||||
|
||||
const clearItem = (typeof this.alert.clear === 'boolean' && this.alert.clear) ? (
|
||||
this.renderClear(this.clearSelected)
|
||||
) : (this.alert !== null && typeof this.alert.clear === 'function') ? (
|
||||
this.renderClear(this.alert.clear)
|
||||
) : null
|
||||
|
||||
return (
|
||||
<a-alert showIcon={true} style="margin-bottom: 16px">
|
||||
<template slot="message">
|
||||
<span style="margin-right: 12px">已选择: <a style="font-weight: 600">{this.selectedRows.length}</a></span>
|
||||
{needTotalItems}
|
||||
{clearItem}
|
||||
</template>
|
||||
</a-alert>
|
||||
)
|
||||
}
|
||||
},
|
||||
|
||||
render () {
|
||||
const props = {}
|
||||
const localKeys = Object.keys(this.$data)
|
||||
const showAlert = (typeof this.alert === 'object' && this.alert !== null && this.alert.show) && typeof this.rowSelection.selectedRowKeys !== 'undefined' || this.alert
|
||||
|
||||
Object.keys(T.props).forEach(k => {
|
||||
const localKey = `local${k.substring(0, 1).toUpperCase()}${k.substring(1)}`
|
||||
if (localKeys.includes(localKey)) {
|
||||
props[k] = this[localKey]
|
||||
return props[k]
|
||||
}
|
||||
if (k === 'rowSelection') {
|
||||
if (showAlert && this.rowSelection) {
|
||||
props[k] = {
|
||||
selectedRows: this.selectedRows,
|
||||
selectedRowKeys: this.selectedRowKeys,
|
||||
onChange: (selectedRowKeys, selectedRows) => {
|
||||
this.updateSelect(selectedRowKeys, selectedRows)
|
||||
typeof this[k].onChange !== 'undefined' && this[k].onChange(selectedRowKeys, selectedRows)
|
||||
}
|
||||
}
|
||||
return props[k]
|
||||
} else if (!this.rowSelection) {
|
||||
props[k] = null
|
||||
return props[k]
|
||||
}
|
||||
}
|
||||
props[k] = this[k]
|
||||
return props[k]
|
||||
})
|
||||
const table = (
|
||||
<a-table {...{ props, scopedSlots: { ...this.$scopedSlots } }} onChange={this.loadData}>
|
||||
{ Object.keys(this.$slots).map(name => (<template slot={name}>{this.$slots[name]}</template>)) }
|
||||
</a-table>
|
||||
)
|
||||
|
||||
return (
|
||||
<div class="table-wrapper">
|
||||
{ showAlert ? this.renderAlert() : null }
|
||||
{ table }
|
||||
</div>
|
||||
)
|
||||
}
|
||||
}
|
||||
@ -1,153 +0,0 @@
|
||||
<template>
|
||||
<div :class="['detail-list', size, layout === 'vertical' ? 'vertical': 'horizontal']">
|
||||
<div v-if="title" class="title">{{ title }}</div>
|
||||
<a-row>
|
||||
<slot></slot>
|
||||
</a-row>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { Col } from 'ant-design-vue/es/grid/'
|
||||
|
||||
const Item = {
|
||||
name: 'DetailListItem',
|
||||
props: {
|
||||
term: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
}
|
||||
},
|
||||
inject: {
|
||||
col: {
|
||||
type: Number
|
||||
}
|
||||
},
|
||||
render () {
|
||||
return (
|
||||
<Col {...{ props: responsive[this.col] }}>
|
||||
<div class="term">{this.$props.term}</div>
|
||||
<div class="content">{this.$slots.default}</div>
|
||||
</Col>
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
const responsive = {
|
||||
1: { xs: 24 },
|
||||
2: { xs: 24, sm: 12 },
|
||||
3: { xs: 24, sm: 12, md: 8 },
|
||||
4: { xs: 24, sm: 12, md: 6 }
|
||||
}
|
||||
|
||||
export default {
|
||||
name: 'DetailList',
|
||||
Item: Item,
|
||||
components: {
|
||||
Col
|
||||
},
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: '',
|
||||
required: false
|
||||
},
|
||||
col: {
|
||||
type: Number,
|
||||
required: false,
|
||||
default: 3
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'large'
|
||||
},
|
||||
layout: {
|
||||
type: String,
|
||||
required: false,
|
||||
default: 'horizontal'
|
||||
}
|
||||
},
|
||||
provide () {
|
||||
return {
|
||||
col: this.col > 4 ? 4 : this.col
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
|
||||
.detail-list {
|
||||
|
||||
.title {
|
||||
color: rgba(0,0,0,.85);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
/deep/ .term {
|
||||
color: rgba(0,0,0,.85);
|
||||
display: table-cell;
|
||||
line-height: 20px;
|
||||
margin-right: 8px;
|
||||
padding-bottom: 16px;
|
||||
white-space: nowrap;
|
||||
|
||||
&:not(:empty):after {
|
||||
content: ":";
|
||||
margin: 0 8px 0 2px;
|
||||
position: relative;
|
||||
top: -.5px;
|
||||
}
|
||||
}
|
||||
|
||||
/deep/ .content {
|
||||
color: rgba(0,0,0,.65);
|
||||
display: table-cell;
|
||||
min-height: 22px;
|
||||
line-height: 22px;
|
||||
padding-bottom: 16px;
|
||||
width: 100%;
|
||||
&:empty {
|
||||
content: ' ';
|
||||
height: 38px;
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&.small {
|
||||
|
||||
.title {
|
||||
font-size: 14px;
|
||||
color: rgba(0, 0, 0, .65);
|
||||
font-weight: normal;
|
||||
margin-bottom: 12px;
|
||||
}
|
||||
/deep/ .term, .content {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&.large {
|
||||
/deep/ .term, .content {
|
||||
padding-bottom: 16px;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-size: 16px;
|
||||
}
|
||||
}
|
||||
|
||||
&.vertical {
|
||||
.term {
|
||||
padding-bottom: 8px;
|
||||
}
|
||||
/deep/ .term, .content {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,69 +0,0 @@
|
||||
<template>
|
||||
<div class="head-info" :class="center && 'center'">
|
||||
<span class="head-info-title">{{ title }}</span>
|
||||
<p class="head-info-content">{{ content }}</p>
|
||||
<em class="head-info-border" v-if="bordered"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'HeadInfo',
|
||||
props: {
|
||||
title: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
content: {
|
||||
type: String,
|
||||
default: ''
|
||||
},
|
||||
bordered: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
},
|
||||
center: {
|
||||
type: Boolean,
|
||||
default: true
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="less" scoped>
|
||||
.head-info {
|
||||
position: relative;
|
||||
text-align: left;
|
||||
padding: 0 32px 0 0;
|
||||
min-width: 125px;
|
||||
|
||||
&.center {
|
||||
text-align: center;
|
||||
padding: 0 32px;
|
||||
}
|
||||
|
||||
&-title {
|
||||
color: rgba(0, 0, 0, .45);
|
||||
display: inline-block;
|
||||
font-size: 14px;
|
||||
line-height: 22px;
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
&-content {
|
||||
color: rgba(0, 0, 0, .85);
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
&-border {
|
||||
background-color: #e8e8e8;
|
||||
position: absolute;
|
||||
height: 56px;
|
||||
width: 1px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@ -1,89 +0,0 @@
|
||||
<template>
|
||||
<!-- 两步验证 -->
|
||||
<a-modal
|
||||
centered
|
||||
v-model="visible"
|
||||
@cancel="handleCancel"
|
||||
:maskClosable="false"
|
||||
>
|
||||
<div slot="title" :style="{ textAlign: 'center' }">两步验证</div>
|
||||
<template slot="footer">
|
||||
<div :style="{ textAlign: 'center' }">
|
||||
<a-button key="back" @click="handleCancel">返回</a-button>
|
||||
<a-button key="submit" type="primary" :loading="stepLoading" @click="handleStepOk">
|
||||
继续
|
||||
</a-button>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<a-spin :spinning="stepLoading">
|
||||
<a-form layout="vertical" :auto-form-create="(form)=>{this.form = form}">
|
||||
<div class="step-form-wrapper">
|
||||
<p style="text-align: center" v-if="!stepLoading">请在手机中打开 Google Authenticator 或两步验证 APP<br />输入 6 位动态码</p>
|
||||
<p style="text-align: center" v-else>正在验证..<br/>请稍后</p>
|
||||
<a-form-item
|
||||
:style="{ textAlign: 'center' }"
|
||||
hasFeedback
|
||||
fieldDecoratorId="stepCode"
|
||||
:fieldDecoratorOptions="{rules: [{ required: true, message: '请输入 6 位动态码!', pattern: /^\d{6}$/, len: 6 }]}"
|
||||
>
|
||||
<a-input :style="{ textAlign: 'center' }" @keyup.enter.native="handleStepOk" placeholder="000000" />
|
||||
</a-form-item>
|
||||
<p style="text-align: center">
|
||||
<a @click="onForgeStepCode">遗失手机?</a>
|
||||
</p>
|
||||
</div>
|
||||
</a-form>
|
||||
</a-spin>
|
||||
</a-modal>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
props: {
|
||||
visible: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
}
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
stepLoading: false,
|
||||
|
||||
form: null
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
handleStepOk () {
|
||||
const vm = this
|
||||
this.stepLoading = true
|
||||
this.form.validateFields((err, values) => {
|
||||
if (!err) {
|
||||
console.log('values', values)
|
||||
setTimeout(() => {
|
||||
vm.stepLoading = false
|
||||
vm.$emit('success', { values })
|
||||
}, 2000)
|
||||
return
|
||||
}
|
||||
this.stepLoading = false
|
||||
this.$emit('error', { err })
|
||||
})
|
||||
},
|
||||
handleCancel () {
|
||||
this.visible = false
|
||||
this.$emit('cancel')
|
||||
},
|
||||
onForgeStepCode () {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="less" scoped>
|
||||
.step-form-wrapper {
|
||||
margin: 0 auto;
|
||||
width: 80%;
|
||||
max-width: 400px;
|
||||
}
|
||||
</style>
|
||||
@ -1,94 +0,0 @@
|
||||
import { message } from 'ant-design-vue/es'
|
||||
|
||||
let lessNodesAppended
|
||||
|
||||
const colorList = [
|
||||
{
|
||||
key: '薄暮', color: '#F5222D'
|
||||
},
|
||||
{
|
||||
key: '火山', color: '#FA541C'
|
||||
},
|
||||
{
|
||||
key: '日暮', color: '#FAAD14'
|
||||
},
|
||||
{
|
||||
key: '明青', color: '#13C2C2'
|
||||
},
|
||||
{
|
||||
key: '极光绿', color: '#52C41A'
|
||||
},
|
||||
{
|
||||
key: '拂晓蓝(默认)', color: '#1890FF'
|
||||
},
|
||||
{
|
||||
key: '极客蓝', color: '#2F54EB'
|
||||
},
|
||||
{
|
||||
key: '酱紫', color: '#722ED1'
|
||||
}
|
||||
]
|
||||
|
||||
const updateTheme = primaryColor => {
|
||||
// Don't compile less in production!
|
||||
/* if (process.env.NODE_ENV === 'production') {
|
||||
return;
|
||||
} */
|
||||
// Determine if the component is remounted
|
||||
if (!primaryColor) {
|
||||
return
|
||||
}
|
||||
const hideMessage = message.loading('正在编译主题!', 0)
|
||||
function buildIt () {
|
||||
if (!window.less) {
|
||||
return
|
||||
}
|
||||
setTimeout(() => {
|
||||
window.less
|
||||
.modifyVars({
|
||||
'@primary-color': primaryColor
|
||||
})
|
||||
.then(() => {
|
||||
hideMessage()
|
||||
})
|
||||
.catch(() => {
|
||||
message.error('Failed to update theme')
|
||||
hideMessage()
|
||||
})
|
||||
}, 200)
|
||||
}
|
||||
if (!lessNodesAppended) {
|
||||
// insert less.js and color.less
|
||||
const lessStyleNode = document.createElement('link')
|
||||
const lessConfigNode = document.createElement('script')
|
||||
const lessScriptNode = document.createElement('script')
|
||||
lessStyleNode.setAttribute('rel', 'stylesheet/less')
|
||||
lessStyleNode.setAttribute('href', '/color.less')
|
||||
lessConfigNode.innerHTML = `
|
||||
window.less = {
|
||||
async: true,
|
||||
env: 'production',
|
||||
javascriptEnabled: true
|
||||
};
|
||||
`
|
||||
lessScriptNode.src = 'https://gw.alipayobjects.com/os/lib/less.js/3.8.1/less.min.js'
|
||||
lessScriptNode.async = true
|
||||
lessScriptNode.onload = () => {
|
||||
buildIt()
|
||||
lessScriptNode.onload = null
|
||||
}
|
||||
document.body.appendChild(lessStyleNode)
|
||||
document.body.appendChild(lessConfigNode)
|
||||
document.body.appendChild(lessScriptNode)
|
||||
lessNodesAppended = true
|
||||
} else {
|
||||
buildIt()
|
||||
}
|
||||
}
|
||||
|
||||
const updateInvertedMode = invertedMode => {
|
||||
invertedMode = true
|
||||
invertedMode ? document.body.classList.add('layout-inverted-mode') : document.body.classList.remove('layout-inverted-mode')
|
||||
}
|
||||
|
||||
export { updateTheme, colorList, updateInvertedMode }
|
||||
@ -67,7 +67,7 @@
|
||||
|
||||
<script>
|
||||
|
||||
import ChartCard from '@/components/chart/ChartCard'
|
||||
import ChartCard from '@/components/widgets/ChartCard'
|
||||
|
||||
export default {
|
||||
name: 'FormView',
|
||||
|
||||
@ -13,14 +13,7 @@
|
||||
<slot name="name">
|
||||
<h4>
|
||||
{{ resource.displayname || resource.name }}
|
||||
<a
|
||||
v-if="['vm', 'systemvm', 'router'].includes($route.meta.name)"
|
||||
:href="'/client/console?cmd=access&vm=' + resource.id"
|
||||
target="_blank">
|
||||
<a-button shape="circle" >
|
||||
<a-icon type="code" />
|
||||
</a-button>
|
||||
</a>
|
||||
<console :resource="resource" size="default" />
|
||||
</h4>
|
||||
<a-tag v-if="resource.instancename">
|
||||
{{ resource.instancename }}
|
||||
@ -372,12 +365,14 @@
|
||||
<script>
|
||||
|
||||
import { api } from '@/api'
|
||||
import Console from '@/components/widgets/Console'
|
||||
import OsLogo from '@/components/widgets/OsLogo'
|
||||
import Status from '@/components/widgets/Status'
|
||||
|
||||
export default {
|
||||
name: 'InfoCard',
|
||||
components: {
|
||||
Console,
|
||||
OsLogo,
|
||||
Status
|
||||
},
|
||||
|
||||
@ -19,6 +19,7 @@
|
||||
<a slot="name" slot-scope="text, record" href="javascript:;">
|
||||
<router-link :to="{ path: $route.path + '/' + record.id }" v-if="record.id">{{ text }}</router-link>
|
||||
<router-link :to="{ path: $route.path + '/' + record.name }" v-else>{{ text }}</router-link>
|
||||
<console :resource="record" size="small" style="float: right" />
|
||||
</a>
|
||||
<a slot="displayname" slot-scope="text, record" href="javascript:;">
|
||||
<router-link :to="{ path: $route.path + '/' + record.id }">{{ text }}</router-link>
|
||||
@ -56,11 +57,13 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Console from '@/components/widgets/Console'
|
||||
import Status from '@/components/widgets/Status'
|
||||
|
||||
export default {
|
||||
name: 'ListView',
|
||||
components: {
|
||||
Console,
|
||||
Status
|
||||
},
|
||||
props: {
|
||||
|
||||
26
ui/src/components/widgets/Console.vue
Normal file
26
ui/src/components/widgets/Console.vue
Normal file
@ -0,0 +1,26 @@
|
||||
<template>
|
||||
<a
|
||||
v-if="['vm', 'systemvm', 'router'].includes($route.meta.name) && !['Stopped', 'Error', 'Destroyed'].includes(resource.state)"
|
||||
:href="'/client/console?cmd=access&vm=' + resource.id"
|
||||
target="_blank">
|
||||
<a-button shape="circle" type="dashed" :size="size" >
|
||||
<a-icon type="code" />
|
||||
</a-button>
|
||||
</a>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
name: 'Console',
|
||||
props: {
|
||||
resource: {
|
||||
type: Object,
|
||||
required: true
|
||||
},
|
||||
size: {
|
||||
type: String,
|
||||
default: 'small'
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
@ -9,7 +9,7 @@
|
||||
|
||||
<script>
|
||||
import RouteView from '@/layouts/RouteView'
|
||||
import MultiTab from '@/components/MultiTab'
|
||||
import MultiTab from '@/components/multitab'
|
||||
import GlobalLayout from '@/components/page/GlobalLayout'
|
||||
|
||||
export default {
|
||||
|
||||
@ -200,8 +200,8 @@ import { mixinDevice } from '@/utils/mixin.js'
|
||||
import store from '@/store'
|
||||
|
||||
import Breadcrumb from '@/components/widgets/Breadcrumb'
|
||||
import ChartCard from '@/components/widgets/ChartCard'
|
||||
import Status from '@/components/widgets/Status'
|
||||
import ChartCard from '@/components/chart/ChartCard'
|
||||
import ListView from '@/components/view/ListView'
|
||||
import ResourceView from '@/components/view/ResourceView'
|
||||
|
||||
|
||||
@ -105,13 +105,11 @@
|
||||
<script>
|
||||
import { api } from '@/api'
|
||||
|
||||
import ChartCard from '@/components/chart/ChartCard'
|
||||
import ACol from 'ant-design-vue/es/grid/Col'
|
||||
import ChartCard from '@/components/widgets/ChartCard'
|
||||
|
||||
export default {
|
||||
name: 'CapacityDashboard',
|
||||
components: {
|
||||
ACol,
|
||||
ChartCard
|
||||
},
|
||||
data () {
|
||||
|
||||
@ -48,13 +48,11 @@
|
||||
<script>
|
||||
import { api } from '@/api'
|
||||
|
||||
import ChartCard from '@/components/chart/ChartCard'
|
||||
import ACol from 'ant-design-vue/es/grid/Col'
|
||||
import ChartCard from '@/components/widgets/ChartCard'
|
||||
|
||||
export default {
|
||||
name: 'UsageDashboard',
|
||||
components: {
|
||||
ACol,
|
||||
ChartCard
|
||||
},
|
||||
data () {
|
||||
|
||||
@ -46,7 +46,7 @@
|
||||
import { api } from '@/api'
|
||||
import router from '@/router'
|
||||
|
||||
import ChartCard from '@/components/chart/ChartCard'
|
||||
import ChartCard from '@/components/widgets/ChartCard'
|
||||
|
||||
export default {
|
||||
name: 'InfraSummary',
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user