/* * Copyright 2025 coze-dev Authors * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import React, { useEffect, useState, useRef, useMemo } from 'react'; import { debounce } from 'lodash-es'; import { PUBLIC_SPACE_ID } from '@coze-workflow/base/constants'; import { concatTestId } from '@coze-workflow/base'; import { I18n } from '@coze-arch/i18n'; import { Typography, Spin, Avatar, Select } from '@coze-arch/bot-semi'; import { ListBotDraftType, PublishStatus, } from '@coze-arch/bot-api/developer_api'; import { DeveloperApi } from '@coze-arch/bot-api'; import { IconSearch } from '@douyinfe/semi-icons'; import { useGlobalState } from '../../hooks'; import { useExtraBotOption } from './use-extra-bot-option'; import type { IBotSelectOption } from './types'; import styles from './bots.module.less'; type IBotSelectOptions = IBotSelectOption[]; const RenderCustomOption = item => { if (!item) { return null; } return (
{item.name}
); }; const RenderFootLoading = ({ onObserver, }: { onObserver: () => Promise; }) => { const indicatorRef = useRef(null); useEffect(() => { const callback = entries => { if (entries[0].isIntersecting) { onObserver?.(); } }; const loadingObserver = new IntersectionObserver(callback); indicatorRef.current && loadingObserver.observe(indicatorRef.current); return () => loadingObserver.disconnect(); }, []); return (
{I18n.t('workflow_add_common_loading')}
); }; interface BotsProps { value?: string; onChange?: (value: string) => void; } export const Bots: React.FC = ({ value, onChange, ...props }) => { const globalState = useGlobalState(); const DebounceTime = 500; const isLoadMoreDate = useRef(false); const [selectList = [], setSelectList] = useState([]); const [isLoading, setIsLoading] = useState(false); const [isShowFoot, setIsShowFoot] = useState(false); const [pageIndex, setPageIndex] = useState(1); const [search, setSearch] = useState(''); const [searchTotal, setTotal] = useState(0); const containerRef = useRef(null); // Due to paging restrictions, the selected botId may not find the corresponding option and needs to be added const extraBotOption = useExtraBotOption(selectList, value); // The total number obtained by the interface is not the real total, and the front end may splice options. const listMaxHeight = useMemo(() => { const realTotal = extraBotOption ? searchTotal + 1 : searchTotal; // eslint-disable-next-line @typescript-eslint/no-magic-numbers return realTotal < 7 ? realTotal * 32 : 208; }, [searchTotal, extraBotOption]); useEffect(() => { fetchBotList(); }, []); const fetchBotList = async ( index?: number, query?: string, isReset = false, ) => { if (query) { setIsLoading(true); } const res = await DeveloperApi.GetDraftBotList({ space_id: globalState.spaceId === PUBLIC_SPACE_ID ? globalState.personalSpaceId : globalState.spaceId, bot_name: query ?? search, order_by: 0, team_bot_type: ListBotDraftType.TeamBots, page_index: index ?? pageIndex, page_size: 30, is_publish: PublishStatus.All, }); const { bot_draft_list, total = 0 } = res?.data ?? {}; const list: IBotSelectOptions = (bot_draft_list ?? []).map(it => ({ name: it.name ?? '', value: it.id ?? '', avatar: it.icon_url ?? '', })); const totalList = isReset ? list : [...selectList, ...list]; setTotal(total); setSelectList(totalList); setIsShowFoot(totalList.length < total); setIsLoading(false); }; const loadMoreData = async () => { if (isLoadMoreDate.current) { return; } isLoadMoreDate.current = true; const newPageIndex = pageIndex + 1; setPageIndex(newPageIndex); await fetchBotList(newPageIndex); isLoadMoreDate.current = false; }; const handleSearch = query => { setSearch(query); setPageIndex(1); fetchBotList(1, query, true); }; return (
); };