# Migration Guide: Old List Pages → Unified Action Pattern
## Before (Manual Pattern)
```tsx
const getCurrentPermissions = useCurrentPermissions();
let toolBarRender = (action: any) => {
return getCurrentPermissions({
export: ,
});
};
let tableRender = (item: any, action: any) => {
let permissions = getCurrentPermissions({
view: ,
update: ,
});
let permissionsSpace = getCurrentPermissions({
delete: { key: '1', label: },
});
let Others = (
);
return [...permissions, ...[Others]];
};
toolBarRender={(action) => [toolBarRender(action)]}
// ...
MyColumns.Option({
render: (_, item, index, action) => (
<>{tableRender(item, action)}>
),
})
```
## After (Unified Pattern)
```tsx
import { MyTableActions, MyToolBarActions } from '@/common';
toolBarRender={(action) => [
,
}}
/>,
]}
MyColumns.Option({
render: (_, item, index, action) => (
,
update: ,
delete: ,
}}
maxVisible={2}
/>
),
})
```
## Steps
1. Remove `useCurrentPermissions` import if it is no longer needed elsewhere.
2. Remove `toolBarRender` local function; replace `toolBarRender` prop with `MyToolBarActions`.
3. Remove `tableRender` local function and any `permissionsSpace` / `Others` / `Dropdown` boilerplate.
4. Replace `MyColumns.Option` render body with `MyTableActions`.
5. Tune `maxVisible` based on design needs (default `3`).
## Special Case: Link in Column Render
If a column (e.g., "名称") renders a clickable `AssetInfo` link that should also be permission-controlled:
```tsx
const getCurrentPermissions = useCurrentPermissions();
const hasInfo = getCurrentPermissions({ info: true }).length > 0;
{
title: '名称',
dataIndex: 'name',
render: (_, item: any) => {
if (!hasInfo) return item?.name;
return ;
},
}
```
Note: `useCurrentPermissions` may still be imported for this use case.