职业指导服务开发问题记录与避坑指南.md 9.4 KB

职业指导服务模块 — 开发问题记录与避坑指南

记录日期:2026-06-09 模块路径:就业一湛通服务平台 > 职业指导服务 涉及子模块:公开文件、专家库、服务管理


目录

  1. 后端路径不一致导致 API 404
  2. 数据库视图不存在导致全页面崩溃
  3. 列非空约束导致新增失败
  4. Flyway SQL 缺少角色授权
  5. 菜单 ID 冲突
  6. 前端级联错误 (rowSelection) 的实际根因
  7. Vite import.meta.glob 热更新缓存问题
  8. 表单隐藏字段未注册导致提交缺字段

1. 后端路径不一致导致 API 404

问题现象

No static resource careerguidancedocument/careerGuidanceDocument/list.
No static resource careerguidanceexpert/careerGuidanceExpert/list.

Spring MVC 返回 "No static resource",表示没有 @RequestMapping 匹配请求路径。

根因

三个子模块的 @RequestMapping 使用了 三种不同风格

模块 实际代码 前端请求路径 是否匹配
Service /careerguidanceservice/careerGuidanceService /careerguidanceservice/careerGuidanceService/list
Document /zjrs/careerguidancedocument /careerguidancedocument/careerGuidanceDocument/list ❌ 多了一级 /zjrs/
Expert /careerguidanceexpert /careerguidanceexpert/careerGuidanceExpert/list ❌ 缺少类名层级

修复

统一路径格式为 /{模块名}/{Controller类名}/{action}

// Document
@RequestMapping("/careerguidancedocument/careerGuidanceDocument")

// Expert
@RequestMapping("/careerguidanceexpert/careerGuidanceExpert")

// Service (已正确)
@RequestMapping("/careerguidanceservice/careerGuidanceService")

教训

代码生成/新建 Controller 时,必须统一 @RequestMapping 命名规范 ✅ 建议格式:全小写模块名 + 首字母大写的 Controller 类名(对应 Jeecg 默认代码生成器规则) ✅ 前后端 API 路径必须严格一致,建议先定好规范再开发


2. 数据库视图不存在导致全页面崩溃

问题现象

无效的表或视图名[V_CAREER_GUIDANCE_SERVICE]
SQL: SELECT * FROM V_CAREER_GUIDANCE_SERVICE

根因

Mapper XML 中查询了 V_CAREER_GUIDANCE_SERVICE 视图,但该视图未在数据库中创建。

级联影响

视图不存在 → 后端 API 报错 → 前端接收错误响应
  → 组件 setup 阶段数据加载失败
  → 级联报错 "Cannot read properties of undefined (reading 'rowSelection')"
  → Vue render 崩溃 "Cannot read properties of null (reading 'flags')"

前端 rowSelection 报错是表象,实际根因是后端 API 异常。

修复

执行视图创建 SQL:

CREATE OR REPLACE VIEW V_CAREER_GUIDANCE_SERVICE AS
SELECT ... FROM CAREER_GUIDANCE_SERVICE cgs
LEFT JOIN PERSONAL_INFO pi ON cgs.PERSONAL_ID = pi.ID;

教训

建表 SQL 和视图 SQL 必须一起执行,缺一不可 ✅ 前端报错时要先排查后端 API 是否正常工作(浏览器 F12 → Network → 查看接口响应) ✅ 前端的 rowSelection / flags / component 等 Vue 内部报错,通常都是级联错误,不要直接在前端代码中加 try-catch 掩盖,应先排查后端


3. 列非空约束导致新增失败

问题现象

违反列[CATEGORY_ID]非空约束
INSERT INTO career_guidance_document (id, name, file_url, sort_no, ...) VALUES (?, ?, ?, ?, ...)

SQL INSERT 语句中没有 CATEGORY_ID

根因

前端表单的 formSchema 中没有注册 categoryId 字段。虽然前端代码调用了 setCategoryId(),但该字段不在 schema 中,提交时被表单框架过滤掉了。

修复

formSchema 中添加隐藏字段:

{
  label: '所属目录',
  field: 'categoryId',
  component: 'Input',
  show: false,  // 不在 UI 显示
}

教训

表单中使用的所有字段必须在 formSchema 中注册,即使是隐藏字段 ✅ 使用 show: false 隐藏字段而不移除 ✅ 数据库 NOT NULL 列必须有对应的前端提交逻辑


4. Flyway SQL 缺少角色授权

问题现象

菜单在 sys_permission 表中存在,但用户登录后看不到菜单。

根因

Flyway 迁移脚本 V20260609_1__menu_insert_CareerGuidance.sql 只插入了菜单记录,没有插入角色授权sys_role_permission)。

-- 只有 INSERT INTO sys_permission
-- 缺少 INSERT INTO sys_role_permission

修复

补充角色授权 SQL:

INSERT INTO sys_role_permission (ID, ROLE_ID, PERMISSION_ID)
VALUES ('xxx', 'f6817f48af4fb3af11b9e8bf182f618b', '菜单ID');

教训

菜单 SQL 必须包含两步:插入菜单表 + 插入角色授权表 ✅ 测试账号的 ROLE_ID 通常是固定的(如 admin: f6817f48af4fb3af11b9e8bf182f618b) ✅ 建议将菜单 + 授权写在一个 SQL 文件中,避免遗漏


5. 菜单 ID 冲突

问题现象

-- 终版 SQL 注释
-- 修复说明:之前使用的 ID (如 178060100000031) 已被"见习岗位管理"占用

根因

Flyway SQL 使用的菜单 ID(178060100000003 等)与已有模块的菜单 ID 冲突,导致插入失败或覆盖。

修复

更换新的 ID 号段(178060300000000 等),并统一在回滚 SQL 中清理两种号段:

DELETE FROM sys_role_permission WHERE PERMISSION_ID IN ('1780601...', '1780603...');
DELETE FROM sys_permission WHERE ID IN ('1780601...', '1780603...');

教训

新增模块的菜单 ID 必须使用不重复的号段 ✅ 建议记录项目中已使用到的最大的 ID 号段,新模块在此基础上递增 ✅ 保留回滚 SQL(移除 SQL)以便重来


6. 前端级联错误 (rowSelection) 的实际根因

问题现象

TypeError: Cannot read properties of undefined (reading 'rowSelection')
    at setup (CareerGuidanceServiceList.vue:24:64)

实际根因

不是 rowSelection 代码有问题,而是 后端 API 先报错(视图不存在或路径不匹配),组件在 setup 阶段获取数据失败,导致后续渲染全部崩溃。

排查方法

  1. 打开浏览器 F12 → Console
  2. 看完整的错误堆栈,不要只看第一行
  3. 切换到 Network 标签,看对应 API 的响应状态码和内容
  4. 后端也要看日志,定位真正的异常

教训

前端错误往上查(看组件树),后端错误往下查(看调用栈) ✅ Vue 的 setup 阶段报错往往是后端数据加载失败导致的 ✅ 不要在前端加 try-catch 掩盖 rowSelection 的访问,这不能解决根因


7. Vite import.meta.glob 热更新缓存问题

问题现象

重启前端后,新增的页面组件无法加载,路由跳转失败。

根因

Vite 的 import.meta.glob('../views/**/*.{vue,tsx}') 只在服务启动时静态扫描一次。如果在开发过程中新增了 .vue 文件,Vite 可能不会自动刷新缓存。

修复

pnpm clean:cache && pnpm dev

教训

新增 Vue 文件后,必须重启 Vite 开发服务器 ✅ 先执行 pnpm clean:cache 清理缓存再重启 ✅ 生产环境 build 时不会出现此问题


8. 表单隐藏字段未注册导致提交缺字段

问题现象

表单提交后,数据库报 NOT NULL 约束错误,但前端看起来字段值已设置。

根因

使用 setFieldsValue({ categoryId: xxx }) 设置了字段值,但该字段不在 formSchema 中注册。表单框架(useForm)在 validate() 或提交时,只收集 schema 中注册的字段值,未注册的字段会被丢弃。

修复

// 在 formSchema 中添加隐藏字段
{
  label: '所属目录',
  field: 'categoryId',
  component: 'Input',
  show: false,  // 隐藏
}

教训

所有提交到后端的字段必须在 formSchema 中注册 ✅ 使用 show: false 隐藏不需要 UI 展示的字段 ✅ 如果字段不需要校验,不写 required 即可


通用开发检查清单

后端启动前

  • 数据库表是否已创建(含所有字段、索引)
  • 数据库视图是否已创建
  • 菜单 SQL 是否包含角色授权
  • 菜单 ID 是否与已有模块冲突
  • @RequestMapping 路径是否符合统一规范
  • 新 Controller/Mapper 是否被 Spring 扫描到(包路径正确)
  • 后端是否重新编译(mvn compile)

前端启动前

  • API 路径是否与后端 @RequestMapping 一致
  • formSchema 是否包含所有提交字段(包含隐藏字段)
  • 列字段名(dataIndex)是否与后端返回字段名一致
  • Vite 缓存是否清理(新增文件后必须重启)
  • 路由组件路径是否被 import.meta.glob 覆盖

调试排查顺序

页面崩溃 → F12 → Network 看 API 响应是否有错误
  ↓ 有错误 → 修复后端(SQL / 路径 / 逻辑)
  ↓ 无错误 → Console 看具体报错堆栈
    ↓ Vue 内部错误 → 大概率是后端数据问题导致的级联崩溃
    ↓ 业务逻辑错误 → 排查具体代码