自考社区门户网站 (Vue3 + Element Plus 实现)
下面是一个基于 Vue3 和 Element Plus 的自考社区门户网站的完整实现方案。这个实现包括首页、关于自考、公告栏目、自考政策、相关介绍、综合查询和便民服务等模块。
项目结构
self-exam-portal/
├── public/ # 静态资源
├── src/
│ ├── assets/ # 静态资源
│ ├── components/ # 公共组件
│ │ ├── Header.vue # 头部导航
│ │ ├── Footer.vue # 页脚
│ │ └── Sidebar.vue # 侧边栏
│ ├── router/ # 路由配置
│ │ └── index.js
│ ├── store/ # Vuex 状态管理
│ │ └── index.js
│ ├── views/ # 页面组件
│ │ ├── Home.vue # 首页
│ │ ├── About.vue # 关于自考
│ │ ├── Notice.vue # 公告栏目
│ │ ├── Policy.vue # 自考政策
│ │ ├── Introduction.vue # 相关介绍
│ │ ├── Query.vue # 综合查询
│ │ └── Service.vue # 便民服务
│ ├── App.vue # 根组件
│ └── main.js # 入口文件
├── package.json
└── vite.config.js # Vite 配置
1. 安装依赖
首先创建项目并安装所需依赖:
npm create vue@latest self-exam-portal
cd self-exam-portal
npm install element-plus axios vue-router pinia
npm install
2. 配置 Element Plus
在 main.js 中引入 Element Plus:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import { createPinia } from 'pinia'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(createPinia())
app.use(router)
app.use(ElementPlus)
app.mount('#app')
3. 路由配置 (router/index.js)
import { createRouter, createWebHistory } from 'vue-router'
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/Home.vue')
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
},
{
path: '/notice',
name: 'Notice',
component: () => import('../views/Notice.vue')
},
{
path: '/policy',
name: 'Policy',
component: () => import('../views/Policy.vue')
},
{
path: '/introduction',
name: 'Introduction',
component: () => import('../views/Introduction.vue')
},
{
path: '/query',
name: 'Query',
component: () => import('../views/Query.vue')
},
{
path: '/service',
name: 'Service',
component: () => import('../views/Service.vue')
}
]
const router = createRouter({
history: createWebHistory(import.meta.env.BASE_URL),
routes
})
export default router
4. 公共组件
Header.vue (导航栏)
<template>
<el-header class="header">
<div class="logo">自考社区</div>
<el-menu
:default-active="activeIndex"
class="el-menu-demo"
mode="horizontal"
@select="handleSelect"
router
>
<el-menu-item index="/">首页</el-menu-item>
<el-menu-item index="/about">关于自考</el-menu-item>
<el-menu-item index="/notice">公告栏目</el-menu-item>
<el-menu-item index="/policy">自考政策</el-menu-item>
<el-menu-item index="/introduction">相关介绍</el-menu-item>
<el-menu-item index="/query">综合查询</el-menu-item>
<el-menu-item index="/service">便民服务</el-menu-item>
</el-menu>
<div class="user-info">
<el-button type="text" @click="login">登录</el-button>
<el-button type="text" @click="register">注册</el-button>
</div>
</el-header>
</template>
<script setup>
import { ref } from 'vue'
import { useRouter } from 'vue-router'
const router = useRouter()
const activeIndex = ref('/')
const handleSelect = (key) => {
activeIndex.value = key
}
const login = () => {
router.push('/login')
}
const register = () => {
router.push('/register')
}
</script>
<style scoped>
.header {
display: flex;
justify-content: space-between;
align-items: center;
background-color: #409EFF;
color: white;
padding: 0 20px;
}
.logo {
font-size: 24px;
font-weight: bold;
}
.el-menu-demo {
flex: 1;
background-color: transparent;
}
.el-menu-item {
color: white !important;
}
.user-info {
margin-left: 20px;
}
</style>
Footer.vue (页脚)
<template>
<el-footer class="footer">
<div class="footer-content">
<div class="links">
<a href="#">关于我们</a>
<a href="#">联系我们</a>
<a href="#">帮助中心</a>
<a href="#">隐私政策</a>
</div>
<div class="copyright">
© 2023 自考社区 版权所有
</div>
</div>
</el-footer>
</template>
<style scoped>
.footer {
background-color: #f5f7fa;
color: #666;
text-align: center;
padding: 20px 0;
margin-top: 20px;
}
.footer-content {
max-width: 1200px;
margin: 0 auto;
}
.links {
margin-bottom: 10px;
}
.links a {
margin: 0 15px;
color: #666;
text-decoration: none;
}
.links a:hover {
color: #409EFF;
}
.copyright {
font-size: 14px;
}
</style>
5. 页面组件示例
Home.vue (首页)
<template>
<div class="home">
<el-carousel height="400px">
<el-carousel-item v-for="item in banners" :key="item.id">
<img :src="item.image" :alt="item.title" class="banner-image">
</el-carousel-item>
</el-carousel>
<div class="container">
<el-row :gutter="20">
<el-col :span="16">
<div class="news-section">
<h2 class="section-title">最新公告</h2>
<el-card shadow="hover" v-for="notice in notices" :key="notice.id" class="notice-card">
<div slot="header" class="clearfix">
<span>{{ notice.title }}</span>
<el-button style="float: right; padding: 3px 0" type="text">查看详情</el-button>
</div>
<div class="notice-content">{{ notice.content }}</div>
<div class="notice-time">{{ notice.time }}</div>
</el-card>
</div>
</el-col>
<el-col :span="8">
<div class="quick-links">
<h2 class="section-title">快速通道</h2>
<el-card shadow="hover">
<el-button type="primary" class="quick-btn" @click="$router.push('/query')">成绩查询</el-button>
<el-button type="primary" class="quick-btn" @click="$router.push('/query')">考试报名</el-button>
<el-button type="primary" class="quick-btn" @click="$router.push('/policy')">政策解读</el-button>
<el-button type="primary" class="quick-btn" @click="$router.push('/service')">常见问题</el-button>
</el-card>
</div>
</el-col>
</el-row>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const banners = ref([
{ id: 1, title: '自考报名进行中', image: 'https://via.placeholder.com/1200x400' },
{ id: 2, title: '最新考试政策', image: 'https://via.placeholder.com/1200x400' },
{ id: 3, title: '自考学习资料', image: 'https://via.placeholder.com/1200x400' }
])
const notices = ref([
{
id: 1,
title: '2023年下半年自考报名通知',
content: '2023年下半年自考报名将于9月1日开始,请考生提前做好准备...',
time: '2023-08-20'
},
{
id: 2,
title: '自考成绩查询系统开放',
content: '2023年上半年自考成绩查询系统已开放,考生可登录查询...',
time: '2023-08-15'
},
{
id: 3,
title: '自考教材更新通知',
content: '部分专业教材有更新,请考生购买最新版教材进行复习...',
time: '2023-08-10'
}
])
</script>
<style scoped>
.home {
min-height: calc(100vh - 120px);
}
.banner-image {
width: 100%;
height: 100%;
object-fit: cover;
}
.container {
max-width: 1200px;
margin: 20px auto;
padding: 0 20px;
}
.section-title {
color: #409EFF;
border-bottom: 1px solid #eee;
padding-bottom: 10px;
margin-bottom: 20px;
}
.notice-card {
margin-bottom: 15px;
}
.notice-content {
color: #666;
margin-bottom: 10px;
}
.notice-time {
color: #999;
font-size: 12px;
}
.quick-links {
margin-bottom: 20px;
}
.quick-btn {
width: 100%;
margin-bottom: 10px;
}
</style>
Query.vue (综合查询)
<template>
<div class="query">
<div class="container">
<h1 class="page-title">综合查询</h1>
<el-tabs v-model="activeTab" class="query-tabs">
<el-tab-pane label="成绩查询" name="score">
<el-form :model="scoreForm" label-width="100px">
<el-form-item label="准考证号">
<el-input v-model="scoreForm.examNumber" placeholder="请输入准考证号"></el-input>
</el-form-item>
<el-form-item label="身份证号">
<el-input v-model="scoreForm.idCard" placeholder="请输入身份证号"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="queryScore">查询</el-button>
</el-form-item>
</el-form>
<el-table :data="scoreData" v-if="scoreData.length" border>
<el-table-column prop="subject" label="科目"></el-table-column>
<el-table-column prop="score" label="成绩"></el-table-column>
<el-table-column prop="status" label="状态"></el-table-column>
</el-table>
</el-tab-pane>
<el-tab-pane label="考试安排" name="schedule">
<el-form :model="scheduleForm" label-width="100px">
<el-form-item label="考试年份">
<el-select v-model="scheduleForm.year" placeholder="请选择年份">
<el-option label="2023年" value="2023"></el-option>
<el-option label="2024年" value="2024"></el-option>
</el-select>
</el-form-item>
<el-form-item label="考试月份">
<el-select v-model="scheduleForm.month" placeholder="请选择月份">
<el-option label="4月" value="4"></el-option>
<el-option label="10月" value="10"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="querySchedule">查询</el-button>
</el-form-item>
</el-form>
<el-table :data="scheduleData" v-if="scheduleData.length" border>
<el-table-column prop="date" label="日期" width="120"></el-table-column>
<el-table-column prop="time" label="时间" width="120"></el-table-column>
<el-table-column prop="subject" label="科目"></el-table-column>
<el-table-column prop="location" label="考点"></el-table-column>
</el-table>
</el-tab-pane>
</el-tabs>
</div>
</div>
</template>
<script setup>
import { ref } from 'vue'
const activeTab = ref('score')
const scoreForm = ref({
examNumber: '',
idCard: ''
})
const scheduleForm = ref({
year: '',
month: ''
})
const scoreData = ref([])
const scheduleData = ref([])
const queryScore = () => {
// 模拟API调用
scoreData.value = [
{ subject: '马克思主义基本原理概论', score: '85', status: '合格' },
{ subject: '中国近现代史纲要', score: '78', status: '合格' },
{ subject: '英语(二)', score: '62', status: '合格' }
]
}
const querySchedule = () => {
// 模拟API调用
scheduleData.value = [
{ date: '2023-10-21', time: '上午9:00-11:30', subject: '马克思主义基本原理概论', location: '第一中学' },
{ date: '2023-10-21', time: '下午14:30-17:00', subject: '中国近现代史纲要', location: '第一中学' },
{ date: '2023-10-22', time: '上午9:00-11:30', subject: '英语(二)', location: '第二中学' }
]
}
</script>
<style scoped>
.query {
min-height: calc(100vh - 120px);
}
.container {
max-width: 1200px;
margin: 20px auto;
padding: 0 20px;
}
.page-title {
color: #409EFF;
margin-bottom: 30px;
text-align: center;
}
.query-tabs {
background: #fff;
padding: 20px;
border-radius: 4px;
box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1);
}
</style>
6. App.vue (根组件)
<template>
<div class="app">
<Header />
<router-view />
<Footer />
</div>
</template>
<script setup>
import Header from './components/Header.vue'
import Footer from './components/Footer.vue'
</script>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
.app {
display: flex;
flex-direction: column;
min-height: 100vh;
}
</style>
7. 运行项目
npm run dev
功能扩展建议
- 用户系统:添加登录/注册功能,保存用户查询记录
- 数据API:连接后端服务获取真实数据
- 响应式设计:优化移动端显示
- 搜索功能:添加全局搜索框
- 收藏功能:允许用户收藏重要公告和政策
这个实现提供了自考社区门户网站的基本框架,您可以根据实际需求进一步扩展和完善各个功能模块。