Files
stamp-ant/src/layouts/ContractManageLayout.vue
T
2026-05-26 10:10:32 +08:00

195 lines
4.2 KiB
Vue

<template>
<a-layout class="contract-layout">
<a-layout-sider width="244" class="contract-sider">
<div class="sider-brand">
<div class="brand-badge">合同管理</div>
<h2>业务示例控制台</h2>
<p>模拟业务系统中的发起合同与模板管理菜单结构</p>
</div>
<a-menu
mode="inline"
:selected-keys="[selectedKey]"
class="contract-menu"
@click="handleMenuClick"
>
<a-menu-item key="/contract-console/launch">
<form-outlined />
<span>发起合同</span>
</a-menu-item>
<a-menu-item key="/contract-console/manifest">
<file-text-outlined />
<span>模板管理</span>
</a-menu-item>
<a-menu-item key="/contract-console/partner">
<team-outlined />
<span>相关方管理</span>
</a-menu-item>
</a-menu>
<div class="sider-footer">
<a-button block @click="router.push('/')">返回首页</a-button>
</div>
</a-layout-sider>
<a-layout>
<a-layout-header class="contract-header">
<div>
<div class="header-title">{{ currentTitle }}</div>
<div class="header-desc">
按需求文档模拟业务人员发起合同合同管理员维护模板的真实菜单入口
</div>
</div>
<a-tag color="blue">Mock + 本地测试</a-tag>
</a-layout-header>
<a-layout-content class="contract-content">
<router-view />
</a-layout-content>
</a-layout>
</a-layout>
</template>
<script setup>
import { computed } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { FileTextOutlined, FormOutlined, TeamOutlined } from '@ant-design/icons-vue'
const route = useRoute()
const router = useRouter()
const selectedKey = computed(() => {
if (route.path.startsWith('/contract-console/manifest')) {
return '/contract-console/manifest'
}
if (route.path.startsWith('/contract-console/partner')) {
return '/contract-console/partner'
}
return '/contract-console/launch'
})
const currentTitle = computed(() => route.meta?.title || '合同管理')
function handleMenuClick({ key }) {
router.push(key)
}
</script>
<style scoped>
.contract-layout {
min-height: 100vh;
background: #eef2f7;
}
.contract-sider {
background:
radial-gradient(circle at top left, rgba(59, 130, 246, 0.18), transparent 34%),
linear-gradient(180deg, #ffffff 0%, #f7f9fc 100%);
border-right: 1px solid rgba(226, 232, 240, 0.88);
display: flex;
flex-direction: column;
}
.sider-brand {
padding: 24px 20px 18px;
}
.brand-badge {
display: inline-flex;
align-items: center;
height: 28px;
padding: 0 12px;
border-radius: 999px;
background: rgba(37, 99, 235, 0.1);
color: #1d4ed8;
font-size: 12px;
font-weight: 700;
margin-bottom: 12px;
}
.sider-brand h2 {
font-size: 22px;
font-weight: 700;
color: #0f172a;
margin-bottom: 8px;
}
.sider-brand p {
color: #64748b;
line-height: 1.8;
font-size: 13px;
}
.contract-menu {
border-inline-end: none;
background: transparent;
padding: 8px 12px;
}
.contract-menu :deep(.ant-menu-item) {
height: 48px;
line-height: 48px;
border-radius: 12px;
margin-bottom: 6px;
}
.contract-menu :deep(.ant-menu-item-selected) {
background: linear-gradient(90deg, rgba(37, 99, 235, 0.14), rgba(59, 130, 246, 0.06));
color: #1d4ed8;
font-weight: 600;
}
.sider-footer {
margin-top: auto;
padding: 16px 20px 20px;
}
.contract-header {
height: auto;
background: rgba(255, 255, 255, 0.96);
border-bottom: 1px solid rgba(226, 232, 240, 0.88);
padding: 20px 28px;
display: flex;
align-items: center;
justify-content: space-between;
gap: 16px;
}
.header-title {
font-size: 24px;
font-weight: 700;
color: #0f172a;
margin-bottom: 4px;
}
.header-desc {
font-size: 13px;
color: #64748b;
line-height: 1.8;
}
.contract-content {
padding: 20px;
min-height: 0;
}
@media (max-width: 960px) {
.contract-layout {
flex-direction: column;
}
.contract-sider {
width: 100% !important;
max-width: 100%;
}
.contract-header {
padding: 18px 20px;
align-items: flex-start;
flex-direction: column;
}
}
</style>