task-275(验收反馈): 菜单权限标识/路由后台自动生成(menu_auto_/auto/ 前缀),表单移除两项输入;编辑缺省保持原值
This commit is contained in:
@@ -225,9 +225,6 @@ onMounted(loadMenus)
|
|||||||
<el-form-item label="菜单名称">
|
<el-form-item label="菜单名称">
|
||||||
<el-input v-model="menuForm.name" placeholder="如:用户管理" />
|
<el-input v-model="menuForm.name" placeholder="如:用户管理" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="权限标识">
|
|
||||||
<el-input v-model="menuForm.columnKey" placeholder="如:admin_users(唯一,稳定授权标识)" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="菜单类型">
|
<el-form-item label="菜单类型">
|
||||||
<el-select v-model="menuForm.menuType" style="width: 100%" @change="onMenuTypeChange">
|
<el-select v-model="menuForm.menuType" style="width: 100%" @change="onMenuTypeChange">
|
||||||
<el-option v-for="opt in MENU_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
<el-option v-for="opt in MENU_TYPE_OPTIONS" :key="opt.value" :label="opt.label" :value="opt.value" />
|
||||||
@@ -243,9 +240,6 @@ onMounted(loadMenus)
|
|||||||
/>
|
/>
|
||||||
</el-select>
|
</el-select>
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
<el-form-item label="路由">
|
|
||||||
<el-input v-model="menuForm.routePath" placeholder="如:/account/users 或 group-xxx" />
|
|
||||||
</el-form-item>
|
|
||||||
<el-form-item label="排序">
|
<el-form-item label="排序">
|
||||||
<el-input-number v-model="menuForm.sortOrder" :min="0" />
|
<el-input-number v-model="menuForm.sortOrder" :min="0" />
|
||||||
</el-form-item>
|
</el-form-item>
|
||||||
|
|||||||
@@ -38,13 +38,14 @@ export interface MenuManageForm {
|
|||||||
sortOrder: number
|
sortOrder: number
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 请求体字段与 Java PermissionMenuCreate/UpdateRequest 对齐(camelCase)。 */
|
/** 请求体字段与 Java PermissionMenuCreate/UpdateRequest 对齐(camelCase)。
|
||||||
|
* 权限标识/路由由后台自动生成,不随表单提交,故为可选字段。 */
|
||||||
export interface MenuManagePayload {
|
export interface MenuManagePayload {
|
||||||
name: string
|
name: string
|
||||||
columnKey: string
|
columnKey?: string
|
||||||
parentId: number | null
|
parentId: number | null
|
||||||
menuType: string
|
menuType: string
|
||||||
routePath: string
|
routePath?: string
|
||||||
sortOrder: number
|
sortOrder: number
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -258,23 +259,20 @@ export function emptyMenuManageForm(): MenuManageForm {
|
|||||||
return { name: '', columnKey: '', parentId: null, menuType: ADMIN_MENU_TYPE, routePath: '', sortOrder: 0 }
|
return { name: '', columnKey: '', parentId: null, menuType: ADMIN_MENU_TYPE, routePath: '', sortOrder: 0 }
|
||||||
}
|
}
|
||||||
|
|
||||||
/** 表单校验(镜像后端 NotBlank 文案);返回逐字段错误。 */
|
/** 表单校验(镜像后端 NotBlank 文案);返回逐字段错误。权限标识/路由由后台自动生成,不参与校验。 */
|
||||||
export function validateMenuManageForm(form: MenuManageForm): { valid: boolean; errors: MenuManageFormErrors } {
|
export function validateMenuManageForm(form: MenuManageForm): { valid: boolean; errors: MenuManageFormErrors } {
|
||||||
const errors: MenuManageFormErrors = {}
|
const errors: MenuManageFormErrors = {}
|
||||||
if (!text(form.name)) errors.name = '菜单名称不能为空'
|
if (!text(form.name)) errors.name = '菜单名称不能为空'
|
||||||
if (!text(form.columnKey)) errors.columnKey = '菜单标识不能为空'
|
|
||||||
if (!text(form.menuType)) errors.menuType = '菜单类型不能为空'
|
if (!text(form.menuType)) errors.menuType = '菜单类型不能为空'
|
||||||
if (!text(form.routePath)) errors.routePath = '菜单路由不能为空'
|
|
||||||
return { valid: Object.keys(errors).length === 0, errors }
|
return { valid: Object.keys(errors).length === 0, errors }
|
||||||
}
|
}
|
||||||
|
|
||||||
function toMenuManagePayload(form: MenuManageForm): MenuManagePayload {
|
function toMenuManagePayload(form: MenuManageForm): MenuManagePayload {
|
||||||
|
// 权限标识(column_key)/路由(route_path) 不随表单提交:由后台自动生成(创建)或保持原值(编辑)。
|
||||||
return {
|
return {
|
||||||
name: text(form.name),
|
name: text(form.name),
|
||||||
columnKey: text(form.columnKey),
|
|
||||||
parentId: typeof form.parentId === 'number' ? form.parentId : null,
|
parentId: typeof form.parentId === 'number' ? form.parentId : null,
|
||||||
menuType: text(form.menuType),
|
menuType: text(form.menuType),
|
||||||
routePath: text(form.routePath),
|
|
||||||
sortOrder: normalizeMenuSort(form.sortOrder),
|
sortOrder: normalizeMenuSort(form.sortOrder),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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\(\)/, '编辑缺省保持原权限标识')
|
||||||
|
})
|
||||||
@@ -13,12 +13,12 @@ test('test_task_252_menus_list_normal_primary_path', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('test_task_252_menus_list_normal_variant_input', () => {
|
test('test_task_252_menus_list_normal_variant_input', () => {
|
||||||
// 正常变体:权限标识/路由不作为列表列展示(运维从对话框维护),列宽自适应;删除确认含菜单名。
|
// 正常变体:权限标识/路由不作为列表列展示,也不再出现在表单内(后台自动生成);列宽自适应;删除确认含菜单名。
|
||||||
const page = readSource('src/pages/account/MenusPage.vue')
|
const page = readSource('src/pages/account/MenusPage.vue')
|
||||||
assert.equal(/<el-table-column[^>]*prop="columnKey"/.test(page), false, '权限标识不应作为列表列')
|
assert.equal(/<el-table-column[^>]*prop="columnKey"/.test(page), false, '权限标识不应作为列表列')
|
||||||
assert.equal(/<el-table-column[^>]*prop="routePath"/.test(page), false, '路由不应作为列表列')
|
assert.equal(/<el-table-column[^>]*prop="routePath"/.test(page), false, '路由不应作为列表列')
|
||||||
assert.match(page, /menuForm\.columnKey/, '权限标识字段仍在编辑表单内')
|
assert.ok(!page.includes('menuForm.columnKey'), '权限标识输入项已从表单移除')
|
||||||
assert.match(page, /menuForm\.routePath/, '路由字段仍在编辑表单内')
|
assert.ok(!page.includes('menuForm.routePath'), '路由输入项已从表单移除')
|
||||||
assert.match(page, /确定删除菜单/, '删除确认需含“确定删除菜单”')
|
assert.match(page, /确定删除菜单/, '删除确认需含“确定删除菜单”')
|
||||||
assert.match(page, /menuDeleteReason/, '删除需过前置校验')
|
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', () => {
|
test('test_task_252_menus_list_boundary_limit_or_missing_field', () => {
|
||||||
// 边界上限:创建/编辑表单含名称/标识/父菜单/路由/排序。
|
// 边界上限:创建/编辑表单含名称/父菜单/排序(权限标识/路由后台自动生成,不在表单)。
|
||||||
const page = readSource('src/pages/account/MenusPage.vue')
|
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}`)
|
assert.ok(page.includes(field), `表单需含 ${field}`)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -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', () => {
|
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 })
|
const req = toMenuUpdateRequest({ ...emptyMenuManageForm(), name: 'n', columnKey: 'c', routePath: '/r', sortOrder: 2.7 })
|
||||||
assert.equal(req.sortOrder, 2)
|
assert.equal(req.sortOrder, 2)
|
||||||
assert.ok('menuType' in req)
|
assert.ok('menuType' in req)
|
||||||
assert.ok('routePath' in req)
|
assert.ok(!('routePath' in req), '路由由后台自动生成,不提交')
|
||||||
assert.equal(req.columnKey, 'c')
|
assert.ok(!('columnKey' in req), '权限标识由后台自动生成,不提交')
|
||||||
})
|
})
|
||||||
|
|
||||||
test('test_task_053_menu_manage_dto_invalid_input_rejected', () => {
|
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())
|
const r = validateMenuManageForm(emptyMenuManageForm())
|
||||||
assert.equal(r.valid, false)
|
assert.equal(r.valid, false)
|
||||||
assert.ok(r.errors.name)
|
assert.ok(r.errors.name)
|
||||||
assert.ok(r.errors.columnKey)
|
assert.ok(!('columnKey' in r.errors), '权限标识不参与表单校验(后台自动生成)')
|
||||||
assert.ok(r.errors.routePath)
|
assert.ok(!('routePath' in r.errors), '路由不参与表单校验(后台自动生成)')
|
||||||
assert.equal(parseMenuManageItem('garbage'), null)
|
assert.equal(parseMenuManageItem('garbage'), null)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|||||||
@@ -23,11 +23,11 @@ test('test_task_056_menu_edit_form_normal_primary_path', () => {
|
|||||||
})
|
})
|
||||||
|
|
||||||
test('test_task_056_menu_edit_form_normal_variant_input', () => {
|
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 node = parseMenuManageList([{ id: 1, name: '账号', column_key: 'account', parent_id: null, sort_order: 0 }])[0]
|
||||||
const form = menuFormFromNode(node)
|
const form = menuFormFromNode(node)
|
||||||
assert.equal(form.parentId, null)
|
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', () => {
|
test('test_task_056_menu_edit_form_normal_repeated_operation_is_idempotent', () => {
|
||||||
|
|||||||
+2
-2
@@ -10,7 +10,7 @@ public class PermissionMenuCreateRequest {
|
|||||||
@NotBlank(message = "菜单名称不能为空")
|
@NotBlank(message = "菜单名称不能为空")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@NotBlank(message = "菜单标识不能为空")
|
/** 菜单标识;不传由后台自动生成(menu_auto_<类型>_<时间戳>)。 */
|
||||||
@JsonAlias("column_key")
|
@JsonAlias("column_key")
|
||||||
private String columnKey;
|
private String columnKey;
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ public class PermissionMenuCreateRequest {
|
|||||||
@JsonAlias("menu_type")
|
@JsonAlias("menu_type")
|
||||||
private String menuType;
|
private String menuType;
|
||||||
|
|
||||||
@NotBlank(message = "菜单路由不能为空")
|
/** 页面路由;不传由后台自动生成(auto/<菜单标识>)。 */
|
||||||
@JsonAlias("route_path")
|
@JsonAlias("route_path")
|
||||||
private String routePath;
|
private String routePath;
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -10,7 +10,7 @@ public class PermissionMenuUpdateRequest {
|
|||||||
@NotBlank(message = "菜单名称不能为空")
|
@NotBlank(message = "菜单名称不能为空")
|
||||||
private String name;
|
private String name;
|
||||||
|
|
||||||
@NotBlank(message = "菜单标识不能为空")
|
/** 菜单标识;不传保持原值(表单不采集)。 */
|
||||||
@JsonAlias("column_key")
|
@JsonAlias("column_key")
|
||||||
private String columnKey;
|
private String columnKey;
|
||||||
|
|
||||||
@@ -22,7 +22,7 @@ public class PermissionMenuUpdateRequest {
|
|||||||
@JsonAlias("menu_type")
|
@JsonAlias("menu_type")
|
||||||
private String menuType;
|
private String menuType;
|
||||||
|
|
||||||
@NotBlank(message = "菜单路由不能为空")
|
/** 页面路由;不传保持原值(表单不采集)。 */
|
||||||
@JsonAlias("route_path")
|
@JsonAlias("route_path")
|
||||||
private String routePath;
|
private String routePath;
|
||||||
|
|
||||||
|
|||||||
+38
-4
@@ -74,9 +74,16 @@ public class PermissionMenuService {
|
|||||||
throw new BusinessException("菜单参数不能为空");
|
throw new BusinessException("菜单参数不能为空");
|
||||||
}
|
}
|
||||||
String name = normalizeRequired(request.getName(), "菜单名称不能为空");
|
String name = normalizeRequired(request.getName(), "菜单名称不能为空");
|
||||||
String columnKey = normalizeRequired(request.getColumnKey(), "菜单标识不能为空");
|
|
||||||
String menuType = normalizeMenuTypeRequired(request.getMenuType());
|
String menuType = normalizeMenuTypeRequired(request.getMenuType());
|
||||||
String routePath = normalizeRequired(request.getRoutePath(), "页面路径不能为空");
|
// 权限标识/路由由后台自动生成:表单不采集,缺省时生成稳定唯一值。
|
||||||
|
String columnKey = normalizeOptional(request.getColumnKey());
|
||||||
|
if (columnKey == null) {
|
||||||
|
columnKey = generateColumnKey(menuType);
|
||||||
|
}
|
||||||
|
String routePath = normalizeOptional(request.getRoutePath());
|
||||||
|
if (routePath == null) {
|
||||||
|
routePath = generateRoutePath(columnKey);
|
||||||
|
}
|
||||||
Long parentId = normalizeParentId(request.getParentId());
|
Long parentId = normalizeParentId(request.getParentId());
|
||||||
ensureParentValid(parentId, null, menuType);
|
ensureParentValid(parentId, null, menuType);
|
||||||
ensureUniqueColumnKey(columnKey, null);
|
ensureUniqueColumnKey(columnKey, null);
|
||||||
@@ -107,9 +114,16 @@ public class PermissionMenuService {
|
|||||||
throw new BusinessException("菜单参数不能为空");
|
throw new BusinessException("菜单参数不能为空");
|
||||||
}
|
}
|
||||||
String name = normalizeRequired(request.getName(), "菜单名称不能为空");
|
String name = normalizeRequired(request.getName(), "菜单名称不能为空");
|
||||||
String columnKey = normalizeRequired(request.getColumnKey(), "菜单标识不能为空");
|
|
||||||
String menuType = normalizeMenuTypeRequired(request.getMenuType());
|
String menuType = normalizeMenuTypeRequired(request.getMenuType());
|
||||||
String routePath = normalizeRequired(request.getRoutePath(), "页面路径不能为空");
|
// 编辑时未传权限标识/路由则保持原值(表单不采集,避免覆盖为自动值)。
|
||||||
|
String columnKey = normalizeOptional(request.getColumnKey());
|
||||||
|
if (columnKey == null) {
|
||||||
|
columnKey = entity.getColumnKey();
|
||||||
|
}
|
||||||
|
String routePath = normalizeOptional(request.getRoutePath());
|
||||||
|
if (routePath == null) {
|
||||||
|
routePath = entity.getRoutePath();
|
||||||
|
}
|
||||||
Long parentId = normalizeParentId(request.getParentId());
|
Long parentId = normalizeParentId(request.getParentId());
|
||||||
ensureParentValid(parentId, id, menuType);
|
ensureParentValid(parentId, id, menuType);
|
||||||
ensureMenuTypeChangeAllowed(entity, menuType);
|
ensureMenuTypeChangeAllowed(entity, menuType);
|
||||||
@@ -824,6 +838,26 @@ public class PermissionMenuService {
|
|||||||
return normalized;
|
return normalized;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** trim 后为空的返回 null(用于“后台自动生成/保持原值”的可选字段)。 */
|
||||||
|
private String normalizeOptional(String value) {
|
||||||
|
String normalized = value == null ? "" : value.trim();
|
||||||
|
return normalized.isEmpty() ? null : normalized;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 未传菜单标识时后台自动生成(menu_auto_<类型>_<毫秒时间戳>,唯一性由 ensureUniqueColumnKey 兜底)。 */
|
||||||
|
private String generateColumnKey(String menuType) {
|
||||||
|
String generated = "menu_auto_" + menuType + "_" + System.currentTimeMillis();
|
||||||
|
log.info("[menu-auto-key] 未传菜单标识,后台自动生成 columnKey={}", generated);
|
||||||
|
return generated;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** 未传页面路径时后台自动生成(auto/<菜单标识>,不与真实页面路由冲突)。 */
|
||||||
|
private String generateRoutePath(String columnKey) {
|
||||||
|
String generated = "auto/" + columnKey;
|
||||||
|
log.info("[menu-auto-key] 未传页面路径,后台自动生成 routePath={}", generated);
|
||||||
|
return generated;
|
||||||
|
}
|
||||||
|
|
||||||
private Long normalizeParentId(Long value) {
|
private Long normalizeParentId(Long value) {
|
||||||
return value == null || value <= 0 ? null : value;
|
return value == null || value <= 0 ? null : value;
|
||||||
}
|
}
|
||||||
|
|||||||
+52
@@ -672,6 +672,58 @@ class PermissionMenuServiceTest {
|
|||||||
assertThat(inserted.getValue().getMenuType()).isEqualTo("admin");
|
assertThat(inserted.getValue().getMenuType()).isEqualTo("admin");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void createWithoutColumnKeyAndRoutePathAutoGenerates() {
|
||||||
|
PermissionMenuMapper menuMapper = mock(PermissionMenuMapper.class);
|
||||||
|
UserColumnPermissionMapper permissionMapper = mock(UserColumnPermissionMapper.class);
|
||||||
|
AdminUserMapper userMapper = mock(AdminUserMapper.class);
|
||||||
|
PermissionMenuService service = new PermissionMenuService(menuMapper, permissionMapper, userMapper);
|
||||||
|
|
||||||
|
PermissionMenuEntity adminTail = menu(9L, null, "admin", 134);
|
||||||
|
adminTail.setName("admin tail");
|
||||||
|
when(menuMapper.selectOne(any())).thenReturn(null, null, adminTail);
|
||||||
|
when(menuMapper.selectById(any())).thenReturn(adminTail);
|
||||||
|
|
||||||
|
PermissionMenuCreateRequest request = new PermissionMenuCreateRequest();
|
||||||
|
request.setName("新菜单");
|
||||||
|
request.setMenuType("admin");
|
||||||
|
// 不传 columnKey / routePath:由后台自动生成。
|
||||||
|
|
||||||
|
service.create(request);
|
||||||
|
|
||||||
|
ArgumentCaptor<PermissionMenuEntity> inserted = ArgumentCaptor.forClass(PermissionMenuEntity.class);
|
||||||
|
verify(menuMapper).insert(inserted.capture());
|
||||||
|
assertThat(inserted.getValue().getColumnKey()).startsWith("menu_auto_admin_");
|
||||||
|
assertThat(inserted.getValue().getRoutePath()).startsWith("auto/").contains(inserted.getValue().getColumnKey());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void updateWithoutColumnKeyAndRoutePathKeepsOriginal() {
|
||||||
|
PermissionMenuMapper menuMapper = mock(PermissionMenuMapper.class);
|
||||||
|
UserColumnPermissionMapper permissionMapper = mock(UserColumnPermissionMapper.class);
|
||||||
|
AdminUserMapper userMapper = mock(AdminUserMapper.class);
|
||||||
|
PermissionMenuService service = new PermissionMenuService(menuMapper, permissionMapper, userMapper);
|
||||||
|
|
||||||
|
PermissionMenuEntity current = menu(1L, null, "admin", 1);
|
||||||
|
current.setName("原名");
|
||||||
|
when(menuMapper.selectById(1L)).thenReturn(current);
|
||||||
|
when(menuMapper.selectOne(any())).thenReturn(null, null, current);
|
||||||
|
when(menuMapper.selectById(any())).thenReturn(current);
|
||||||
|
|
||||||
|
PermissionMenuUpdateRequest request = new PermissionMenuUpdateRequest();
|
||||||
|
request.setName("改名");
|
||||||
|
request.setMenuType("admin");
|
||||||
|
// 不传 columnKey / routePath:保持原值。
|
||||||
|
|
||||||
|
service.update(1L, request);
|
||||||
|
|
||||||
|
ArgumentCaptor<PermissionMenuEntity> updated = ArgumentCaptor.forClass(PermissionMenuEntity.class);
|
||||||
|
verify(menuMapper).updateById(updated.capture());
|
||||||
|
assertThat(updated.getValue().getColumnKey()).isEqualTo("menu-1");
|
||||||
|
assertThat(updated.getValue().getRoutePath()).isEqualTo("route-1");
|
||||||
|
assertThat(updated.getValue().getName()).isEqualTo("改名");
|
||||||
|
}
|
||||||
|
|
||||||
private PermissionMenuCreateRequest createRequest(Long parentId, String menuType) {
|
private PermissionMenuCreateRequest createRequest(Long parentId, String menuType) {
|
||||||
PermissionMenuCreateRequest request = new PermissionMenuCreateRequest();
|
PermissionMenuCreateRequest request = new PermissionMenuCreateRequest();
|
||||||
request.setName("child");
|
request.setName("child");
|
||||||
|
|||||||
Reference in New Issue
Block a user