164
社区成员
发帖
与我相关
我的任务
分享学生姓名:李宗衡
FZUID:832301117
MUID:23126230
https://github.com/Moneett/832301117
本项目是基于前后端分离架构开发的多功能通讯录管理系统,核心目标是实现联系人信息的高效管理,同时适配多终端访问场景,帮助用户快速完成联系人的添加、修改、删除等基础操作,兼顾功能完整性与使用便捷性。
| PSP阶段 | 预估时间 | 实际时间 | 差异分析 |
|---|---|---|---|
| 需求分析 | 2 | 1.5 | 需求明确,效率较高 |
| 架构设计 | 1 | 1.5 | 技术选型调研比预期复杂 |
| 前端开发 | 6 | 7 | 难度较大,开发耗时多 |
| 后端开发 | 8 | 9 | 部署环境配置耗时较多 |
| 前后端调试 | 3 | 4 | 出现错误消耗时间 |
| 博客编写 | 2 | 3 | 精益求精,细致整理 |
| 合计 | 22 | 26 | 消耗时间较多,追求高完成质量 |
1、界面展示

2、添加联系人


3、删除联系人


4、编辑联系人


本通讯录管理系统采用现代化Web开发技术栈,实现了前后端分离的架构设计。下表列出了系统主要技术选型及其选型理由:
| 分类 | 技术 | 版本 | 选型理由 |
|---|---|---|---|
| 前端框架 | Vue 3 | 3.x | 采用组合式API,性能卓越,响应式设计简化数据绑定,学习曲线平缓,社区活跃。 |
| UI样式 | 原生CSS | - | 轻量级实现,无需额外依赖,便于自定义样式,适合小型应用快速开发。 |
| 构建方式 | CDN引入 | - | 无需复杂构建配置,直接在浏览器中运行,简化部署流程,适合教学演示。 |
| 本地存储 | localStorage | - | 浏览器内置存储机制,无需后端即可实现数据持久化,使用简单,适合单机应用。 |
| 后端框架 | Express | 4.x | 轻量级Node.js Web框架,API简洁,中间件丰富,学习成本低,适合快速开发RESTful API。 |
| 运行环境 | Node.js | 14.x+ | JavaScript运行时,实现JavaScript全栈开发,生态丰富,跨平台支持良好。 |
| 跨域处理 | cors | 2.x | Express中间件,简单配置即可解决跨域问题,提高前后端协作效率。 |
| 数据存储(后端) | 内存数据库 | - | 开发阶段使用,简化数据库配置,便于快速原型开发和测试。 |
系统采用典型的前后端分离架构,具体架构设计如下图所示:
┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐
│ 前端应用层 │ │ 后端服务层 │ │ 数据存储层 │
│ (Vue 3) │◄───►│ (Express) │◄───►│ (localStorage/│
│ │ │ │ │ 内存存储) │
└─────────────────┘ └─────────────────┘ └─────────────────┘
架构说明:
前端应用层:负责用户界面展示和交互逻辑,使用Vue 3框架实现组件化开发。采用组合式API管理应用状态,通过localStorage实现本地数据持久化,同时预留了与后端API交互的接口。
后端服务层:提供RESTful API接口,处理业务逻辑和数据操作。使用Express框架构建Web服务器,配置cors中间件处理跨域请求,实现了完整的联系人CRUD操作。
数据存储层:前端采用localStorage实现本地存储,后端采用内存数据库进行开发测试,支持后续平滑迁移到MongoDB或MySQL等持久化数据库。
前端目录结构:
student123_contacts_frontend/
├── index.html # 主页面
├── README.md # 项目说明文档
├── codestyle.md # 代码规范文档
└── src/ # 源代码目录(可扩展)
├── assets/ # 静态资源
├── components/ # Vue组件
└── utils/ # 工具函数
后端目录结构:
student123_contacts_backend/
├── server.js # 应用入口文件
├── package.json # 项目配置和依赖
├── README.md # 项目说明文档
├── codestyle.md # 代码规范文档
└── src/ # 源代码目录
└── controller/ # 控制器目录
└── contacts.js # 联系人控制器
目录设计说明:
通讯录管理系统是一个基于前后端分离架构的Web应用,支持联系人信息的添加、查询、修改和删除操作。系统采用现代化Web开发技术,前端使用Vue 3框架实现响应式界面,后端基于Express构建RESTful API服务,同时提供了纯前端localStorage存储方案,实现了无需后端服务也能独立运行的数据持久化功能。
前端代码采用单文件设计,集成了HTML结构、CSS样式和JavaScript逻辑,使用Vue 3的组合式API构建响应式界面。
<div id="app" class="container">
<h1>通讯录管理系统</h1>
<div class="button-group">
<button class="btn-primary" @click="showAddModal = true">添加联系人</button>
</div>
<table>
<thead>
<tr>
<th>姓名</th>
<th>电话</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="contact in contacts" :key="contact.id">
<td>{{ contact.name }}</td>
<td>{{ contact.phone }}</td>
<td>
<button class="btn-default" @click="editContact(contact)">修改</button>
<button class="btn-danger" @click="deleteContact(contact.id)">删除</button>
</td>
</tr>
</tbody>
</table>
<!-- 添加/编辑模态框 -->
<div v-if="showAddModal || showEditModal" class="modal" @click.self="closeModal">
<div class="modal-content">
<h2>{{ showEditModal ? '编辑联系人' : '添加联系人' }}</h2>
<div class="form-item">
<label>姓名</label>
<input v-model="formData.name" type="text" placeholder="请输入姓名">
</div>
<div class="form-item">
<label>电话</label>
<input v-model="formData.phone" type="tel" placeholder="请输入电话">
</div>
<div class="button-group">
<button class="btn-primary" @click="submitForm">{{ showEditModal ? '更新' : '添加' }}</button>
<button class="btn-default" @click="closeModal">取消</button>
</div>
</div>
</div>
</div>
HTML结构采用了清晰的语义化设计:
v-for、v-if、v-model、@click)实现数据绑定和事件处理showAddModal和showEditModal两个状态变量控制显示逻辑和内容const { createApp, ref, reactive, onMounted } = Vue
createApp({
setup() {
const contacts = ref([])
const showAddModal = ref(false)
const showEditModal = ref(false)
const editingId = ref(null)
const formData = reactive({
name: '',
phone: ''
})
// 组件逻辑...
return {
contacts,
showAddModal,
showEditModal,
formData,
editContact,
deleteContact,
submitForm,
closeModal
}
}
}).mount('#app')
Vue 3应用初始化采用了组合式API风格:
ref()创建响应式基本类型数据(联系人列表、模态框状态等)reactive()创建响应式对象(表单数据)setup()函数中定义所有逻辑和状态// 从localStorage获取联系人数据
const fetchContacts = () => {
const storedContacts = localStorage.getItem('contacts')
if (storedContacts) {
contacts.value = JSON.parse(storedContacts)
} else {
// 设置默认模拟数据
contacts.value = [
{ id: 1, name: '张三', phone: '13800138000' },
{ id: 2, name: '李四', phone: '13900139000' }
]
// 保存默认数据到localStorage
localStorage.setItem('contacts', JSON.stringify(contacts.value))
}
}
// 保存联系人数据到localStorage
const saveContacts = () => {
localStorage.setItem('contacts', JSON.stringify(contacts.value))
}
本地存储功能设计:
fetchContacts()函数在组件挂载时调用,从localStorage读取数据saveContacts()函数在任何数据变更后调用,确保数据持久化JSON.parse()和JSON.stringify()进行数据格式转换编辑联系人:
const editContact = (contact) => {
editingId.value = contact.id
formData.name = contact.name
formData.phone = contact.phone
showEditModal.value = true
}
删除联系人:
const deleteContact = (id) => {
if (confirm('确定要删除这个联系人吗?')) {
contacts.value = contacts.value.filter(c => c.id !== id)
saveContacts()
}
}
表单提交处理:
const submitForm = () => {
if (!formData.name || !formData.phone) {
alert('请填写完整信息')
return
}
if (showEditModal.value) {
// 更新现有联系人
const index = contacts.value.findIndex(c => c.id === editingId.value)
if (index !== -1) {
contacts.value[index] = {
...contacts.value[index],
name: formData.name,
phone: formData.phone
}
}
} else {
// 添加新联系人
const newContact = {
id: Date.now(), // 使用时间戳作为唯一ID
name: formData.name,
phone: formData.phone
}
contacts.value.push(newContact)
}
// 保存到localStorage
saveContacts()
closeModal()
}
模态框管理:
const closeModal = () => {
showAddModal.value = false
showEditModal.value = false
editingId.value = null
formData.name = ''
formData.phone = ''
}
生命周期管理:
// 初始化数据
onMounted(() => {
fetchContacts()
})
核心功能实现亮点:
fetchContacts()初始化数据const express = require('express');
const cors = require('cors');
const app = express();
const PORT = 3000;
// 导入控制器
const contactController = require('./src/controller/contacts');
// 中间件
app.use(cors());
app.use(express.json());
// API路由
app.get('/api/contacts', contactController.getAllContacts);
app.get('/api/contacts/:id', contactController.getContactById);
app.post('/api/contacts', contactController.createContact);
app.put('/api/contacts/:id', contactController.updateContact);
app.delete('/api/contacts/:id', contactController.deleteContact);
// 启动服务器
app.listen(PORT, () => {
console.log(`后端服务启动在 http://localhost:${PORT}`);
});
// 添加一个简单的健康检查接口
app.get('/api/health', (req, res) => {
res.json({ status: 'ok', message: '服务正常运行' });
});
后端服务器设计采用了典型的Express应用架构:
// 模拟数据库
let contacts = [
{ id: 1, name: '张三', phone: '13800138000' },
{ id: 2, name: '李四', phone: '13900139000' }
];
let nextId = 3;
// 获取所有联系人
exports.getAllContacts = (req, res) => {
res.json(contacts);
};
// 获取单个联系人
exports.getContactById = (req, res) => {
const id = parseInt(req.params.id);
const contact = contacts.find(c => c.id === id);
if (contact) {
res.json(contact);
} else {
res.status(404).json({ error: '联系人不存在' });
}
};
// 添加联系人
exports.createContact = (req, res) => {
const { name, phone } = req.body;
if (!name || !phone) {
return res.status(400).json({ error: '姓名和电话不能为空' });
}
const newContact = {
id: nextId++,
name,
phone
};
contacts.push(newContact);
res.status(201).json(newContact);
};
// 更新联系人
exports.updateContact = (req, res) => {
const id = parseInt(req.params.id);
const { name, phone } = req.body;
if (!name || !phone) {
return res.status(400).json({ error: '姓名和电话不能为空' });
}
const contactIndex = contacts.findIndex(c => c.id === id);
if (contactIndex === -1) {
return res.status(404).json({ error: '联系人不存在' });
}
contacts[contactIndex] = {
...contacts[contactIndex],
name,
phone
};
res.json(contacts[contactIndex]);
};
// 删除联系人
exports.deleteContact = (req, res) => {
const id = parseInt(req.params.id);
const contactIndex = contacts.findIndex(c => c.id === id);
if (contactIndex === -1) {
return res.status(404).json({ error: '联系人不存在' });
}
contacts.splice(contactIndex, 1);
res.json({ message: '删除成功' });
};
联系人控制器实现了完整的CRUD操作:
nextId用于生成自增IDgetAllContacts: 获取所有联系人列表getContactById: 根据ID获取单个联系人createContact: 创建新联系人updateContact: 更新现有联系人deleteContact: 删除指定联系人本次前后端分离通讯录编程作业,让我系统掌握了前后端分离开发的核心流程与关键技术。在问题解决方面,遇到了前后端跨域、接口联调数据格式不匹配、部署后访问超时等问题,通过查阅官方文档、调试工具排查与社区求助,最终逐一解决,提升了问题排查与解决能力。同时,严格按照作业要求进行代码规范整理与 Github 版本管理,养成了良好的开发习惯。通过本次作业,不仅提升了技术实操能力,更培养了从需求分析、设计、开发到部署的完整项目思维,为后续更复杂的项目开发奠定了基础。