界面效果
必要条件 node.js 18+ antd element plus vue3.2
首先设计模块
分为上面导航条 下面主体 两部分
所以在router里面定义好layout
router.ts
import Layout from '@/layout/index.vue';
{
path: '',
component: Layout,
redirect: '/index',
children: [
{
path: '/index',
component: () => import('@/views/home.vue'),
name: 'Index',
meta: { title: '首页', icon: 'dashboard', affix: true },
},
],
},
layout/index.vue
<template>
<div class="app-wrapper">
<Navbar />
<Main />
<!-- <app-main /> -->
</div>
</template>
<script setup lang="ts">
import { ref, reactive } from "vue";
import { Navbar, Main } from "./components/index.ts";
const needTagsView = ref<Boolean>(true);
</script>
<style lang="scss" scoped>
@import "@/assets/styles/mixin.scss";
@import "@/assets/styles/variables.module.scss";
.app-wrapper {
@include clearfix;
position: relative;
height: 100%;
width: 100%;
&.mobile.openSidebar {
position: fixed;
top: 0;
}
}
</style>
index.ts
export { default as Navbar } from './Navbar/index.vue'
export { default as Main } from './main/index.vue'
navbar组件
<template>
<a-layout class="layout">
<a-layout-header>
<a-row>
<a-col :span="12">
<div class="logo" />
<a-menu
theme="dark"
mode="horizontal"
:style="{ lineHeight: '64px', background: '#fff' }"
>
<template v-for="(item, index) in menuList" :key="index">
<a-menu-item @click="getOpen(item)">{{ item.name }}</a-menu-item>
</template>
</a-menu></a-col
>
<a-col :span="12">
<a-row>
<a-col :span="16" class="searchInfo">
<a-input-search
v-model:value="params.title"
enter-button
@search="onSearch"
/>
</a-col>
<a-col :span="8" class="navBar"
><BellOutlined
:style="{
fontSize: '20px',
color: '#f56c6c',
margin: '0 0 0 10px',
}"
/><span class="message">消息</span>
<PlusSquareOutlined
:style="{ fontSize: '20px', color: '#f56c6c' }"
/>
<span class="message">发布</span>
<el-button type="danger" size="small" class="login_button" round
>登录</el-button
>
</a-col>
</a-row>
</a-col>
</a-row>
</a-layout-header>
<a-row class="topContent">
<a-col :span="12" class="top_main"></a-col>
<a-col :span="12" class="top_main">
<icon-font
:style="{ fontSize: '16px', color: '#f56c6c' }"
type="icon-resou"
/>
热搜:
<span
v-for="(item, index) in TopList"
:key="index"
class="topInfo"
@click="getSearch(item)"
>{{ item }}</span
>
</a-col>
</a-row>
</a-layout>
</template>
<script lang="ts" setup >
import { ref, reactive } from "vue";
import { BellOutlined } from "@ant-design/icons-vue";
import {
createFromIconfontCN,
PlusSquareOutlined,
} from "@ant-design/icons-vue";
const IconFont = createFromIconfontCN({
scriptUrl: "./iconfont.js",
});
const selectedKeys = ref<string[]>(["1"]);
const menuList = ref<Array[]>([
{ name: "博客", path: "/boke" },
{ name: "反馈", path: "/fk" },
]);
const TopList = ref<array>([
"杭州亚运会奖牌里的东方美学",
"苹果秋季发布会9月13日举行",
"开学季被这些迎新方式打动了",
]);
const params = reactive<any>({
title: "",
});
const getOpen = (item) => {
console.log(item.path);
//跳转备用
};
const onSearch = () => {};
//点击热搜方法
const getSearch = (value) => {
console.log(value);
};
</script>
<style scoped lang="scss">
.site-layout-content {
min-height: 280px;
padding: 24px;
background: #fff;
}
.ant-layout-header {
background: #fff !important;
height: 64px !important;
}
.ant-menu-submenu-selected {
background: #aaa;
}
::v-deep(.ant-menu-item-selected) {
background-color: rgb(255, 255, 255) !important;
color: #000 !important;
}
::v-deep(.ant-menu-item) {
background-color: #fff !important;
color: #000 !important;
}
::v-deep(.ant-menu-item:hover) {
background-color: #ccc !important;
color: #000 !important;
}
#components-layout-demo-top .logo {
float: left;
width: 120px;
height: 31px;
margin: 16px 24px 16px 0;
background: rgba(255, 255, 255, 0.3);
}
.ant-row-rtl #components-layout-demo-top .logo {
float: right;
margin: 16px 0 16px 24px;
}
::v-deep(.searchInfo) {
height: 72px;
display: flex;
align-items: center;
}
.topContent {
margin-top: 1px;
.top_main {
background: #fff;
height: 30px;
line-height: 30px;
.topInfo {
margin-right: 10px;
}
}
}
.navBar {
line-height: 74px;
text-align: right;
.message {
margin: 0 10px 0 3px;
font-size: 14px;
}
}
.login_button {
vertical-align: baseline;
padding: 15px 20px;
margin-left: 20px;
}
</style>
main组件
<template>
<section class="app-main">
<router-view v-slot="{ Component, route }">
<transition name="fade-transform" mode="out-in">
<keep-alive>
<component
v-if="!route.meta.link"
:is="Component"
:key="route.path"
/>
</keep-alive>
</transition>
</router-view>
</section>
</template>
<script setup lang="ts">
// import iframeToggle from './IframeToggle/index.vue';
// import useTagsViewStore from "@/store/modules/tagsView";
// const tagsViewStore = useTagsViewStore();
</script>
<style lang="scss" scoped>
.app-main {
/* 50= navbar 50 */
min-height: calc(100vh - 95px);
width: 100%;
// background: #f6f6f6;
position: relative;
overflow: hidden;
}
.fixed-header + .app-main {
padding-top: 50px;
}
.hasTagsView {
.app-main {
/* 84 = navbar + tags-view = 50 + 34 */
min-height: calc(100vh - 84px);
}
.fixed-header + .app-main {
padding-top: 84px;
}
}
</style>
<style lang="scss">
// fix css style bug in open el-dialog
.el-popup-parent--hidden {
.fixed-header {
padding-right: 17px;
}
}
</style>
主体home.vue
<template>
<div class="home">
<div class="app-content">
<a-row :gutter="[8, 8]">
<a-col :span="16">
<div class="common">
<a-tabs v-model:activeKey="activeKey">
<a-tab-pane
v-for="(item, index) in TabList"
:key="index"
:tab="item.title"
>
<div v-for="(arr, index) in homeList" :key="index">
<div>
<div class="home-card-article" v-if="arr.type == '1'">
<div :class="arr.istop ? 'title' : ''">
{{ arr.title }}
</div>
</div>
<div class="home-card-article" v-if="arr.type == '2'">
<div :class="arr.istop ? 'title' : ''">
{{ arr.title }}
</div>
</div>
</div>
</div>
</a-tab-pane>
</a-tabs>
</div>
</a-col>
<a-col :span="8">
<div class="loginItem">
<div>
<div class="itemTitle">更多内容为您呈现</div>
<div class="itembutton">
<el-button type="danger">立即登录</el-button>
</div>
</div>
</div>
<div>
<div class="topInfo">
<div class="topIcon">
<icon-font
:style="{
fontSize: '16px',
color: '#f56c6c',
marginRight: '5px',
}"
type="icon-resou"
/>热点推荐
<span
:style="{
fontSize: '14px',
color: '#f56c6c',
float: 'right',
cursor: 'pointer',
}"
>
<RedoOutlined
:style="{
fontSize: '14px',
color: '#f56c6c',
}"
/>
换一批
</span>
</div>
<div>
<div class="topItem">
<icon-font
:style="{ fontSize: '16px', color: '#f56c6c' }"
type="icon-top"
/>
共促开放合作 共创美好未来
</div>
<div v-for="(item, index) in ToprightList" :key="index">
<div class="topItem">
{{ item.title }}
<icon-font
:style="{ fontSize: '16px', color: '#f56c6c' }"
type="icon-reInfo"
/>
</div>
</div>
</div>
</div>
</div>
</a-col>
</a-row>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref } from "vue";
import { createFromIconfontCN, RedoOutlined } from "@ant-design/icons-vue";
const IconFont = createFromIconfontCN({
scriptUrl: "./iconfont.js",
});
const activeKey = ref(0);
const TabList = ref<array>([
{ title: "推荐", id: "1" },
{ title: "热点", id: "2" },
{ title: "新闻", id: "3" },
{ title: "开源", id: "4" },
{ title: "娱乐", id: "5" },
{ title: "视频", id: "6" },
{ title: "游戏", id: "7" },
{ title: "国际", id: "8" },
{ title: "财经", id: "9" },
{ title: "下载", id: "10" },
// { title: "更多", id: "11" },
]);
const ToprightList = ref<array>([
{ title: "共促开放合作 共创美好未来", id: "1" },
{ title: "美将对华出售芯片 但不卖最顶尖的", id: "2" },
{ title: "期待杭州亚运会到来", id: "3" },
{ title: "上海现不明飞行物 似火球般高速坠落", id: "4" },
{ title: "共促开放合作 共创美好未来", id: "5" },
{ title: "美将对华出售芯片 但不卖最顶尖的", id: "6" },
{ title: "期待杭州亚运会到来", id: "7" },
{ title: "上海现不明飞行物 似火球般高速坠落", id: "7" },
{ title: "期待杭州亚运会到来", id: "9" },
{ title: "上海现不明飞行物 似火球般高速坠落", id: "10" },
// { title: "更多", id: "11" },
]);
const homeList = ref<array>([
{
title: "深圳:全市停工 非必要不外出",
id: "1",
content: "",
istop: true,
type: 1,
},
{ title: "北京发生2.7级地震", content: "", id: "2", istop: true, type: 1 },
{
title: "实拍台风风眼画面!飞机对“苏拉”进行探测:结构紧密清晰可见",
id: "3",
content: "",
istop: true,
type: 1,
},
{
title: "9月全球重要节日梳理好了,请注意查收!|巴西|韩国|国庆日",
content:
" 金秋九月,这些日子值得关注→2023-09-01 10:21转眼间,九月来了 瓜果渐熟,稻谷飘香,蟹肥菊黄…… 新的一个月,继续努力前行! 愿你在金秋九月 收获满满,硕果累累地址,",
id: "4",
istop: false,
type: 2,
},
{
title: "北京朝阳区发生2.7级地震,很多市民表示震感明显",
content:
"据中国地震台网正式测定,9月1日15时34分在北京顺义区发生2.7级地震,震源深度17公里,震中位于北纬40.14度,东经116.48度",
id: "5",
istop: false,
type: 3,
},
]);
</script>
<style lang="scss" scoped>
.home {
border-top: 4px solid #f6f6f6;
background: #fafcff;
height: calc(100vh - 95px);
.app-content {
width: 1066px;
margin: 0 auto;
padding: 16px 16px 0;
.common {
padding: 10px;
background: #fafcff;
margin-top: 10px;
}
}
.home-card-article {
padding: 4px 0;
font-size: 20px;
color: #222;
&:hover {
color: #1890ff;
cursor: pointer;
}
.title {
&::after {
content: "置顶";
display: inline-block;
font-weight: 400;
font-size: 12px;
line-height: 16px;
color: #f04142;
background: #fafcff;
border-radius: 4px;
padding: 2px 4px;
position: relative;
top: -2px;
left: 6px;
}
}
}
.loginItem {
height: 160px;
display: flex;
margin-top: 20px;
background: #f6f6f6;
font-size: 20px;
flex-wrap: wrap;
align-items: center;
justify-content: center;
.itemTitle {
width: 100%;
text-align: center;
}
.itembutton {
margin-top: 10px;
text-align: center;
}
}
.topInfo {
margin-top: 10px;
background: #fff;
height: calc(100vh - 310px);
padding: 10px;
.topIcon {
border-bottom: 1px solid #e9e9eb;
height: 25px;
}
.topItem {
font-size: 16px;
padding: 10px 5px;
&:hover {
color: #1890ff;
cursor: pointer;
}
}
}
}
::v-deep(.ant-tabs-nav) {
&:before {
border: none !important;
}
}
::v-deep(.ant-tabs-tab) {
font-size: 20px;
}
::v-deep(.ant-tabs-tab-active) {
font-size: 20px;
}
</style>
这样页面就写好了 这个项目我有空的话后续会更新成前端后端可发布的完整的项目。
源码地址gitee:https://gitee.com/wuhongyu123456/stu-wike
或者私聊博主
如果在写毕业设计需要参考的话这是初学者一个很好的项目 其他问题也欢迎咨询
可开发app h5 pc web端 微信小程序 微信公众号等项目 如有需要私信联系
感谢你的关注。觉得有用点个赞吧!!!!!!!!