1
This commit is contained in:
@@ -7,3 +7,11 @@ export function getServer() {
|
|||||||
method: 'get'
|
method: 'get'
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 获取服务健康度检测
|
||||||
|
export function getHealth() {
|
||||||
|
return request({
|
||||||
|
url: '/monitor/server/health',
|
||||||
|
method: 'get'
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
<template>
|
<template>
|
||||||
<div class="mobile-bottom-nav" v-if="isMobile && show">
|
<div class="mobile-bottom-nav" :class="{ 'scrollable': navItems.length > 5 }" v-if="isMobile && show">
|
||||||
<div
|
<div
|
||||||
v-for="item in navItems"
|
v-for="item in navItems"
|
||||||
:key="item.path"
|
:key="item.path"
|
||||||
@@ -106,7 +106,7 @@ export default {
|
|||||||
|
|
||||||
const flatRoutes = flattenRoutes(routes)
|
const flatRoutes = flattenRoutes(routes)
|
||||||
|
|
||||||
// 过滤并选择前5个主要路由
|
// 过滤并获取所有主要路由(不限制数量)
|
||||||
const mainRoutes = flatRoutes
|
const mainRoutes = flatRoutes
|
||||||
.filter(route => {
|
.filter(route => {
|
||||||
// 过滤掉一些特殊路由
|
// 过滤掉一些特殊路由
|
||||||
@@ -117,7 +117,9 @@ export default {
|
|||||||
!excludePaths.some(exclude => path.includes(exclude)) &&
|
!excludePaths.some(exclude => path.includes(exclude)) &&
|
||||||
!path.startsWith('/user/')
|
!path.startsWith('/user/')
|
||||||
})
|
})
|
||||||
.slice(0, 5)
|
// 不限制数量,显示所有可用路由
|
||||||
|
// 但限制最多10个,避免过多导致显示问题
|
||||||
|
.slice(0, 10)
|
||||||
|
|
||||||
// 缓存结果
|
// 缓存结果
|
||||||
if (mainRoutes.length > 0) {
|
if (mainRoutes.length > 0) {
|
||||||
@@ -215,17 +217,28 @@ export default {
|
|||||||
z-index: 1000;
|
z-index: 1000;
|
||||||
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
box-shadow: 0 -2px 10px rgba(0, 0, 0, 0.05);
|
||||||
padding-bottom: env(safe-area-inset-bottom);
|
padding-bottom: env(safe-area-inset-bottom);
|
||||||
|
overflow-x: auto;
|
||||||
|
-webkit-overflow-scrolling: touch;
|
||||||
|
|
||||||
|
// 如果导航项超过5个,允许横向滚动
|
||||||
|
&.scrollable {
|
||||||
|
justify-content: flex-start;
|
||||||
|
padding: 0 8px;
|
||||||
|
}
|
||||||
|
|
||||||
.nav-item {
|
.nav-item {
|
||||||
flex: 1;
|
flex: 1;
|
||||||
|
min-width: 60px;
|
||||||
|
max-width: 80px;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
justify-content: center;
|
justify-content: center;
|
||||||
padding: 6px 0;
|
padding: 6px 4px;
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
-webkit-tap-highlight-color: transparent;
|
-webkit-tap-highlight-color: transparent;
|
||||||
|
flex-shrink: 0;
|
||||||
|
|
||||||
.nav-icon {
|
.nav-icon {
|
||||||
width: 28px;
|
width: 28px;
|
||||||
@@ -252,6 +265,11 @@ export default {
|
|||||||
font-size: 11px;
|
font-size: 11px;
|
||||||
color: #909399;
|
color: #909399;
|
||||||
transition: all 0.3s;
|
transition: all 0.3s;
|
||||||
|
white-space: nowrap;
|
||||||
|
overflow: hidden;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
max-width: 100%;
|
||||||
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.active {
|
&.active {
|
||||||
|
|||||||
@@ -47,85 +47,8 @@ export default {
|
|||||||
}),
|
}),
|
||||||
...mapGetters(['sidebarRouters']),
|
...mapGetters(['sidebarRouters']),
|
||||||
mobileNavItems() {
|
mobileNavItems() {
|
||||||
// 根据业务需求配置底部导航项
|
// 如果返回空数组,组件会使用默认逻辑从路由中自动获取所有可用路由
|
||||||
// 匹配关键词来自动查找路由,如果找不到则使用指定路径
|
return []
|
||||||
const navConfig = [
|
|
||||||
{ keywords: ['慢单', 'sloworder'], label: '下好的慢单', icon: 'el-icon-list', defaultPath: '/sloworder/index' },
|
|
||||||
{ keywords: ['指令', 'instruction', 'jd-instruction'], label: '指令执行', icon: 'el-icon-edit-outline', defaultPath: '/jd-instruction/index' },
|
|
||||||
{ keywords: ['型号', 'productJdConfig', 'product'], label: '型号配置', icon: 'el-icon-setting', defaultPath: '/jarvis/productJdConfig' },
|
|
||||||
{ keywords: ['商品', 'favorite', 'erpProduct'], label: '商品列表', icon: 'el-icon-goods', defaultPath: '/favorite/index' }
|
|
||||||
]
|
|
||||||
|
|
||||||
const routes = this.sidebarRouters || []
|
|
||||||
|
|
||||||
// 扁平化路由
|
|
||||||
const flattenRoutes = (routes, parentPath = '') => {
|
|
||||||
let result = []
|
|
||||||
if (!routes || !Array.isArray(routes)) return result
|
|
||||||
|
|
||||||
routes.forEach(route => {
|
|
||||||
if (route.hidden) return
|
|
||||||
|
|
||||||
let fullPath = route.path || ''
|
|
||||||
if (parentPath) {
|
|
||||||
if (fullPath.startsWith('/')) {
|
|
||||||
fullPath = fullPath
|
|
||||||
} else {
|
|
||||||
const basePath = parentPath.endsWith('/') ? parentPath.slice(0, -1) : parentPath
|
|
||||||
fullPath = `${basePath}/${fullPath}`.replace(/\/+/g, '/')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!fullPath.startsWith('/')) {
|
|
||||||
fullPath = '/' + fullPath
|
|
||||||
}
|
|
||||||
|
|
||||||
if (route.children && route.children.length > 0) {
|
|
||||||
result = result.concat(flattenRoutes(route.children, fullPath))
|
|
||||||
} else {
|
|
||||||
if (route.meta && route.meta.title && fullPath) {
|
|
||||||
result.push({
|
|
||||||
path: fullPath,
|
|
||||||
label: route.meta.title,
|
|
||||||
route: route
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
return result
|
|
||||||
}
|
|
||||||
|
|
||||||
const flatRoutes = flattenRoutes(routes)
|
|
||||||
|
|
||||||
// 为每个配置项查找匹配的路由
|
|
||||||
const navItems = navConfig.map(config => {
|
|
||||||
// 先尝试从路由中匹配
|
|
||||||
const matchedRoute = flatRoutes.find(route => {
|
|
||||||
const path = (route.path || '').toLowerCase()
|
|
||||||
const title = (route.label || '').toLowerCase()
|
|
||||||
return config.keywords.some(keyword =>
|
|
||||||
path.includes(keyword.toLowerCase()) || title.includes(keyword.toLowerCase())
|
|
||||||
)
|
|
||||||
})
|
|
||||||
|
|
||||||
if (matchedRoute) {
|
|
||||||
return {
|
|
||||||
path: matchedRoute.path,
|
|
||||||
label: config.label,
|
|
||||||
icon: config.icon
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 如果没找到,使用默认路径
|
|
||||||
return {
|
|
||||||
path: config.defaultPath,
|
|
||||||
label: config.label,
|
|
||||||
icon: config.icon
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
// 过滤掉无效的路由
|
|
||||||
return navItems.filter(item => item.path)
|
|
||||||
},
|
},
|
||||||
classObj() {
|
classObj() {
|
||||||
return {
|
return {
|
||||||
|
|||||||
@@ -171,23 +171,109 @@
|
|||||||
</div>
|
</div>
|
||||||
</el-card>
|
</el-card>
|
||||||
</el-col>
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="card-box">
|
||||||
|
<el-card>
|
||||||
|
<div slot="header">
|
||||||
|
<span><i class="el-icon-truck"></i> 物流服务健康度</span>
|
||||||
|
</div>
|
||||||
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
|
<table cellspacing="0" style="width: 100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="el-table__cell is-leaf"><div class="cell">服务状态</div></td>
|
||||||
|
<td class="el-table__cell is-leaf">
|
||||||
|
<div class="cell">
|
||||||
|
<el-tag :type="health.logistics && health.logistics.healthy ? 'success' : 'danger'">
|
||||||
|
{{ health.logistics && health.logistics.status ? health.logistics.status : '未知' }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="el-table__cell is-leaf"><div class="cell">服务地址</div></td>
|
||||||
|
<td class="el-table__cell is-leaf">
|
||||||
|
<div class="cell" style="word-break: break-all;">
|
||||||
|
{{ health.logistics && health.logistics.serviceUrl ? health.logistics.serviceUrl : '-' }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="el-table__cell is-leaf"><div class="cell">状态信息</div></td>
|
||||||
|
<td class="el-table__cell is-leaf">
|
||||||
|
<div class="cell" :class="{'text-danger': health.logistics && !health.logistics.healthy}">
|
||||||
|
{{ health.logistics && health.logistics.message ? health.logistics.message : '-' }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
|
|
||||||
|
<el-col :span="12" class="card-box">
|
||||||
|
<el-card>
|
||||||
|
<div slot="header">
|
||||||
|
<span><i class="el-icon-message"></i> 微信推送服务健康度</span>
|
||||||
|
</div>
|
||||||
|
<div class="el-table el-table--enable-row-hover el-table--medium">
|
||||||
|
<table cellspacing="0" style="width: 100%;">
|
||||||
|
<tbody>
|
||||||
|
<tr>
|
||||||
|
<td class="el-table__cell is-leaf"><div class="cell">服务状态</div></td>
|
||||||
|
<td class="el-table__cell is-leaf">
|
||||||
|
<div class="cell">
|
||||||
|
<el-tag :type="health.wxSend && health.wxSend.healthy ? 'success' : 'danger'">
|
||||||
|
{{ health.wxSend && health.wxSend.status ? health.wxSend.status : '未知' }}
|
||||||
|
</el-tag>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="el-table__cell is-leaf"><div class="cell">服务地址</div></td>
|
||||||
|
<td class="el-table__cell is-leaf">
|
||||||
|
<div class="cell" style="word-break: break-all;">
|
||||||
|
{{ health.wxSend && health.wxSend.serviceUrl ? health.wxSend.serviceUrl : '-' }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="el-table__cell is-leaf"><div class="cell">状态信息</div></td>
|
||||||
|
<td class="el-table__cell is-leaf">
|
||||||
|
<div class="cell" :class="{'text-danger': health.wxSend && !health.wxSend.healthy}">
|
||||||
|
{{ health.wxSend && health.wxSend.message ? health.wxSend.message : '-' }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</el-card>
|
||||||
|
</el-col>
|
||||||
</el-row>
|
</el-row>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
import { getServer } from "@/api/monitor/server"
|
import { getServer, getHealth } from "@/api/monitor/server"
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: "Server",
|
name: "Server",
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
// 服务器信息
|
// 服务器信息
|
||||||
server: []
|
server: [],
|
||||||
|
// 健康度检测信息
|
||||||
|
health: {
|
||||||
|
logistics: null,
|
||||||
|
wxSend: null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
this.getList()
|
this.getList()
|
||||||
|
this.getHealthInfo()
|
||||||
this.openLoading()
|
this.openLoading()
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
@@ -198,6 +284,16 @@ export default {
|
|||||||
this.$modal.closeLoading()
|
this.$modal.closeLoading()
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
|
/** 查询健康度检测信息 */
|
||||||
|
getHealthInfo() {
|
||||||
|
getHealth().then(response => {
|
||||||
|
if (response.data) {
|
||||||
|
this.health = response.data
|
||||||
|
}
|
||||||
|
}).catch(error => {
|
||||||
|
console.error("获取健康度检测信息失败", error)
|
||||||
|
})
|
||||||
|
},
|
||||||
// 打开加载层
|
// 打开加载层
|
||||||
openLoading() {
|
openLoading() {
|
||||||
this.$modal.loading("正在加载服务监控数据,请稍候!")
|
this.$modal.loading("正在加载服务监控数据,请稍候!")
|
||||||
|
|||||||
@@ -9,20 +9,20 @@
|
|||||||
<el-form-item label="输入指令">
|
<el-form-item label="输入指令">
|
||||||
<el-input v-model="form.command" type="textarea" :rows="8" placeholder="例如:京今日统计 / 京昨日订单 / 慢搜关键词 / 录单20250101-20250107" />
|
<el-input v-model="form.command" type="textarea" :rows="8" placeholder="例如:京今日统计 / 京昨日订单 / 慢搜关键词 / 录单20250101-20250107" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item class="button-group button-group-primary">
|
<div class="button-group button-group-primary">
|
||||||
<el-button type="success" size="medium" @click="run" :loading="loading">执行</el-button>
|
<el-button type="success" size="medium" @click="run" :loading="loading">执行</el-button>
|
||||||
<el-button type="danger" size="medium" @click="clearAll">清空</el-button>
|
<el-button type="danger" size="medium" @click="clearAll">清空</el-button>
|
||||||
<el-button size="warning" @click="fillMan">慢单</el-button>
|
<el-button size="warning" @click="fillMan">慢单</el-button>
|
||||||
<el-button size="success" @click="fillSheng">生</el-button>
|
<el-button size="success" @click="fillSheng">生</el-button>
|
||||||
</el-form-item>
|
</div>
|
||||||
<el-form-item class="button-group button-group-secondary">
|
<div class="button-group button-group-secondary">
|
||||||
<el-button size="primary" @click="fillTF">腾峰</el-button>
|
<el-button size="primary" @click="fillTF">腾峰</el-button>
|
||||||
<el-button type="primary" size="medium" @click="fillFan">凡</el-button>
|
<el-button type="primary" size="medium" @click="fillFan">凡</el-button>
|
||||||
<el-button type="primary" size="medium" @click="fillWen">纹</el-button>
|
<el-button type="primary" size="medium" @click="fillWen">纹</el-button>
|
||||||
<el-button type="primary" size="medium" @click="fillHong">鸿</el-button>
|
<el-button type="primary" size="medium" @click="fillHong">鸿</el-button>
|
||||||
<el-button type="primary" size="medium" @click="fillPDD">拼多多</el-button>
|
<el-button type="primary" size="medium" @click="fillPDD">拼多多</el-button>
|
||||||
<el-button type="primary" size="medium" @click="fillPDDWen">拼多多-纹</el-button>
|
<el-button type="primary" size="medium" @click="fillPDDWen">拼多多-纹</el-button>
|
||||||
</el-form-item>
|
</div>
|
||||||
</el-form>
|
</el-form>
|
||||||
|
|
||||||
<el-divider>响应</el-divider>
|
<el-divider>响应</el-divider>
|
||||||
@@ -533,6 +533,7 @@ export default {
|
|||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
gap: 10px;
|
gap: 10px;
|
||||||
|
width: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-group .el-button {
|
.button-group .el-button {
|
||||||
@@ -597,14 +598,10 @@ export default {
|
|||||||
font-size: 12px;
|
font-size: 12px;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 确保el-form-item不会影响布局 */
|
/* 确保按钮组独立于form-item */
|
||||||
.button-group.el-form-item {
|
.button-group {
|
||||||
margin-bottom: 12px !important;
|
|
||||||
}
|
|
||||||
|
|
||||||
.button-group.el-form-item ::v-deep .el-form-item__content {
|
|
||||||
margin-left: 0 !important;
|
margin-left: 0 !important;
|
||||||
width: 100% !important;
|
margin-right: 0 !important;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user