| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309 |
- /*
- Copyright (C) 2025 QuantumNous
- This program is free software: you can redistribute it and/or modify
- it under the terms of the GNU Affero General Public License as
- published by the Free Software Foundation, either version 3 of the
- License, or (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU Affero General Public License for more details.
- You should have received a copy of the GNU Affero General Public License
- along with this program. If not, see <https://www.gnu.org/licenses/>.
- For commercial licensing, please contact support@quantumnous.com
- */
- import { useRef, useState } from 'react';
- import { API, showError, showInfo, showSuccess } from '../../helpers';
- import { normalizeModelList } from './upstreamUpdateUtils';
- const getManualIgnoredModelCountFromSettings = (settings) => {
- let parsed = null;
- if (settings && typeof settings === 'object') {
- parsed = settings;
- } else if (typeof settings === 'string') {
- try {
- parsed = JSON.parse(settings);
- } catch (error) {
- parsed = null;
- }
- }
- if (!parsed || typeof parsed !== 'object') {
- return 0;
- }
- return normalizeModelList(parsed.upstream_model_update_ignored_models).length;
- };
- export const useChannelUpstreamUpdates = ({ t, refresh }) => {
- const [showUpstreamUpdateModal, setShowUpstreamUpdateModal] = useState(false);
- const [upstreamUpdateChannel, setUpstreamUpdateChannel] = useState(null);
- const [upstreamUpdateAddModels, setUpstreamUpdateAddModels] = useState([]);
- const [upstreamUpdateRemoveModels, setUpstreamUpdateRemoveModels] = useState(
- [],
- );
- const [upstreamUpdatePreferredTab, setUpstreamUpdatePreferredTab] =
- useState('add');
- const [upstreamApplyLoading, setUpstreamApplyLoading] = useState(false);
- const [detectAllUpstreamUpdatesLoading, setDetectAllUpstreamUpdatesLoading] =
- useState(false);
- const [applyAllUpstreamUpdatesLoading, setApplyAllUpstreamUpdatesLoading] =
- useState(false);
- const applyUpstreamUpdatesInFlightRef = useRef(false);
- const detectChannelUpstreamUpdatesInFlightRef = useRef(false);
- const detectAllUpstreamUpdatesInFlightRef = useRef(false);
- const applyAllUpstreamUpdatesInFlightRef = useRef(false);
- const openUpstreamUpdateModal = (
- record,
- pendingAddModels = [],
- pendingRemoveModels = [],
- preferredTab = 'add',
- ) => {
- const normalizedAddModels = normalizeModelList(pendingAddModels);
- const normalizedRemoveModels = normalizeModelList(pendingRemoveModels);
- if (
- !record?.id ||
- (normalizedAddModels.length === 0 && normalizedRemoveModels.length === 0)
- ) {
- showInfo(t('该渠道暂无可处理的上游模型更新'));
- return;
- }
- setUpstreamUpdateChannel(record);
- setUpstreamUpdateAddModels(normalizedAddModels);
- setUpstreamUpdateRemoveModels(normalizedRemoveModels);
- const normalizedPreferredTab = preferredTab === 'remove' ? 'remove' : 'add';
- setUpstreamUpdatePreferredTab(normalizedPreferredTab);
- setShowUpstreamUpdateModal(true);
- };
- const closeUpstreamUpdateModal = () => {
- setShowUpstreamUpdateModal(false);
- setUpstreamUpdateChannel(null);
- setUpstreamUpdateAddModels([]);
- setUpstreamUpdateRemoveModels([]);
- setUpstreamUpdatePreferredTab('add');
- };
- const applyUpstreamUpdates = async ({
- addModels: selectedAddModels = [],
- removeModels: selectedRemoveModels = [],
- } = {}) => {
- if (applyUpstreamUpdatesInFlightRef.current) {
- showInfo(t('正在处理,请稍候'));
- return;
- }
- if (!upstreamUpdateChannel?.id) {
- closeUpstreamUpdateModal();
- return;
- }
- applyUpstreamUpdatesInFlightRef.current = true;
- setUpstreamApplyLoading(true);
- try {
- const normalizedSelectedAddModels = normalizeModelList(selectedAddModels);
- const normalizedSelectedRemoveModels =
- normalizeModelList(selectedRemoveModels);
- const selectedAddSet = new Set(normalizedSelectedAddModels);
- const ignoreModels = upstreamUpdateAddModels.filter(
- (model) => !selectedAddSet.has(model),
- );
- const res = await API.post(
- '/api/channel/upstream_updates/apply',
- {
- id: upstreamUpdateChannel.id,
- add_models: normalizedSelectedAddModels,
- ignore_models: ignoreModels,
- remove_models: normalizedSelectedRemoveModels,
- },
- { skipErrorHandler: true },
- );
- const { success, message, data } = res.data || {};
- if (!success) {
- showError(message || t('操作失败'));
- return;
- }
- const addedCount = data?.added_models?.length || 0;
- const removedCount = data?.removed_models?.length || 0;
- const totalIgnoredCount = getManualIgnoredModelCountFromSettings(
- data?.settings,
- );
- const ignoredCount = normalizeModelList(ignoreModels).length;
- showSuccess(
- t(
- '已处理上游模型更新:加入 {{added}} 个,删除 {{removed}} 个,本次忽略 {{ignored}} 个,当前已忽略模型 {{totalIgnored}} 个',
- {
- added: addedCount,
- removed: removedCount,
- ignored: ignoredCount,
- totalIgnored: totalIgnoredCount,
- },
- ),
- );
- closeUpstreamUpdateModal();
- await refresh();
- } catch (error) {
- showError(
- error?.response?.data?.message || error?.message || t('操作失败'),
- );
- } finally {
- applyUpstreamUpdatesInFlightRef.current = false;
- setUpstreamApplyLoading(false);
- }
- };
- const applyAllUpstreamUpdates = async () => {
- if (applyAllUpstreamUpdatesInFlightRef.current) {
- showInfo(t('正在批量处理,请稍候'));
- return;
- }
- applyAllUpstreamUpdatesInFlightRef.current = true;
- setApplyAllUpstreamUpdatesLoading(true);
- try {
- const res = await API.post(
- '/api/channel/upstream_updates/apply_all',
- {},
- { skipErrorHandler: true },
- );
- const { success, message, data } = res.data || {};
- if (!success) {
- showError(message || t('批量处理失败'));
- return;
- }
- const channelCount = data?.processed_channels || 0;
- const addedCount = data?.added_models || 0;
- const removedCount = data?.removed_models || 0;
- const failedCount = (data?.failed_channel_ids || []).length;
- showSuccess(
- t(
- '已批量处理上游模型更新:渠道 {{channels}} 个,加入 {{added}} 个,删除 {{removed}} 个,失败 {{fails}} 个',
- {
- channels: channelCount,
- added: addedCount,
- removed: removedCount,
- fails: failedCount,
- },
- ),
- );
- await refresh();
- } catch (error) {
- showError(
- error?.response?.data?.message || error?.message || t('批量处理失败'),
- );
- } finally {
- applyAllUpstreamUpdatesInFlightRef.current = false;
- setApplyAllUpstreamUpdatesLoading(false);
- }
- };
- const detectChannelUpstreamUpdates = async (channel) => {
- if (detectChannelUpstreamUpdatesInFlightRef.current) {
- showInfo(t('正在检测,请稍候'));
- return;
- }
- if (!channel?.id) {
- return;
- }
- detectChannelUpstreamUpdatesInFlightRef.current = true;
- try {
- const res = await API.post(
- '/api/channel/upstream_updates/detect',
- {
- id: channel.id,
- },
- { skipErrorHandler: true },
- );
- const { success, message, data } = res.data || {};
- if (!success) {
- showError(message || t('检测失败'));
- return;
- }
- const addCount = data?.add_models?.length || 0;
- const removeCount = data?.remove_models?.length || 0;
- showSuccess(
- t('检测完成:新增 {{add}} 个,删除 {{remove}} 个', {
- add: addCount,
- remove: removeCount,
- }),
- );
- await refresh();
- } catch (error) {
- showError(
- error?.response?.data?.message || error?.message || t('检测失败'),
- );
- } finally {
- detectChannelUpstreamUpdatesInFlightRef.current = false;
- }
- };
- const detectAllUpstreamUpdates = async () => {
- if (detectAllUpstreamUpdatesInFlightRef.current) {
- showInfo(t('正在批量检测,请稍候'));
- return;
- }
- detectAllUpstreamUpdatesInFlightRef.current = true;
- setDetectAllUpstreamUpdatesLoading(true);
- try {
- const res = await API.post(
- '/api/channel/upstream_updates/detect_all',
- {},
- { skipErrorHandler: true },
- );
- const { success, message, data } = res.data || {};
- if (!success) {
- showError(message || t('批量检测失败'));
- return;
- }
- const channelCount = data?.processed_channels || 0;
- const addCount = data?.detected_add_models || 0;
- const removeCount = data?.detected_remove_models || 0;
- const failedCount = (data?.failed_channel_ids || []).length;
- showSuccess(
- t(
- '批量检测完成:渠道 {{channels}} 个,新增 {{add}} 个,删除 {{remove}} 个,失败 {{fails}} 个',
- {
- channels: channelCount,
- add: addCount,
- remove: removeCount,
- fails: failedCount,
- },
- ),
- );
- await refresh();
- } catch (error) {
- showError(
- error?.response?.data?.message || error?.message || t('批量检测失败'),
- );
- } finally {
- detectAllUpstreamUpdatesInFlightRef.current = false;
- setDetectAllUpstreamUpdatesLoading(false);
- }
- };
- return {
- showUpstreamUpdateModal,
- setShowUpstreamUpdateModal,
- upstreamUpdateChannel,
- upstreamUpdateAddModels,
- upstreamUpdateRemoveModels,
- upstreamUpdatePreferredTab,
- upstreamApplyLoading,
- detectAllUpstreamUpdatesLoading,
- applyAllUpstreamUpdatesLoading,
- openUpstreamUpdateModal,
- closeUpstreamUpdateModal,
- applyUpstreamUpdates,
- applyAllUpstreamUpdates,
- detectChannelUpstreamUpdates,
- detectAllUpstreamUpdates,
- };
- };
|