首页 / 资讯中心 / 文章详情

从零搭建校园图书馆管理系统:Django全栈与协同过滤推荐实践

从零搭建校园图书馆管理系统:Django全栈与协同过滤推荐实践 ★ FEATURED ARTICLE
1. 项目背景与需求拆解前阵子帮某高校图书馆做一个内部的图书管理和推荐系统做完之后有不少同行问我整体思路和技术选型索性把整个项目的核心设计、踩坑记录和关键实现整理出来分享给正在做类似全栈项目的朋友。这个项目的完整名称是“校园图书馆管理与推荐系统”关键词有两个核心一个是“管理”一个是“推荐”。管理意味着要覆盖图书信息、借阅流程、读者档案、超期处理、统计报表这些常规业务推荐则意味着要在读者和图书之间建立主动连接解决“有书没人借、想借找不到”的信息差问题。整个系统面向三类角色学生读者、图书管理员、系统管理员。先说结论这是典型的业务管理系统加一个轻量级个性化推荐模块的组合。技术难点不在推荐算法本身而在于如何把推荐结果嵌进一个功能完整、权限清晰、操作流畅的管理系统里。推荐算法做得再花哨如果图书编目混乱、借还流程断档、统计口径错误整个系统照样没法用。适合参考这个项目的人群正在做Python全栈课程设计的同学、准备搭建图书管理类业务系统的开发者、想把协同过滤推荐整合进业务系统的后端工程师。下文我会从技术选型、数据库设计、推荐模块实现、权限控制、部署避坑几个维度完整拆解每个关键点都会给出选择理由和出错案例。2. 技术选型与整体架构设计2.1 后端框架选型分析后端我最终选了Django。选型过程中其实对比过Flask和FastAPI三者的差异不是“谁比谁好”而是“谁更适合这个项目”。Flask的优势是轻量灵活适合做纯API服务或者微服务架构中的一环。但图书管理系统涉及后台模板渲染、表单处理、用户登录会话、Admin后台、文件上传封面图片这些常规功能Flask全都要自己集成第三方库项目规模上来之后模块之间的兼容性维护成本不低。FastAPI的优势是异步性能和高性能API文档适合高并发读写、前后端完全分离的场景。但校园图书馆的并发量级通常在几十到几百人同时操作结构优化和技术炫技的动态性和实际业务需求不匹配。点击“借书”按钮等接口响应真正决定快慢的是数据库查询而不是Web框架本身。Django适合这类业务的原因很直接自带Admin后台图书管理员的日常操作导入导出、批量修改、模糊搜索可以直接基于Admin二次开发完成自带用户认证体系和权限框架不用重新发明轮子ORM层对复杂查询的支持成熟稳定。做业务系统稳比快更重要Django天然适合这种“表单密集、权限分角色、后台管理需求大于高并发需求”的场景。2.2 前端方案与数据交互模式前端部分我没有选择前后端完全分离的SPA方案而是采用了Django模板加原生JavaScript配合AJAX的混合模式。原因有两个。第一是开发效率。这个项目有一定规模如果全部接口化并用Vue或React重写前端工作量大概会是现在的两倍。图书管理的关键操作入库登记、借书、还书、续借本质上都是表单提交加列表刷新的组合Django模板配合少量JavaScript完全能实现流畅体验。第二是实际维护场景。高校图书馆的管理员大多不是技术人员他们习惯的是页面刷新式的传统后台操作逻辑。SPA模式在弱网条件下首次加载耗时较长反而让管理员产生“系统变慢了”的错觉。混合模式下页面由服务端渲染每个功能模块的URL清晰可维护也方便后续交给其他同学继续开发。数据交互方面我统一用AJAX提交JSON数据服务端返回JSON响应页面局部刷新。这种模式的体验比纯表单提交好很多比如借书成功之后不用整页刷新书架状态区域即时更新操作节奏更顺畅。2.3 数据库选型与部署拓扑数据库用的MySQL 8.0原因很简单MySQL是校园里最常见的关系型数据库后续交给低年级同学维护时上手门槛低。数据量一万本图书、三万条借阅记录这种规模MySQL绰绰有余。图片存储方面图书封面没有走对象存储服务而是存在本地媒体目录用Nginx直接提供静态文件访问。这样做在单机部署场景下少依赖一项外部服务部署更简单。如果你是有运维条件的环境建议把封面图片迁移到对象存储并加CDN加速那是后话。整体部署拓扑是Nginx → Gunicorn → Django → MySQLRedis用来做缓存和推荐结果的临时存储。应用服务和数据库在同一台服务器上推荐计算任务通过定时任务独立执行详细内容后面单独讲。3. 数据库表结构设计与关键字段解析3.1 图书馆业务的核心表设计数据库设计是整个系统最重要的地基表关系理清楚了后面所有功能都会顺畅理不清楚就会处处卡壳。我的核心表设计分六块第一块是图书信息表。除了常规的书名、作者、ISBN、出版社、出版日期、分类我额外加了几个字段total_stock总馆藏数量、available_stock当前可借数量、shelf_location馆藏位置、cover_image封面图、brief_intro简介。available_stock这个字段就是经典的“字段冗余”它存储的是可借数量的实时值维护成本是每次借书和还书必须同时更新它但换来的收益是查询可借图书时不需要实时做关联统计效率明显更高。第二块是读者表。包含学号、姓名、学院专业、手机号、读者类型学生/教师、借阅权限等级。权限等级这个字段很重要因为学生和教师的借阅上限、借阅时长通常不一样一个字段就能区分多种规则。第三块是借阅记录表。核心字段包括读者ID、图书ID、借出时间、应还时间、实际归还时间、续借次数、状态借出中/已归还/超期。这个表是借阅业务的核心流水账每次借还操作都会产生或更新一条记录。第四块是预约表。当热门图书被借空时读者可以预约图书归还后系统按预约顺序通知排队读者。这块功能在校园场景里很实用比如考研参考书、热门小说经常处于借空状态没有预约功能读者只能反复跑图书馆查看体验很差。第五块是公告与推荐位管理表。用来维护首页 Banner 和书单推荐位管理员可以手动配置推荐书单也可以一键将系统算法推荐的结果推上首页。第六块是操作日志表。记录谁在什么时间做了什么操作内容涵盖登录、借书、还书、图书入库、修改库存等。这块一开始我担心会拖慢系统后来证明完全多余——用异步方式写日志对业务请求的性能影响极小。3.2 为什么推荐系统需要单独的数据支撑真正设计推荐模块时我才发现一个现实问题图书管理系统里借阅记录表天然适合做协同过滤但数据规模非常小。可能总共才几万条借阅记录而且很多读者一学期只借三五本书矩阵稀疏度极高传统的基于用户的协同过滤效果往往不理想。更重要的是用户真实的阅读需求很难完全从借阅记录里看出来。有人借书是替同学代借有人借了专业书但一本没看有人天天泡在馆里用电子资源从不借纸质书。单纯依赖借阅行为建画像推荐结果很容易偏。因此我在表结构里额外加了读者偏好标签表和阅读反馈表。偏好标签来自两个渠道读者注册时的主动选择以及系统对借阅历史的分析结果。阅读反馈则是读者对已读书籍的打分和评论类似豆瓣的模式。这两张表让推荐系统有了行为以外的数据来源推荐效果随使用时间逐渐提升。3.3 数据一致性维护心得操作日志表和借阅记录表之间的数据一致性是踩过坑之后才真正注意的。之前设计时借书返回的JSON里直接返回成功日志异步写入失败就丢失了。后来加上事务处理和失败重试机制才彻底解决。借书、还书、续借这几个核心操作必须加事务控制。一次借书操作涉及至少三张表的变更借阅记录表插入一条记录、图书表减少可借库存、读者表更新当前借阅数。这三步任何一步失败整个操作都要回滚。不然会出现书被借走但库存没减或者库存减了但没产生借阅记录的问题。注意库存扣减不要用先查再改的写法要直接在UPDATE语句里加条件判断类似UPDATE books SET available_stock available_stock - 1 WHERE id %s AND available_stock 0这样可以防止并发借书时超卖同一本书。4. 推荐系统模块的选型与实现4.1 算法选型的现实考虑图书推荐模块我采用了混合推荐策略核心由三部分组成基于物品的协同过滤、基于内容的推荐、热度排行榜兜底。先说基于内容的推荐。它的逻辑很好理解把读者借过的书和收藏过的书画出标签向量比如“Python”、“深度学习”、“算法”、“考研数学”然后推荐标签相似的图书。冷启动阶段效果显著新读者没有任何借阅历史时可以通过注册时选择的偏好标签推荐同分类的图书不用等行为数据积累。再说基于物品的协同过滤。核心思想是“喜欢这本书的人也喜欢那本”。计算物品之间的相似度不是比较书本身的内容属性而是比较哪些读者同时借了这两本书。因为校园图书馆读者兴趣相对集中同一专业的同学会借相似的书物品协同过滤的效果通常比用户协同过滤好物品数量比用户数量少得多相似度矩阵的计算和存储成本更可控。热度排行榜兜底则是为了保证推荐列表永远不会空。当推荐数据不足或者算法计算失败时系统自动推荐近期借阅量大的书。这套兜底策略保证用户任何时候打开页面都能看到一个像样的推荐栏。4.2 推荐计算的工程实现计算推荐结果的工作流分三步走。第一步是任务定时触发。我用Django的定时任务框架在每天凌晨计算一次全量推荐结果计算好的结果写入Redis缓存缓存格式是“用户ID为键、推荐图书ID列表为值”有效期为24小时。读者端请求推荐接口时直接读缓存响应速度快不会每次推荐都做矩阵计算。第二步是实际算法实现。物品相似度计算公式选择的是余弦相似度。举个例子假设图书A被读者1、2、3借过图书B被读者2、3、4借过把“是否借过”转成向量A对应(1,1,1,0)B对应(0,1,1,1)余弦相似度算出来大约是0.67表示相似程度还不错。实现时不需要手动算向量直接用矩阵库计算即可。第三步是生成待推荐列表。对读者已借图书按相似度矩阵找到最相似的Top N图书排除掉该读者已经借过的按照相似度加权汇总排序然后结合内容推荐的标签匹配分和图书热度分做加权融合。我的权重经验值是协同过滤占0.5、内容推荐占0.3、热度分占0.2这套参数在模拟数据集上效果较为稳定。4.3 推荐系统的冷启动处理冷启动是推荐系统永远绕不开的问题。新读者没有任何行为数据新书上架没有任何借阅记录这两种情况都得有对策。新读者的处理相对简单注册时强制或引导选择至少三个兴趣标签系统根据标签直接推荐对应分类的热门图书。实际效果显示标签选得准的新读者推荐点击率远高于随机推荐。新书的处理比较困难。我的方案是“人工加权加自然衰减”新书上架后30天内热度分按固定倍率加成保证新书有机会出现在推荐流里30天后加成归零靠真实借阅量说话。同时管理员可以通过后台把新书手动置顶到首页推荐位两种方式相互配合。5. 图书管理核心功能的细节实现5.1 批量导入与查重逻辑图书管理员手里常常有一批Excel格式的书目数据如果一本书一本书手动录进系统效率和准确性都很难保证。所以批量导入是管理端功能里使用频率最高的功能之一。导入流程用Python的Excel处理库读取文件逐行校验格式核心是查重。查重逻辑不只看ISBN因为很多旧书没有ISBN或者ISBN在数据录入时有误差。我的方案是多重匹配优先按ISBN精确匹配匹配不到再按“书名作者”组合匹配两边都没有的才当作新书。这种方式误伤率比较低。查重之后的数据分三类处理新增、更新、跳过。新增是录入新书更新是对已存在图书追加馆藏数量跳过是导入文件中与系统数据完全重复的无效行。导入完成后生成详细导入报告以表格形式展示成功多少条、失败多少条、失败原因是什么管理员可以下载错误报告修改后重新导入。注意Excel导入时日期格式、数字格式的脏数据是最大的坑。比如有的行写“2024-9-1”有的写“2024/9/1”有的单元格是文本格式如果不规范处理入库数据会出现大量错误。建议统一使用文本读取加自定义解析函数处理不要直接依赖Excel库的日期自动识别。5.2 借书还书流程的状态机设计借书、还书、续借、预约这一套流程本质上是图书状态和借阅记录状态的流转我用的状态机模式来管理比写大量if-else分支清晰得多。借阅记录的四个状态借出中、已归还、已超期、已取消。图书的两种状态可借、借出中。还有预约状态的三种变化待处理、已通知、已取消。状态流转受限已超期记录调用续借会直接报业务错误这时提示读者先归还或缴纳逾期费用已取消的预约记录不能重新激活只有借出中的记录能续借而且续借次数不能超过两次。全部检查逻辑抽成一个独立校验器函数借书之后还书之前不用重复写判断。5.3 图书检索优化图书搜索是读者使用频率最高的功能。初始版本直接用了数据库的LIKE模糊查询结果数据量过万之后速度还算可以但匹配效果不够理想搜索“python入门”这种含空格的词组匹配率明显偏低。最终方案是用数据库全文索引配合查询分词处理。查询输入先经过分词按空格、中英文标点拆分然后每个词单独匹配标题、作者、出版社、ISBN字段匹配到的结果按相关度排序。这个方案虽然没有引入独立搜索引擎那套复杂的分词算法但实测响应时间在百毫秒级别搜索结果准确率显著提升。搜索功能还做了一个重要体验优化支持按分类筛选、按馆藏状态筛选只显示可借的、排序方式切换按热度、按出版时间、按书名。高级筛选放在搜索结果页侧边栏不用跳转就能完成操作成本更低。6. 权限控制与会话安全实践6.1 三角色权限模型系统按角色划分定义权限每类角色能访问的功能模块不一样系统管理员用户管理、角色权限配置、数据备份恢复、系统参数设置、操作日志审计。图书管理员图书信息管理增删改查、批量导入导出、借还处理、预约管理与通知、公告发布、读者管理注册审核、挂失停用。学生/教师读者图书检索、个人借阅记录查询、续借/预约操作、推荐书单浏览、个人偏好设置。权限控制在Django的权限框架基础上做了二次封装每个视图函数用装饰器标注所需权限权限不足时返回统一的错误码和提示页面。管理员后台的每个按钮都按当前用户权限做模板层渲染控制不展示无权操作入口降低误操作概率。6.2 会话与密码安全细节会话管理方面Django默认的会话机制能满足大部分需求。额外设置了两项安全参数会话超时时间和闲置自动退出。图书馆电脑是公共设备读者在检索机上登录后如果忘记退出后面的人就可能看到他的借阅历史所以闲置自动退出必须开启时间设在10分钟左右。密码存储方面项目用的是Django默认的PBKDF2算法这点不需要额外调整。真正需要注意的是密码重置流程和初始密码策略。学生初次登录的初始密码是一串随机字符串不允许用固定默认密码首次登录时强制修改密码这条规则能拦住大量安全隐患。7. 前端交互与使用体验优化7.1 读者端核心页面的交互逻辑读者端的核心页面是检索页、详情页、个人中心。检索页默认展示热门图书和推荐书单。图书卡片直接显示封面、书名、作者、可借数量可借数量为0的卡片置灰点击进去会提示可预约。搜索框支持扫码枪输入这是实际调研图书馆管理员需求时了解到的高频场景读者在馆内看到实体书可以直接扫ISBN条形码定位电子记录。图书详情页主要展示基本信息、内容简介、馆藏位置哪个校区哪层哪个书架、当前可借状态、相关推荐“借过这本书的人也借了这些”。信息布局按“决策-浏览-推荐”三层排读者第一眼就能判断这书有没有、在哪、要不要借。个人中心除了常规借阅记录查询和续借操作还做了一个阅读统计面板累计借阅册数、当前借阅数量、超期次数、最常借的图书分类分布。数据可视化用的是轻量图表库不增加整体包体积。7.2 管理端“少点一次多看一眼”原则管理端设计的最关键原则是减少操作步骤增强信息可见度。以还书处理为例管理员扫码或输入图书编号后页面立即显示出读者信息、借出时间、应还时间、是否超期超期天数、应付金额全部算好所有操作一屏完成不用来回切换页面。借阅排行榜页面对管理员的决策价值很大用来辅助采购决策。导航栏直接展示最近30天借阅排行榜前20名的图表同时支持按分类维度查看排行趋势。7.3 检索页的分页与数据懒加载上万本图书数据一次性渲染到页面上会明显卡顿。检索结果分页设置为每页20本配合“加载更多”按钮实现数据懒加载滚动到底部自动请求下一页。实际测试中快速滚动翻页时没有出现内容闪烁或重复的问题。为保证加载过程体验稳定图书封面图加了延迟加载属性真正进入视口时才加载图片资源。这个细节对弱网用户影响很明显之前每次翻页都等半天图片优化后刷列表流畅多了。8. 常见问题与排查技巧实录8.1 借书并发冲突导致库存负数线上运行后遇到的第一类高频问题是热门图书多人同时借书时库存变成负数。根因是检查库存和扣减库存两步之间不是原子操作两个请求同时读到库存为1都认为可以借都执行了扣减库存就变成了-1。修复方案很简单改用条件更新的原子操作UPDATE books SET available_stock available_stock - 1 WHERE id %s AND available_stock 0。受影响函数返回值如果为0说明库存不足提示读者库存不足。这种写法在并发下也能保证数据正确。8.2 ISBN重复数据导致图书信息错乱批量导入时同一本ISBN的书可能因为不同批次数据源不同被当成两条记录入库。借书检索时ID选择自动选了第一条详情展示的却是第二条的信息导致馆藏位置和馆藏数量对不上。排查方法是在数据库里按ISBN分组查询找出隐藏的重复记录。修复之后给ISBN字段加了唯一索引约束同时完善导入查重逻辑从根源上解决这类问题。8.3 推荐列表“万年不变”背后的问题推荐系统上线一周后用户反馈推荐内容基本没变化。定位发现定时任务在凌晨执行时服务器负载较高任务超时被系统自动杀掉推荐结果一直在用旧缓存。我增加了定时任务的异常自动重跑机制同时加了一条失败告警推送问题解决。8.4 管理员账号权限过大带来的风险系统刚上线时管理员账号几乎是全功能的。运营一段时间后发现一个隐患图书管理员可以修改自己的角色权限也能查看系统操作日志这与审计分权原则相悖。后来拆分为“系统管理员”和“图书管理员”两套权限组图书管理员不能查看审计日志不能修改角色权限配置操作日志只读不写。9. 避坑指南与实战经验总结9.1 开发顺序与计划安排建议按我的经验这类系统最合适的开发顺序是数据库设计先行然后做管理系统核心功能再做推荐模块最后做读者端体验优化。很多人习惯先把推荐算法跑起来看好不好玩再做管理功能结果推荐算法调了很久但数据库表结构设计不合理后面所有功能都得跟着返工。数据库表结构设计这一步花一周时间反复推敲都不为过。表关系、字段类型、索引策略、冗余字段这些内容在项目初期想得越透后期开发效率越高。9.2 数据备份与恢复策略校园图书馆系统直接服务学生和教师的日常借阅数据安全极其重要。我配置了两层备份策略每天凌晨全量备份数据库并同步备份到异地存储实时操作日志记录在日志表里即使数据库备份丢失也能根据日志追溯关键业务操作。这里分享一个教训备份不是配好策略就万事大吉。每两周要做一次恢复演练真正把备份文件还原到一个测试库里确认数据完整可用。否则等出事故才发现备份文件早已损坏那时候做什么都来不及。9.3 系统性能优化的关键指标性能优化的关键指标有三条检索接口响应时间控制在300毫秒以内推荐接口响应时间控制在200毫秒以内借书还书事务操作响应时间控制在500毫秒以内。在测试环境用一万条图书数据、五万条借阅记录做压测。检索接口主要靠索引设计和查询优化来保障热门查询比如按书名关键词走复合索引不走回表全扫。推荐接口靠的就是Redis缓存基本不会触及数据库压力。只要参数调好、索引加对这几项指标不难做到。9.4 需求迭代中容易被忽视的小功能开发过程中有些功能容易被当成“顺便加一下”的小事实际用起来却非常重要。第一个是导出Excel功能。馆长要月度统计报表管理员要导出逾期名单、导出热门书单这个功能几乎每周都有人在用。接口实现其实不难但一定要处理大数据量下的内存问题超过几千行用分页查询加流式写入一次全查出来导出极容易把服务搞挂。第二个是数据字典管理。图书分类、学院名称、读者类型这些选项如果直接写死在枚举里或前端模板里后续调整非常麻烦。把它们抽到数据字典表后台页面可维护上线后就不用每次改动都麻烦开发同学重发代码。第三个是站内消息通知。预约到书有通知、借阅即将到期有提醒、超期有告警这些消息除了展示在系统站内信里最好还支持邮件和微信模板消息推送可以通过对接校园统一消息平台实现读者才不会错过重要提醒。10. 推荐系统效果评估与调优方向10.1 评估指标选择的现实意义推荐系统的效果评估我用了三个指标推荐曝光点击率推荐的图书被点击查看详情的比率、推荐借阅转化率推荐位展示后被实际借阅的图书占推荐总量的比例、读者反馈参与率读者对推荐结果点“不感兴趣”或给图书打分的频率。初期推荐点击率大约在15%左右推荐借阅转化率在5%上下。后来随着数据积累、权重参数调整特别是加入了读者反馈机制后点击率稳定在25%以上借阅转化率提升到10%左右。这个提升说明了一个道理推荐系统要持续收集反馈数据不断调整算法里的各项参数权重而不是上线后就不管了。10.2 算法参数的迭代调优方向推荐结果的加权融合公式里我固定了一组基础参数协同过滤0.5、内容匹配0.3、热度0.2但参数要随着数据变化而调整优化。新系统早期数据量少热度分权重应该调高到0.3数据积累丰富之后协同过滤的权重可以提高到0.6。具体做法是每月跑一次测试集用离线回放的方式比较不同参数组合下的推荐效果指标选最优组合再上线。10.3 进一步优化的思路后续计划做两件事一是引入Word2Vec词向量的语义相似度匹配提升搜索和内容推荐的语义理解能力二是尝试图神经网络模型把作者、分类、读者群之间的高阶关系建模得更充分进一步提升推荐准确率。这些方向技术路径已经比较成熟等数据量进一步积累之后就可以逐步落地。11. 部署上线与持续运维要点11.1 服务器基础设施配置项目的部署配置我用的方案是Nginx做反向代理和静态文件服务Gunicorn启动Django应用服务MySQL作为数据库Redis做缓存和推荐结果存储。系统配置参考如下两核四G的云服务器即可Nginx绑定域名或IP的80端口和443端口配置HTTPS证书。Django的静态文件和媒体文件都交由Nginx直接服务减少应用服务器的请求压力。Gunicorn启动4个worker进程每个worker处理并发请求。MySQL开启慢查询日志方便后续排查性能问题同时设置访问白名单不对外暴露端口。11.2 上线前的自测清单上线前自测我总结了几个最容易出问题的环节权限测试三类角色各建一个测试账号把每个角色能访问的URL全走一遍确认角色越权访问都能被正确拦截。越权访问的问题看似小实际是安全事件的大头。并发测试模拟50个用户同时操作借书和还书场景确认库存不会出错、事务不会互相阻塞。数据一致性抽查测试环境中模拟借书-还书-续借-预约-取消的完整流程确认每个流转节点的数据状态转换正确。极端输入测试空值、超长字符串、SQL关键字注入、XSS脚本等输入场景的防御处理情况。11.3 日常运维的关键实践部署后就进入了运维阶段。固定环境会巡检以下项目MySQL慢查询日志能快速发现未加索引或查询效率较差的接口定时任务的执行记录和失败告警磁盘空间增长最明显的是数据库备份文件日志文件定期清理避免越积越大HTTPS证书的到期时间并及时续期。经历过系统运行几个月后突然变慢的事件排查后发现是操作日志表已经涨到百万行级别导致相关查询变慢。解决方案是日志按月份分表热点数据只保留最近三个月的表数据更早的数据打包归档查询速度很快恢复正常。12. 写在最后的一点项目复盘心得把这个项目完整做完再回顾我发现一个之前低估的点这类系统里最花时间的不是推荐算法而是那些“看起来很简单”的常规功能——借书还书边界条件怎么处理、批量导入时各种脏数据怎么清洗、权限边界怎么设计才不出漏洞、历史数据怎么迁移。这些工作是系统能不能真正被用起来的决定性因素推荐算法只是锦上添花。也分享一个经验做这种项目一定要想办法拿到真实的业务数据做测试。我用模拟数据测试跑的流程全部正常但上线后用真实数据一跑暴露出一堆在模拟环境永远发现不了的问题。比如真实书目里大量存在“同名不同书”“同书不同版”的现象真实借阅记录里大量读者已经毕业但借的书还没还。这些情况没有真实数据驱动根本想不到去处理。最后给正在做类似项目的同学一个建议把精力重点放在数据库设计和业务逻辑的鲁棒性上。推荐算法做得再亮眼数据库表结构设计有缺陷借还书数据错乱整个项目的根基就塌了。先把管理系统的每个环节做扎实再让推荐功能锦上添花这才是这类全栈项目的正解。
阅读完成 · 觉得有帮助?
咨询建站