closeEvalDialog is not defined、pages.json 语法、硬编码 ID ——记几个低级错误

这篇写几个"低级但致命"的错误。都是那种一看就是低级失误,但真的发生在你身上的时候会让你怀疑人生的类型。

Bug 1:保存后按钮短暂消失

给三级指标打完分,点"保存本项",右下角的"提交全部评分"按钮闪了一下就没了,得手动切一下步骤才能重新看到。

排查

看保存成功的回调:

async saveCurrentIndicatorScores() { // ... 保存到本地 allScoreRecords ... uni.showToast({ title: '保存成功', icon: 'success' }); // ← 这里 setTimeout(() => { this.currentStep--; }, 1500); }

保存成功后自动跳回上一步——步骤 4(评分页)跳到步骤 3(选三级指标页),"提交全部"按钮是步骤 4 特有的,跳过去自然就没了。

估计是前人为了"引导用户继续评下一个指标"加的,但用户想连续提交的时候就崩了。

修复

直接删掉这个 setTimeout:

async saveCurrentIndicatorScores() { // ... 保存 ... uni.showToast({ title: '保存成功', icon: 'success' }); // 不自动跳转,用户自己切 }

一点感受

表单类操作不要主动帮用户跳转。你以为在帮用户,其实在打断用户的操作流。多步骤表单尤其如此,让用户自己控制步骤切换。


Bug 2:pages.json 语法错误,编译直接崩

改了个路由配置,HBuilderX 编译时报:

Unexpected token ] in JSON at position 1554

排查

pages.json严格按 JSON 规范,不能有尾逗号:

{ "pages": [ { "path": "pages/home_page", "style": {} }, { "path": "pages/login", "style": {} }, ← 尾逗号 ] }

而且路径写错了——本来想加pages/school/studentScore/index,我写成了pages/school/studentScore/index/index(多套了一层文件夹)。

修复

删尾逗号 + 修正路径

一点感受

两个小 tip:

  1. JSON 严格模式不允许尾逗号(虽然 JS 对象允许),改pages.json时手别快
  2. 加路由前先在文件夹里对着看一眼实际路径,特别是有多层嵌套的时候

VS Code 装个 JSON 语法检查插件也能救命。


Bug 3:saveStudentEvaluationResult is not a function

写完学生评价页面,点提交按钮直接报:

TypeError: saveStudentEvaluationResult is not a function

排查

页面顶部已经 import 了:

import { saveStudentEvaluationResult } from '@/api/school/evaluationResult';

打开api/school/evaluationResult.js,翻半天没找到这个方法。

原来写页面的时候先写的调用,想着 API 后面补——然后忘了。

修复

在 API 文件补上定义:

export function saveStudentEvaluationResult(data) { return request({ url: '/school/evaluationResult/saveStudentEvaluationResult', method: 'post', data: data }); }

一点感受

这个错完全是自己的问题。以后养成个小习惯:页面里引用一个不存在的方法名,IDE 应该会有波浪线提示。看到波浪线千万别忽略。

或者更好的做法:先写 API 再写页面调用,反过来容易忘。


Bug 4:取消按钮点了没反应

班级验证码弹窗,点"取消"按钮没反应,控制台报:

Property or method "closeEvalDialog" is not defined

排查

看模板:

<view class="dialog-footer"> <button @click="closeEvalDialog">取消</button> <button @click="confirmEvalForm">确定</button> </view>

看 methods:

methods: { confirmEvalForm() { ... }, // closeEvalDialog 不在这里 }

方法压根没定义。

修复

补上:

methods: { confirmEvalForm() { ... }, closeEvalDialog() { this.showEvalDialog = false; } }

一点感受

跟 Bug 3 一样都是"引用了不存在的东西"。Vue 模板绑定的方法即使不存在,页面渲染的时候也不会报错,只有真点击了才炸。

开发完页面统一 Ctrl+F 搜一遍@click@change这些绑定,确认对应方法都存在,是个好习惯。


Bug 5:本地测试没问题,别的学校账号一登录就报"未找到评价模式"

家长评价页面的"评价模式"下拉,本地测试家长账号进去有选项,换成别的学校的账号进去,直接提示"未找到评价模式"。

排查

看筛选代码:

const parentModes = allModes.filter(m => [311, 314].includes(m.id));

311314是本地测试环境里"高年级家长评"和"低年级家长评"的主键 ID。

生产环境别的学校的数据库里,这两个模式的 ID 完全不一样(可能是 508、509 之类的),过滤条件永远匹配不上。

这是典型的"硬编码主键 ID"错误——只在自己电脑上能跑。

修复

不看主键,看业务字段

// 按 eval_category_id 判断,家长评固定是 3 const parentModes = allModes.filter(m => Number(m.evalCategoryId) === 3 );

eval_category_id是业务枚举,所有学校都一样。

一点感受

永远不要在前端硬编码数据库自增主键 ID

因为:

  • 主键值在不同环境(本地/测试/生产)大概率不一样
  • 业务人员在后台新增/删除数据,ID 会变
  • 数据迁移的时候 ID 也会变

判断业务类型永远靠业务字段:分类枚举、字典值、name 关键字。哪怕字符串匹配(name.includes('家长评'))都比硬编码主键 ID 强。


最后总结

这五个 bug 没什么技术含量,全是低级失误。但真的很有代表性——写代码时间一长,人容易松懈,越是简单的东西越容易出错。

  • 模板绑定的@click@change,对应方法都存在吗?
  • import 的函数,源文件里真的 export 了吗?
  • pages.json/ JSON 文件有没有尾逗号?
  • 有没有硬编码的数据库主键 ID?
  • 自动跳转 / setTimeout 是不是打断了用户操作?

下一篇写移动端和后端联调那个大坑(RuoYi 移动端启动跑不通),感兴趣可以关注。