ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

基于ThinkPHP 5+Vue.js+MySQL的个人记账管理系统毕业设计实战

基于ThinkPHP 5+Vue.js+MySQL的个人记账管理系统毕业设计实战 在实际的计算机专业毕业设计选题中一个融合了后端框架、前端框架和数据库的“个人记账管理系统”是一个经典且实用的选择。它不仅能串联起Web开发的核心技术栈还能体现一个开发者从需求分析、技术选型、编码实现到系统部署的完整工程能力。对于即将在2026年毕业的同学而言掌握ThinkPHP 5、Vue.js和MySQL的组合意味着你不仅完成了一个课程作业更构建了一个可以写入简历、应对初级开发岗位面试的实战项目。本文将带你从零开始理解如何将ThinkPHP 5作为后端API服务Vue.js构建前端单页面应用MySQL存储数据最终完成一个具备用户注册登录、账目CRUD、分类统计等核心功能的个人记账系统。我们会重点关注环境搭建中的版本兼容性陷阱、前后端分离的数据交互逻辑、生产环境部署的常见故障并提供一套可复现的代码骨架和排查清单。1. 理解技术栈选型为什么是ThinkPHP 5 Vue.js MySQL在开始编码之前明确每个技术组件扮演的角色和它们之间的协作关系至关重要。这能帮助你在遇到问题时快速定位是前端、后端还是数据库的职责范围。1.1 后端ThinkPHP 5 作为API服务器ThinkPHP 5简称TP5是一个在国内广泛使用的PHP开源框架。对于毕业设计而言它提供了清晰的MVC架构、丰富的内置功能和相对友好的学习曲线。在本系统中TP5的核心职责是提供RESTful API处理业务逻辑并与MySQL数据库进行交互。通俗理解TP5就像是系统的“后台办公室”和“规则制定者”。它接收前端发来的请求如“添加一笔餐饮消费”验证数据合法性金额是否为数字执行操作向数据库插入记录最后将结果成功或失败信息返回给前端。技术定义一个基于MVC设计模式的PHP开发框架通过路由、控制器、模型、视图等组件帮助开发者快速构建Web应用程序。在前后端分离架构中其“视图V”层通常仅用于输出JSON/XML数据。关键作用路由解析将类似/api/v1/record/add的URL请求映射到对应的控制器方法。请求验证对前端提交的数据进行过滤和验证防止非法数据进入系统。业务逻辑处理计算统计信息、处理分类逻辑等。数据库操作通过模型Model优雅地进行数据的增删改查CRUD。响应返回以JSON格式将处理结果数据或错误信息返回给前端。1.2 前端Vue.js 构建用户界面Vue.js是一个渐进式的JavaScript框架用于构建用户界面。它的核心是声明式渲染和组件化系统。通俗理解Vue.js是系统的“前台接待”和“交互设计师”。它负责把枯燥的数据如账单列表变成漂亮的表格和图表并处理用户的所有点击、输入等操作然后将这些操作打包成HTTP请求发送给TP5后端。两大核心响应式数据绑定当Vue实例中的数据发生变化时视图会自动更新。例如当你删除一条账单记录对应的表格行会立刻消失无需手动操作DOM。组件系统允许你将页面拆分成独立、可复用的组件。例如一个“账单表单”组件可以在添加和编辑页面共用。在本项目中的角色构建单页面应用SPA通过Axios等库与后端API通信管理应用状态如用户登录态并渲染动态页面。1.3 数据层MySQL 作为关系型数据库MySQL是一个开源的关系型数据库管理系统用于持久化存储所有记账数据。通俗理解MySQL是系统的“档案库”。它以表格的形式分门别类地存储用户信息、账单记录、分类字典等所有数据并保证数据的安全和一致性。关键设计需要设计合理的数据库表结构。一个简单的核心表可能包括user表存储用户ID、用户名、加密后的密码。category表存储收入/支出的分类如餐饮、交通、工资。account_record表存储每一条账单记录关联用户ID和分类ID包含金额、时间、备注等字段。1.4 前后端分离架构的工作流程理解数据流是调试的基础。一次典型的“添加账单”操作流程如下用户在Vue前端页面填写表单并点击提交。Vue组件收集表单数据通过Axios发送一个POST请求到http://your-api-server/api/v1/record。NginxWeb服务器接收到请求如果是PHP文件请求则通过FastCGI协议转发给PHP-FPM进程处理。PHP-FPM执行ThinkPHP 5框架的入口文件路由解析到对应的控制器方法。控制器验证数据调用模型Model在account_record表中插入新记录。模型操作成功控制器返回一个JSON响应{“code”: 200, “msg”: “添加成功”, “data”: {…}}。这个JSON响应通过网络返回到用户的浏览器。Vue前端接收到响应根据code判断成功与否更新页面状态如提示“添加成功”并刷新账单列表。2. 开发环境准备与关键配置避坑一个一致的开发环境能避免大量“在我电脑上是好的”这类问题。以下是基于Windows/macOS的推荐环境配置清单。2.1 后端环境PHP Composer ThinkPHP 5核心要求PHP版本ThinkPHP 5.0/5.1要求PHP 5.6但强烈建议使用PHP 7.x如7.4以获得更好的性能和安全性。避免使用PHP 8.0以上版本因为TP5对其兼容性支持不完善容易踩坑。Web服务器Apache或Nginx。本地开发推荐使用集成环境。数据库MySQL 5.7 或 MariaDB。包管理Composer。本地快速搭建方案Windows使用XAMPP或PHPStudy。它们集成了Apache、PHP、MySQL。macOS可以使用MAMP Pro或Homebrew单独安装。关于“mac mamp pro 的php如何做全局替换电脑内部的php”这通常是为了让命令行使用的PHP版本与MAMP内置的保持一致。打开终端编辑~/.zshrc或~/.bash_profile文件。添加一行export PATH/Applications/MAMP/bin/php/php7.4.33/bin:$PATH请将路径替换为你MAMP中实际PHP版本路径。执行source ~/.zshrc使配置生效。运行php -v检查版本是否已切换为MAMP的版本。创建ThinkPHP 5项目 通过Composer在项目目录下创建这是最规范的方式。# 进入你的工作目录例如 www 或 htdocs cd /path/to/your/webroot # 使用Composer创建ThinkPHP 5.1项目 composer create-project topthink/think5.1.* your-project-name如果下载慢可以配置中国镜像composer config -g repo.packagist composer https://mirrors.aliyun.com/composer/关键目录结构your-project-name/ ├── application/ # 应用目录核心 │ ├── index/ # 默认模块可以改为 api 模块 │ │ ├── controller/ # 控制器 │ │ ├── model/ # 模型 │ │ └── view/ # 视图前后端分离项目中可少用 │ └── ... (其他模块如 common) ├── config/ # 配置文件 ├── route/ # 路由定义 ├── public/ # Web入口目录 │ └── index.php # 入口文件 ├── thinkphp/ # 框架核心 ├── vendor/ # Composer依赖包 └── runtime/ # 运行时缓存需写权限2.2 前端环境Node.js Vue CLI核心要求Node.js建议安装LTS版本如18.x, 20.x。从官网下载安装包即可。npm 或 yarn包管理工具随Node.js安装。Vue CLIVue.js项目的官方脚手架。安装Vue CLI并创建项目# 1. 安装Vue CLI如果已安装可跳过 npm install -g vue/cli # 或使用 yarn # yarn global add vue/cli # 2. 创建一个新的Vue项目项目名如 account-frontend vue create account-frontend # 3. 进入项目目录 cd account-frontend # 4. 安装axios用于HTTP请求 npm install axios # 或 yarn add axios在创建项目时可以选择手动配置确保包含Router和Vuex用于状态管理这对稍复杂的SPA很有帮助。开发工具浏览器插件Vue.js Devtools。这是调试Vue应用的必备工具。如何下载适配最新谷歌浏览器且兼容Vue 2请直接访问Chrome网上应用店搜索“Vue.js devtools”安装。如果无法访问可以从Vue.js官方GitHub仓库的devtools项目下寻找安装说明。安装后在开发Vue 2项目时浏览器开发者工具中会出现一个“Vue”面板。2.3 数据库环境MySQL安装与初始化从MySQL官网下载安装包安装过程注意记住设置的root用户密码。也可以使用集成环境自带的MySQL。使用命令行或MySQL Workbench创建数据库和表-- 1. 登录MySQL mysql -u root -p -- 2. 创建数据库 CREATE DATABASE IF NOT EXISTS personal_account DEFAULT CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- 3. 使用数据库 USE personal_account; -- 4. 创建用户表 CREATE TABLE user ( id int(11) NOT NULL AUTO_INCREMENT, username varchar(50) NOT NULL COMMENT 用户名, password varchar(255) NOT NULL COMMENT 密码加密存储, email varchar(100) DEFAULT NULL, created_at timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), UNIQUE KEY username (username) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户表; -- 5. 创建分类表 CREATE TABLE category ( id int(11) NOT NULL AUTO_INCREMENT, name varchar(20) NOT NULL COMMENT 分类名称, type tinyint(1) NOT NULL COMMENT 类型1-收入2-支出, user_id int(11) DEFAULT NULL COMMENT 用户IDNULL为系统默认分类, PRIMARY KEY (id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT分类表; -- 6. 创建账单记录表 CREATE TABLE account_record ( id int(11) NOT NULL AUTO_INCREMENT, user_id int(11) NOT NULL COMMENT 用户ID, category_id int(11) NOT NULL COMMENT 分类ID, amount decimal(10,2) NOT NULL COMMENT 金额, record_date date NOT NULL COMMENT 记账日期, remark varchar(255) DEFAULT COMMENT 备注, created_at timestamp NULL DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_user_date (user_id,record_date) -- 添加索引便于按用户和日期查询 ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT账单记录表;2.4 连接前后端解决跨域问题在开发阶段Vue前端项目通常运行在http://localhost:8080而ThinkPHP后端运行在http://localhost或http://localhost:80。浏览器出于安全考虑会阻止这种跨域请求。必须在后端进行配置以允许跨域。在ThinkPHP 5中解决跨域 最简便的方法是在应用入口文件public/index.php或公共控制器中添加响应头。在application/index/controller/Base.php创建一个基础控制器如果没有的话?php namespace app\index\controller; use think\Controller; class Base extends Controller { public function _initialize() { // 允许跨域访问 header(Access-Control-Allow-Origin: *); // 生产环境应替换为具体前端域名如 http://localhost:8080 header(Access-Control-Allow-Headers: Origin, X-Requested-With, Content-Type, Accept, Authorization); header(Access-Control-Allow-Methods: GET, POST, PUT, DELETE, OPTIONS); if (request()-isOptions()) { exit(); // 处理预检请求 } } }让其他控制器如LoginRecord都继承这个Base控制器。注意Access-Control-Allow-Origin: *在生产环境中是极不安全的应替换为确切的前端域名。开发阶段为了方便可以暂时使用*。3. 核心功能实现从数据库到API再到界面我们将以实现“用户登录”和“添加账单”这两个核心流程为例串联起整个技术栈。3.1 后端实现ThinkPHP 5 API开发步骤一配置数据库连接修改application/database.php配置文件return [ // 数据库类型 type mysql, // 服务器地址 hostname 127.0.0.1, // 数据库名 database personal_account, // 用户名 username root, // 密码 password your_password, // 替换为你的MySQL root密码 // 端口 hostport 3306, // 连接dsn dsn , // 数据库连接参数 params [], // 数据库编码默认采用utf8 charset utf8mb4, // 数据库表前缀 prefix , // ... ];步骤二创建用户模型和控制器创建用户模型application/index/model/User.php?php namespace app\index\model; use think\Model; class User extends Model { // 设置数据表名如果表名是‘user’可省略 protected $table user; // 自动写入时间戳 protected $autoWriteTimestamp datetime; // 或 true protected $createTime created_at; protected $updateTime false; // 如果没有更新时间字段则设为false }创建登录控制器application/index/controller/Login.php?php namespace app\index\controller; use app\index\model\User; use think\Request; use think\facade\Session; class Login extends Base // 继承我们之前创建的Base控制器 { /** * 用户登录 * param Request $request * return \think\response\Json */ public function index(Request $request) { // 1. 接收参数 $username $request-param(username); $password $request-param(password); // 2. 简单验证 if (empty($username) || empty($password)) { return json([code 400, msg 用户名和密码不能为空]); } // 3. 查询用户 $user User::where(username, $username)-find(); if (!$user) { return json([code 401, msg 用户不存在]); } // 4. 验证密码假设密码使用 password_hash 加密存储 if (!password_verify($password, $user-password)) { return json([code 401, msg 密码错误]); } // 5. 登录成功生成会话或Token这里使用Session示例 Session::set(user_id, $user-id); Session::set(username, $user-username); // 6. 返回成功信息注意不要返回密码等敏感信息 return json([ code 200, msg 登录成功, data [ user_id $user-id, username $user-username ] ]); } /** * 用户注册示例 */ public function register(Request $request) { $data $request-param(); // 验证数据... $data[password] password_hash($data[password], PASSWORD_DEFAULT); $user new User($data); if ($user-save()) { return json([code 200, msg 注册成功]); } else { return json([code 500, msg 注册失败]); } } }步骤三创建账单记录API创建账单模型application/index/model/AccountRecord.php?php namespace app\index\model; use think\Model; class AccountRecord extends Model { protected $table account_record; protected $autoWriteTimestamp datetime; protected $createTime created_at; protected $updateTime false; // 定义关联方便查询时携带分类信息 public function category() { return $this-belongsTo(Category::class); } }创建账单控制器application/index/controller/Record.php?php namespace app\index\controller; use app\index\model\AccountRecord; use app\index\model\Category; use think\Request; use think\facade\Session; class Record extends Base { // 添加账单 public function add(Request $request) { // 1. 验证用户是否登录 $userId Session::get(user_id); if (!$userId) { return json([code 403, msg 请先登录]); } // 2. 接收并验证数据 $data $request-param(); $validate new \think\Validate([ category_id require|number, amount require|float|gt:0, record_date require|date, ]); if (!$validate-check($data)) { return json([code 400, msg $validate-getError()]); } // 3. 补充用户ID $data[user_id] $userId; // 4. 保存到数据库 $record new AccountRecord(); if ($record-save($data)) { return json([code 200, msg 添加成功, data $record-id]); } else { return json([code 500, msg 添加失败]); } } // 获取账单列表带分页和筛选 public function list(Request $request) { $userId Session::get(user_id); if (!$userId) { return json([code 403, msg 请先登录]); } $page $request-param(page, 1); $size $request-param(size, 10); $type $request-param(type); // 收入/支出类型 $startDate $request-param(start_date); $endDate $request-param(end_date); // 构建查询 $query AccountRecord::where(user_id, $userId) -with([category]) // 关联分类信息 -order(record_date desc, id desc); // 按分类类型筛选 if (in_array($type, [1, 2])) { $query-whereHas(category, function($q) use ($type) { $q-where(type, $type); }); } // 按日期范围筛选 if ($startDate) { $query-where(record_date, , $startDate); } if ($endDate) { $query-where(record_date, , $endDate); } // 分页查询 $list $query-paginate([page $page, list_rows $size]); return json([code 200, msg success, data $list]); } }步骤四配置路由可选但推荐为了拥有更清晰的API地址可以配置路由。编辑application/route/route.phpuse think\facade\Route; // 登录注册 Route::post(api/login, index/Login/index); Route::post(api/register, index/Login/register); // 账单记录 Route::post(api/record/add, index/Record/add); Route::get(api/record/list, index/Record/list);这样登录API的访问地址就从/index/login/index变成了/api/login。3.2 前端实现Vue.js组件与API调用步骤一配置API请求基地址在Vue项目src目录下创建utils/request.js文件使用axios实例import axios from axios // 创建axios实例 const service axios.create({ baseURL: process.env.VUE_APP_API_BASE_URL || http://localhost, // 后端API基础地址 timeout: 10000 // 请求超时时间 }) // 请求拦截器 service.interceptors.request.use( config { // 在发送请求之前做些什么例如添加token const token localStorage.getItem(token) || sessionStorage.getItem(token) if (token) { config.headers[Authorization] Bearer token } return config }, error { // 对请求错误做些什么 console.error(Request Error:, error) return Promise.reject(error) } ) // 响应拦截器 service.interceptors.response.use( response { const res response.data // 假设后端统一返回格式为 { code, msg, data } if (res.code 200) { return res.data // 直接返回数据部分 } else { // 非200 code提示错误信息 console.error(API Error:, res.msg) // 可以在这里处理401未登录、403无权限等通用错误 if (res.code 401) { // 跳转到登录页 window.location.href /login } return Promise.reject(new Error(res.msg || Error)) } }, error { console.error(Response Error:, error) return Promise.reject(error) } ) export default service在项目根目录创建.env.development文件设置开发环境变量VUE_APP_API_BASE_URLhttp://localhost/your-project-name/public步骤二创建登录组件创建src/views/Login.vuetemplate div classlogin-container h2个人记账系统 - 登录/h2 form submit.preventhandleLogin div label用户名/label input typetext v-modelform.username required / /div div label密码/label input typepassword v-modelform.password required / /div button typesubmit :disabledloading{{ loading ? 登录中... : 登录 }}/button p v-iferrorMsg classerror{{ errorMsg }}/p /form /div /template script import request from /utils/request export default { name: Login, data() { return { form: { username: , password: }, loading: false, errorMsg: } }, methods: { async handleLogin() { this.loading true this.errorMsg try { // 调用后端登录API const data await request.post(/api/login, this.form) // 登录成功保存用户信息这里简单用localStorage localStorage.setItem(user_info, JSON.stringify(data)) // 跳转到首页 this.$router.push(/) } catch (error) { this.errorMsg error.message || 登录失败 } finally { this.loading false } } } } /script style scoped .login-container { max-width: 400px; margin: 50px auto; } .error { color: red; } /style步骤三创建账单管理组件创建src/views/RecordList.vue和src/views/RecordForm.vue。以RecordForm.vue为例template div classrecord-form h3{{ isEdit ? 编辑账单 : 添加账单 }}/h3 form submit.preventhandleSubmit div label分类/label select v-modelform.category_id required option v-forcat in categories :keycat.id :valuecat.id{{ cat.name }}/option /select /div div label金额/label input typenumber step0.01 v-modelform.amount required / /div div label日期/label input typedate v-modelform.record_date required / /div div label备注/label textarea v-modelform.remark/textarea /div button typesubmit :disabledloading{{ loading ? 提交中... : 提交 }}/button /form /div /template script import request from /utils/request export default { name: RecordForm, props: { recordData: { type: Object, default: () ({}) }, isEdit: { type: Boolean, default: false } }, data() { return { form: { category_id: , amount: 0, record_date: new Date().toISOString().split(T)[0], // 默认今天 remark: }, categories: [], // 从后端获取的分类列表 loading: false } }, created() { this.fetchCategories() if (this.isEdit this.recordData.id) { this.form { ...this.recordData } } }, methods: { async fetchCategories() { try { // 假设有一个获取分类的API this.categories await request.get(/api/category/list) } catch (error) { console.error(获取分类失败:, error) } }, async handleSubmit() { this.loading true try { const url this.isEdit ? /api/record/update/${this.form.id} : /api/record/add const method this.isEdit ? put : post await request({ url, method, data: this.form }) this.$emit(success) // 通知父组件操作成功 if (!this.isEdit) { this.form { // 重置表单 category_id: , amount: 0, record_date: new Date().toISOString().split(T)[0], remark: } } } catch (error) { alert(操作失败: error.message) } finally { this.loading false } } } } /script步骤四配置Vue Router在src/router/index.js中配置路由将组件映射到URL路径。4. 运行验证与联调测试4.1 启动后端服务确保你的集成环境如XAMPP、MAMP已启动Apache/Nginx和MySQL。将你的ThinkPHP项目目录放到Web服务器的根目录下如htdocs或www。在浏览器中访问http://localhost/your-project-name/public如果看到ThinkPHP的欢迎页面说明后端环境基本正常。测试API使用Postman或浏览器插件如RESTED测试你的API端点。例如向http://localhost/your-project-name/public/api/login发送一个POST请求Body为x-www-form-urlencoded格式的username和password查看是否返回预期的JSON。4.2 启动前端开发服务器在Vue项目根目录下运行npm run serve控制台会输出本地访问地址通常是http://localhost:8080。访问该地址你应该能看到Vue应用的默认页面或你配置的登录页。4.3 前后端联调在前端登录页面输入凭据点击登录。打开浏览器开发者工具F12切换到“Network”网络面板。观察是否向正确的后端地址发送了登录请求。查看请求的响应状态码和返回的JSON数据。如果遇到跨域错误CORS检查后端Base控制器的响应头是否设置正确。如果遇到404错误检查后端路由配置和URL地址是否正确。如果遇到500错误查看后端runtime目录下的日志文件如log/yyyymm_dd.log或打开ThinkPHP的调试模式config/app.php中设置‘app_debug’ true查看具体错误信息。5. 常见问题排查与解决方案在开发过程中你几乎一定会遇到以下问题。这里提供排查路径。问题现象可能原因检查方式处理建议前端请求后端API报跨域错误1. 后端未设置CORS响应头。2. 后端设置了CORS但未处理OPTIONS预检请求。1. 浏览器开发者工具Network面板查看请求响应头是否有Access-Control-Allow-Origin。2. 查看请求方法是否为OPTIONS。1. 确保后端基础控制器正确设置了跨域头。2. 在_initialize方法中添加对OPTIONS请求的直接返回。Vue页面空白控制台无错误1. Vue Router路由配置错误或模式不对。2. 组件引入路径错误。3. 使用了未定义的变量或方法。1. 检查浏览器地址栏URL与路由配置是否匹配。2. 检查Vue Devtools中组件树是否正常。3. 查看浏览器控制台Console和Vue Devtools控制台。1. 确保路由模式history/hash与服务器配置匹配。单页应用部署常需配置Nginx重定向。2. 使用/别名确保路径正确。ThinkPHP报“控制器不存在”1. 控制器文件名或类名不符合规范。2. 路由配置错误URL无法映射到控制器。3. 命名空间错误。1. 检查控制器文件是否在application/模块/controller/目录下且类名首字母大写。2. 检查URL访问路径尝试直接访问index.php/模块/控制器/方法看是否正常。1. 控制器类名必须首字母大写如Login。2. 关闭路由调试config/app.php中‘url_route_on’ true并确保路由定义正确。数据库连接失败1.database.php配置错误密码、端口。2. MySQL服务未启动。3. 数据库不存在。1. 检查config/database.php配置文件。2. 在命令行或工具中尝试用相同配置连接MySQL。3. 查看ThinkPHP日志或开启调试模式看具体错误。1. 确保MySQL服务运行。2. 使用php think命令行工具测试连接。Vue Devtools不显示Vue面板1. 页面不是开发模式构建的Vue应用。2. 插件版本与Vue版本不兼容。3. 页面使用了生产环境构建。1. 确认运行的是npm run serve开发模式。2. 检查浏览器插件管理页面Vue Devtools是否已启用。1. 使用npm run serve启动开发服务器。2. 确保Vue版本与Devtools兼容。Vue 2项目需安装支持Vue 2的Devtools版本。前端请求成功但后端收不到POST数据1. 前端发送的数据格式不对如JSON但后端接收param。2. PHP配置问题如post_max_size太小。1. 浏览器Network面板查看请求的Content-Type和Payload。2. 在后端控制器中使用input(‘post.’)或Request::instance()-post()尝试接收。1. 前后端约定数据格式。通常表单提交用application/x-www-form-urlencoded复杂数据用application/json后端用$request-param()或$request-getInput()接收。Nginx部署后访问PHP文件直接下载Nginx未正确配置PHP-FPM处理。检查Nginx站点配置中对.php文件的处理是否交给了php-fpm。确保Nginx配置中有类似location ~ \.php$ { ... fastcgi_pass 127.0.0.1:9000; ... }的配置并指向正确的PHP-FPM socket或端口。修改代码后页面无变化1. 浏览器缓存。2. ThinkPHP缓存runtime目录。3. Vue开发服务器热更新失败。1. 浏览器强制刷新CtrlF5。2. 删除runtime目录TP5会自动重建。3. 检查Vue终端是否有编译错误。1. 开发时打开浏览器开发者工具的“Disable cache”。2. 可以配置ThinkPHP关闭模板缓存。6. 从毕业设计到生产部署的最佳实践完成基本功能后若想让项目更扎实需考虑以下方面。6.1 安全性增强密码存储必须使用password_hash()加密验证使用password_verify()。绝对不要明文存储。SQL注入防护ThinkPHP的模型和Db类默认使用参数绑定能有效防止SQL注入。避免直接拼接SQL字符串。XSS防护前端Vue默认对渲染的数据进行HTML转义。后端在输出到非Vue模板时可使用htmlspecialchars函数。CSRF防护对于表单提交应考虑添加CSRF Token。ThinkPHP 5内置了表单令牌验证功能。API认证上述示例使用了Session这在前后端分离且同域下可行。更常见的做法是使用JWTJSON Web Token进行无状态认证。用户登录后后端生成一个Token返回给前端前端后续请求在Header中携带此Token。6.2 代码结构与可维护性后端分层将业务逻辑尽量放在模型Model或独立的服务层Service控制器保持“瘦”。验证逻辑可以使用ThinkPHP的验证器Validate类。前端状态管理当组件间共享状态如用户信息、全局分类变得复杂时考虑引入Vuex进行集中式状态管理。错误处理统一化前后端都应定义统一的响应格式如{code, msg, data}和错误码。前端在request.js的拦截器中统一处理通用错误如401跳登录。配置管理将数据库连接、API密钥等敏感信息从代码中剥离使用环境变量或配置文件管理。ThinkPHP支持.env文件。6.3 部署上线毕业设计答辩通常需要演示你可能需要将项目部署到一台公网可访问的服务器。购买云服务器选择一家云服务商购买一台最低配置的云服务器如1核1G安装Linux系统如CentOS 7/8或Ubuntu 20.04。环境搭建在服务器上安装LNMPLinux, Nginx, MySQL, PHP环境。可以使用一键安装脚本如lnmp.org或手动安装。代码上传使用Git克隆或SFTP工具将前后端代码上传到服务器。后端部署将ThinkPHP项目代码放在Nginx的Web目录下如/www/wwwroot/account-api。配置Nginx将域名或IP指向该目录的public文件夹。确保runtime目录有写权限chmod -R 755 runtime。配置.env生产环境数据库信息。前端部署在本地运行npm run build生成静态文件在dist目录。将dist目录下的所有文件上传到服务器另一个Web目录如/www/wwwroot/account-web。配置Nginx将该域名或另一个子域名指向此目录。由于是单页应用需要在Nginx配置中添加try_files指令将非文件请求重定向到index.html。location / { try_files $uri $uri/ /index.html; }域名与HTTPS为你的服务器绑定域名并申请免费的SSL证书如Let‘s Encrypt配置HTTPS访问。6.4 毕业设计文档与扩展方向一个完整的毕业设计除了代码还需要设计文档。你可以围绕此系统撰写需求分析阐述个人记账管理的功能性需求增删改查、统计和非功能性需求安全性、易用性。系统设计包括架构图前后端分离、数据库E-R图、表结构设计、API接口设计。核心功能实现挑选1-2个有亮点的模块如基于ECharts的消费趋势图表、基于规则的账单分类自动建议详细说明。系统测试描述测试环境、测试用例如登录失败、账单查询和测试结果。总结与展望总结开发过程中的收获、遇到的难点及解决方案并提出未来可扩展的功能如多账本、预算管理、数据导出、移动端适配等。通过这个项目你不仅完成了一个毕业设计更实践了一个现代Web应用从开发到部署的全流程。在面试中你可以清晰地讲述技术选型理由、前后端如何协作、遇到了哪些问题以及如何解决这远比一个简单的增删改查系统更有说服力。
返回列表