Merge branch 'dev-2.0' of https://git.mesalab.cn/nezha/nezha-fronted into dev-2.0

This commit is contained in:
zhangyu
2021-05-12 09:47:46 +08:00
14 changed files with 666 additions and 128 deletions

View File

@@ -61,12 +61,12 @@ const cn = {
type: '类别',
detail: '详细信息',
changePin: '修改密码',
createCabinet: '创建机柜',
createModel: '创建型号',
createModule: '创建模块',
createMib: '创建MIB',
createAssetType: '创建设备类型',
createAssetState: '创建设备状态',
createCabinet: '新增机柜',
createModel: '新增型号',
createModule: '新增模块',
createMib: '新增MIB',
createAssetType: '新增设备类型',
createAssetState: '新增设备状态',
exportExcel: '导出',
importExcel: '导入',
importExcelLower: '导入',
@@ -1463,6 +1463,35 @@ const cn = {
cancelButtonText: '取消'
}
},
guide: {
title: '6步开始使用',
dc: '数据中心',
dcTip: '数据中心包含机柜和资产与Prometheus服务相关联机柜是资产的容器',
addDc: '新增数据中心',
addCabinet: '新增机柜',
agent: 'Agent',
agentTip: 'Prometheusagent是本系统的核心包含“Global”和“Per-datacenter”两种类型前者汇总数据并发出告警消息后者从Endpoint中采集监控数据。两者都必须配置',
addAgent: '新增agent',
downloadAgent: '下载agent',
asset: '资产',
assetTip: '资产是被系统监控的主要部分',
addAsset: '新增资产',
importAsset: '导入资产',
webTerminal: '打开终端',
monitor: '监控',
monitorTip: '帮助用户根据系统需求监控组件',
addProject: '新增系统',
addModule: '新增模块',
addEndpoint: '新增endpoint',
importEndpoint: '导入endpoint',
visualization: '可视化',
visualizationTip: '面板由不同组的自定义图表组成,您可以创建多个面板并在它们之间切换',
addPanel: '新增面板',
addChart: '新增图表',
alert: '告警',
alertTip: '用户可以通过配置表达式,阈值,持续时间等来创建告警规则',
addAlertRule: '新增告警规则'
},
buttons: {
view: '查看',
add: '新增',

View File

@@ -1364,6 +1364,35 @@ const en = {
seven: 'SUN'
}
},
guide: {
title: 'Get started in 6 steps',
dc: 'Datacenter',
dcTip: 'Data center associated with Prometheus servers contains cabinets and assets; cabinet is a container for assets.',
addDc: 'Add datacenter',
addCabinet: 'Add cabinet',
agent: 'Agent',
agentTip: 'The Prometheus service (agent) is the core of the system, including two types: "Global" and "Per-datacenter". The former collects data and sends out alert messages, while the latter collects data from Endpoint. You must configure both.',
addAgent: 'Add agent',
downloadAgent: 'Download agent',
asset: 'Asset',
assetTip: 'Assets are the main part monitored by the system',
addAsset: 'Add asset',
importAsset: 'Import asset',
webTerminal: 'Web terminal',
monitor: 'Monitor',
monitorTip: 'Help user to monitor components and contents based on project requirement',
addProject: 'Add project',
addModule: 'Add module',
addEndpoint: 'Add endpoint',
importEndpoint: 'Import endpoint',
visualization: 'Visualization',
visualizationTip: 'Panels consist of different sets of customized charts. You can create several panels and switch between them.',
addPanel: 'Add panel',
addChart: 'Add chart',
alert: 'Alert',
alertTip: 'User can create alert rule by configuring expression, threshold, duration, etc.',
addAlertRule: 'Add alert rule'
},
buttons: {
view: 'View',
add: 'Add',

View File

@@ -0,0 +1,441 @@
<template>
<div>
<el-dialog
:title="$t('guide.title')"
:visible.sync="visible"
custom-class="guild-pop"
width="1000px"
@closed="dialogClosed"
@open="dialogOpened"
>
<div class="guide-list">
<div ref="guideShadow" class="guide-shadow"></div>
<div v-for="(guide, index) in guideList" :key="index" :class="{'guide-item--active': index === activeIndex}" class="guide-item"
@mouseenter="enter(index)" @mouseleave="leave(index)"
>
<div class="item__title">{{guide.title}}</div>
<div class="item__icon" @click="jump(guide.route)"><i :class="guide.icon"></i></div>
</div>
</div>
<div class="guide-desc">
<template v-if="activeIndex === 0">
<div class="desc-text">{{$t('guide.dcTip')}}</div>
<div class="guide__btn-group">
<button class="guide__btn" type="button" @click="jumpAndOpen('dc')">{{$t('guide.addDc')}}</button>
<button class="guide__btn" type="button" @click="jumpAndOpen('cabinet')">{{$t('guide.addCabinet')}}</button>
</div>
</template>
<template v-if="activeIndex === 1">
<div class="desc-text">{{$t('guide.agentTip')}}</div>
<div class="guide__btn-group">
<button class="guide__btn" type="button" @click="jumpAndOpen('agent')">{{$t('guide.addAgent')}}</button>
<button class="guide__btn" type="button" @click="downloadAgent">{{$t('guide.downloadAgent')}}</button>
</div>
</template>
<template v-if="activeIndex === 2">
<div class="desc-text">{{$t('guide.assetTip')}}</div>
<div class="guide__btn-group">
<button class="guide__btn" type="button" @click="jumpAndOpen('asset')">{{$t('guide.addAsset')}}</button>
<button class="guide__btn" type="button" @click="jumpAndOpen('importAsset')">{{$t('guide.importAsset')}}</button>
<button class="guide__btn" type="button" @click="openTerminal">{{$t('guide.webTerminal')}}</button>
</div>
</template>
<template v-if="activeIndex === 3">
<div class="desc-text">{{$t('guide.monitorTip')}}</div>
<div class="guide__btn-group">
<button class="guide__btn" type="button" @click="jumpAndOpen('project')">{{$t('guide.addProject')}}</button>
<button class="guide__btn" type="button" @click="jumpAndOpen('module')">{{$t('guide.addModule')}}</button>
<button class="guide__btn" type="button" @click="jumpAndOpen('endpoint')">{{$t('guide.addEndpoint')}}</button>
<button class="guide__btn" type="button" @click="jumpAndOpen('importEndpoint')">{{$t('guide.importEndpoint')}}</button>
</div>
</template>
<template v-if="activeIndex === 4">
<div class="desc-text">{{$t('guide.visualizationTip')}}</div>
<div class="guide__btn-group">
<button class="guide__btn" type="button" @click="jumpAndOpen('panel')">{{$t('guide.addPanel')}}</button>
<button class="guide__btn" type="button" @click="jumpAndOpen('chart')">{{$t('guide.addChart')}}</button>
</div>
</template>
<template v-if="activeIndex === 5">
<div class="desc-text">{{$t('guide.alertTip')}}</div>
<div class="guide__btn-group">
<button class="guide__btn" type="button" @click="jumpAndOpen('alertRule')">{{$t('guide.addAlertRule')}}</button>
</div>
</template>
</div>
</el-dialog>
</div>
</template>
<script>
export default {
name: 'guide',
props: {
showDialog: {
type: Boolean,
default: false
}
},
data () {
return {
visible: false,
activeIndex: 0, // 当前激活的guideList的index
guideList: [
{
route: '/dc',
title: this.$t('guide.dc'),
icon: 'nz-icon nz-icon-datacenter1',
tip: this.$t('guide.dcTip')
},
{
route: '/agent',
title: this.$t('guide.agent'),
icon: 'nz-icon nz-icon-agent',
tip: this.$t('guide.agentTip')
},
{
route: '/asset',
title: this.$t('guide.asset'),
icon: 'nz-icon nz-icon-menu-assets',
tip: this.$t('guide.assetTip')
},
{
route: '/monitor/project',
title: this.$t('guide.monitor'),
icon: 'nz-icon nz-icon-menu-project',
tip: this.$t('guide.monitorTip')
},
{
route: '/panel',
title: this.$t('guide.visualization'),
icon: 'nz-icon nz-icon-visualization',
tip: this.$t('guide.visualizationTip')
},
{
route: '/alertRule',
title: this.$t('guide.alert'),
icon: 'nz-icon nz-icon-menu-alert',
tip: this.$t('guide.alertTip')
}
],
interval: null
}
},
methods: {
dialogOpened () {
if (this.$refs.changePinForm) {
this.$refs.changePinForm.resetFields()
}
},
dialogClosed () {
this.$emit('dialogClosed')
},
close () {
this.visible = false
},
enter (index) {
this.interval = setInterval(() => {
this.activeIndex = index
}, 300)
},
leave (index) {
this.interval && clearInterval(this.interval)
},
downloadAgent () {
},
openTerminal () {
},
jump (route) {
this.visible = false
this.$router.push({
path: route,
query: {
t: +new Date()
}
})
},
jumpAndOpen (cmd, open) {
this.visible = false
switch (cmd) {
case 'dc': {
this.$router.push({
path: '/dc',
query: {
t: +new Date(),
add: 'dc'
}
})
break
}
case 'agent': {
this.$router.push({
path: '/agent',
query: {
t: +new Date(),
add: 'agent'
}
})
break
}
case 'asset': {
this.$router.push({
path: '/asset',
query: {
t: +new Date(),
add: 'asset'
}
})
break
}
case 'project': {
this.$router.push({
path: '/monitor/project',
query: {
t: +new Date(),
add: 'project'
}
})
break
}
case 'module': {
this.$router.push({
path: '/monitor/module',
query: {
t: +new Date(),
add: 'module'
}
})
break
}
case 'endpoint': {
this.$router.push({
path: '/monitor/endpoint',
query: {
t: +new Date(),
add: 'endpoint'
}
})
break
}
case 'panel': {
this.$router.push({
path: '/panel',
query: {
t: +new Date(),
add: 'panel'
}
})
break
}
case 'chart': {
this.$router.push({
path: '/panel',
query: {
t: +new Date(),
add: 'chart'
}
})
break
}
case 'alertRule': {
this.$router.push({
path: '/alertRule',
query: {
t: +new Date(),
add: 'alertRule'
}
})
break
}
default: break
}
}
},
watch: {
showDialog (n) {
this.visible = n
},
activeIndex (n) {
this.$refs.guideShadow.style.left = `${n * this.$refs.guideShadow.offsetWidth}px`
}
}
}
</script>
<style lang="scss">
.guild-pop {
.el-dialog__header {
padding: 22px;
background-color: var(--theme-color-light-10);
text-align: center;
.el-dialog__title {
color: white;
font-size: 24px;
}
.el-dialog__headerbtn {
top: 29px;
i {
color: white;
font-size: 24px;
}
}
}
.el-dialog__body {
display: flex;
flex-direction: column;
padding: 30px 30px 43px;
box-sizing: border-box;
.guide-list {
display: flex;
position: relative;
width: 100%;
height: 170px;
.guide-shadow {
position: absolute;
height: 100%;
width: 16.67%;
top: -1px;
left: 0;
transition: all linear .3s;
border-bottom: 3px solid #101B27;
background-color: #F6F6F6;
}
.guide-shadow:after {
position: absolute;
z-index: 11;
content: '';
border-style: solid;
transition-duration: .3s;
transition-property: bottom;
left: calc(50% - 6px);
bottom: -9px;
border-width: 6px 6px 0;
border-color: #424242 transparent transparent transparent;
}
.guide-item {
flex: 1;
position: relative;
&:not(:nth-of-type(2)):before {
top: 100px;
width: 50%;
height: 2px;
background-color: #d8d8d8;
position: absolute;
left: 0;
content: "";
}
&:not(:last-of-type):after {
top: 100px;
width: 50%;
height: 2px;
background-color: #d8d8d8;
position: absolute;
right: 0;
content: "";
}
&.guide-item--active {
.item__title {
color: #101B27;
font-weight: bold;
}
.item__icon {
border-color: #ABABAB;
background-color: white;
cursor: pointer;
i {
color: #ABABAB;
}
}
}
.item__title {
padding-top: 20px;
color: #666;
text-align: center;
font-size: 16px;
transition: all linear .3s;
}
.item__icon {
position: relative;
top: 23px;
left: 50%;
transform: translateX(-50%);
height: 62px;
width: 62px;
border: 1px solid #E0E0E0;
border-radius: 50%;
box-sizing: border-box;
background-color: #F6F6F6;
transition: all linear .3s;
z-index: 1;
i {
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
color: #BEBEBE;
font-size: 30px;
transition: all linear .3s;
}
}
}
}
.guide-desc {
display: flex;
flex-direction: column;
width: 100%;
height: 200px;
padding-bottom: 32px;
box-sizing: border-box;
border: 1px solid #999;
.desc-text {
flex: auto;
padding: 0 30px;
display: flex;
align-items: center;
color: #101B27;
font-size: 18px;
word-break: keep-all;
}
.guide__btn-group {
display: flex;
justify-content: center;
height: 46px;
.guide__btn {
margin: 0 15px;
padding: 0 15px;
height: 100%;
color: white;
border: none;
border-radius: $--primary-border-radius;
background-color: #666;
font-size: 18px;
outline: none;
cursor: pointer;
opacity: 1;
transition: all linear .2s;
}
.guide__btn:hover {
opacity: .9;
}
}
}
}
}
</style>

View File

@@ -88,9 +88,6 @@ export default {
areaData: [],
coordinateFlag: false
}
},
created() {
},
methods: {
/* 关闭弹框 */
@@ -198,10 +195,6 @@ export default {
}
}
},
mounted () {
// this.getAreaData();
// console.log(this.editDc)
},
watch: {
obj: {
immediate: true,

View File

@@ -1,126 +1,130 @@
<template>
<transition name="right-box-580">
<div class="right-box right-box-panel z-top" v-if="rightBox.show" v-clickoutside="{obj:panel,func:clickos}">
<div v-clickoutside="{obj:editPanel,func:clickOutside}" class="right-box right-box-panel">
<!-- begin--标题-->
<div class="right-box-title right-box__header">{{rightBox.title}}</div>
<!-- end--标题-->
<div class="right-box__header">
<div class="header__title">{{editPanel.id ? ($t("config.dc.editPanel")) : $t("config.dc.createDc")}}</div>
<div class="header__operation">
<span v-cancel="{obj: editPanel, func: esc}"><i class="nz-icon nz-icon-close"></i></span>
</div>
</div>
<!-- begin--表单-->
<div class="right-box-form-box right-box__container">
<el-form class="right-box-form right-box-form-left" label-width="120px" :model="panel" label-position = "top" ref="panelForm">
<el-form-item :label='$t("overall.name")' prop="name" :rules="{required: true, message: $t('validate.required'), trigger: 'blur'}">
<el-input placeholder="" maxlength="64" show-word-limit v-model="panel.name" size="small" id="panel-box-input-name"></el-input>
<div class="right-box__container">
<div class="container__form">
<el-form ref="form" :model="editPanel" :rules="rules" label-position = "top" label-width="120px" size="small">
<el-form-item :label='$t("overall.name")' prop="name">
<el-input id="dc-box-input-name" v-model="editPanel.name" maxlength="64" placeholder="" show-word-limit size="small"></el-input>
</el-form-item>
</el-form>
</div>
<!-- end--表单-->
<!-- begin--底部按钮-->
</div>
<!--底部按钮-->
<div class="right-box__footer">
<button v-cancel="{obj:panel,func:esc}" id="panel-box-esc" class="footer__btn footer__btn--light">
<button id="dc-box-esc" v-cancel="{obj:editPanel, func:esc}" class="footer__btn footer__btn--light">
<span>{{$t('overall.cancel')}}</span>
</button>
<button :class="{'nz-btn-disabled':prevent_opt.save}" :disabled="prevent_opt.save" @click="save" class="footer__btn" id="panel-box-save">
<button id="dc-box-save" :class="{'nz-btn-disabled':prevent_opt.save}" :disabled="prevent_opt.save" class="footer__btn" @click="save">
<span>{{$t('overall.save')}}</span>
</button>
</div>
<!-- end--底部按钮-->
</div>
</transition>
</template>
<script>
export default {
name: 'panelBox',
props: {
panel: Object
obj: {
type: Object
}
},
data () {
return {
rightBox: { // 面板弹出框相关
show: false,
title: this.$t('dashboard.panel.createPanelTitle')
url: '/panel',
editPanel: {},
rules: {
name: [
{ required: true, message: this.$t('validate.required'), trigger: 'blur' }
]
}
}
},
methods: {
show (show) {
this.rightBox.show = show
/* 关闭弹框 */
esc (refresh) {
this.prevent_opt.save = false
this.$emit('close', refresh)
},
setTitle (title) {
this.rightBox.title = title
clickOutside () {
this.esc(false)
},
clickos () {
this.esc()
/* 保存 */
save () {
if (this.prevent_opt.save) {
return
}
this.prevent_opt.save = true
this.$refs.form.validate((valid) => {
if (valid) {
if (this.editPanel.id) {
this.$put(this.url, this.editPanel).then(response => {
this.prevent_opt.save = false
if (response.code === 200) {
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
this.esc(true)
} else {
this.$message.error(response.msg)
}
})
} else {
this.$post(this.url, this.editPanel).then(response => {
this.prevent_opt.save = false
if (response.code === 200) {
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
this.esc(true)
} else {
this.$message.error(response.msg)
}
})
}
} else {
this.prevent_opt.save = false
return false
}
})
},
// 面板相关方法
del: function (u) {
/* 删除 */
del () {
if (this.prevent_opt.save) { return } ;
this.prevent_opt.save = true
this.$confirm(this.$t('tip.confirmDelete'), {
confirmButtonText: this.$t('tip.yes'),
cancelButtonText: this.$t('tip.no'),
type: 'warning'
}).then(() => {
this.$delete('visual/panel?ids=' + u.id).then(response => {
this.$delete(`${this.url}?ids=${this.editPanel.id}`).then(response => {
this.prevent_opt.save = false
if (response.code === 200) {
this.esc()
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.deleteSuccess') })
this.$emit('reloadForDel')
this.esc(true)
} else {
this.$message.error(response.msg)
}
})
})
},
save: function () {
this.$refs.panelForm.validate((valid) => {
if (valid) {
this.prevent_opt.save = true
if (this.panel.id) {
this.$put('visual/panel', this.panel).then(response => {
if (response.code === 200) {
this.esc()
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
this.$emit('reload')
} else {
this.$message.error(response.msg)
}
this.prevent_opt.save = false
})
} else {
this.$post('visual/panel', this.panel).then(response => {
if (response.code === 200) {
this.esc()
this.$message({ duration: 1000, type: 'success', message: this.$t('tip.saveSuccess') })
this.$emit('reload', this.panel.name)
} else {
this.$message.error(response.msg)
}
}).catch(() => {
this.prevent_opt.save = false
})
}
} else {
return false
}
})
},
esc: function () {
this.rightBox.show = false
}
},
created () {
},
mounted: function () {
},
watch: {
obj: {
immediate: true,
deep: true,
handler (n, o) {
this.editPanel = JSON.parse(JSON.stringify(n))
}
}
}
}
</script>
<style scoped>
.z-top{
z-index: 3000 !important;
}
</style>

View File

@@ -22,11 +22,10 @@
<span v-show="$store.state.consoleCount>0" class="right-tip">{{$store.state.consoleCount<=10?$store.state.consoleCount:'10+'}}</span>
</div>
</el-dropdown>
<!-- <el-dropdown>
<el-dropdown>
<el-dropdown-menu></el-dropdown-menu>
<div class="header-menu__item" @click="centerDialogVisible = true"><i class="nz-icon nz-icon-guide"></i></div>
<path-navigation :show.sync="centerDialogVisible"></path-navigation>
</el-dropdown>-->
<div class="header-menu__item" @click="showGuide = true"><i class="nz-icon nz-icon-guide"></i></div>
</el-dropdown>
</div>
<!--个人操作-->
<div class="personal">
@@ -56,6 +55,7 @@
</el-dropdown>
</div>
<change-password :cur-user="username" :show-dialog="showChangePin" @click="showPinDialog" @dialogClosed="dialogClosed"></change-password>
<guide :show-dialog="showGuide" @dialogClosed="dialogClosed"></guide>
</div>
</template>
@@ -63,12 +63,12 @@
import bus from '../../libs/bus'
import { mapActions } from 'vuex'
import changePin from '../page/config/changePin'
import PathNavigation from './path_navigation/PathNavigation'
import guide from '@/components/common/popBox/guide'
export default {
name: 'Header',
components: {
'change-password': changePin,
PathNavigation
guide
},
data () {
return {
@@ -109,7 +109,7 @@ export default {
}
],
showChangePin: false,
centerDialogVisible: false
showGuide: false
}
},
methods: {
@@ -162,6 +162,7 @@ export default {
},
dialogClosed () {
this.showChangePin = false
this.showGuide = false
},
cancel () {
this.jumpTo(this.$route.path.slice(1, this.$route.path.length))

View File

@@ -158,26 +158,16 @@ export default {
this.rightBox.show = true
}
})
},
initEvent () {
bus.$on('alert-rule-list-change', () => {
this.getTableData()
})
bus.$on('dc-list-change', () => {
this.getTableData()
})
bus.$on('alert-message-change', () => {
this.getTableData()
})
}
},
beforeDestroy () {
bus.$off('alert-rule-list-change')
bus.$off('dc-list-change')
bus.$off('alert-message-change')
},
mounted () {
this.initEvent()
// 是否弹出侧滑
const add = this.$route.query.add
if (add) {
if (add === 'alertRule') {
this.add()
}
}
}
}
</script>

View File

@@ -434,6 +434,14 @@ export default {
this.getSearchableMetaData()
this.getSnmpCredentialData()
this.getFieldGroupData()
// 是否弹出侧滑
const add = this.$route.query.add
if (add) {
if (add === 'asset') {
this.add()
}
}
}
}
</script>

View File

@@ -270,6 +270,13 @@ export default {
}
},
mounted () {
// 是否弹出侧滑
const add = this.$route.query.add
if (add) {
if (add === 'agent') {
this.add()
}
}
}
}
</script>

View File

@@ -42,7 +42,6 @@
</div>
</template>
<script>
import bus from '@/libs/bus'
import dcBox from '@/components/common/rightBox/dcBox' // dc弹框
import trafficSettingBox from '@/components/common/rightBox/trafficSetting/trafficSettingBox'
import deleteButton from '@/components/common/deleteButton'
@@ -134,6 +133,13 @@ export default {
},
mounted () {
this.getUserData()
// 是否弹出侧滑
const add = this.$route.query.add
if (add) {
if (add === 'dc') {
this.add()
}
}
}
}
</script>

View File

@@ -83,7 +83,7 @@
<chart-temp-box :obj="chart" :from="$CONSTANTS.fromRoute.panel" :panel-data="panelData" :show-panel="showPanel" @close="closeChartTempBox" @on-create-success="createSuccess" v-if="rightBox.chartTemp.show"></chart-temp-box>
</transition>
<transition name="right-box">
<panel-box v-if="closePanelBox" :panel="panel" @reload="panelReload" @reloadForDel="panelReloadForDel" ref="panelBox"></panel-box>
<panel-box v-if="rightBox.panel.show" ref="panelBox" :panel="panel" @reload="panelReload" @reloadForDel="panelReloadForDel"></panel-box>
</transition>
</div>
</template>
@@ -779,6 +779,14 @@ export default {
this.onScroll()
document.querySelector('#tableList').addEventListener('mouseenter', this.tableListEnter)
document.querySelector('#tableList').addEventListener('mouseleave', this.tableListLeave)
// 是否弹出侧滑
const add = this.$route.query.add
if (add) {
if (add === 'chart') {
this.addChart()
}
}
},
watch: {
'filter.searchName': function (n, o) {

View File

@@ -319,6 +319,14 @@ export default {
})
this.$refs.dataList.$refs.searchInput.sreach_num = 1
}
// 是否弹出侧滑
const add = this.$route.query.add
if (add) {
if (add === 'endpoint') {
this.add()
}
}
}
}
</script>

View File

@@ -213,6 +213,13 @@ export default {
}
},
mounted () {
// 是否弹出侧滑
const add = this.$route.query.add
if (add) {
if (add === 'module') {
this.add()
}
}
}
}
</script>

View File

@@ -1,6 +1,6 @@
<template>
<div class="main-list">
<projectList :class="showList?'projectList':'hide'" />
<projectList ref="dataList" :class="showList?'projectList':'hide'"/>
<projectTopo :class="showList?'projectTopo':'projectTopo ml10'" />
</div>
</template>
@@ -25,6 +25,13 @@ export default {
},
watch: {},
mounted () {
// 是否弹出侧滑
const add = this.$route.query.add
if (add) {
if (add === 'project') {
this.$refs.dataList.add()
}
}
},
methods: {}
}