✨ feat: Add prefill group management system for models
- Add new PrefillGroup model with CRUD operations * Support for model, tag, and endpoint group types * JSON storage for group items with GORM datatypes * Automatic database migration support - Implement backend API endpoints * GET /api/prefill_group - List groups by type with admin auth * POST /api/prefill_group - Create new groups * PUT /api/prefill_group - Update existing groups * DELETE /api/prefill_group/:id - Delete groups - Add comprehensive frontend management interface * PrefillGroupManagement component for group listing * EditPrefillGroupModal for group creation/editing * Integration with EditModelModal for auto-filling * Responsive design with CardTable and SideSheet - Enhance model editing workflow * Tag group selection with auto-fill functionality * Endpoint group selection with auto-fill functionality * Seamless integration with existing model forms - Create reusable UI components * Extract common rendering utilities to models/ui/ * Shared renderLimitedItems and renderDescription functions * Consistent styling across all model-related components - Improve user experience * Empty state illustrations matching existing patterns * Fixed column positioning for operation buttons * Item content display with +x indicators for overflow * Tooltip support for long descriptions
This commit is contained in:
@@ -23,14 +23,14 @@ import {
|
||||
Space,
|
||||
Tag,
|
||||
Typography,
|
||||
Modal,
|
||||
Popover
|
||||
Modal
|
||||
} from '@douyinfe/semi-ui';
|
||||
import {
|
||||
timestamp2string,
|
||||
getLobeHubIcon,
|
||||
stringToColor
|
||||
} from '../../../helpers';
|
||||
import { renderLimitedItems, renderDescription } from './ui/RenderUtils.jsx';
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
@@ -39,34 +39,6 @@ function renderTimestamp(timestamp) {
|
||||
return <>{timestamp2string(timestamp)}</>;
|
||||
}
|
||||
|
||||
// Generic renderer for list-style tags with limit and popover
|
||||
function renderLimitedItems({ items, renderItem, maxDisplay = 3 }) {
|
||||
if (!items || items.length === 0) return '-';
|
||||
const displayItems = items.slice(0, maxDisplay);
|
||||
const remainingItems = items.slice(maxDisplay);
|
||||
return (
|
||||
<Space spacing={1} wrap>
|
||||
{displayItems.map((item, idx) => renderItem(item, idx))}
|
||||
{remainingItems.length > 0 && (
|
||||
<Popover
|
||||
content={
|
||||
<div className='p-2'>
|
||||
<Space spacing={1} wrap>
|
||||
{remainingItems.map((item, idx) => renderItem(item, idx))}
|
||||
</Space>
|
||||
</div>
|
||||
}
|
||||
position='top'
|
||||
>
|
||||
<Tag size='small' shape='circle' color='grey'>
|
||||
+{remainingItems.length}
|
||||
</Tag>
|
||||
</Popover>
|
||||
)}
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
|
||||
// Render vendor column with icon
|
||||
const renderVendorTag = (vendorId, vendorMap, t) => {
|
||||
if (!vendorId || !vendorMap[vendorId]) return '-';
|
||||
@@ -82,15 +54,6 @@ const renderVendorTag = (vendorId, vendorMap, t) => {
|
||||
);
|
||||
};
|
||||
|
||||
// Render description with ellipsis
|
||||
const renderDescription = (text) => {
|
||||
return (
|
||||
<Text ellipsis={{ showTooltip: true }} style={{ maxWidth: 200 }}>
|
||||
{text || '-'}
|
||||
</Text>
|
||||
);
|
||||
};
|
||||
|
||||
// Render groups (enable_groups)
|
||||
const renderGroups = (groups) => {
|
||||
if (!groups || groups.length === 0) return '-';
|
||||
@@ -223,7 +186,7 @@ export const getModelsColumns = ({
|
||||
{
|
||||
title: t('描述'),
|
||||
dataIndex: 'description',
|
||||
render: renderDescription,
|
||||
render: (text) => renderDescription(text, 200),
|
||||
},
|
||||
{
|
||||
title: t('供应商'),
|
||||
|
||||
Reference in New Issue
Block a user