feat(web): 配置中心聚合页、路由迁移与权限页 key 同步
将原十余个独立配置页聚合为 调度策略/设备与库位/业务与集成/运维与回放/系统与权限 等聚合页 (Tab 与 URL ?tab= 同步),旧路径以 redirect 兼容深链接;AppShell 菜单与 mock/rbac 的页面 key 同步后端 PageCatalog;Dashboard 快捷入口改指聚合页对应 tab;新增 TaskTemplateView 取代并删除 MissionEditorView / OrchestrationView。 Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -392,12 +392,12 @@ const activeMissionCount = computed(() =>
|
||||
interface QuickEntry { key: string; label: string; icon: unknown; hint?: string; primary?: boolean; to?: string; action?: () => void }
|
||||
const quickEntries = computed<QuickEntry[]>(() => [
|
||||
{ key: 'platform-config', label: '平台配置', icon: Setting, primary: true, hint: '进入地图编辑 / 平台搭建(map-editor)', to: '/admin/map-editor' },
|
||||
{ key: 'mission', label: '任务编排', icon: Operation, to: '/admin/missions' },
|
||||
{ key: 'mission', label: '任务编排', icon: Operation, to: '/admin/task-templates' },
|
||||
{ key: 'cars', label: 'AGV 配置', icon: Van, to: '/admin/cars' },
|
||||
{ key: 'auth', label: '权限配置', icon: Avatar, to: '/admin/config/auth' },
|
||||
{ key: 'system', label: '系统配置', icon: Tools, to: '/admin/config/system' },
|
||||
{ key: 'ops', label: '异常处理', icon: Warning, to: '/admin/config/ops' },
|
||||
{ key: 'tasks', label: '任务管理', icon: List, to: '/admin/config/task' },
|
||||
{ key: 'auth', label: '权限配置', icon: Avatar, to: '/admin/config/system-center?tab=auth' },
|
||||
{ key: 'system', label: '系统配置', icon: Tools, to: '/admin/config/system-center?tab=system' },
|
||||
{ key: 'ops', label: '异常处理', icon: Warning, to: '/admin/config/ops-center?tab=ops' },
|
||||
{ key: 'tasks', label: '任务管理', icon: List, to: '/admin/config/strategy?tab=task' },
|
||||
{ key: 'add', label: '添加', icon: Plus, hint: '自定义快捷入口(待实现)', action: () => { ElMessage.info('自定义快捷入口 — 即将在 v1.8 中开放') } }
|
||||
])
|
||||
function onQuickClick(item: QuickEntry) {
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
<template>
|
||||
<div class="mission-page">
|
||||
<ReflectionManagerPanel
|
||||
kind="process"
|
||||
kind-label="任务"
|
||||
title="任务编排(Mission / 进程,含插件 MissionType 实例化)"
|
||||
empty-text="当前没有任务;点击右上角「新建任务」从已加载的 MissionType 中选一个实例化。"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* /admin/missions 路由的页面入口。
|
||||
*
|
||||
* 由于「任务」与「进程」在后端 ReflectionApiController 共用 kind=process / mission
|
||||
* (UiDiscoveryCache.MissionCreatableTypes 同源),这里直接用 ReflectionManagerPanel
|
||||
* 接入,按下「新建任务」会列出所有 MissionType 子类(含 taskflow / trigger)。
|
||||
*
|
||||
* 旧版本的 DataTablePro + listMissions mock 已经下线,所有数据走 SimpleLite 反射 API。
|
||||
*/
|
||||
import ReflectionManagerPanel from '@/components/reflection/ReflectionManagerPanel.vue'
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.mission-page {
|
||||
height: calc(100vh - 56px);
|
||||
padding: 12px 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
</style>
|
||||
@@ -1,67 +0,0 @@
|
||||
<template>
|
||||
<div class="orchestration-page">
|
||||
<el-tabs v-model="tab" class="orch-tabs" type="border-card" @tab-change="onTabChange">
|
||||
<el-tab-pane label="车辆" name="cars">
|
||||
<CarPanelView v-if="tab === 'cars'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="进程" name="process">
|
||||
<MissionEditorView v-if="tab === 'process'" />
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="脚本" name="script">
|
||||
<ReflectionKindTable
|
||||
v-if="tab === 'script'"
|
||||
kind="script"
|
||||
empty-text="脚本(继承 CarProgram 的子类型)未发现可暴露条目"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="任务流" name="taskflow">
|
||||
<ReflectionKindTable
|
||||
v-if="tab === 'taskflow'"
|
||||
kind="mission"
|
||||
extra-filter="taskflow"
|
||||
empty-text="未发现任务流条目"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane label="触发器" name="trigger">
|
||||
<ReflectionKindTable
|
||||
v-if="tab === 'trigger'"
|
||||
kind="mission"
|
||||
extra-filter="trigger"
|
||||
empty-text="未发现触发器条目"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { onMounted, ref } from 'vue'
|
||||
import CarPanelView from '@/views/admin/CarPanelView.vue'
|
||||
import MissionEditorView from '@/views/admin/MissionEditorView.vue'
|
||||
import ReflectionKindTable from '@/components/orchestration/ReflectionKindTable.vue'
|
||||
|
||||
const tab = ref<'cars' | 'process' | 'script' | 'taskflow' | 'trigger'>('cars')
|
||||
|
||||
function onTabChange(name: string | number) {
|
||||
tab.value = name as typeof tab.value
|
||||
}
|
||||
|
||||
onMounted(() => {
|
||||
const cached = sessionStorage.getItem('orchestration.tab')
|
||||
if (cached) tab.value = cached as typeof tab.value
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.orchestration-page {
|
||||
height: calc(100vh - 56px);
|
||||
padding: 12px;
|
||||
}
|
||||
.orch-tabs {
|
||||
height: 100%;
|
||||
}
|
||||
.orch-tabs :deep(.el-tabs__content) {
|
||||
height: calc(100% - 40px);
|
||||
overflow: auto;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,27 @@
|
||||
<template>
|
||||
<div class="task-template-page">
|
||||
<WorkflowEditor />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
/**
|
||||
* 任务编排页(路由 /admin/task-templates):承接 workflow 可视化编排组件。
|
||||
*
|
||||
* 原独立的 /admin/missions(MissionEditor / 进程实例管理)入口已下线并合并至此,
|
||||
* 这里专注任务流程的可视化编排、模板设计、导入导出和本地流程库。
|
||||
*/
|
||||
import WorkflowEditor from '@/components/workflow/WorkflowEditor.vue'
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.task-template-page {
|
||||
height: calc(100vh - 56px);
|
||||
padding: 12px 14px;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.task-template-page :deep(.workflow-editor) {
|
||||
height: 100%;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,79 @@
|
||||
<template>
|
||||
<div class="config-hub-page">
|
||||
<el-tabs v-model="activeTab" class="hub-tabs">
|
||||
<el-tab-pane name="integrations" label="外部系统对接">
|
||||
<div class="config-pane"><ExternalIntegrationView /></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="scenario" label="场景模板" lazy>
|
||||
<div class="config-pane"><ScenarioTemplateView /></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="widget" label="自定义控件" lazy>
|
||||
<div class="config-pane"><CustomWidgetView /></div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import ExternalIntegrationView from '@/views/admin/config/ExternalIntegrationView.vue'
|
||||
import ScenarioTemplateView from '@/views/admin/config/ScenarioTemplateView.vue'
|
||||
import CustomWidgetView from '@/views/admin/config/CustomWidgetView.vue'
|
||||
|
||||
// 聚合页:对外接口、业务场景建模与自定义控件。Tab 与 URL ?tab= 同步。
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const TAB_NAMES = ['integrations', 'scenario', 'widget'] as const
|
||||
type TabName = (typeof TAB_NAMES)[number]
|
||||
function readTab(): TabName {
|
||||
const q = route.query.tab
|
||||
return typeof q === 'string' && (TAB_NAMES as readonly string[]).includes(q) ? (q as TabName) : 'integrations'
|
||||
}
|
||||
const activeTab = ref<TabName>(readTab())
|
||||
watch(activeTab, (t) => {
|
||||
if (route.query.tab !== t) router.replace({ query: { ...route.query, tab: t } })
|
||||
})
|
||||
watch(() => route.query.tab, () => {
|
||||
const next = readTab()
|
||||
if (next !== activeTab.value) activeTab.value = next
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.config-hub-page {
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
.hub-tabs {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
:deep(.el-tabs__content) {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
:deep(.el-tab-pane) { height: 100%; }
|
||||
.config-pane {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
:deep(.el-tabs__item) {
|
||||
color: var(--mg-text-muted, rgba(255, 255, 255, 0.65));
|
||||
}
|
||||
:deep(.el-tabs__item.is-active) {
|
||||
color: var(--mg-text-light, #fff);
|
||||
}
|
||||
:deep(.el-tabs__active-bar) {
|
||||
background-color: var(--mg-accent, var(--el-color-primary));
|
||||
}
|
||||
:deep(.el-tabs__nav-wrap::after) {
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div class="config-hub-page">
|
||||
<el-tabs v-model="activeTab" class="hub-tabs">
|
||||
<el-tab-pane name="device" label="设备接入">
|
||||
<div class="config-pane"><DeviceHubView /></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="location" label="库位管理" lazy>
|
||||
<div class="config-pane"><LocationView /></div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import DeviceHubView from '@/views/admin/config/DeviceHubView.vue'
|
||||
import LocationView from '@/views/admin/config/LocationView.vue'
|
||||
|
||||
// 聚合页:第三方设备接入与库位管理。Tab 与 URL ?tab= 同步。
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const TAB_NAMES = ['device', 'location'] as const
|
||||
type TabName = (typeof TAB_NAMES)[number]
|
||||
function readTab(): TabName {
|
||||
const q = route.query.tab
|
||||
return typeof q === 'string' && (TAB_NAMES as readonly string[]).includes(q) ? (q as TabName) : 'device'
|
||||
}
|
||||
const activeTab = ref<TabName>(readTab())
|
||||
watch(activeTab, (t) => {
|
||||
if (route.query.tab !== t) router.replace({ query: { ...route.query, tab: t } })
|
||||
})
|
||||
watch(() => route.query.tab, () => {
|
||||
const next = readTab()
|
||||
if (next !== activeTab.value) activeTab.value = next
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.config-hub-page {
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
.hub-tabs {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
:deep(.el-tabs__content) {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
:deep(.el-tab-pane) { height: 100%; }
|
||||
.config-pane {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
:deep(.el-tabs__item) {
|
||||
color: var(--mg-text-muted, rgba(255, 255, 255, 0.65));
|
||||
}
|
||||
:deep(.el-tabs__item.is-active) {
|
||||
color: var(--mg-text-light, #fff);
|
||||
}
|
||||
:deep(.el-tabs__active-bar) {
|
||||
background-color: var(--mg-accent, var(--el-color-primary));
|
||||
}
|
||||
:deep(.el-tabs__nav-wrap::after) {
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div class="config-hub-page">
|
||||
<el-tabs v-model="activeTab" class="hub-tabs">
|
||||
<el-tab-pane name="playback" label="调度回放">
|
||||
<div class="config-pane"><PlaybackView /></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="ops" label="运营维护" lazy>
|
||||
<div class="config-pane"><OpsConfigView /></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="logs" label="日志管理" lazy>
|
||||
<div class="config-pane"><LogManagementView /></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="map-monitor" label="地图监控配置" lazy>
|
||||
<div class="config-pane"><MapMonitorConfigView /></div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import PlaybackView from '@/views/admin/PlaybackView.vue'
|
||||
import OpsConfigView from '@/views/admin/config/OpsConfigView.vue'
|
||||
import LogManagementView from '@/views/admin/LogManagementView.vue'
|
||||
import MapMonitorConfigView from '@/views/admin/config/MapMonitorConfigView.vue'
|
||||
|
||||
// 聚合页:运维与回放(调度回放从顶级菜单移入此处)。Tab 与 URL ?tab= 同步。
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const TAB_NAMES = ['playback', 'ops', 'logs', 'map-monitor'] as const
|
||||
type TabName = (typeof TAB_NAMES)[number]
|
||||
function readTab(): TabName {
|
||||
const q = route.query.tab
|
||||
return typeof q === 'string' && (TAB_NAMES as readonly string[]).includes(q) ? (q as TabName) : 'playback'
|
||||
}
|
||||
const activeTab = ref<TabName>(readTab())
|
||||
watch(activeTab, (t) => {
|
||||
if (route.query.tab !== t) router.replace({ query: { ...route.query, tab: t } })
|
||||
})
|
||||
watch(() => route.query.tab, () => {
|
||||
const next = readTab()
|
||||
if (next !== activeTab.value) activeTab.value = next
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.config-hub-page {
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
.hub-tabs {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
:deep(.el-tabs__content) {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
:deep(.el-tab-pane) { height: 100%; }
|
||||
.config-pane {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
:deep(.el-tabs__item) {
|
||||
color: var(--mg-text-muted, rgba(255, 255, 255, 0.65));
|
||||
}
|
||||
:deep(.el-tabs__item.is-active) {
|
||||
color: var(--mg-text-light, #fff);
|
||||
}
|
||||
:deep(.el-tabs__active-bar) {
|
||||
background-color: var(--mg-accent, var(--el-color-primary));
|
||||
}
|
||||
:deep(.el-tabs__nav-wrap::after) {
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,83 @@
|
||||
<template>
|
||||
<div class="config-hub-page">
|
||||
<el-tabs v-model="activeTab" class="hub-tabs">
|
||||
<el-tab-pane name="routing" label="路径规划">
|
||||
<div class="config-pane"><RoutingPolicyView /></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="task" label="任务分配" lazy>
|
||||
<div class="config-pane"><TaskAllocationView /></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="traffic" label="交通管制" lazy>
|
||||
<div class="config-pane"><TrafficRuleView /></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="charge" label="充电策略" lazy>
|
||||
<div class="config-pane"><ChargePolicyView /></div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import RoutingPolicyView from '@/views/admin/config/RoutingPolicyView.vue'
|
||||
import TaskAllocationView from '@/views/admin/config/TaskAllocationView.vue'
|
||||
import TrafficRuleView from '@/views/admin/config/TrafficRuleView.vue'
|
||||
import ChargePolicyView from '@/views/admin/config/ChargePolicyView.vue'
|
||||
|
||||
// 聚合页:调度运行策略统一入口。Tab 与 URL ?tab= 同步,旧的独立配置路由 redirect 到此页对应 tab。
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const TAB_NAMES = ['routing', 'task', 'traffic', 'charge'] as const
|
||||
type TabName = (typeof TAB_NAMES)[number]
|
||||
function readTab(): TabName {
|
||||
const q = route.query.tab
|
||||
return typeof q === 'string' && (TAB_NAMES as readonly string[]).includes(q) ? (q as TabName) : 'routing'
|
||||
}
|
||||
const activeTab = ref<TabName>(readTab())
|
||||
watch(activeTab, (t) => {
|
||||
if (route.query.tab !== t) router.replace({ query: { ...route.query, tab: t } })
|
||||
})
|
||||
watch(() => route.query.tab, () => {
|
||||
const next = readTab()
|
||||
if (next !== activeTab.value) activeTab.value = next
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.config-hub-page {
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
.hub-tabs {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
:deep(.el-tabs__content) {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
:deep(.el-tab-pane) { height: 100%; }
|
||||
.config-pane {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
:deep(.el-tabs__item) {
|
||||
color: var(--mg-text-muted, rgba(255, 255, 255, 0.65));
|
||||
}
|
||||
:deep(.el-tabs__item.is-active) {
|
||||
color: var(--mg-text-light, #fff);
|
||||
}
|
||||
:deep(.el-tabs__active-bar) {
|
||||
background-color: var(--mg-accent, var(--el-color-primary));
|
||||
}
|
||||
:deep(.el-tabs__nav-wrap::after) {
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,75 @@
|
||||
<template>
|
||||
<div class="config-hub-page">
|
||||
<el-tabs v-model="activeTab" class="hub-tabs">
|
||||
<el-tab-pane name="system" label="系统级配置">
|
||||
<div class="config-pane"><SystemConfigView /></div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane name="auth" label="权限与角色" lazy>
|
||||
<div class="config-pane"><AuthRoleView /></div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, watch } from 'vue'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
import SystemConfigView from '@/views/admin/config/SystemConfigView.vue'
|
||||
import AuthRoleView from '@/views/admin/config/AuthRoleView.vue'
|
||||
|
||||
// 聚合页:系统级配置与权限角色。Tab 与 URL ?tab= 同步。
|
||||
const route = useRoute()
|
||||
const router = useRouter()
|
||||
const TAB_NAMES = ['system', 'auth'] as const
|
||||
type TabName = (typeof TAB_NAMES)[number]
|
||||
function readTab(): TabName {
|
||||
const q = route.query.tab
|
||||
return typeof q === 'string' && (TAB_NAMES as readonly string[]).includes(q) ? (q as TabName) : 'system'
|
||||
}
|
||||
const activeTab = ref<TabName>(readTab())
|
||||
watch(activeTab, (t) => {
|
||||
if (route.query.tab !== t) router.replace({ query: { ...route.query, tab: t } })
|
||||
})
|
||||
watch(() => route.query.tab, () => {
|
||||
const next = readTab()
|
||||
if (next !== activeTab.value) activeTab.value = next
|
||||
})
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.config-hub-page {
|
||||
padding: 16px;
|
||||
height: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
overflow: hidden;
|
||||
}
|
||||
.hub-tabs {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
:deep(.el-tabs__content) {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
overflow: auto;
|
||||
}
|
||||
:deep(.el-tab-pane) { height: 100%; }
|
||||
.config-pane {
|
||||
height: 100%;
|
||||
overflow: auto;
|
||||
}
|
||||
:deep(.el-tabs__item) {
|
||||
color: var(--mg-text-muted, rgba(255, 255, 255, 0.65));
|
||||
}
|
||||
:deep(.el-tabs__item.is-active) {
|
||||
color: var(--mg-text-light, #fff);
|
||||
}
|
||||
:deep(.el-tabs__active-bar) {
|
||||
background-color: var(--mg-accent, var(--el-color-primary));
|
||||
}
|
||||
:deep(.el-tabs__nav-wrap::after) {
|
||||
background-color: rgba(255, 255, 255, 0.08);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user