public-components-skill
npx skills add https://github.com/mahailiang999-creator/public-components-skill --skill public-components-skill
Agent 安装分布
Skill 文档
Public Components Library Skill
è¿æ¯ä¸ä¸ªä¸ä¸ºå端å¼å设计ç AI æè½ï¼ä¸é¨ç¨äºçè§£åä½¿ç¨ @arim-aisdc/public-components ç»ä»¶åºã该æè½æ¶µçäºç»ä»¶åºçæææ ¸å¿åè½ãä½¿ç¨æ¨¡å¼ã主é¢é
ç½®åæä½³å®è·µã
When to use
èªå¨è§¦åæ¡ä»¶ï¼ å½ç¨æ·æå°ä»¥ä¸ä»»ä½å ³é®è¯æ¶ï¼AI åºèªå¨å è½½æ¤æè½ï¼
æ ¸å¿ç»ä»¶å ³é®è¯
@arim-aisdc/public-components– ç»ä»¶åºå åTableMax– é«çº§è¡¨æ ¼ç»ä»¶ConfigProvider– å ¨å±é ç½®æä¾èPermissionProviderãRestrictedãPermissionContext– æéæ§å¶ThemeProvider– 䏻颿ä¾èCustomForm– èªå®ä¹è¡¨åQueryFilter– æ¥è¯¢çéå¨SchemaForm– Schema驱å¨è¡¨åBaseInfo– åºç¡ä¿¡æ¯å±ç¤ºCenterModal– å± ä¸å¼¹çªDrawerCom– æ½å±ç»ä»¶SplitPaneãSplitterPane– åå²é¢æ¿CacheTabs– ç¼åæ ç¾é¡µDraggableBox– 坿æ½çåEmpty– ç©ºç¶æç»ä»¶Icon– 徿 ç»ä»¶ColorSelector– é¢è²éæ©å¨MessageTipãModalTip– å ¨å±æç¤ºMicroComponent– å¾®ç»ä»¶
Filter ç»ä»¶ç³»å
FilterSelect– éæ©å¨çéFilterInputNumber– æ°å¼çéFilterSlider– æ»åçéFilterSwitch– å¼å ³çéFilterColor– é¢è²çéFilterRadio– åéçéConditionExpression– æ¡ä»¶è¡¨è¾¾å¼
Hooks å ³é®è¯
useTranslation– å½é åç¿»è¯useEventBus– äºä»¶æ»çº¿usePageCacheState– 页é¢ç¼åç¶æuseCenterModalState– å¼¹çªç¶æç®¡çuseConfig– é ç½®è·å
å½é åå ³é®è¯
public_zhCN– 䏿è¯è¨åpublic_enUS– è±æè¯è¨åpublic_viVN– è¶åæè¯è¨å
ç±»ååæä¸¾å ³é®è¯
TableMaxPropsãTableMaxColumnType– è¡¨æ ¼ç±»åFilterTypeãInputType– çéåè¾å ¥ç±»åCustomFormItemType– 表å项类åColumnVisibleConfigTypeãColumnPinningConfigType– åé 置类åProFieldValueTypeEnumãDataSourceTypeEnum– Schema表åç±»å
æå¨ä½¿ç¨åºæ¯ï¼ å½ç¨æ·éè¦ï¼
- ä½¿ç¨ @arim-aisdc/public-components ç»ä»¶åºå¼åå端åºç¨
- é ç½® TableMax é«çº§è¡¨æ ¼ï¼å页ãçéãæåºãç¼è¾ã导åºçï¼
- æå»ºå¤æè¡¨åï¼CustomFormãQueryFilterãSchemaFormï¼
- 设置主é¢ãæéãå½é åçå ¨å±é ç½®
- å®ç°ææ½ãåå²é¢æ¿ç交äºåè½
- å¤çæéæ§å¶åæ¡ä»¶æ¸²æ
- è§£å³ç»ä»¶åºä½¿ç¨ä¸ç常è§é®é¢
- å®ç°è¡¨æ ¼ CRUD æä½ãèææ»å¨ãè¡ææ½çé«çº§åè½
- èªå®ä¹ä¸»é¢åéåæ ·å¼
- å®ç°å¤è¯è¨å½é å
Instructions
æ ¸å¿ç»ä»¶è½å
1. TableMax é«çº§è¡¨æ ¼ç»ä»¶
è¿æ¯ç»ä»¶åºçæ ¸å¿ç»ä»¶ï¼åºäº TanStack React Table æå»ºï¼åè½æå ¶å¼ºå¤§ï¼
æ ¸å¿ç¹æ§:
- æ°æ®ç®¡ç: æ¯æå端/å端å页ãæåºãçé
- 交äºåè½: è¡éæ©ãè¡ææ½ãåææ½ãè¡ç¼è¾
- å±ç¤ºä¼å: èæå表ãååºå®ãåå®½è°æ´ãç´§åæ¨¡å¼
- æ°æ®æä½: å¯¼åº Excelãä¸ä¼ æ°æ®ãå·æ°ãå é¤
- ç¼åæºå¶: èªå¨ç¼åç¨æ·çå设置ãç鿡件ãæåºç¶æ
宿´ API åæ°:
<TableMax
// åºç¡é
ç½®
tableId="unique-table-id" // ãå¿
é¡»ãç¨äºç¼åï¼å¿
é¡»å¯ä¸
columns={columns} // ãå¿
é¡»ãåé
ç½®
datas={data} // ãå¿
é¡»ãè¡¨æ ¼æ°æ®
// å页é
ç½®
totalCount={1000} // æ°æ®æ»æ¡æ°
pageSize={20} // æ¯é¡µæ¡æ°
skipCount={0} // æ°æ®ä»ç¬¬å æ¡å¼å§
showSizeChanger={true} // æ¯å¦æ¾ç¤ºæ¯é¡µæ¡æ°éæ©å¨
changePagination={handlePagination} // å页åååè°
pageSizeOptions={[10, 20, 50, 100]} // èªå®ä¹æ¯é¡µæ¡æ°é项
showLessItems={false} // 翻页ç»ä»¶æ¾ç¤ºè¾å°é¡µç
// åé
ç½®
columnVisibleConfig={{ name: true }} // æ§å¶åæ¾ç¤ºéè
columnPinningConfig={{
// ååºå®é
ç½®
left: ['selection', 'name'],
right: ['actions'],
}}
disableColumnDrag={false} // ç¦æ¢åææ½
columnResizeMode="onEnd" // åå®½è°æ´æ¶æº: "onEnd" | "onChange"
// éæ©åè½
canSelection={true} // æ¯å¦æ¯æå¤é
defaultSelectedRowIds={[1, 2]} // é»è®¤éä¸çè¡IDæ°ç»
defaultSelectedRowId="1" // é»è®¤éä¸çè¡IDï¼åéï¼
selectionWithoutChecked={false} // å¤é䏿¾ç¤ºå¾éæ¡
canSelectionUseShift={true} // æ¯å¦æ¯æShiftå¤é
enableRowSelection={true} // è¡æ¯å¦å¯é
selectRowWhenClick={true} // ç¹å»è¡æ¶æ¯å¦éä¸
onRowCheckboxClick={handleRowCheckboxClick} // è¡checkboxç¹å»åè°
onSelectChange={handleSelectChange} // è¡éæ©åååè°
rowSelectionChange={handleRowSelectionChange} // è¡å¤éåååè°
selectedRowChange={handleSelectedRowChange} // ãå·²åºå¼ãè¡åéåè°
onSelectAllChange={handleSelectAllChange} // å
¨éåè°
// ææ½åè½
canRowDrag={true} // æ¯å¦æ¯æè¡ææ½
disableDragRowIds={[1, 2]} // ç¦æ¢ææ½çè¡ID
dragBeforeStart={() => true} // ææ½å¼å§ååè°
dragBeforeEnd={dragValidator} // ææ½ç»æåéªè¯
rowOrderChange={handleRowOrderChange} // è¡ææ½é¡ºåºåååè°
// çéåè½
canFilter={true} // æ¯å¦æ¯æçé
defaultEnableFilters={false} // é»è®¤æ¯å¦å¼å¯çé
defaultColumnFilters={[]} // é»è®¤ç鿡件
manualFiltering={false} // æ¯å¦å端çé
onFilteringChange={handleFilteringChange} // çéåååè°ï¼æ¨èï¼
manualFilteringChange={manualFilterHandler} // ãå·²åºå¼ãå端çéåè°
getColumnFiltersData={getFilterData} // ãå·²åºå¼ãçéåæ°åååè°
getDynamicFilterOptionsFn={getDynamicOptions} // 卿çéé项è·å彿°
openNullValueFilter={true} // å¼å¯ç©ºå¼è¿æ»¤
// æåºåè½
canSorting={true} // æ¯å¦æ¯ææåº
enableMultiSort={false} // æ¯å¦æ¯æå¤åæåº
manualSorting={false} // æ¯å¦å端æåº
onSortingChange={handleSortingChange} // æåºåååè°ï¼æ¨èï¼
manualSortingChange={manualSortHandler} // ãå·²åºå¼ãå端æåºåè°
// ç¼è¾åè½
canEditting={true} // æ¯å¦æ¯æç¼è¾
canEditRowWhenDClick={false} // æ¯å¦åå»è¡è¿å
¥ç¼è¾
saveEditing={handleSaveEditing} // ä¿åç¼è¾å
容åè°
onEditValueChange={handleEditValueChange} // ç¼è¾å¼åååè°
// å±ç¤ºé
ç½®
rowHeight={42} // è¡é«åº¦
defaultHeaderRowNum={1} // 表头é»è®¤è¡æ°
defaultCompactMode={false} // æ¯å¦é»è®¤ç´§å模å¼
canCompact={true} // æ¯å¦æ¾ç¤ºç´§åæ¨¡å¼æé®
enableVirtualList={false} // æ¯å¦å¼å¯èæå表
openVirtualColumns={false} // å¼å¯èæå
openVirtualRows={false} // å¼å¯èæè¡
autoHeight={false} // é«åº¦æ¯å¦èªå¨å 满ç¶çº§
tooltip={true} // åå
æ ¼æ¯å¦æ¾ç¤ºtooltip
// æ°æ®æä½
canRefresh={true} // æ¯å¦æ¾ç¤ºå·æ°æé®
refreshFun={handleRefresh} // å·æ°åè°
canUpload={false} // æ¯å¦æ¾ç¤ºä¸ä¼ æé®
uploadProps={{}} // ä¸ä¼ ç»ä»¶å±æ§
canDownload={false} // æ¯å¦æ¾ç¤ºä¸è½½æé®
downloadProps={{}} // ä¸è½½é
ç½®
canDelete={false} // æ¯å¦æ¾ç¤ºå 餿é®
deleteFun={handleDelete} // å é¤åè°
canExport={false} // æ¯å¦å¯¼åºè¡¨æ ¼æ°æ®
exportConfig={{}} // 导åºé
ç½®
request={customRequest} // èªå®ä¹è¯·æ±å½æ°ï¼ç¨äºä¸è½½ï¼
// ç¼åé
ç½®
version="1.0.0" // ç¼åçæ¬
openMemo={true} // æ¯å¦å¼å¯memoç¼å
// æ»è®¡è¡
hasTotalRow={false} // æ¯å¦ææ»è®¡è¡
totalDatas={[]} // æ»è®¡è¡æ°æ®
// åºå·å
openIndexColumn={false} // å¼å¯åºå·å
// èªå®ä¹æ¸²æ
renderOperate={customRender} // èªå®ä¹è¡¨æ ¼é¡¶é¨ææå
容
tableTitle="è¡¨æ ¼æ é¢" // è¡¨æ ¼é¡¶é¨å·¦ä¾§æ é¢
renderOperateLeft={customLeftRender} // èªå®ä¹è¡¨æ ¼é¡¶é¨å·¦ä¾§å
容
renderOperateRight={customRightRender} // èªå®ä¹è¡¨æ ¼é¡¶é¨å³ä¾§å
容
renderSubComponent={subComponentRender} // å表渲æç»ä»¶
getRowCanExpand={() => true} // è¡æ¯å¦å¯å±å¼
// æ ·å¼é
ç½®
rowClassName={rowClassGetter} // è¡ç±»å彿°
cellClassName={cellClassGetter} // åå
æ ¼ç±»å彿°
rowStyle={{}} // è¡å
æ ·å¼
getCellProps={cellPropsGetter} // åå
æ ¼å±æ§è·å彿°
getHeaderCellProps={headerPropsGetter} // 表头åå
æ ¼å±æ§è·å彿°
// äºä»¶å¤ç
onRowMouseEnter={handleRowMouseEnter} // é¼ æ è¿å
¥è¡äºä»¶
onRowMouseLeave={handleRowMouseLeave} // é¼ æ 离å¼è¡äºä»¶
onRowMouseClick={handleRowMouseClick} // é¼ æ ç¹å»è¡äºä»¶
onRowMouseDoubleClick={handleRowDblClick} // é¼ æ åå»è¡äºä»¶
getContextMenu={getContextMenu} // è·åå³é®èå
onClickContextMenu={handleContextMenuClick} // ç¹å»èåé项
getRowHoverTipConfig={getHoverTip} // è·åè¡hoveræç¤ºé
ç½®
// å
¶ä»é
ç½®
rowKey="id" // è¡å¯ä¸æ è¯å段
canSetting={true} // æ¯å¦æ¾ç¤ºè®¾ç½®æé®
loading={false} // å è½½ç¶æ
defaultHighLightRowId="1" // é»è®¤é«äº®è¡ID
// ãå·²åºå¼ã屿§
theme="light" // ãå·²åºå¼ã主é¢
defaultScrollY={600} // ãå·²åºå¼ãè¡¨æ ¼å
容åºé«åº¦
emptyDataHeight={300} // ãå·²åºå¼ãç©ºæ°æ®é«åº¦
/>
宿´åé ç½®åæ°:
const columns: TableMaxColumnType[] = [
{
// åºç¡é
ç½®
id: 'name', // ãå¿
é¡»ãåå¯ä¸æ è¯
header: 'å§å', // è¡¨å¤´ææ¡ææ¸²æå½æ°
accessorKey: 'name', // æ°æ®å段å
accessorFn: (row, index) => row.name, // èªå®ä¹åå¼å½æ°
size: 120, // å宽度
parent: false, // æ¯å¦ä¸ºç¶åï¼åç»ï¼
child: false, // æ¯å¦ä¸ºåå
columns: [], // ååé
ç½®ï¼åç»ç¨ï¼
// çéé
ç½®
filterType: FilterType.Input, // çéç»ä»¶ç±»å
filterOptions: [
// çéå¯éå¼
{ label: 'é项1', value: '1' },
{ label: 'é项2', value: '2' },
],
filterKey: 'customFilterKey', // èªå®ä¹çéå¼key
enableColumnFilter: true, // æ¯å¦å¯çé
filterFn: customFilterFunction, // èªå®ä¹çé彿°
filterComProps: {
// çéç»ä»¶å±æ§é
ç½®
showTime: true, // æ¶é´ç鿝妿¾ç¤ºæ¶åç§
format: 'YYYY-MM-DD', // æ¶é´æ ¼å¼
picker: 'date', // æ¶é´éæ©å¨ç±»å
rangePresets: [
// æ¶é´å¿«æ·é项
{ label: 'æè¿7天', value: [dayjs().subtract(7, 'day'), dayjs()] },
],
},
dynamicFilterOptionsLabelField: 'name', // 卿é项æ ç¾å段
dynamicFilterOptionsValueField: 'id', // 卿é项å¼å段
dynamicFilterOptionsLabelFn: option => option.name, // 卿é项æ ç¾å½æ°
getFilterOptionsFn: getFilterOptions, // 卿è·åçéé项
isFilterOptionsFrontSearch: false, // çéé项æ¯å¦å端æç´¢
// ç¼è¾é
ç½®
editable: true, // æ¯å¦å¯ç¼è¾
editComType: InputType.Input, // ç¼è¾ç»ä»¶ç±»å
editOptions: [
// ç¼è¾é项ï¼selectç¨ï¼
{ label: 'é项1', value: '1' },
{ label: 'é项2', value: '2' },
],
getEditOptionsFn: getEditOptions, // 卿è·åç¼è¾é项
editComDisabled: false, // ç¼è¾ç»ä»¶æ¯å¦ç¦ç¨
required: true, // ç¼è¾æ¶æ¯å¦å¿
å¡«
unitsChangeFn: value => value, // åä½è½¬æ¢å½æ°
// æåºé
ç½®
enableSorting: true, // æ¯å¦å¯æåº
sortingFn: customSortFunction, // èªå®ä¹æåºå½æ°
sortUndefined: false, // undefinedå¼å¤çæ¹å¼
sortingKey: 'customSortKey', // èªå®ä¹æåºkey
// æ ·å¼é
ç½®
tooltip: true, // æ¯å¦æ¾ç¤ºtooltip
ellipsis: false, // ãå·²åºå¼ãæ¯å¦çç¥æ¾ç¤º
columnClassName: ['custom-col'], // åç±»å
enableResizing: true, // æ¯å¦å¯è°æ´å宽
// å
æ°æ®é
ç½®
meta: {
isDate: true, // æ¯å¦ä¸ºæ¥æå段
dateFormat: 'YYYY-MM-DD', // æ¥ææ ¼å¼
},
// å
¶ä»é
ç½®
openMemo: true, // æ¯å¦ç¼ååå
æ ¼
disabledExport: false, // æ¯å¦ç¦æ¢å¯¼åº
exportValueFormat: value => formatValue(value), // 导åºå¼æ ¼å¼å彿°
},
];
åé 置模å¼:
const columns: TableMaxColumnType[] = [
{
id: 'name',
header: 'å§å',
accessorKey: 'name',
size: 120,
enableSorting: true,
enableColumnFilter: true,
filterType: FilterType.Input, // çéç»ä»¶ç±»å
editable: true, // å¯ç¼è¾
editComType: InputType.Input, // ç¼è¾ç»ä»¶ç±»å
tooltip: true, // æ¾ç¤ºtooltip
},
];
2. ConfigProvider å ¨å±é ç½®
æä¾å ¨å±é ç½®è½åï¼æ¯ä½¿ç¨ç»ä»¶åºçåºç¡ï¼
<ConfigProvider
config={{
// åºç¡é
ç½®
theme: 'dark', // 主é¢ï¼'light' | 'dark'
userId: 'user123', // ç¨æ·IDï¼ç¨äºç¼åé离
tableKeyPrefixCls: 'my-app', // è¡¨æ ¼ç¼ååç¼ï¼é»è®¤'TableMax'
locale: public_zhCN, // å½é
åè¯è¨é
ç½®
dateFormat: 'YYYY-MM-DD HH:mm', // æ¥ææ ¼å¼
// 主é¢é
ç½®
themePackageName: 'DefaultThemePackage', // 主é¢å
åç§°
variablesJson: {
// 主é¢åéé
ç½®
'--global-primary-color': '#1890ff',
'--table-row-hover-bgc': '#f0f0f0',
},
autoSetCssVars: true, // æ¯å¦èªå¨è®¾ç½®CSSåé
root: '#root', // é¡¹ç®æ ¹èç¹éæ©å¨
getRootContainer: () => document.getElementById('root'), // è·åæ ¹å®¹å¨å½æ°
// TableMax å
¨å±é
ç½®
tableMax: {
canExport: true, // å
¨å±å¯¼åºæé
pageSizeOptions: [10, 20, 50, 100], // å
¨å±å页é项
cacheMaxAge: 3600000, // ç¼åè¿ææ¶é´ï¼æ¯«ç§ï¼
openMemo: true, // æ¯å¦å¼å¯memoç¼å
canSelectionUseShift: true, // Shiftå¤é
openNullValueFilter: true, // 空å¼è¿æ»¤
openIndexColumn: false, // åºå·å
},
tableMaxNewPagination: false, // æ¯å¦ä½¿ç¨æ°ç¿»é¡µç»ä»¶
// èªå®ä¹é
ç½®
renderEmpty: theme => <CustomEmpty theme={theme} />, // èªå®ä¹ç©ºç¶æç»ä»¶
request: customRequest, // èªå®ä¹è¯·æ±å½æ°ï¼ç¨äºä¸è½½çï¼
// KeepAlive é
ç½®
keepAliveActivateKey: 1, // æ¿æ´»key
keepAliveUnactivateKey: 2, // éæ¿æ´»key
}}
>
<App />
</ConfigProvider>
é»è®¤é ç½®å¼ï¼
const DEFAULT_CONTEXT = {
theme: 'light',
userId: '',
tableKeyPrefixCls: 'TableMax',
locale: public_zhCN,
dateFormat: 'YYYY-MM-DD HH:mm',
};
3. Permission æéæ§å¶
æä¾ç»ç²åº¦çæéæ§å¶è½åï¼
// æéæä¾è
<PermissionProvider
permissions={['user:read', 'user:write', 'admin']}
>
<App />
</PermissionProvider>
// æééå¶ç»ä»¶
<Restricted
permissions={['user:write']} // éè¦çæéå表
fallback={<NoPermission />} // æ æéæ¶çfallbackç»ä»¶ï¼å¯éï¼
>
<Button>ç¼è¾ç¨æ·</Button>
</Restricted>
// 使ç¨Contextç´æ¥è®¿é®
import { PermissionContext } from '@arim-aisdc/public-components';
const { hasPermission, permissions, currentUser } = useContext(PermissionContext);
// æ£æ¥æé
if (hasPermission('user:write')) {
// ææéæ¶çæä½
}
// æ£æ¥å¤ä¸ªæé
if (hasPermission(['user:read', 'user:write'])) {
// ææææéæ¶çæä½
}
æéç±»åå®ä¹ï¼
type Permission = string;
// å¸¸è§æéæ¨¡å¼
('user:read'); // ç¨æ·è¯»åæé
('user:write'); // ç¨æ·åå
¥æé
('user:delete'); // ç¨æ·å 餿é
('admin:system'); // ç³»ç»ç®¡çæé
('data:export'); // æ°æ®å¯¼åºæé
4. Filter ç»ä»¶ç³»å
æä¾åç§çéç»ä»¶ï¼ç¨äºè¡¨æ ¼çéæè¡¨åçéï¼
// éæ©å¨çé
<FilterSelect
value={value} // å½åå¼
onChange={setValue} // å¼åååè°
options={[ // é项å表
{ label: 'é项1', value: '1' },
{ label: 'é项2', value: '2' }
]}
placeholder="è¯·éæ©" // placeholder
allowClear={true} // æ¯å¦å¯æ¸
é¤
showSearch={true} // æ¯å¦æ¯ææç´¢
mode="multiple" // å¤é模å¼
maxTagCount={3} // æå¤æ¾ç¤ºtagæ°é
/>
// æ°å¼èå´çé
<FilterInputNumber
value={value} // å½åå¼ï¼å弿æ°ç»ï¼
onChange={setValue} // å¼åååè°
min={0} // æå°å¼
max={100} // æå¤§å¼
step={1} // æ¥é¿
precision={2} // ä¿çå°æ°ä½æ°
placeholder="请è¾å
¥æ°å¼" // placeholder
isShowInterval={true} // æ¯å¦æ¾ç¤ºä¸ºåºé´è¾å
¥
suffix="å
" // åç¼åä½
/>
// æ»åçé
<FilterSlider
value={value} // å½åå¼
onChange={setValue} // å¼åååè°
range={[0, 100]} // æ»åèå´
min={0} // æå°å¼
max={100} // æå¤§å¼
step={1} // æ¥é¿
marks={{ // å»åº¦æ è®°
0: '0%',
50: '50%',
100: '100%'
}}
tooltipVisible={true} // æ¯å¦æ¾ç¤ºtooltip
/>
// å¼å
³çé
<FilterSwitch
value={value} // å½åå¼
onChange={setValue} // å¼åååè°
checkedChildren="å¼å¯" // é䏿¶æå
unCheckedChildren="å
³é" // æªé䏿¶æå
disabled={false} // æ¯å¦ç¦ç¨
/>
// é¢è²çé
<FilterColor
value={value} // å½åå¼
onChange={setValue} // å¼åååè°
showText={true} // æ¯å¦æ¾ç¤ºæå
allowClear={true} // æ¯å¦å¯æ¸
é¤
presets={[ // é¢è®¾é¢è²
{ label: '红è²', value: '#ff0000' },
{ label: 'èè²', value: '#0000ff' }
]}
/>
// åéçé
<FilterRadio
value={value} // å½åå¼
onChange={setValue} // å¼åååè°
options={[ // é项å表
{ label: 'é项1', value: '1' },
{ label: 'é项2', value: '2' }
]}
optionType="button" // é项类åï¼'default' | 'button'
disabled={false} // æ¯å¦ç¦ç¨
/>
çéç»ä»¶éç¨å±æ§ï¼
// ææçéç»ä»¶é½æ¯æç屿§
interface FilterComponentProps {
value: any; // å½åå¼
onChange: (value: any) => void; // å¼åååè°
placeholder?: string; // placeholder
disabled?: boolean; // æ¯å¦ç¦ç¨
allowClear?: boolean; // æ¯å¦å¯æ¸
é¤
className?: string; // èªå®ä¹ç±»å
style?: React.CSSProperties; // èªå®ä¹æ ·å¼
}
5. ConditionExpression æ¡ä»¶è¡¨è¾¾å¼
ç¨äºæå»ºå¤æçæ¥è¯¢æ¡ä»¶ï¼æ¯æå¤æ¡ä»¶ç»ååå¤åç»ï¼
<ConditionExpression
value={conditions} // æ¡ä»¶è¡¨è¾¾å¼å¼
onChange={setConditions} // å¼åååè°
showParameter={true} // æ¯å¦æ¾ç¤ºåæ°éæ©æ¡
parameterOptions={[
// åæ°é项
{ label: 'å§å', value: 'name' },
{ label: 'å¹´é¾', value: 'age' },
{ label: 'å建æ¶é´', value: 'createTime' },
]}
labelInValue={false} // SelectçlabelInValue屿§
canFrontFilter={true} // æ¯å¦æ¯æå端çé
frontendFilterOptionFun={(input, option) => {
// èªå®ä¹å端çé彿°
return option.label.toLowerCase().includes(input.toLowerCase());
}}
/>
æ°æ®ç»æå®ä¹ï¼
// æ¡ä»¶é¡¹ç±»å
type conditionItemType = {
arguments?: any; // åæ°å¼
operator?: any; // æä½ç¬¦ï¼'=', '!=', '>', '>=', '<', '<=', 'Between', 'In'ç
argumentsValue?: any; // åæ°å
·ä½å¼
logicOperator?: string | null; // é»è¾æä½ç¬¦ï¼'and', 'or', null
};
// æ¡ä»¶è¡¨è¾¾å¼é¡¹ç±»å
type conditionExpressionItemType = {
conditionItem: conditionItemType[]; // æ¡ä»¶é¡¹æ°ç»
logicOperator?: string | null; // ä¸ä¸ä¸ç»çè¿æ¥ç¬¦ï¼'and', 'or', null
};
// ç»ä»¶Propsç±»å
type ConditionExpressionPropsType = {
value?: conditionExpressionItemType[]; // ç»ä»¶çå¼
onChange?: (value: conditionExpressionItemType[]) => void; // å¼åååè°
showParameter?: boolean; // 第ä¸ä¸ªåæ°æ¯å¦å±ç¤º
parameterOptions?: { label: any; value: any }[]; // åæ°é项
labelInValue?: boolean; // SelectçlabelInValue屿§
canFrontFilter?: boolean; // æ¯å¦æ¯æå端çé
frontendFilterOptionFun?: (input: any, option: any) => boolean; // å端çé彿°
};
// é»è®¤å¼ç»æ
const defaultConditions = [
{
conditionItem: [
{
arguments: null,
operator: '=',
argumentsValue: null,
logicOperator: null,
},
],
logicOperator: null,
},
];
æä½ç¬¦è¯´æï¼
const operatorOptions = [
{ label: '=', value: '=' },
{ label: '!=', value: '!=' },
{ label: '>', value: '>' },
{ label: '>=', value: '>=' },
{ label: '<', value: '<' },
{ label: '<=', value: '<=' },
{ label: 'å¨...ä¹é´', value: 'Between' }, // éè¦ä¸¤ä¸ªå¼ï¼ç¨éå·åé
{ label: 'ä¸å¨...ä¹é´', value: 'NotBetween' },
{ label: 'å
å«', value: 'In' }, // éè¦å¤ä¸ªå¼ï¼ç¨éå·åé
{ label: 'ä¸å
å«', value: 'NotIn' },
];
// ç¹æ®æä½ç¬¦æç¤º
const tooltipList = ['Between', 'NotBetween', 'In', 'NotIn'];
const tooltipTitle = '请使ç¨éå·éå¼å¤ä¸ªåæ°å¼ï¼å¦ï¼1,2';
6. ThemeProvider 主é¢ç³»ç»
æ¯æææä¸»é¢åæ¢åèªå®ä¹ä¸»é¢åéï¼
<ThemeProvider
theme="dark" // 主é¢ç±»åï¼'light' | 'dark'
variablesConfig={{
// èªå®ä¹ä¸»é¢åé
'--global-primary-color': '#1890ff',
'--global-default-text-color': '#ffffff',
'--table-row-hover-bgc': '#f0f0f0',
'--global-curd-input-background-color': '#494c5d',
}}
>
<App />
</ThemeProvider>
主é¢ç±»åå®ä¹ï¼
type ThemeType = 'light' | 'dark';
type VariablesConfigType = {
[key: string]: string | number; // CSSåéé®å¼å¯¹
};
type ThemeProviderPropsType = {
theme: ThemeType; // 主é¢ç±»å
variablesConfig?: VariablesConfigType; // èªå®ä¹ä¸»é¢åéé
ç½®
children?: ReactNode; // åç»ä»¶
};
å 置主é¢åéï¼
/* 主è¦é¢è²åé */
--global-primary-color /* å
¨å±ä¸»è² */
--global-curd-input-background-color /* è¾å
¥æ¡èæ¯è² */
--global-desc-text-disabled-color /* ç¦ç¨æåé¢è² */
--scrollThumb /* æ»å¨æ¡é¢è² */
--rowHoverBackgroundColor /* è¡hoverèæ¯è² */
/* è¡¨æ ¼é¢è²åé */
--tableColor1 /* è¡¨æ ¼åä½é¢è² */
--tableColor2 /* è¡¨æ ¼è¾¹æ¡é¢è² */
--tableColor3 /* è¡¨æ ¼è¾¹æ¡é¢è² */
--selectTableRow /* éä¸è¡é¢è² */
--tableTooltipBgc /* è¡¨æ ¼tooltipèæ¯è² */
/* å¸å±é¢è²åé */
--globalColor0 ~ globalColor17 /* å¸å±é¢è²ç³»å */
--splite-line /* åå²çº¿é¢è² */
--global-tip-text-color /* æç¤ºæåé¢è² */
7. Empty ç©ºç¶æç»ä»¶
ç¨äºæ¾ç¤ºç©ºæ°æ®ç¶æï¼
<Empty
emptyDarkImage={customDarkImage} // èªå®ä¹æè²ä¸»é¢ç©ºç¶æå¾ç
emptyLightImage={customLightImage} // èªå®ä¹äº®è²ä¸»é¢ç©ºç¶æå¾ç
text="ææ æ°æ®" // èªå®ä¹ææ¬
/>
// 使ç¨ConfigProviderçé»è®¤ç©ºç¶æ
<Empty />
8. SchemaForm Schema驱å¨è¡¨å
åºäº ProComponents ç Schema 驱å¨è¡¨åï¼æ¯æå¨æè¡¨åé ç½®åå¤ç§æ°æ®æºã
import { SchemaForm, ProFieldValueTypeEnum, DataSourceTypeEnum } from '@arim-aisdc/public-components';
<SchemaForm
layoutType="ModalForm" // å¸å±ç±»åï¼'ModalForm' | 'DrawerForm' | 'Form'
title="åå»ºç¨æ·" // è¡¨åæ é¢
open={visible} // æ¯å¦æ¾ç¤º
onOpenChange={setVisible} // æ¾ç¤ºç¶æåååè°
columns={[ // 表ååé
ç½®
{
title: 'ç¨æ·å',
dataIndex: 'username',
valueType: ProFieldValueTypeEnum.Text, // åæ®µç±»å
formItemProps: {
rules: [{ required: true, message: '请è¾å
¥ç¨æ·å' }],
},
},
{
title: 'è§è²',
dataIndex: 'role',
valueType: ProFieldValueTypeEnum.Select,
dataSourceType: DataSourceTypeEnum.Remote, // æ°æ®æºç±»å
request: async () => { // è¿ç¨æ°æ®è¯·æ±
const roles = await fetchRoles();
return roles.map(r => ({ label: r.name, value: r.id }));
},
},
]}
onFinish={async (values) => { // æäº¤åè°
await createUser(values);
return true;
}}
/>
ProFieldValueTypeEnum åæ®µç±»åï¼
- Text – ææ¬è¾å ¥
- Select – 䏿鿩
- Radio – åé
- Checkbox – å¤é
- DatePicker – æ¥æéæ©
- DateTimePicker – æ¥ææ¶é´éæ©
- DateRangePicker – æ¥æèå´
- TextArea – ææ¬å
- Digit – æ°åè¾å ¥
- Money – éé¢è¾å ¥
- Password – å¯ç è¾å ¥
- Switch – å¼å ³
DataSourceTypeEnum æ°æ®æºç±»åï¼
- Static – éææ°æ®
- Remote – è¿ç¨æ°æ®
9. å ¶ä»æ ¸å¿ç»ä»¶
// CenterModal å±
ä¸å¼¹çªï¼æ¯æææ½åè°æ´å¤§å°ï¼
<CenterModal
visible={visible} // æ¯å¦æ¾ç¤º
title="æ é¢" // å¼¹çªæ é¢
onOk={handleOk} // 确认åè°
onCancel={handleCancel} // åæ¶åè°
okText="确认" // 确认æé®æå
cancelText="åæ¶" // åæ¶æé®æå
width={520} // å¼¹çªå®½åº¦
maskClosable={false} // ç¹å»é®ç½©æ¯å¦å
³é
destroyOnClose={true} // å
³éæ¶éæ¯
draggable={true} // æ¯å¦å¯ææ½
resizable={true} // æ¯å¦å¯è°æ´å¤§å°
/>
// Drawer æ½å±ç»ä»¶
<DrawerCom
visible={visible} // æ¯å¦æ¾ç¤º
title="æ é¢" // æ½å±æ é¢
placement="right" // ä½ç½®ï¼'left' | 'right' | 'top' | 'bottom'
onClose={handleClose} // å
³éåè°
width={300} // 宽度ï¼left/rightæ¶ï¼
height={300} // é«åº¦ï¼top/bottomæ¶ï¼
mask={true} // æ¯å¦æ¾ç¤ºé®ç½©
maskClosable={false} // ç¹å»é®ç½©æ¯å¦å
³é
/>
// SplitPane åå²é¢æ¿
<SplitPane
defaultSize="50%" // é»è®¤å°ºå¯¸
minSize="10%" // æå°å°ºå¯¸
maxSize="90%" // æå¤§å°ºå¯¸
split="vertical" // å岿¹åï¼'vertical' | 'horizontal'
onDragFinished={handleResize} // ææ½å®æåè°
>
<SplitPane left>
左侧å
容
</SplitPane>
<SplitPane right>
å³ä¾§å
容
</SplitPane>
</SplitPane>
// QueryFilter æ¥è¯¢çéå¨
<QueryFilter
fields={filterFields} // çéåæ®µé
ç½®
initialValues={initialFilterValues} // åå§çéå¼
onSubmit={handleSubmit} // æäº¤åè°
onReset={handleReset} // éç½®åè°
layout="inline" // å¸å±æ¹å¼
submitText="æ¥è¯¢" // æäº¤æé®æå
resetText="éç½®" // éç½®æé®æå
/>
// DraggableBox 坿æ½çå
<DraggableBox
position={{ x: 100, y: 100 }} // åå§ä½ç½®
onDrag={handleDrag} // ææ½ä¸åè°
onDragEnd={handleDragEnd} // ææ½ç»æåè°
bounds="parent" // è¾¹çéå¶
disabled={false} // æ¯å¦ç¦ç¨ææ½
>
ææ½å
容
</DraggableBox>
// Icon 徿 ç»ä»¶
<Icon
prefix="other" // 徿 åç¼
name="add" // 徿 åç§°
size={16} // 徿 大å°
color="#1890ff" // 徿 é¢è²
className="custom-icon" // èªå®ä¹ç±»å
onClick={handleClick} // ç¹å»åè°
/>
// CacheTabs ç¼åæ ç¾é¡µ
<CacheTabs
activeKey={activeKey} // å½åæ¿æ´»æ ç¾
onChange={handleChange} // æ ç¾åååè°
items={tabItems} // æ ç¾é
ç½®
type="card" // æ ç¾ç±»å
size="default" // æ ç¾å¤§å°
tabBarExtraContent={extraContent} // æ ç¾æ é¢å¤å
容
/>
// BaseInfo åºç¡ä¿¡æ¯å±ç¤º
<BaseInfo
data={infoData} // å±ç¤ºæ°æ®
columns={infoColumns} // ä¿¡æ¯åé
ç½®
layout="vertical" // å¸å±æ¹å¼
labelWidth={120} // label宽度
bordered={true} // æ¯å¦æ¾ç¤ºè¾¹æ¡
size="default" // 尺寸大å°
/>
Hooks è½å
1. useTranslation å½é åç¿»è¯
强大çå½é åç¿»è¯ Hookï¼æ¯æåµå¥é®æ¥æ¾ãå ä½ç¬¦æ¿æ¢åæ°ç»ç¿»è¯è¾ å©å½æ°ã
import { useTranslation } from '@arim-aisdc/public-components';
const [t, localeCode] = useTranslation();
// åºç¡ç¿»è¯
const title = t('global.title'); // è·åç¿»è¯ææ¬
// åµå¥é®ç¿»è¯
const message = t('user.profile.name'); // æ¯æç¹å·åéçåµå¥é®
// å ä½ç¬¦æ¿æ¢
const greeting = t('global.welcome', 'John', '2024'); // "æ¬¢è¿ {0} å¨ {1} å¹´å å
¥"
// è·åå½åè¯è¨ä»£ç
console.log(localeCode); // 'zh-CN' | 'en-US' | 'vi-VN'
æ°ç»ç¿»è¯è¾ å©å½æ°ï¼
// tA - éç¨æ°ç»ç¿»è¯ï¼èªå®ä¹å段ï¼
const translatedData = t.tA(data, {
fieldKey: 'type', // æå®åªä¸ªå段ä½ä¸ºç¿»è¯é®
labelKey: 'typeName', // æå®åªä¸ªå段ä¿åç¿»è¯åçå¼
groupPrefix: 'status', // å¯éçåç»åç¼
});
// tT - ç¿»è¯ TableMax åé
ç½®
const columns = t.tT([
{ id: 'name', accessorKey: 'name' },
{ id: 'age', accessorKey: 'age' },
]);
// èªå¨å° header 设置为 t(`apiField.${accessorKey}`)
// tQ - ç¿»è¯ QueryFilter é
ç½®
const filterFields = t.tQ([
{ field: 'name', formType: 'text' },
{ field: 'status', formType: 'select' },
]);
// èªå¨è®¾ç½® label å inputTips
// tF - ç¿»è¯ CustomForm é
ç½®
const formFields = t.tF([
{ field: 'name', formType: CustomFormItemType.Text },
{ field: 'email', formType: CustomFormItemType.Text },
]);
// tB - ç¿»è¯ BaseInfo é
ç½®
const infoFields = t.tB([
{ field: 'name', value: 'John' },
{ field: 'age', value: 25 },
]);
// èªå¨å° text 设置为 t(`apiField.${field}`)
èªå®ä¹è¯è¨å ï¼
const customLocales = {
'zh-CN': {
myApp: {
title: 'æçåºç¨',
welcome: '欢è¿ä½¿ç¨',
},
},
'en-US': {
myApp: {
title: 'My App',
welcome: 'Welcome',
},
},
};
const [t] = useTranslation(customLocales);
const title = t('myApp.title'); // èªå¨åå¹¶èªå®ä¹è¯è¨å
2. useEventBus äºä»¶æ»çº¿
å ¨å±äºä»¶æ»çº¿ Hookï¼ç¨äºè·¨ç»ä»¶éä¿¡ã
import { useEventBus, events } from '@arim-aisdc/public-components';
// åéäºä»¶ï¼ä»»ä½å°æ¹ï¼
events.emit('data-changed', { id: 1, name: 'test' });
events.emit('user-login', { userId: '123', username: 'john' });
// çå¬äºä»¶ï¼å¨ç»ä»¶ä¸ï¼
useEventBus('data-changed', data => {
console.log('æ°æ®åå:', data);
// èªå¨å¨ç»ä»¶å¸è½½æ¶æ¸
ççå¬å¨
});
// 䏿¬¡æ§çå¬
events.once('init-complete', () => {
console.log('åå§å宿');
});
// æå¨ç§»é¤çå¬å¨
const handler = data => console.log(data);
events.on('my-event', handler);
events.off('my-event', handler);
// è°ç¨ææçå¬å¨å¹¶è¿åç»ææ°ç»
const results = events.invoke('calculate', 10, 20);
3. usePageCacheState 页é¢ç¼åç¶æ
èªå¨ç¼å页é¢ç¶æå° localStorage/sessionStorageï¼å·æ°é¡µé¢åèªå¨æ¢å¤ã
import { usePageCacheState } from '@arim-aisdc/public-components';
// åºç¡ç¨æ³
const [state, setState] = usePageCacheState('page-key', { count: 0 });
// æ´æ°ç¶æï¼èªå¨ç¼åï¼
setState({ count: 1 });
// æ¯æåµå¥åæ®µæ´æ°
const [formData, setFormData] = usePageCacheState('form-data', {
user: { name: '', age: 0 },
settings: { theme: 'light' },
});
setFormData({ user: { name: 'John' } }); // 深度åå¹¶
// åå§åç¶æï¼é置为åå§å¼ï¼
const [state, setState, initState] = usePageCacheState('key', initialValue);
initState();
// æ¸
é¤ç¼å
const [state, setState, initState, clearState] = usePageCacheState('key', initialValue);
clearState();
ç¼åç¹æ§ï¼
- èªå¨ç¼åå° localStorage
- ç¼åæææï¼1å°æ¶
- æ¯ææ·±åº¦åå¹¶åµå¥å¯¹è±¡
- ç»ä»¶å¸è½½æ¶ä¿çç¼å
- å·æ°é¡µé¢èªå¨æ¢å¤ç¶æ
4. useCenterModalState å¼¹çªç¶æç®¡ç
ç®å CenterModal ç¶æç®¡çç Hookã
import { useCenterModalState, CenterModal } from '@arim-aisdc/public-components';
const [modalProps, setModalProps, closeModal] = useCenterModalState();
// æå¼å¼¹çª
const openModal = () => {
setModalProps({
visible: true,
title: 'ç¼è¾ç¨æ·',
width: 600,
// å
¶ä» CenterModal 屿§
});
};
// å
³éå¼¹çª
const handleOk = () => {
// å¤ç确认é»è¾
closeModal();
};
// 渲æå¼¹çª
<CenterModal
{...modalProps}
onOk={handleOk}
onCancel={closeModal}
>
å¼¹çªå
容
</CenterModal>
5. useConfig é ç½®è·å
è·å ConfigProvider æä¾çå ¨å±é ç½®ã
import { useConfig } from '@arim-aisdc/public-components';
const config = useConfig();
// 访é®é
ç½®
const theme = config.theme; // 'light' | 'dark'
const locale = config.locale; // è¯è¨å
对象
const userId = config.userId; // ç¨æ·ID
const dateFormat = config.dateFormat; // æ¥ææ ¼å¼
const tableMaxConfig = config.tableMax; // TableMax å
¨å±é
ç½®
æ ¸å¿ä½¿ç¨æ¨¡å¼
1. è¡¨æ ¼ CRUD æä½æ¨¡å¼
// 1. å®ä¹åé
ç½®
const columns = useMemo(
() => [
{
id: 'id',
header: 'ID',
accessorKey: 'id',
size: 80,
},
{
id: 'name',
header: 'å§å',
accessorKey: 'name',
editable: true,
filterType: FilterType.Input,
},
],
[],
);
// 2. å¤çæ°æ®åæ´
const handlePagination = useCallback(({ skipCount, pageSize }) => {
fetchData({ skipCount, pageSize });
}, []);
const handleSort = useCallback((sortValueArr, sortValueStr, sortedData) => {
fetchData({ sort: sortValueStr });
}, []);
const handleFilter = useCallback(({ filters, formatFiltersV2 }) => {
fetchData({ filters: formatFiltersV2 });
}, []);
// 3. 渲æè¡¨æ ¼
<TableMax
tableId="user-table"
columns={columns}
datas={users}
totalCount={total}
pageSize={pageSize}
skipCount={skipCount}
canSelection={true}
canEditting={true}
canFilter={true}
manualSorting={true}
manualFiltering={true}
changePagination={handlePagination}
onSortingChange={handleSort}
onFilteringChange={handleFilter}
/>;
2. CustomForm 表åé 置模å¼
import { CustomForm, CustomFormItemType, CustomSearchFieldType } from '@arim-aisdc/public-components';
const formFields: CustomSearchFieldType[] = [
{
field: 'name', // ãå¿
é¡»ãåæ®µå
label: 'å§å', // åæ®µæ ç¾
formType: CustomFormItemType.Text, // 表åç±»å
defaultValue: '', // é»è®¤å¼
inputTips: '请è¾å
¥å§å', // placeholder
required: true, // æ¯å¦å¿
å¡«
maxLength: 50, // æå¤§é¿åº¦ï¼ææ¬åï¼
span: 8, // æ
æ ¼å 使 ¼æ°
tooltip: 'å§åç¨äºç¨æ·æ è¯', // tooltipæç¤º
},
{
field: 'status',
label: 'ç¶æ',
formType: CustomFormItemType.Select,
defaultValue: 'active',
setting: [
// 䏿é项é
ç½®
{ label: 'å¯ç¨', value: 'active' },
{ label: 'ç¦ç¨', value: 'inactive' },
],
showSearch: true, // æ¯å¦æ¯ææç´¢
mode: 'multiple', // å¤é模å¼
maxTagCount: 3, // æå¤æ¾ç¤ºtagæ°é
required: true,
},
{
field: 'age',
label: 'å¹´é¾',
formType: CustomFormItemType.Number,
defaultValue: 18,
min: 0, // æå°å¼
max: 120, // æå¤§å¼
step: 1, // æ¥é¿
precision: 0, // ä¿çå°æ°ä½æ°
unit: 'å²', // åä½
required: true,
},
{
field: 'createTime',
label: 'å建æ¶é´',
formType: CustomFormItemType.DateTime,
defaultValue: null,
picker: 'date', // æ¶é´éæ©å¨ç±»å
showTime: true, // æ¯å¦æ¾ç¤ºæ¶é´
format: 'YYYY-MM-DD HH:mm:ss', // æ¾ç¤ºæ ¼å¼
allowClear: true, // æ¯å¦å¯æ¸
é¤
disabledDate: current => {
// ç¦ç¨æ¥æ
return current && current > dayjs().endOfDay();
},
},
{
field: 'description',
label: 'æè¿°',
formType: CustomFormItemType.TextArea,
defaultValue: '',
rows: 4, // ææ¬åè¡æ°
maxLength: 500,
isShowToolTip: true, // æ¯å¦æ¾ç¤ºtooltip
},
{
field: 'condition',
label: 'æ¡ä»¶è¡¨è¾¾å¼',
formType: CustomFormItemType.ConditionExpression,
showParameter: true, // æ¯å¦æ¾ç¤ºåæ°éæ©æ¡
parameterOptions: [
// åæ°é项
{ label: 'å§å', value: 'name' },
{ label: 'å¹´é¾', value: 'age' },
],
canFrontFilter: true,
},
{
field: 'avatar',
label: '头å',
formType: CustomFormItemType.UploadImg,
defaultValue: '',
baseUrl: '/api/upload', // ä¸ä¼ å°å
token: 'your-upload-token', // ä¸ä¼ token
method: 'POST', // ä¸ä¼ æ¹æ³
},
];
<CustomForm
data={formFields} // ãå¿
é¡»ã表ååæ®µé
ç½®
initialValues={initialData} // åå§å¼
handleSubmit={handleSubmit} // ãå¿
é¡»ãæäº¤åè°
handleCancel={handleCancel} // åæ¶åè°
layout="horizontal" // å¸å±æ¹å¼ï¼'horizontal' | 'inline' | 'vertical'
labelCol="120px" // label宽度
span={24} // æ
æ ¼é
ç½®
showButton={true} // æ¯å¦æ¾ç¤ºæé®
isOkText="æäº¤" // 确认æé®æå
cancelText="åæ¶" // åæ¶æé®æå
submitLoading={false} // æäº¤loadingç¶æ
labelAlign="right" // label坹齿¹å¼
btnSpan={24} // æé®æ
æ ¼å ä½
usage="submit" // ç¨éï¼'filter' | 'submit'
/>;
表åç±»åæä¸¾ï¼
enum CustomFormItemType {
Text = 'text', // ææ¬è¾å
¥
TextArea = 'textArea', // ææ¬å
Number = 'number', // æ°åè¾å
¥
Switch = 'switch', // å¼å
³
Select = 'select', // éæ©å¨
Cascader = 'cascader', // 级èéæ©
RemoteCascader = 'remoteCascader', // è¿ç¨çº§èéæ©
DateTime = 'datetime', // æ¥ææ¶é´
DateRang = 'daterang', // æ¥æèå´
Interval = 'interval', // åºé´è¾å
¥
Radio = 'radio', // åé
StartEnd = 'start-end', // èµ·æ¢è¾å
¥
AutoComplete = 'autoComplete', // èªå¨å®æ
MinMax = 'min-max', // æå°æå¤§å¼
CheckBox = 'checkbox', // å¤éæ¡
Color = 'color', // é¢è²éæ©
ConditionExpression = 'conditionExpression', // æ¡ä»¶è¡¨è¾¾å¼
RemoteSelect = 'remoteSelect', // è¿ç¨éæ©
UploadImg = 'uploadImg', // å¾çä¸ä¼
}
3. 主é¢é 置模å¼
// å¨åºç¨å
¥å£é
置主é¢
const App = () => {
return (
<ConfigProvider
config={{
theme: 'dark',
userId: getCurrentUserId(),
variablesJson: {
'--global-primary-color': '#1890ff',
'--table-row-hover-bgc': '#1f1f1f',
},
}}
>
<ThemeProvider theme="dark">
<Router>
<Routes>
<Route path="/" element={<HomePage />} />
</Routes>
</Router>
</ThemeProvider>
</ConfigProvider>
);
};
æä½³å®è·µæå¯¼
1. æ§è½ä¼å
- 使ç¨
useMemoç¼ååé ç½® - 使ç¨
useCallbackç¼åäºä»¶å¤ç彿° - å¤§æ°æ®éæ¶å¼å¯èæå表
enableVirtualList={true} - åç设置ç¼åæ¶é´
cacheMaxAge
2. ç¼åçç¥
- æ¯ä¸ªè¡¨æ ¼å¿
须设置å¯ä¸ç
tableId - éè¿
ConfigProviderè®¾ç½®ç¨æ· ID å®ç°ç¼åé离 - 使ç¨
versionåæ°æ§å¶ç¼åçæ¬
3. å½é åé ç½®
// æ¯æçè¯è¨
import {
public_zhCN, // 䏿
public_enUS, // è±æ
public_viVN, // è¶åæ
} from '@arim-aisdc/public-components';
4. é误å¤ç
- 使ç¨
toå·¥å ·å½æ°å¤ç Promise é误 - è¡¨æ ¼æä½æ¶æ·»å loading ç¶æ
- åçå¤çç©ºæ°æ®ç¶æ
常è§é®é¢è§£å³æ¹æ¡
1. è¡¨æ ¼ç¼åé®é¢
// æ¸
é¤ç¹å®è¡¨æ ¼ç¼å
localStorage.removeItem(`${tableKeyPrefixCls}-${pathname}-${tableId}-${userId}`);
// å级ç¼åçæ¬
<TableMax version="1.0.1" />;
2. 主é¢åéè¦ç
// éè¿CSSåéè¦ç主é¢
:root {
--global-primary-color: #custom-color;
--table-row-hover-bgc: #custom-hover;
}
3. æéæ§å¶éæ
// ä¸å端æéç³»ç»éæ
const userPermissions = await fetchUserPermissions();
<PermissionProvider permissions={userPermissions}>
<App />
</PermissionProvider>;
ææ¯æ å ¼å®¹æ§
- React: 17.0.1+
- Ant Design: 5.27.3+
- TypeScript: æ¯æï¼ä½ strict 模å¼å ³é
- æå»ºå·¥å ·: Father (æå ) + Dumi (ææ¡£)
- æ ·å¼: Less + CSS åé
å·¥å ·å½æ°
ç»ä»¶åºæä¾äºä¸äºå®ç¨çå·¥å ·å½æ°ï¼
import { getTextWidth, to, judgeHasPermission } from '@arim-aisdc/public-components';
// 1. getTextWidth - è®¡ç®ææ¬å®½åº¦
const width = getTextWidth('Hello World', 14); // è¿ååç´ å®½åº¦
// ç¨éï¼å¨æè®¡ç®åå®½ãææ¬æªæå¤æ
// 2. to - Promise é误å¤çï¼Go 飿 ¼ï¼
const [error, data] = await to(fetchUserData());
if (error) {
console.error('请æ±å¤±è´¥:', error);
return;
}
console.log('æ°æ®:', data);
// 3. judgeHasPermission - æéæ°ç»æ¯è¾
const hasPermission = judgeHasPermission(
['user:read', 'user:write'], // éè¦çæé
['user:read', 'user:write', 'admin'] // ç¨æ·æ¥æçæé
);
// è¿å trueï¼ç¨æ·æ¥æææéè¦çæéï¼
éè¦æé
AI å©æä½¿ç¨æåï¼
- èªå¨è§¦åæ£æµ – 彿£æµå°ä¸è¿°å ³é®è¯æ¶ï¼ç«å³å è½½æ¤æè½
- ä¼å ä½¿ç¨æ¬æè½ – ä¼å éµå¾ªæ¬æè½ç API 模å¼åæä½³å®è·µ
- ç¼åå¯ä¸æ§ – ç¡®ä¿æ»æ¯æéç¨æ·ä¸º TableMax æä¾å¯ä¸ç tableId
- å ¨å±é ç½® – ç¡®ä¿æ»æ¯æ£æ¥ ConfigProvider çæ£ç¡®é ç½®
- æ§è½å»ºè®® – æ ¹æ®ä½¿ç¨åºæ¯ä¸»å¨æä¾æ§è½ä¼å建议
- ç±»åå®å ¨ – ä½¿ç¨æ£ç¡®çç±»åå®ä¹ï¼TableMaxPropsãTableMaxColumnTypeãCustomFormItemType çï¼
- å½é åæ¯æ – ä¼å ä½¿ç¨ useTranslation çè¾ å©å½æ°ï¼tTãtQãtFãtBï¼è¿è¡é 置翻è¯
- é误å¤ç – æ¨èä½¿ç¨ to() å·¥å ·å½æ°è¿è¡ Promise é误å¤ç
å¼åè ä½¿ç¨æéï¼
-
TableMax å¿ é¡»é ç½®ï¼
- æ»æ¯ä¸º TableMax ç»ä»¶æä¾å¯ä¸ç tableId
- æ ¹æ®æ°æ®ééæ©æ¯å¦å¼å¯èææ»å¨ï¼enableVirtualListï¼
- å端å页æ¶è®¾ç½® manualSorting å manualFiltering 为 true
-
å ¨å±é ç½®æä½³å®è·µï¼
- å¨åºç¨æ ¹ç»ä»¶é ç½® ConfigProvider
- 设置 userId 以å®ç°ç¨æ·çº§ç¼åé离
- é ç½® tableKeyPrefixCls é¿å ç¼åå²çª
- ä½¿ç¨ ThemeProvider å®ç°ä¸»é¢åæ¢
-
æ§è½ä¼åçç¥ï¼
- ä½¿ç¨ useMemo ç¼ååé ç½®
- ä½¿ç¨ useCallback ç¼åäºä»¶å¤ç彿°
- å¤§æ°æ®éï¼>1000è¡ï¼å¼å¯èæå表
- åç设置 cacheMaxAge æ§å¶ç¼åæ¶é´
-
æéæ§å¶éæï¼
- ä½¿ç¨ PermissionProvider å 裹åºç¨æ ¹ç»ä»¶
- ä½¿ç¨ Restricted ç»ä»¶è¿è¡æ¡ä»¶æ¸²æ
- ä½¿ç¨ judgeHasPermission å·¥å ·å½æ°è¿è¡æé夿
-
å½é åé ç½®ï¼
- å¨ ConfigProvider ä¸é ç½® locale
- ä½¿ç¨ useTranslation çè¾ å©å½æ°ç®åé 置翻è¯
- æ¯æèªå®ä¹è¯è¨å æ©å±
常è§é®é¢å¿«éè§£å³ï¼
- è¡¨æ ¼ç¼åé®é¢ï¼æ¸ é¤ localStorage ä¸çè¡¨æ ¼ç¼åæå级 version
- 主é¢ä¸çæï¼æ£æ¥ ConfigProvider ç autoSetCssVars æ¯å¦ä¸º true
- æéä¸çæï¼ç¡®ä¿ PermissionProvider å 裹äºéè¦æéæ§å¶çç»ä»¶
- å½é åä¸çæï¼æ£æ¥ ConfigProvider ç locale é ç½®æ¯å¦æ£ç¡®
- èææ»å¨é®é¢ï¼ç¡®ä¿è®¾ç½®äºæ£ç¡®ç rowHeight
æè½çæ¬ä¿¡æ¯ï¼
- ç»ä»¶åºçæ¬ï¼@arim-aisdc/public-components v2.3.77
- æè½å建æ¶é´ï¼2026-01-29
- æè½ç»´æ¤ï¼æ¤æè½åºéç»ä»¶åºçæ¬æ´æ°èæ´æ°
- æåæ´æ°ï¼2026-01-29
ç»ä»¶åºæ ¸å¿ä¾èµï¼
- React: >=17.0.1
- Ant Design: ^5.27.3
- @tanstack/react-table: ^8.9.1ï¼TableMax æ ¸å¿ï¼
- @tanstack/react-virtual: ^3.13.12ï¼èææ»å¨ï¼
- dayjs: ^1.11.11ï¼æ¥æå¤çï¼
- react-dnd: ^16.0.1ï¼ææ½åè½ï¼
- xlsx: ^0.18.5ï¼Excel 导åºï¼
è¿ä¸ªæè½å°å¸®å© AI æ¨¡åæ´å¥½å°çè§£å使ç¨è¿ä¸ªç»ä»¶åºï¼æä¾åç¡®ã髿çå端å¼åè§£å³æ¹æ¡ã