
简介面向本科毕业设计的日语词汇学习小程序完整项目包适合计算机相关专业学生完成微信小程序与SSM后端及MySQL的课程设计或毕业设计。系统同时提供用户端与管理员端用户可查看N2词汇、签到打卡、在线练习管理员可维护用户、词汇单词、试卷试题与系统配置。压缩包共纳入1031个文件约73.22MB覆盖java后端逻辑、vue后台页面、小程序wxml与wxss界面、sql数据库脚本、doc毕业论文、pptx答辩演示及mp4视频教程等关键材料还包含启动脚本与项目配置文件目录结构完整文件分类清晰。已有114人浏览学习。整套资料从项目源码、数据库设计、论文撰写到答辩演示配套齐全既可直接部署运行与二次开发也可作为毕业设计说明书和答辩PPT的写作范本能有效节省资料收集与调试时间适合需要快速搭建可运行毕设项目的开发者。1. 微信小程序 SSM MySQL 的日语词库毕设先估工作量再动手一个反直觉的事实这类「微信小程序 SSM MySQL」的日语词汇学习毕设真难点在把别人写好的代码跑通、讲清、改得动而不是从零写一遍。包里带着源代码、数据库脚本、论文、答辩 PPT 和视频教程意味着它是一次「交付工程」的验收挑战。小程序端负责刷词卡、收藏和练习SSM 后端从 MySQL 取词条做成接口前端按页加载。适合拿它做毕设的学生、想补齐全栈链路的初学者以及要快速搭课设项目的团队。第一步不是装环境是把这条链路的走向画清楚。2. 从数据库脚本到数据表日语词库怎么设计才不翻车2.1 词库类小程序的数据模型三张表起步还不够词汇学习小程序的数据模型比普通 CRUD 多两个特殊点一是日文写法有「汉字 假名」两套二是「背没背过」本身要记录状态。如果只有一张单词表你能做出词卡但做不出「复习进度」和「错题本」。常见的表结构是三张核心表加若干扩展表单词表存词条本身用户表存微信用户信息学习记录表存每个用户对每个词的掌握状态扩展表按需加收藏、练习记录和分类。很多第一次做这类项目的人会把学习状态字段直接塞进单词表给voc_word加一个user_id和status这是典型的翻车设计。同一个词条要对所有用户可见而学习状态是每个用户私有的把两者混在一张表里词条会被重复插入成千上万次。正确的拆法是让词条表保持公共性学习状态单独建表。单词表的字段设计是所有逻辑的地基我直接给一份能跑起来的建表脚本-- 词汇表一份能支撑词卡、列表、按级筛选的建表脚本 CREATE TABLE voc_word ( id INT UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 主键, word_kana VARCHAR(64) NOT NULL COMMENT 假名写法必填, word_kanji VARCHAR(64) DEFAULT NULL COMMENT 汉字写法可空空则只显示假名, meaning VARCHAR(255) NOT NULL COMMENT 中文释义多个义项用分号分隔, example_sentence VARCHAR(255) DEFAULT NULL COMMENT 例句, example_translation VARCHAR(255) DEFAULT NULL COMMENT 例句翻译, level TINYINT UNSIGNED NOT NULL DEFAULT 5 COMMENT 等级1N12N23N34N45N5, category VARCHAR(32) DEFAULT NULL COMMENT 分类标记比如 动词/名词/形容词, create_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, update_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, PRIMARY KEY (id), KEY idx_level (level), KEY idx_category (category) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_general_ci COMMENT日语词汇表;参数说明word_kana和word_kanji分开存很关键词卡上要做「显示汉字/只显示假名」的切换字段分开就不用每次请求回来再解析。level用TINYINT而不用字符串排序和IN条件都比字符串快接口里做level IN (1,2)也很顺手。meaning用分号分隔多义项是妥协方案胜在简单后端不需要额外建关联表。索引只覆盖了level和category两个查询最频繁的列因为列表页绝大多数请求是「按等级拉一页词」不会按假名精确匹配。学习记录表的核心字段是user_id、word_id、status和review_count-- 学习记录表支撑「已背/未背/复习次数」的状态流转 CREATE TABLE voc_user_word ( id INT UNSIGNED NOT NULL AUTO_INCREMENT, user_id INT UNSIGNED NOT NULL COMMENT 用户表主键, word_id INT UNSIGNED NOT NULL COMMENT 词汇表主键, status TINYINT NOT NULL DEFAULT 0 COMMENT 0未学1学习中2已掌握, review_count INT NOT NULL DEFAULT 0 COMMENT 复习次数每次刷词1, last_review_at DATETIME DEFAULT NULL COMMENT 上次复习时间, PRIMARY KEY (id), UNIQUE KEY uk_user_word (user_id, word_id) ) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COMMENT用户学习记录表;逻辑说明这张表是「列表页显示掌握状态」和「个人页统计学习进度」的数据来源。UNIQUE KEY加在(user_id, word_id)上是防止同一用户对同一词插出两条记录的最简单手段。review_count每次刷词加 1last_review_at用来筛选「今天该复习哪些词」这两个字段如果缺失后面的打卡和复习二开都会很痛苦。答辩时评审大概率会问「为什么不用一张表存所有数据」这个拆表思路就是标准答案。2.2 数据库脚本的导入路径字符集和 MySQL 版本是两个坎标题里的「数据库脚本」通常是指一份.sql文件里面包含建库、建表、初始词条。很多人在这一步不是 SQL 写错而是导入方式不对。最常见的现场是用 Navicat 直接双击运行脚本所有日文变成问号或者是 MySQL 8.0 连不上报Public Key Retrieval is not allowed。命令行导入我一般这么写# 以 utf8mb4 字符集导入避免日文假名和汉字变成问号 mysql -uroot -p --default-character-setutf8mb4 -e CREATE DATABASE IF NOT EXISTS japan_vocab DEFAULT CHARSET utf8mb4; mysql -uroot -p --default-character-setutf8mb4 japan_vocab japan_vocab.sql参数说明--default-character-setutf8mb4是必须的不指定时客户端可能用latin1或gbk向服务器发送 SQL 文本日文片假名和长音符号在这种编码下会直接丢字。第一个命令里用DEFAULT CHARSET utf8mb4把库的默认字符集定死后面的表和字段即使建表语句里没写字符集也会继承库级别默认值。如果你参考安装教程自己装的是 MySQL 8.xJDBC URL 上还要加allowPublicKeyRetrievaltrueuseSSLfalse这个坑后面避障清单里会单独说。导入方式的选择上我列一个对比导入方式字符集处理适用场景命令行 mysql 客户端加--default-character-setutf8mb4干净环境、答辩现场演示Navicat 运行 SQL 文件连接属性 Encoding 选 utf8mb4日常调试、改表结构Docker 容器内的 MySQL容器启动参数配character-set-server不想污染本机环境时初始词条不用一次塞太多。常见做法是先把 N5 和 N4 的常用词导进去词条数控制在 200 到 500 条够演示「按等级筛选、分页加载、搜索」三个功能就行。词条来源优先用课程提供的清单或自己整理不要从网上复制没有出处的词库格式不可控后期清洗比前期手动录入还累。脚本文件如果是拆分的一般是schema.sql建库建表和data.sql初始数据两份答辩时拆开讲更容易说清楚「结构归结构、数据归数据」。2.3 排序和分页别只按主键排词表列表页的常见交互是「按等级刷词」落到 MySQL 就是WHERE level ? ORDER BY id。这里有个容易被忽略的点ORDER BY id和ORDER BY create_time在数据量小的时候结果一样但脚本导入时如果用了多行 INSERTid顺序和create_time顺序可能不一致。如果前端要展示「最新添加的词」排序字段必须写create_time不能偷懒用主键。另一个排序陷阱是混合排序既要按等级筛选又要在同一类别里随机抽词。随机抽词在数据量小的时候可以直接ORDER BY RAND()但词表超过几千条后这条语句会全表扫描性能明显变差。我一般用WHERE level ? ORDER BY RAND() LIMIT 20只在小范围内随机性能可控语义也够用。前端在做「每日一练」这类功能时后端接口要单独开一个随机抽词的方法不要和列表分页接口混在一起。分页的另一个细节是ORDER BY字段必须唯一。如果只按level排序同一等级的词条顺序不稳定翻页时会出现上一页最后一词和下一页第一词重复。稳定排序的做法是ORDER BY level, id或ORDER BY id保证每次查询顺序一致。这套源码如果首页是「全部词汇」入口默认排序就用id ASC新导入的词会出现在末尾符合用户预期。3. SSM 后端把词库交给小程序接口设计与 4 个必调配置3.1 SSM 承担的角色和这套架构的边界SSM 是 Spring SpringMVC MyBatis 的缩写在这个项目里任务很纯粹接收小程序的 HTTP 请求查 MySQL返回 JSON。Spring 管对象生命周期和事务SpringMVC 负责 URL 到方法的映射MyBatis 把 SQL 和 Java 方法绑定起来。选择它而不是 Spring Boot不是因为 Boot 不好而是毕设场景里 SSM 有现实优势教材和论文范例多、答辩时每个注解都能对应一个明确概念、不需要纠缠自动配置的黑匣子。这套架构的边界也要讲清楚它是单机应用没有服务注册、没有消息队列并发能力有限。小程序端几百人同时刷词的量级它能扛住但把它讲成高并发架构答辩时一问就露馅。SSM 的定位是「把业务逻辑讲清楚」不是「扛住大流量」。源码包拿到手先别急着跑打开pom.xml看依赖版本这是整个项目最容易出问题的地方我列一份能用的核心依赖组合!-- pom.xml 关键依赖 -- dependency groupIdorg.springframework/groupId artifactIdspring-webmvc/artifactId version5.3.27/version /dependency dependency groupIdorg.mybatis/groupId artifactIdmybatis-spring/artifactId version2.0.7/version /dependency dependency groupIdmysql/groupId artifactIdmysql-connector-java/artifactId version8.0.33/version /dependency参数说明spring-webmvc5.3.x 是兼容javax.servlet的最后一个大版本线配 Tomcat 9 没问题一旦换成 Tomcat 10Spring 要升到 6.xjavax包名全部变jakarta几乎所有 import 都要改这是毕设最容易卡一周的地方。mybatis-spring2.0.7 对应 MyBatis 3.5.x扫描 Mapper 接口和加载 XML 文件都靠它。MySQL 驱动版本要跟数据库对齐8.0.x 驱动连 5.7 和 8.0 都可以5.x 驱动连 8.0 会直接报错。这四个依赖的版本组合对了后端启动就成功了一半。3.2 词汇查询接口Controller-Service-Mapper 最小闭环SSM 的接口链路由三层组成源码包可能拆得很细但读代码时抓住一条线请求进 ControllerController 调 ServiceService 调 MapperMapper 执行 SQL 返回数据。词汇列表接口是小程序首页一定会调的接口也是理解整套代码的入口。我按最常见的写法拆一遍RestController RequestMapping(/api/word) public class WordController { Autowired private WordService wordService; GetMapping(/list) public Result list(RequestParam(defaultValue 1) Integer page, RequestParam(defaultValue 20) Integer size, RequestParam(required false) Integer level) { PageResultWord data wordService.pageQuery(page, size, level); return Result.ok(data); } }参数说明RestController是Controller加ResponseBody的合并写法类里所有方法直接返回 JSON不需要再配视图解析器。三个RequestParam对应页码、每页条数、等级筛选defaultValue保证前端漏传参数时不会报 400。level用required false因为首页可能展示全部词汇此时不带等级条件。Result.ok()是统一返回体小程序端靠code字段判断成功失败后面专门说它的结构。Service 层和 Mapper 层是业务逻辑和 SQL 真正所在的地方Override public PageResultWord pageQuery(Integer page, Integer size, Integer level) { PageHelper.startPage(page, size); ListWord list wordMapper.selectByCondition(level); PageWord pageInfo (PageWord) list; return PageResult.of(pageInfo.getTotal(), list); } Select(script SELECT id, word_kana, word_kanji, meaning, example_sentence, example_translation, level, category FROM voc_word where if testlevel ! nulllevel #{level}/if /where ORDER BY id ASC /script) ListWord selectByCondition(Integer level);逻辑说明PageHelper.startPage(page, size)是 MyBatis 分页插件原理是在当前线程上下文放一个分页参数插件在 SQL 执行前自动拼接LIMIT所以它必须紧挨着 Mapper 调用写中间隔了别的查询会被线程上下文污染。where加if是 MyBatis 动态 SQL 的标准写法level为空时不拼等级条件返回全量分页结果。ORDER BY id ASC是稳定排序保证翻页不重不漏。如果你要扩展搜索功能在这段动态 SQL 里加if testkeyword ! nullAND (word_kana LIKE CONCAT(%, #{keyword}, %) OR meaning LIKE CONCAT(%, #{keyword}, %))/if就行。3.3 JSON 序列化与登录态小程序端最在意这两件事后端返回给小程序的数据有两点最影响联调效率时间格式和登录态。时间格式的坑是Java 的LocalDateTime默认序列化成数组或带T的字符串小程序端new Date()解析会出错。常见修法是在配置文件里统一全局格式化# spring-mvc.xml 或对应 application 配置 spring.jackson.date-formatyyyy-MM-dd HH:mm:ss spring.jackson.time-zoneGMT8登录态的流程是小程序wx.login()拿到code后端拿code调微信接口换openid再生成自己的token返回给小程序。这个流程对应后端的LoginControllerPostMapping(/login) public Result login(RequestBody LoginRequest req) { // req.getCode() 是 wx.login 拿到的临时凭证五分钟内有效 String openid wxService.code2Session(req.getCode()); User user userMapper.selectByOpenid(openid); if (user null) { user new User(); user.setOpenid(openid); userMapper.insert(user); } String token TokenUtil.generate(user.getId()); return Result.ok(token); }参数说明code2Session是后端调微信接口的核心方法里面要拿appid、secret、code三个参数去换openid。appid和secret必须放在配置文件里不要写死在代码中答辩时这也是一个可讲的点。selectByOpenid先查用户是否存在第一次登录自动注册用户无需手动注册。Token 生成后小程序把它存进wx.storage后续请求放进Authorization头后端用拦截器统一校验这一步是整个联调的基础。3.4 统一返回体和 SSM 常用注解的读法源码包里接口返回体几乎都叫Result统一用code表示成功失败。它的存在让前端request.js可以用一套逻辑处理所有接口否则每个接口要单独判断状态码。结构基本是三个字段public class Result { private Integer code; // 0 成功非 0 失败 private String message; // 给用户看的提示信息 private Object data; // 业务数据 public static Result ok(Object data) { Result r new Result(); r.code 0; r.message ok; r.data data; return r; } }逻辑说明小程序端request.js里判断res.data.code 0再取res.data.data逻辑就统一了。后续后端如果新增接口只要保证返回Result结构前端封装不用改。SSM 常用注解也就这几个读源码时先认注解再读逻辑Service标业务层、Repository标数据层、Autowired注入依赖、GetMapping/PostMapping标 URL 和方法。把 Controller 层每个方法的注解和 URL 抄一遍整个后端的接口地图就出来了比逐个类读快得多。4. 小程序端接入与词卡交互跑通真机前要处理的两道关卡4.1 页面结构与 request 封装所有接口走一个入口小程序端常规的页面拆分是首页词库列表、词卡详情、练习页、个人中心。词库列表的核心是分页加载对应小程序端的「页面列表加载更多」交互。页面结构不用多解释关键是请求封装。如果每个页面都写一遍wx.request后面改BASE_URL或者统一加 token 时会改到怀疑人生。我一般单独建一个utils/request.js// utils/request.js —— 所有接口的请求出口 const BASE_URL http://localhost:8080/api; // 本地联调地址 function request(path, method GET, data {}) { return new Promise((resolve, reject) { wx.request({ url: ${BASE_URL}${path}, method, data, header: { Content-Type: application/json, Authorization: wx.getStorageSync(token) || }, success: (res) { if (res.statusCode 200 res.data.code 0) { resolve(res.data.data); } else { wx.showToast({ title: res.data.message || 请求失败, icon: none }); reject(res.data); } }, fail: (err) reject(err), }); }); } module.exports { request };逻辑说明把wx.getStorageSync(token)放在header里是登录态的公共注入点新接口不需要每个页面处理。resolve(res.data.data)把统一返回体里的业务数据直接抛给调用方页面里拿到的就是纯净数据。失败路径统一弹 Toast页面只需要在catch里处理自己的场景。BASE_URL用http://localhost:8080只适用于开发者工具本地调试真机预览必须改成已备案域名加 HTTPS否则请求会被微信拦截。小程序端切记不要自己在代码里拼http://访问内网 IP线上环境会把这类请求直接判为非法。4.2 词卡渲染与翻卡交互假名/汉字切换和触底加载词卡页是这个小程序的核心页面交互上重点看两个点翻卡动画和「显示假名/显示汉字」切换。翻卡动画常见用两个 view 加 CSStransition实现代码不复杂但逻辑组织得好不好直接影响后续维护。核心视图结构是这样!-- 词卡页面核心结构 -- view classcard bindtaponToggleCard view wx:if{{showMeaning}} classcard-back text{{currentWord.meaning}}/text /view view wx:else classcard-front text{{currentWord.word_kanji || currentWord.word_kana}}/text text classkana{{showKana ? currentWord.word_kana : }}/text /view /view对应 JSPage({ data: { currentWord: {}, showMeaning: false, showKana: true, words: [], page: 1, finished: false, }, onToggleCard() { this.setData({ showMeaning: !this.data.showMeaning }); }, onReachBottom() { if (this.data.finished) return; this.loadMore(); }, loadMore() { request(/word/list?page${this.data.page}size20).then((res) { this.setData({ words: this.data.words.concat(res.list), page: this.data.page 1, finished: res.list.length 20, }); }); }, });逻辑说明wx:if / wx:else做正反面切换加上 CSStransition可以做出翻卡效果关键是切换变量只有一个showMeaning不要同时维护三四个布尔值。onReachBottom是页面滚到底部时触发的生命周期函数「加载更多」用finished标记判断当后端返回条数小于size说明没有更多数据这个判断比「total 减已加载数」简洁得多。currentWord在切换下一张卡时用this.data.words[index]取setData只传单词对象而不是整个数组性能更好。这里有个细节word_kanji为空时显示word_kana这个||逻辑要写在模板里而不是在 JS 里二次赋值。4.3 顶部导航栏高度与真机预览两道关卡小程序端的两个细节问题看着小实际很影响体验。一是顶部导航栏高度如果你把源码包改成自定义导航栏状态栏高度不要硬编码用wx.getWindowInfo().statusBarHeight拿到当前机型的真实值再叠加iPhone 全面屏和 Android 挖孔屏的数值不一样写死 44px 在某些机型上会顶出屏幕。二是合法域名校验本地开发时在开发者工具「详情 → 本地设置」里勾选「不校验合法域名、web-view业务域名、TLS 版本以及 HTTPS 证书」这个开关只对工具生效真机预览走的是完整校验。真机预览的正式流程是后端部署到云服务器域名完成 ICP 备案申请 HTTPS 证书配置到 Tomcat 或 Nginx最后在微信公众平台的小程序后台「开发管理 → 服务器域名」里添加request合法域名。这套流程里最容易翻车的是 Tomcat 配 HTTPS 时证书格式不对pem和jks的互相转换不是开箱即用的建议直接用 Nginx 做 HTTPS 终结Tomcat 保持 HTTP这样改证书时不用重启 Java 进程。4.4 开发/生产环境切换与空状态处理BASE_URL不能每次手改。常见做法是在request.js里根据环境变量区分地址开发环境走localhost生产环境走正式域名。手动切来切去不是不行但容易漏改我见过不止一次因为忘切环境导致线上请求打到本地地址的白屏事故。如果你拿到源码包先看BASE_URL是在哪个文件里定义的全局搜索一遍避免改了一处漏了一处。空状态处理是词库类小程序最容易忽略的词库还没有数据时首页不能白屏。合理的前端处理是判断返回列表长度为 0 时显示「暂无词汇」同时给一个「去导入词库」的提示入口。后端也要处理边界page取 0 或负数时返回第一页size超过 100 时限制为 100这些边界在接口层挡掉前端就不用写一堆防御逻辑。答辩演示时先清空数据库再展示一次空状态反而能证明你处理过边界情况。5. 避坑清单SSM 跑不起来、小程序白屏的 5 个常见根因拿到源码包最常见的不是功能不会写而是整个环境跑不起来。我自己的排查顺序是先确认数据库能连上再确认后端能启动最后才看小程序端请求什么。每层的报错特征不一样数据库层报连接异常后端层报映射或依赖错误小程序层报域名或白屏。按这个顺序定位能省掉大量翻源码的时间。下面五条是我在这类项目里遇到频率最高的坑每一条都是先现象、再原因、再解决。5.1 环境起不来的三个根因Tomcat 版本、MySQL 8 驱动、字符集**现象一**导入 IDEA 后所有import javax.servlet.*的类集体报红项目无法启动。原因源码包按 Tomcat 9 写的你装的是 Tomcat 10。Tomcat 10 把javax.servlet迁移到了jakarta.servlet命名空间整体变了SSM 时代的代码不能直接跑在 Tomcat 10 上。解决去 Tomcat 9.x 官网下载对应版本在 IDEA 的 Run Configuration 里把 Tomcat Server 指向 9.x。坚持用 Tomcat 10 需要把 Spring 升到 6.x 并全局替换包名工作量大毕设阶段不建议碰。**现象二**驱动版本看着没问题Tomcat 启动时数据源初始化失败报Public Key Retrieval is not allowed。原因MySQL 8.0 默认使用caching_sha2_password认证插件客户端首次连接需要向服务器请求公钥JDBC URL 没允许这个行为。解决在 JDBC URL 后面加?useSSLfalseallowPublicKeyRetrievaltrue。如果是 5.7 或更早通常是驱动版本问题把mysql-connector-java换成 8.0.33 即可。useSSLfalse只适合本地开发生产环境根据证书配置调整。现象三japan_vocab.sql导入后Navicat 里看着正常小程序端返回的日语全是???。原因导入时客户端默认字符集不是utf8mb4。命令行没加--default-character-set或 Navicat 的 Encoding 没选 utf8mb4。日文片假名和长音符号对编码很敏感用utf8也可能丢字。解决命令行按前面写的命令加--default-character-setutf8mb4Navicat 在连接属性里把 Encoding 设为utf8mb4。已经乱掉的数据直接DROP表重新导入不要尝试在现有数据上改字符集改完数据依然是坏的。5.2 前后端联调的两个根因合法域名和登录态失效**现象四**开发者工具里接口能通真机预览时wx.request走fail回调控制台提示域名不在合法列表。原因微信要求request必须是 HTTPS且域名已备案并配置在小程序后台合法域名列表。开发者工具勾选的「不校验合法域名」只在工具里生效真机上每个请求都会校验。解决本地用 localhost 加勾选忽略校验真机必须完成后端部署、域名备案、HTTPS 证书配置、微信后台添加合法域名四步。注意后台修改域名后有一个生效延迟改完不要马上重试等几分钟再打开小程序。**现象五**小程序挂了一晚再打开列表页一直 loading所有接口返回 401。原因token 有有效期过期后拿不到数据。常见源码包只在失败回调里弹错误没做「重新登录」的兜底用户看到的就是死循环转圈。解决在request.js里对res.statusCode 401做拦截清掉本地 token重新调wx.login()换 code走完登录流程后重放原请求。注意并发请求同时返回 401 时会触发多次刷新 token 的竞态用一个布尔锁或 Promise 队列把刷新动作挡住只执行一次。6. 答辩前一周从数据库脚本到演示视频的验收路径答辩前一周我不会再改功能而是按交付物清单过一遍验收。最容易出问题的是「干净环境」这四个字很多源码包作者在自己电脑上跑得通换台电脑就缺这个缺那个。拿包之后第一件事就是在虚拟机或另一台电脑上按 README 从头装一遍把所有缺的步骤记下来这些笔记就是答辩时讲「部署难点」的素材。我习惯做这样一张验收表交付物验收动作常见翻车点源代码干净电脑上从零跑通前后端JDK/Maven 版本不一致Tomcat 用错数据库脚本删库重导一次确认日文和词条完整字符集选错导入顺序不对论文与答辩 PPT核对表结构截图、接口图与代码一致截图是旧版界面已改视频教程按视频步骤原样复现一遍视频词库和本地数据不一致演示顺序也有讲究。我一般按「登录 → 刷词列表 → 翻词卡 → 做练习 → 查看个人统计」走主链路把「按等级筛选」和「假名/汉字切换」作为交互亮点重点停留再准备一个备用断点比如现场把数据库服务停掉展示错误提示和恢复过程能证明你处理过异常。我第一次答辩只准备了主链路结果评审对「数据库脚本怎么导入」追问最多我现场演示删库重导反而成了加分项。从那以后我养成了把「删库重导」和「环境重建」录进演示视频的习惯希望帮到你。本文还有配套的精品资源点击获取