task-275(验收反馈): 菜单权限标识/路由后台自动生成(menu_auto_/auto/ 前缀),表单移除两项输入;编辑缺省保持原值

This commit is contained in:
2026-09-06 01:57:17 +08:00
parent c3dc2a3f2f
commit 6e2e4bf8e7
10 changed files with 152 additions and 34 deletions
@@ -0,0 +1,40 @@
import test from 'node:test'
import assert from 'node:assert/strict'
import { readSource } from './helpers.ts'
import { emptyMenuManageForm, toMenuCreateRequest, toMenuUpdateRequest, validateMenuManageForm } from '../src/pages/account/menu-manage-model.ts'
// 验收反馈:权限标识/路由由后台自动生成,不再出现在菜单表单里。
// 前端契约:表单不采集、校验不要求、请求体不携带;后端创建时自动生成、编辑时保持原值。
test('align_menu_auto_key_normal_primary_path', () => {
const page = readSource('src/pages/account/MenusPage.vue')
assert.ok(!page.includes('权限标识'), '表单不应再有“权限标识”项')
assert.ok(!page.includes('label="路由"'), '表单不应再有“路由”项')
})
test('align_menu_auto_key_normal_variant_input', () => {
const createReq = toMenuCreateRequest({ ...emptyMenuManageForm(), name: '新菜单' })
const updateReq = toMenuUpdateRequest({ ...emptyMenuManageForm(), name: '改名' })
assert.ok(!('columnKey' in createReq), '创建请求不携带权限标识')
assert.ok(!('routePath' in createReq), '创建请求不携带路由')
assert.ok(!('columnKey' in updateReq), '更新请求不携带权限标识')
assert.ok(!('routePath' in updateReq), '更新请求不携带路由')
})
test('align_menu_auto_key_boundary_empty_input', () => {
const result = validateMenuManageForm({ ...emptyMenuManageForm(), name: '有名称' })
assert.equal(result.valid, true, '未填权限标识/路由也应通过表单校验')
})
test('align_menu_auto_key_repeated_operation_is_idempotent', () => {
const model = readSource('src/pages/account/menu-manage-model.ts')
assert.match(model, /后台自动生成/, 'model 需注释说明自动生成语义')
})
test('align_menu_auto_key_dependency_failure_returns_actionable_message', () => {
// 后端契约:创建缺省自动生成 menu_auto_<类型>_<时间戳> 与 auto/<标识>,编辑缺省保持原值。
const java = readSource('../backend-java/src/main/java/com/nanri/aiimage/modules/permission/service/PermissionMenuService.java')
assert.match(java, /generateColumnKey|menu_auto_/, '后端含权限标识自动生成逻辑')
assert.match(java, /generateRoutePath|auto\/<columnKey>|"auto\/" \+ columnKey/, '后端含路由自动生成逻辑')
assert.match(java, /entity\.getColumnKey\(\)/, '编辑缺省保持原权限标识')
})
+5 -5
View File
@@ -13,12 +13,12 @@ test('test_task_252_menus_list_normal_primary_path', () => {
})
test('test_task_252_menus_list_normal_variant_input', () => {
// 正常变体:权限标识/路由不作为列表列展示(运维从对话框维护),列宽自适应;删除确认含菜单名。
// 正常变体:权限标识/路由不作为列表列展示,也不再出现在表单内(后台自动生成);列宽自适应;删除确认含菜单名。
const page = readSource('src/pages/account/MenusPage.vue')
assert.equal(/<el-table-column[^>]*prop="columnKey"/.test(page), false, '权限标识不应作为列表列')
assert.equal(/<el-table-column[^>]*prop="routePath"/.test(page), false, '路由不应作为列表列')
assert.match(page, /menuForm\.columnKey/, '权限标识字段仍在编辑表单内')
assert.match(page, /menuForm\.routePath/, '路由字段仍在编辑表单内')
assert.ok(!page.includes('menuForm.columnKey'), '权限标识输入项已从表单移除')
assert.ok(!page.includes('menuForm.routePath'), '路由输入项已从表单移除')
assert.match(page, /确定删除菜单/, '删除确认需含“确定删除菜单”')
assert.match(page, /menuDeleteReason/, '删除需过前置校验')
})
@@ -46,9 +46,9 @@ test('test_task_252_menus_list_boundary_single_item', () => {
})
test('test_task_252_menus_list_boundary_limit_or_missing_field', () => {
// 边界上限:创建/编辑表单含名称/标识/父菜单/路由/排序。
// 边界上限:创建/编辑表单含名称/父菜单/排序(权限标识/路由后台自动生成,不在表单)
const page = readSource('src/pages/account/MenusPage.vue')
for (const field of ['menuForm.name', 'menuForm.columnKey', 'menuForm.parentId', 'menuForm.routePath', 'menuForm.sortOrder']) {
for (const field of ['menuForm.name', 'menuForm.parentId', 'menuForm.sortOrder']) {
assert.ok(page.includes(field), `表单需含 ${field}`)
}
})
+5 -5
View File
@@ -65,12 +65,12 @@ test('test_task_053_menu_manage_dto_boundary_single_item', () => {
})
test('test_task_053_menu_manage_dto_boundary_limit_or_missing_field', () => {
// 边界上限/缺字段:请求体字段与 Java 对齐(必填含 menuType/routePath);排序取整。
// 边界上限/缺字段:请求体字段与 Java 对齐(必填含 menuType);权限标识/路由由后台自动生成,不随表单提交;排序取整。
const req = toMenuUpdateRequest({ ...emptyMenuManageForm(), name: 'n', columnKey: 'c', routePath: '/r', sortOrder: 2.7 })
assert.equal(req.sortOrder, 2)
assert.ok('menuType' in req)
assert.ok('routePath' in req)
assert.equal(req.columnKey, 'c')
assert.ok(!('routePath' in req), '路由由后台自动生成,不提交')
assert.ok(!('columnKey' in req), '权限标识由后台自动生成,不提交')
})
test('test_task_053_menu_manage_dto_invalid_input_rejected', () => {
@@ -78,8 +78,8 @@ test('test_task_053_menu_manage_dto_invalid_input_rejected', () => {
const r = validateMenuManageForm(emptyMenuManageForm())
assert.equal(r.valid, false)
assert.ok(r.errors.name)
assert.ok(r.errors.columnKey)
assert.ok(r.errors.routePath)
assert.ok(!('columnKey' in r.errors), '权限标识不参与表单校验(后台自动生成)')
assert.ok(!('routePath' in r.errors), '路由不参与表单校验(后台自动生成)')
assert.equal(parseMenuManageItem('garbage'), null)
})
+2 -2
View File
@@ -23,11 +23,11 @@ test('test_task_056_menu_edit_form_normal_primary_path', () => {
})
test('test_task_056_menu_edit_form_normal_variant_input', () => {
// 正常变体:根节点回填 parentId=null序列化到 update 请求体字段对齐
// 正常变体:根节点回填 parentId=null权限标识/路由由后台自动生成,不随 update 请求体提交
const node = parseMenuManageList([{ id: 1, name: '账号', column_key: 'account', parent_id: null, sort_order: 0 }])[0]
const form = menuFormFromNode(node)
assert.equal(form.parentId, null)
assert.deepEqual(toMenuUpdateRequest(form).columnKey, 'account')
assert.ok(!('columnKey' in toMenuUpdateRequest(form)), 'update 请求体不携带权限标识')
})
test('test_task_056_menu_edit_form_normal_repeated_operation_is_idempotent', () => {