✨ 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 [groupOptions, setGroupOptions] = useState([]);
|
||||||
const [basicModels, setBasicModels] = useState([]);
|
const [basicModels, setBasicModels] = useState([]);
|
||||||
const [fullModels, setFullModels] = useState([]);
|
const [fullModels, setFullModels] = useState([]);
|
||||||
|
const [modelGroups, setModelGroups] = useState([]);
|
||||||
const [customModel, setCustomModel] = useState('');
|
const [customModel, setCustomModel] = useState('');
|
||||||
const [modalImageUrl, setModalImageUrl] = useState('');
|
const [modalImageUrl, setModalImageUrl] = useState('');
|
||||||
const [isModalOpenurl, setIsModalOpenurl] = useState(false);
|
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(() => {
|
useEffect(() => {
|
||||||
const modelMap = new Map();
|
const modelMap = new Map();
|
||||||
|
|
||||||
@@ -549,6 +561,7 @@ const EditChannelModal = (props) => {
|
|||||||
} else {
|
} else {
|
||||||
formApiRef.current?.setValues(getInitValues());
|
formApiRef.current?.setValues(getInitValues());
|
||||||
}
|
}
|
||||||
|
fetchModelGroups();
|
||||||
// 重置手动输入模式状态
|
// 重置手动输入模式状态
|
||||||
setUseManualInput(false);
|
setUseManualInput(false);
|
||||||
} else {
|
} else {
|
||||||
@@ -1478,6 +1491,32 @@ const EditChannelModal = (props) => {
|
|||||||
>
|
>
|
||||||
{t('复制所有模型')}
|
{t('复制所有模型')}
|
||||||
</Button>
|
</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>
|
</Space>
|
||||||
)}
|
)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
Reference in New Issue
Block a user