This commit is contained in:
Starlight-0208 2025-10-15 20:14:29 +08:00
parent 4edf954980
commit 8e39e66ce8
8 changed files with 375 additions and 178 deletions

6
package-lock.json generated
View File

@ -58,7 +58,6 @@
"integrity": "sha512-2BCOP7TN8M+gVDj7/ht3hsaO/B/n5oDbiAyyvnRlNOs+u1o+JWNYTQrmpuNp1/Wq2gcFrI01JAW+paEKDMx/CA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.3",
@ -1336,7 +1335,6 @@
"integrity": "sha512-anNG/V/Efn/YZY4pRzbACnKxNKoBng2VTFydVu8RRs5hQjikP8CQfaeAV59VFSCzKNp90mXiVXW2QzV56rwMrg==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"undici-types": "~6.21.0"
}
@ -1755,7 +1753,6 @@
}
],
"license": "MIT",
"peer": true,
"dependencies": {
"baseline-browser-mapping": "^2.8.9",
"caniuse-lite": "^1.0.30001746",
@ -2843,7 +2840,6 @@
"integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
"devOptional": true,
"license": "Apache-2.0",
"peer": true,
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@ -2926,7 +2922,6 @@
"integrity": "sha512-CmuvUBzVJ/e3HGxhg6cYk88NGgTnBoOo7ogtfJJ0fefUWAxN/WDSUa50o+oVBxuIhO8FoEZW0j2eW7sfjs5EtA==",
"dev": true,
"license": "MIT",
"peer": true,
"dependencies": {
"esbuild": "^0.25.0",
"fdir": "^6.5.0",
@ -3153,7 +3148,6 @@
"resolved": "https://registry.npmjs.org/vue/-/vue-3.5.22.tgz",
"integrity": "sha512-toaZjQ3a/G/mYaLSbV+QsQhIdMo9x5rrqIpYRObsJ6T/J+RyCSFwN2LHNVH9v8uIcljDNa3QzPVdv3Y6b9hAJQ==",
"license": "MIT",
"peer": true,
"dependencies": {
"@vue/compiler-dom": "3.5.22",
"@vue/compiler-sfc": "3.5.22",

View File

@ -1,17 +1,194 @@
<script setup>
<script setup lang="ts">
// @ts-ignore
import { reactive, ref, watch } from 'vue';
import CardViews from './components/CardViews.vue';
import TabList from './components/TabList.vue';
import HeaderView from './components/HeaderView.vue';
const tabs = reactive([
{
id: 'common',
name: '通用',
tag: 'common'
},
{
id: 'dev',
name: '开发',
tag: 'dev'
},
{
id: 'office',
name: '办公',
tag: 'office'
},
{
id: 'resources',
name: '资源',
tag: 'resources'
}
]);
const simulateData = reactive({
common: [
{
id: 1,
title: "企业邮箱",
description: "公司官方邮件系统,支持多设备同步",
icon: "fa-envelope",
network: "public",
networkName: "StarNet (182.132.22.150)",
visits: 1280
},
{
id: 2,
title: "内部通讯",
description: "企业内部即时通讯工具,支持群组聊天",
icon: "fa-comments",
network: "internal",
networkName: "IntraNet (10.225.10.123)",
visits: 2450
},
{
id: 3,
title: "云文档",
description: "企业文档协作平台,支持多人实时编辑",
icon: "fa-file-alt",
network: "public",
networkName: "StarNet (182.132.22.151)",
visits: 1876
},
{
id: 4,
title: "项目管理系统",
description: "全流程项目管理工具,支持敏捷开发",
icon: "fa-tasks",
network: "internal",
networkName: "DevNet (10.215.10.124)",
visits: 932
}
],
dev: [
{
id: 5,
title: "代码仓库",
description: "企业级代码版本控制系统",
icon: "fa-code-branch",
network: "internal",
networkName: "DevNet (10.215.10.125)",
visits: 1542
},
{
id: 6,
title: "CI/CD平台",
description: "持续集成与持续部署自动化平台",
icon: "fa-rocket",
network: "internal",
networkName: "DevNet (10.215.10.126)",
visits: 876
},
{
id: 7,
title: "API网关",
description: "统一API管理与监控平台",
icon: "fa-plug",
network: "public",
networkName: "StarNet",
visits: 1203
}
],
office: [
{
id: 8,
title: "人力资源系统",
description: "员工信息、考勤、绩效管理平台",
icon: "fa-users",
network: "internal",
networkName: "IntraNet",
visits: 2105
},
{
id: 9,
title: "财务系统",
description: "企业财务核算与报销管理系统",
icon: "fa-calculator",
network: "internal",
networkName: "FinanceNet",
visits: 1876
},
{
id: 10,
title: "合同管理",
description: "企业合同全生命周期管理系统",
icon: "fa-file-contract",
network: "internal",
networkName: "IntraNet",
visits: 945
}
],
resources: [
{
id: 11,
title: "知识库",
description: "企业知识管理与文档共享平台",
icon: "fa-book",
network: "public",
networkName: "StarNet",
visits: 3241
},
{
id: 12,
title: "培训中心",
description: "员工在线学习与技能提升平台",
icon: "fa-graduation-cap",
network: "public",
networkName: "StarNet",
visits: 1876
},
{
id: 13,
title: "资源下载",
description: "软件、模板、文档资源下载中心",
icon: "fa-download",
network: "internal",
networkName: "IntraNet",
visits: 2654
}
]
});
const activeTab = ref('common');
watch(activeTab, (newTab) => {
console.log("activeTab changed to", newTab);
});
</script>
<template>
<h1>You did it!</h1>
<!-- <h1>You did it!</h1>
<p>
Visit <a href="https://vuejs.org/" target="_blank" rel="noopener">vuejs.org</a> to read the
documentation
</p>
<CardViews />
</p> -->
<HeaderView />
<TabList :tabs="tabs" v-bind:active-tab="activeTab" @update:activeTab="activeTab = $event" />
<CardViews :portalData="simulateData[activeTab]" />
</template>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Open Sans', sans-serif;
background: linear-gradient(135deg, #f5f7fa 0%, #c3cfe2 100%);
min-height: 100vh;
color: #2C3E50;
margin: 20px;
}
/* 工具提示 */
.tooltip {
position: relative;

View File

@ -2,7 +2,7 @@
<div class="cards-container" id="cards-container">
<!-- 卡片将通过JavaScript动态生成 -->
<LinkCardItem
v-for="it in portalData.common"
v-for="it in props.portalData"
:key="it.id"
:title="it.title"
:description="it.description"
@ -13,174 +13,16 @@
</div>
</template>
<script setup>
import LinkCardItem from './LinkCardItem.vue';
import { reactive } from 'vue';
<script setup lang="ts">
import { type CardItem } from '@/types/CardItems';
import LinkCardItem from './LinkCardItem.vue';
//
const portalData = reactive({
common: [
{
id: 1,
title: "企业邮箱",
description: "公司官方邮件系统,支持多设备同步",
icon: "fa-envelope",
network: "public",
networkName: "StarNet",
visits: 1280
},
{
id: 2,
title: "内部通讯",
description: "企业内部即时通讯工具,支持群组聊天",
icon: "fa-comments",
network: "internal",
networkName: "IntraNet",
visits: 2450
},
{
id: 3,
title: "云文档",
description: "企业文档协作平台,支持多人实时编辑",
icon: "fa-file-alt",
network: "public",
networkName: "StarNet",
visits: 1876
},
{
id: 4,
title: "项目管理系统",
description: "全流程项目管理工具,支持敏捷开发",
icon: "fa-tasks",
network: "internal",
networkName: "DevNet",
visits: 932
},
{
id: 1,
title: "企业邮箱",
description: "公司官方邮件系统,支持多设备同步",
icon: "fa-envelope",
network: "public",
networkName: "StarNet",
visits: 1280
},
{
id: 2,
title: "内部通讯",
description: "企业内部即时通讯工具,支持群组聊天",
icon: "fa-comments",
network: "internal",
networkName: "IntraNet",
visits: 2450
},
{
id: 3,
title: "云文档",
description: "企业文档协作平台,支持多人实时编辑",
icon: "fa-file-alt",
network: "public",
networkName: "StarNet",
visits: 1876
},
{
id: 4,
title: "项目管理系统",
description: "全流程项目管理工具,支持敏捷开发",
icon: "fa-tasks",
network: "internal",
networkName: "DevNet",
visits: 932
}
],
dev: [
{
id: 5,
title: "代码仓库",
description: "企业级代码版本控制系统",
icon: "fa-code-branch",
network: "internal",
networkName: "DevNet",
visits: 1542
},
{
id: 6,
title: "CI/CD平台",
description: "持续集成与持续部署自动化平台",
icon: "fa-rocket",
network: "internal",
networkName: "DevNet",
visits: 876
},
{
id: 7,
title: "API网关",
description: "统一API管理与监控平台",
icon: "fa-plug",
network: "public",
networkName: "StarNet",
visits: 1203
}
],
office: [
{
id: 8,
title: "人力资源系统",
description: "员工信息、考勤、绩效管理平台",
icon: "fa-users",
network: "internal",
networkName: "IntraNet",
visits: 2105
},
{
id: 9,
title: "财务系统",
description: "企业财务核算与报销管理系统",
icon: "fa-calculator",
network: "internal",
networkName: "FinanceNet",
visits: 1876
},
{
id: 10,
title: "合同管理",
description: "企业合同全生命周期管理系统",
icon: "fa-file-contract",
network: "internal",
networkName: "IntraNet",
visits: 945
}
],
resources: [
{
id: 11,
title: "知识库",
description: "企业知识管理与文档共享平台",
icon: "fa-book",
network: "public",
networkName: "StarNet",
visits: 3241
},
{
id: 12,
title: "培训中心",
description: "员工在线学习与技能提升平台",
icon: "fa-graduation-cap",
network: "public",
networkName: "StarNet",
visits: 1876
},
{
id: 13,
title: "资源下载",
description: "软件、模板、文档资源下载中心",
icon: "fa-download",
network: "internal",
networkName: "IntraNet",
visits: 2654
}
]
});
const props = withDefaults(defineProps<{
portalData: Array<CardItem>
}>(), {
portalData: () => []
})
</script>
<style scoped>
@ -188,6 +30,6 @@ import { reactive } from 'vue';
display: grid;
grid-template-columns: repeat(auto-fill, minmax(300px, 1fr));
gap: 50px;
row-gap: 80px;
/* row-gap: 80px; */
}
</style>

View File

@ -0,0 +1,79 @@
<script setup lang="ts">
import { useUserStore } from '@/stores/user';
const { username, imageUrl } = useUserStore();
</script>
<template>
<header>
<div class="logo">
<i class="fas fa-cube"></i>
<h1>StarNet 综合管理平台</h1>
</div>
<div class="user-info">
<div class="user-avatar">{{ username.charAt(0) }}</div>
<div class="user-name">{{ username }}</div>
<button class="logout-btn"><i class="fas fa-sign-out-alt"></i></button>
</div>
</header>
</template>
<style scoped>
header {
background-color: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
padding: 16px 24px;
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 24px;
}
.logo {
display: flex;
align-items: center;
}
.logo h1 {
font-family: 'Montserrat', sans-serif;
font-size: 24px;
color: #2C3E50;
margin-left: 12px;
}
.user-info {
display: flex;
align-items: center;
}
.user-avatar {
width: 40px;
height: 40px;
border-radius: 50%;
background-color: #3498DB;
display: flex;
align-items: center;
justify-content: center;
color: white;
font-weight: bold;
margin-right: 12px;
}
.user-name {
font-weight: 600;
margin-right: 16px;
}
.logout-btn {
background: none;
border: none;
color: #95A5A6;
cursor: pointer;
font-size: 16px;
transition: color 0.3s ease;
}
.logout-btn:hover {
color: #E74C3C;
}
</style>

View File

@ -0,0 +1,77 @@
<template>
<div class="tabs">
<div class="tab-list">
<div v-for="tab in props.tabs"
:key="tab.id"
class="tab-item"
:class="{'active': tab.id === props.activeTab}"
:data-tab="tab.id"
@click="updateActiveTab(tab.tag)"
>
{{ tab.name }}</div>
</div>
</div>
</template>
<script setup lang="ts">
import { ref } from 'vue';
import { type TabItem } from '@/types/TabItems';
const props = withDefaults(defineProps<{
tabs: Array<TabItem>,
activeTab: string
}>(), {
tabs: () => [],
activeTab: 'common'
})
console.log(props.activeTab);
const emit = defineEmits(['update:activeTab']);
// Tab
function updateActiveTab(tabTag: string) {
console.log("clicked", tabTag);
emit('update:activeTab', tabTag);
}
</script>
<style scoped>
.tabs {
background-color: white;
border-radius: 12px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.08);
margin-bottom: 24px;
overflow: hidden;
}
.tab-list {
display: flex;
border-bottom: 1px solid #ECF0F1;
}
.tab-item {
padding: 16px 24px;
cursor: pointer;
font-weight: 600;
color: #95A5A6;
transition: all 0.3s ease;
position: relative;
}
.tab-item:hover {
color: #3498DB;
background-color: #f8f9fa;
}
.tab-item.active {
color: #3498DB;
}
.tab-item.active::after {
content: "";
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 3px;
background-color: #3498DB;
}
</style>

14
src/stores/user.ts Normal file
View File

@ -0,0 +1,14 @@
import { defineStore } from "pinia";
import { ref } from "vue";
export const useUserStore = defineStore('user', () => {
const username = ref('用户名');
const imageUrl = ref('');
function setUsername(name: string) {
username.value = name;
}
function setImageUrl(url: string) {
imageUrl.value = url;
}
return { username, imageUrl, setUsername, setImageUrl };
});

9
src/types/CardItems.ts Normal file
View File

@ -0,0 +1,9 @@
export interface CardItem {
id: string;
title: string;
description: string;
icon: string;
network: string;
networkName: string;
visits: number;
}

5
src/types/TabItems.ts Normal file
View File

@ -0,0 +1,5 @@
export interface TabItem {
id: string;
name: string;
tag: string;
}