项目里 20+ 个页面有按钮级权限控制,每个都是 if (hasPermission('xxx')) 硬编码在 JSX 里。新增一个按钮要改代码,调整权限要发版。
我让 AI 帮我设计了一个配置驱动的权限方案,把权限逻辑从组件中抽离。然后让 AI 批量生成迁移代码------20 个页面,半天搞定。
改造前的痛点
typescript
// 到处都是这种代码
const StoreList = () => {
const { hasPermission } = useAuth()
return (
<div>
{hasPermission('store:create') && <Button>新增门店</Button>}
{hasPermission('store:edit') && <Button>编辑</Button>}
{hasPermission('store:delete') && <Button>删除</Button>}
{hasPermission('store:export') && <Button>导出</Button>}
{(hasPermission('store:online') || hasPermission('store:admin')) && (
<Button>上线</Button>
)}
</div>
)
}
问题:
vbnet
├── 权限 key 散落在 20+ 个文件里,没人知道一共有多少
├── 运营说"给角色 A 加个按钮权限" → 要改代码发版
├── 同一个权限 key 有人写 'store:create',有人写 'store_create'
├── 无法一眼看出某个角色能看到哪些按钮
└── 新人不知道该用哪个权限 key(没有统一的权限清单)
AI 设计的配置驱动方案
typescript
// permissions/store.ts --- 集中配置
export const storePermissions = {
page: 'store:view',
actions: {
create: {
key: 'store:create',
label: '新增门店',
},
edit: {
key: 'store:edit',
label: '编辑',
},
delete: {
key: 'store:delete',
label: '删除',
danger: true, // 危险操作标记
},
export: {
key: 'store:export',
label: '导出',
},
online: {
key: ['store:online', 'store:admin'], // 多权限 OR 关系
label: '上线',
},
},
}
typescript
// hooks/usePagePermissions.ts --- 通用 Hook
const usePagePermissions = (config: PermissionConfig) => {
const { hasPermission } = useAuth()
const actions = useMemo(() => {
return Object.entries(config.actions).reduce((acc, [name, action]) => {
const keys = Array.isArray(action.key) ? action.key : [action.key]
acc[name] = {
...action,
visible: keys.some(k => hasPermission(k)),
}
return acc
}, {} as Record<string, ActionPermission>)
}, [config, hasPermission])
return { actions, pageVisible: hasPermission(config.page) }
}
typescript
// 组件中使用 --- 干净很多
const StoreList = () => {
const { actions } = usePagePermissions(storePermissions)
return (
<div>
{actions.create.visible && <Button>{actions.create.label}</Button>}
{actions.edit.visible && <Button>{actions.edit.label}</Button>}
{actions.delete.visible && <Button danger>{actions.delete.label}</Button>}
{actions.export.visible && <Button>{actions.export.label}</Button>}
{actions.online.visible && <Button>{actions.online.label}</Button>}
</div>
)
}
进阶:AuthButton 组件
更进一步,封装一个权限按钮:
typescript
// components/AuthButton.tsx
const AuthButton = ({ actionConfig, ...buttonProps }: AuthButtonProps) => {
if (!actionConfig.visible) return null
return (
<Button danger={actionConfig.danger} {...buttonProps}>
{actionConfig.label}
</Button>
)
}
// 使用时
<AuthButton actionConfig={actions.create} onClick={handleCreate} />
<AuthButton actionConfig={actions.delete} onClick={handleDelete} />
AI 批量迁移的过程
我给 AI 的 Prompt:
markdown
这是我的权限配置方案(附上面的代码)。
现在请帮我迁移以下页面:
1. 读取 src/view/selfCatering/storeSetup/index.tsx
2. 找出所有 hasPermission 调用
3. 生成对应的 permissions 配置文件
4. 改写组件使用新方案
保持组件的其他逻辑不变,只替换权限相关代码。
AI 的工作流:
vbnet
Step 1: 扫描文件,提取所有 hasPermission('xxx') 调用
→ 找到 5 个权限 key
Step 2: 生成 permissions/selfCatering/storeSetup.ts
→ 结构化的权限配置
Step 3: 在组件中替换
→ 引入 usePagePermissions
→ 用 actions.xxx.visible 替换 hasPermission('xxx')
→ 删除 useAuth 导入(如果不再需要)
Step 4: 验证
→ 确保 import 路径正确
→ 确保没有遗漏的 hasPermission
20 个页面,每个页面 AI 处理 2-3 分钟,总共半天完成。
迁移后的收益
vbnet
改造前 改造后
────── ──────
权限散落 20+ 文件 集中在 permissions/ 目录
无法枚举所有权限 一目了然
改权限要发版 理论上可以做成后台配置
新人不知道用啥 key 看配置文件就行
权限 key 拼写不一致 TypeScript 类型约束
全局权限清单(自动生成)
配置集中后,可以自动生成权限清单:
typescript
// scripts/generatePermissionList.ts
import * as configs from '@/permissions'
const allPermissions = Object.entries(configs).flatMap(([module, config]) =>
Object.values(config.actions).map(action => ({
module,
key: action.key,
label: action.label,
}))
)
// 输出:
// [
// { module: 'store', key: 'store:create', label: '新增门店' },
// { module: 'store', key: 'store:edit', label: '编辑' },
// ...
// ]
这个清单可以给后端做权限管理界面的数据源。
AI 在这类"批量迁移"中的价值
matlab
人工做:
├── 理解新方案:30min
├── 每个页面迁移:20min × 20 = 400min
├── 检查遗漏:60min
├── 总计:约 8h(1 整天)
AI 辅助:
├── 设计方案(AI + 人):1h
├── 每个页面迁移(AI 执行、人审查):5min × 20 = 100min
├── 修正 AI 的少量错误:30min
├── 总计:约 3.5h(半天)
节省:~55% 时间
核心原因:这类迁移是模式固定、重复度高的工作,正好是 AI 擅长的。
💬 你们项目的权限控制是什么方案?有没有遇到"权限散落各处"的问题?
🔗 完整 Skills 源码已开源 :github.com/sleepyccat/...,欢迎 Star ⭐ 和 PR。