基于vue3的门户首页

界面效果

必要条件 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端 微信小程序 微信公众号等项目 如有需要私信联系

感谢你的关注。觉得有用点个赞吧!!!!!!!!

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值