初始化前端目录

This commit is contained in:
2025-09-02 00:11:55 +08:00
parent 5d3d515b8e
commit 239be643c1
11 changed files with 1458 additions and 115 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -8,7 +8,11 @@ import 'ant-design-vue/dist/reset.css'
const app = createApp(App)
const pinia = createPinia()
app.use(createPinia()) // 注册Pinia
app.use(router) // 注册路由
app.use(pinia);
app.use(Antd) // 注册Ant Design Vue
app.mount('#app')

View File

@@ -0,0 +1,4 @@
import { createPinia } from 'pinia';
const pinia = createPinia();
export default pinia;

View File

@@ -1,39 +1,77 @@
<template>
<div class="app-container">
<a-layout style="min-height: 100%;">
<!-- 顶部导航栏 -->
<!-- 顶部导航栏使用渐变淡蓝色背景 -->
<a-layout-header class="header">
<!-- 左侧Logo和系统名称 - 增加了图标 -->
<div class="logo">
<ApiOutlined />
<span>Capi系统</span>
<img src="/my.png" class="logo-img" />
<span class="system-name">cApi </span>
</div>
<!-- 主导航菜单调整按钮大小和间距 -->
<a-menu
theme="light"
mode="horizontal"
:selectedKeys="selectedKey"
class="menu"
class="main-menu"
@click="handleMenuClick"
>
<a-menu-item key="api">API管理</a-menu-item>
<a-menu-item key="data">数据管理</a-menu-item>
<a-menu-item key="system">系统管理</a-menu-item>
<a-menu-item key="app" class="menu-button">
<ApiOutlined class="menu-icon" />
<span>应用中心</span>
</a-menu-item>
<a-menu-item key="data" class="menu-button">
<DatabaseOutlined class="menu-icon" />
<span>数据中心</span>
</a-menu-item>
<a-menu-item key="integration" class="menu-button">
<LinkOutlined class="menu-icon" />
<span>集成中心</span>
</a-menu-item>
<a-menu-item key="system" class="menu-button">
<SettingOutlined class="menu-icon" />
<span>系统管理</span>
</a-menu-item>
</a-menu>
<!-- 管理员区域下拉菜单 -->
<div class="admin">
<!-- 右侧功能区搜索框图标和用户 -->
<div class="header-actions">
<!-- 搜索框 -->
<div class="search-box">
<SearchOutlined class="search-icon" />
<input type="text" placeholder="搜索" class="search-input" />
</div>
<!-- 功能图标区 -->
<div class="action-icons">
<a-tooltip title="收藏">
<StarOutlined class="action-icon" />
</a-tooltip>
<a-tooltip title="通知">
<BellOutlined class="action-icon" />
</a-tooltip>
<a-tooltip title="帮助">
<QuestionCircleOutlined class="action-icon" />
</a-tooltip>
<a-tooltip title="设置">
<SettingOutlined class="action-icon" />
</a-tooltip>
</div>
<!-- 用户头像 -->
<a-dropdown
placement="bottomRight"
:auto-adjust-overflow="true"
@visible-change="handleDropdownVisible"
>
<span class="admin-btn">
<UserOutlined /> 管理员
<DownOutlined class="ml-2" />
</span>
<div class="user-avatar">
<img src="https://picsum.photos/id/1005/200/200" alt="用户头像" class="avatar-img" />
</div>
<template #overlay>
<a-menu class="logout-menu" @click="handleLogout" selected-keys="">
<a-menu class="user-menu" @click="handleUserMenuClick">
<a-menu-item key="profile">个人资料</a-menu-item>
<a-menu-item key="settings">账户设置</a-menu-item>
<a-menu-divider />
<a-menu-item key="logout" class="logout-menu-item">
<LogoutOutlined class="mr-2" /> 退出登录
</a-menu-item>
@@ -43,12 +81,13 @@
</div>
</a-layout-header>
<!-- 标签栏始终显示 -->
<!-- 标签栏保持原有功能 -->
<div class="tab-bar">
<a-tag
:class="['console-tab', activeTabKey === 'console' ? 'console-tab--active' : '']"
@click="switchToConsole"
>
<HomeOutlined class="console-tab-icon" />
<span>控制台</span>
</a-tag>
@@ -97,7 +136,7 @@
</a-button>
</div>
<!-- 内容区域统一通过component渲染含控制台 -->
<!-- 内容区域保持原有功能 -->
<a-layout-content class="content">
<div class="home-content">
<component
@@ -108,7 +147,7 @@
</a-layout-content>
</a-layout>
<!-- 模块菜单弹窗80%宽度 -->
<!-- 模块菜单弹窗保持原有功能 -->
<a-modal
v-model:open="moduleModalVisible"
:title="currentModuleName"
@@ -145,7 +184,7 @@
</div>
</a-modal>
<!-- 退出确认对话框 -->
<!-- 退出确认对话框保持原有功能 -->
<a-modal
v-model:open="logoutVisible"
:centered="true"
@@ -180,12 +219,12 @@
<script setup>
import { ref, computed, h } from 'vue';
import { Layout, Menu, Button, Tabs, Card, Tag, Dropdown, Modal, Row, Col } from 'ant-design-vue';
import { Layout, Menu, Button, Tabs, Card, Tag, Dropdown, Modal, Row, Col, Tooltip } from 'ant-design-vue';
import {
ApiOutlined,
UserOutlined,
CloseOutlined,
DownOutlined,
LinkOutlined,
LogoutOutlined,
ExclamationCircleOutlined,
BarChartOutlined,
@@ -193,13 +232,19 @@ import {
SettingOutlined,
FormOutlined,
HistoryOutlined,
UserAddOutlined
UserAddOutlined,
HomeOutlined,
DatabaseOutlined, // 用于系统名称前的图标
SearchOutlined,
StarOutlined,
BellOutlined,
QuestionCircleOutlined
} from '@ant-design/icons-vue';
// 导入Main组件控制台要展示的内容
import Main from './main.vue'; // 假设main.vue与当前文件在同一目录
import Main from './main.vue';
// 模拟业务组件(实际项目中替换为真实组件)
// 模拟业务组件
const MockComponent = (props) => {
return h('div', { style: { padding: '20px' } }, [
h('h3', `这是${props.title}页面`),
@@ -209,34 +254,27 @@ const MockComponent = (props) => {
// 模块与菜单映射配置
const moduleMenusConfig = {
api: {
name: 'API管理',
app: {
name: '应用中心',
menus: [
{
key: 'api-list',
title: 'API列表',
key: 'app-list',
title: '应用列表',
icon: ApiOutlined,
component: () => h(MockComponent, { title: 'API列表' }),
component: () => h(MockComponent, { title: '应用列表' }),
closable: true
},
{
key: 'api-add',
title: 'API创建',
key: 'app-create',
title: '创建应用',
icon: FormOutlined,
component: () => h(MockComponent, { title: 'API创建' }),
closable: true
},
{
key: 'api-history',
title: '调用记录',
icon: HistoryOutlined,
component: () => h(MockComponent, { title: 'API调用记录' }),
component: () => h(MockComponent, { title: '创建应用' }),
closable: true
}
]
},
data: {
name: '数据管理',
name: '数据中心',
menus: [
{
key: 'data-analytics',
@@ -254,6 +292,25 @@ const moduleMenusConfig = {
}
]
},
integration: {
name: '集成中心',
menus: [
{
key: 'api-list',
title: 'API列表',
icon: ApiOutlined,
component: () => h(MockComponent, { title: 'API列表' }),
closable: true
},
{
key: 'integration-history',
title: '集成记录',
icon: HistoryOutlined,
component: () => h(MockComponent, { title: '集成记录' }),
closable: true
}
]
},
system: {
name: '系统管理',
menus: [
@@ -270,31 +327,24 @@ const moduleMenusConfig = {
icon: UserOutlined,
component: () => h(MockComponent, { title: '用户管理' }),
closable: true
},
{
key: 'user-add',
title: '用户新增',
icon: UserAddOutlined,
component: () => h(MockComponent, { title: '用户新增' }),
closable: true
}
]
}
};
// 状态管理
const selectedKey = ref(['api']);
const selectedKey = ref(['console']);
const moduleModalVisible = ref(false);
const currentModuleKey = ref('');
const currentModuleKey = ref('console');
const activeTabKey = ref('console');
// 标签页数据初始包含控制台控制台组件使用Main.vue
// 标签页数据
const allTabs = ref([
{
key: 'console',
title: '控制台',
component: Main, // 这里使用导入的Main组件
closable: false // 控制台标签不可关闭
component: Main,
closable: false
}
]);
@@ -359,16 +409,10 @@ const switchTab = (direction) => {
};
const deleteTab = (key) => {
// 禁止删除控制台标签
if (key === 'console') return;
const tabIndex = allTabs.value.findIndex(tab => tab.key === key);
if (tabIndex === -1) return;
// 过滤掉要删除的标签
allTabs.value = allTabs.value.filter(tab => tab.key !== key);
// 如果删除的是当前激活的标签,切换到前一个标签或控制台
if (key === activeTabKey.value) {
const targetTab = allTabs.value[tabIndex - 1] || allTabs.value.find(tab => tab.key === 'console');
activeTabKey.value = targetTab.key;
@@ -376,24 +420,26 @@ const deleteTab = (key) => {
};
const closeAllTabs = () => {
// 只保留控制台标签
allTabs.value = allTabs.value.filter(tab => tab.key === 'console');
activeTabKey.value = 'console';
};
const handleTabChange = (key) => {
activeTabKey.value = key;
// 根据标签页映射到对应的模块
const tabToModuleMap = {
'api-list': 'api',
'api-add': 'api',
'api-history': 'api',
'dashboard': 'console',
'tasks': 'console',
'app-list': 'app',
'app-create': 'app',
'data-analytics': 'data',
'data-export': 'data',
'api-list': 'integration',
'integration-history': 'integration',
'system-settings': 'system',
'user-manage': 'system',
'user-add': 'system'
'user-manage': 'system'
};
selectedKey.value = [tabToModuleMap[key] || 'api'];
selectedKey.value = [tabToModuleMap[key] || 'console'];
};
const handleMenuClick = ({ key }) => {
@@ -404,8 +450,6 @@ const handleMenuClick = ({ key }) => {
const handleMenuCardClick = (menuItem) => {
moduleModalVisible.value = false;
// 检查标签是否已存在,不存在则添加
const isTabExists = allTabs.value.some(tab => tab.key === menuItem.key);
if (!isTabExists) {
allTabs.value.push({
@@ -415,8 +459,6 @@ const handleMenuCardClick = (menuItem) => {
closable: menuItem.closable
});
}
// 切换到该标签
activeTabKey.value = menuItem.key;
};
@@ -424,8 +466,15 @@ const handleDropdownVisible = (visible) => {
console.log('下拉菜单状态:', visible ? '显示' : '隐藏');
};
const logoutVisible = ref(false);
const handleUserMenuClick = ({ key }) => {
if (key === 'logout') {
handleLogout();
} else {
console.log('用户菜单点击:', key);
}
};
const logoutVisible = ref(false);
const handleLogout = () => {
logoutVisible.value = true;
};
@@ -435,11 +484,13 @@ const doLogout = () => {
localStorage.removeItem('userInfo');
logoutVisible.value = false;
alert('退出登录成功,即将跳转到登录页');
// 实际项目中应该使用路由跳转
// router.push('/login');
};
</script>
<style scoped>
/* 样式内容与之前保持一致 */
/* 基础样式 */
* {
margin: 0;
padding: 0;
@@ -456,67 +507,169 @@ body,
flex-direction: column;
}
/* 顶部导航 */
/* 顶部导航:使用渐变淡蓝色背景 */
.header {
background: #fff;
border-bottom: 1px solid #e0e0e0;
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 20px;
height: 64px;
width: 100%;
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
background: linear-gradient(90deg, #e6f7ff 0%, #f0f9ff 100%);
box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);
}
/* Logo和系统名称 - 添加了图标样式 */
.logo {
display: flex;
align-items: center;
padding-right: 20px;
border-right: 1px solid rgba(24, 144, 255, 0.1);
gap: 10px; /* 图标与文字间距 */
}
.logo-icon {
color: #1890ff;
font-size: 22px;
}
.logo-img {
width: 65px; /* 与文字高度匹配,可根据图片比例调整 */
height: 65px;
object-fit: contain; /* 关键:保持图片比例,避免拉伸变形 */
vertical-align: middle; /* 与文字垂直居中对齐 */
}
.system-name {
font-size: 18px;
font-weight: 600;
color: #1890ff;
}
.logo span {
margin-left: 8px;
}
.menu {
/* 主导航菜单:优化按钮样式 */
.main-menu {
flex: 1;
margin: 0 40px;
justify-content: center;
margin: 0 25px;
justify-content: flex-start;
}
.admin {
display: flex;
align-items: center;
:deep(.ant-menu-horizontal) {
background: transparent !important;
border-bottom: none !important;
}
.admin-btn {
display: flex;
align-items: center;
padding: 8px 16px;
cursor: pointer;
/* 调整按钮大小和间距 */
.menu-button {
border-radius: 4px;
transition: background 0.2s;
margin: 110 120px !important;
transition: all 0.3s ease;
margin-top: 12px;
}
.admin-btn:hover {
background: #f5f9ff;
:deep(.ant-menu-item) {
color: #096dd9 !important; /* 加深文字颜色,增强对比 */
font-size: 13px; /* 缩小字体 */
padding: 0 12px !important; /* 减小内边距 */
height: 36px !important; /* 减小按钮高度 */
line-height: 36px !important;
background-color: rgba(255, 255, 255, 0.8) !important; /* 调整背景透明度 */
box-shadow: 0 1px 2px rgba(0, 0, 0, 0.05);
}
:deep(.ant-menu-item-selected) {
background-color: #fff !important;
color: #096dd9 !important;
box-shadow: 0 2px 6px rgba(24, 144, 255, 0.2);
}
:deep(.ant-menu-item:hover:not(.ant-menu-item-selected)) {
background-color: #fff !important;
color: #096dd9 !important;
transform: translateY(-1px);
box-shadow: 0 2px 5px rgba(24, 144, 255, 0.15);
}
.menu-icon {
margin-right: 6px; /* 减小图标与文字间距 */
font-size: 14px; /* 缩小图标 */
}
/* 右侧功能区 */
.header-actions {
display: flex;
align-items: center;
gap: 16px;
}
/* 搜索框 */
.search-box {
display: flex;
align-items: center;
background: rgba(255, 255, 255, 0.8);
border-radius: 4px;
padding: 0 12px;
height: 36px;
width: 240px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.05);
}
.search-icon {
color: #8c8c8c;
margin-right: 8px;
}
.search-input {
background: transparent;
border: none;
outline: none;
color: #333;
width: 100%;
font-size: 14px;
}
.search-input::placeholder {
color: #b3b3b3;
}
/* 功能图标区 */
.action-icons {
display: flex;
align-items: center;
gap: 16px;
padding-right: 16px;
border-right: 1px solid rgba(24, 144, 255, 0.1);
}
.action-icon {
color: #1890ff;
font-size: 18px;
cursor: pointer;
transition: all 0.2s;
}
.logout-menu {
width: 140px;
.action-icon:hover {
color: #096dd9;
transform: scale(1.1);
}
/* 用户头像 */
.user-avatar {
cursor: pointer;
}
.avatar-img {
width: 36px;
height: 36px;
border-radius: 50%;
object-fit: cover;
border: 2px solid transparent;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.1);
transition: all 0.2s;
}
.user-avatar:hover .avatar-img {
border-color: #1890ff;
transform: translateY(-2px);
box-shadow: 0 4px 8px rgba(24, 144, 255, 0.2);
}
/* 用户菜单 */
.user-menu {
width: 160px;
border-radius: 6px;
box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.logout-menu-item {
height: 40px;
display: flex;
align-items: center;
color: #666;
font-size: 14px;
}
.logout-menu-item:hover {
background-color: #e8f4ff !important;
color: #1890ff !important;
color: #f5222d !important;
}
/* 标签栏:始终显示 */
/* 标签栏:保持原有样式 */
.tab-bar {
background: #fff;
border-bottom: 1px solid #e0e0e0;
@@ -543,6 +696,10 @@ body,
background: transparent;
transition: all 0.2s ease;
}
.console-tab-icon {
margin-right: 6px;
font-size: 14px;
}
.console-tab--active {
background: #e8f4ff !important;
color: #1890ff;
@@ -671,7 +828,7 @@ body,
font-size: 12px;
}
/* 内容区域 */
/* 内容区域:保持原有样式 */
.content {
background: #f8f9fa;
padding: 16px;
@@ -688,7 +845,7 @@ body,
overflow: auto;
}
/* 模块菜单弹窗 */
/* 模块菜单弹窗:保持原有样式 */
.module-modal-wrapper .ant-modal-content {
border-radius: 8px;
}
@@ -727,7 +884,7 @@ body,
font-weight: 500;
}
/* 退出对话框 */
/* 退出对话框:保持原有样式 */
.logout-modal-wrapper .ant-modal {
width: 480px !important;
}

View File

@@ -1,5 +1,4 @@
<template>
sddddddddddddd
</template>
<script>