✨ feat(web): add model prefill group quick-add buttons to channel models selector
- Added support to fetch and render “model prefill groups” in `EditChannelModal.jsx` - Users can now click a group button to instantly merge that group’s models into the models Select - Mirrors the prefill-group UX used for tags/endpoints in `EditModelModal.jsx` Details - UI/UX: - Renders one button per model group inside the models field’s extra actions - Clicking a button merges its items into the selected models (trimmed, deduplicated), updating immediately - Non-destructive and works alongside existing actions (fill related/all models, fetch upstream, clear, copy) - API: - GET `/api/prefill_group?type=model` - Handles `items` as either an array or a JSON string array for robustness - If request fails or returns no groups, buttons are simply not shown - i18n: - Reuses existing i18n; group names come from backend and are displayed as-is - Performance: - Simple set merge; negligible overhead - Backward compatibility: - No changes required on the backend or elsewhere; feature is additive - Testing (manual): 1) Open channel modal (new or edit) and navigate to the Models section 2) Confirm model group buttons render when groups are configured 3) Click a group button → models Select updates with merged models (no duplicates) 4) Verify other actions (fill related/all, fetch upstream, clear, copy) still work 5) Close/reopen modal → state resets as expected Implementation - `web/src/components/table/channels/modals/EditChannelModal.jsx` - Added `modelGroups` state and `fetchModelGroups()` (GET `/api/prefill_group?type=model`) - Invoked `fetchModelGroups()` when the modal opens - Rendered group buttons in the models Select `extraText`, merging group items into current selection Chore - Verified no new linter errors were introduced.
This commit is contained in:
@@ -142,6 +142,7 @@ const EditChannelModal = (props) => {
|
||||
const [groupOptions, setGroupOptions] = useState([]);
|
||||
const [basicModels, setBasicModels] = useState([]);
|
||||
const [fullModels, setFullModels] = useState([]);
|
||||
const [modelGroups, setModelGroups] = useState([]);
|
||||
const [customModel, setCustomModel] = useState('');
|
||||
const [modalImageUrl, setModalImageUrl] = useState('');
|
||||
const [isModalOpenurl, setIsModalOpenurl] = useState(false);
|
||||
@@ -477,6 +478,17 @@ const EditChannelModal = (props) => {
|
||||
}
|
||||
};
|
||||
|
||||
const fetchModelGroups = async () => {
|
||||
try {
|
||||
const res = await API.get('/api/prefill_group?type=model');
|
||||
if (res?.data?.success) {
|
||||
setModelGroups(res.data.data || []);
|
||||
}
|
||||
} catch (error) {
|
||||
// ignore
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const modelMap = new Map();
|
||||
|
||||
@@ -549,6 +561,7 @@ const EditChannelModal = (props) => {
|
||||
} else {
|
||||
formApiRef.current?.setValues(getInitValues());
|
||||
}
|
||||
fetchModelGroups();
|
||||
// 重置手动输入模式状态
|
||||
setUseManualInput(false);
|
||||
} else {
|
||||
@@ -1478,6 +1491,32 @@ const EditChannelModal = (props) => {
|
||||
>
|
||||
{t('复制所有模型')}
|
||||
</Button>
|
||||
{modelGroups && modelGroups.length > 0 && modelGroups.map(group => (
|
||||
<Button
|
||||
key={group.id}
|
||||
size='small'
|
||||
type='primary'
|
||||
onClick={() => {
|
||||
let items = [];
|
||||
try {
|
||||
if (Array.isArray(group.items)) {
|
||||
items = group.items;
|
||||
} else if (typeof group.items === 'string') {
|
||||
const parsed = JSON.parse(group.items || '[]');
|
||||
if (Array.isArray(parsed)) items = parsed;
|
||||
}
|
||||
} catch { }
|
||||
const current = formApiRef.current?.getValue('models') || inputs.models || [];
|
||||
const merged = Array.from(new Set([...
|
||||
current,
|
||||
...items
|
||||
].map(m => (m || '').trim()).filter(Boolean)));
|
||||
handleInputChange('models', merged);
|
||||
}}
|
||||
>
|
||||
{group.name}
|
||||
</Button>
|
||||
))}
|
||||
</Space>
|
||||
)}
|
||||
/>
|
||||
|
||||
Reference in New Issue
Block a user