diff --git a/shared/index.tsx b/shared/index.tsx index b2b7391a..283a14a0 100644 --- a/shared/index.tsx +++ b/shared/index.tsx @@ -30,6 +30,7 @@ export { createFastFormSchema, fieldSchema, } from './components/FastForm/schema'; +export { useFastFormContext } from './components/FastForm/context'; export { buildPortal, DefaultEventEmitter } from './components/Portal'; export { TcProvider } from './components/Provider'; diff --git a/web/src/components/modals/GroupDetail/Panel/index.tsx b/web/src/components/modals/GroupDetail/Panel/index.tsx index f8e457a5..c6c5f97f 100644 --- a/web/src/components/modals/GroupDetail/Panel/index.tsx +++ b/web/src/components/modals/GroupDetail/Panel/index.tsx @@ -12,7 +12,7 @@ import _isEqual from 'lodash/isEqual'; import { GroupPanelTree } from './GroupPanelTree'; import { FullModalCommonTitle } from '@/components/FullModal/CommonTitle'; import { closeModal, openModal } from '@/components/Modal'; -import { ModalCreateGroupPanel } from '../../CreateGroupPanel'; +import { ModalCreateGroupPanel } from '../../GroupPanel/CreateGroupPanel'; export const GroupPanel: React.FC<{ groupId: string; diff --git a/web/src/components/modals/GroupPanel/CreateGroupPanel.tsx b/web/src/components/modals/GroupPanel/CreateGroupPanel.tsx new file mode 100644 index 00000000..89f32266 --- /dev/null +++ b/web/src/components/modals/GroupPanel/CreateGroupPanel.tsx @@ -0,0 +1,57 @@ +import { findPluginPanelInfoByName } from '@/utils/plugin-helper'; +import React, { useState } from 'react'; +import { + GroupPanelType, + t, + useAsyncRequest, + createGroupPanel, + createFastFormSchema, + fieldSchema, + showToasts, +} from 'tailchat-shared'; +import { ModalWrapper } from '../../Modal'; +import { WebFastForm } from '../../WebFastForm'; +import { buildDataFromValues } from './helper'; +import type { GroupPanelValues } from './types'; +import { useGroupPanelFields } from './useGroupPanelFields'; + +const schema = createFastFormSchema({ + name: fieldSchema + .string() + .required(t('面板名不能为空')) + .max(20, t('面板名过长')), + type: fieldSchema.string().required(t('面板类型不能为空')), +}); + +/** + * 创建群组面板 + */ +export const ModalCreateGroupPanel: React.FC<{ + groupId: string; + onCreateSuccess: () => void; +}> = React.memo((props) => { + const [currentValues, setValues] = useState>({}); + + const [, handleSubmit] = useAsyncRequest( + async (values: GroupPanelValues) => { + await createGroupPanel(props.groupId, buildDataFromValues(values)); + showToasts(t('创建成功'), 'success'); + props.onCreateSuccess(); + }, + [props.groupId, props.onCreateSuccess] + ); + + const fields = useGroupPanelFields(props.groupId, currentValues); + + return ( + + + + ); +}); +ModalCreateGroupPanel.displayName = 'ModalCreateGroupPanel'; diff --git a/web/src/components/modals/GroupPanel/helper.ts b/web/src/components/modals/GroupPanel/helper.ts new file mode 100644 index 00000000..5f74dd10 --- /dev/null +++ b/web/src/components/modals/GroupPanel/helper.ts @@ -0,0 +1,34 @@ +import { findPluginPanelInfoByName } from '@/utils/plugin-helper'; +import { GroupPanelType } from 'tailchat-shared'; +import type { GroupPanelValues } from './types'; + +/** + * 根据表单数据生成需要提交的内容 + */ +export function buildDataFromValues(values: GroupPanelValues) { + const { name, type, ...meta } = values; + let panelType: number; + let provider: string | undefined = undefined; + let pluginPanelName: string | undefined = undefined; + + if (typeof type === 'string') { + // 创建一个来自插件的面板 + const panelName = type; + panelType = GroupPanelType.PLUGIN; + const pluginPanelInfo = findPluginPanelInfoByName(panelName); + if (pluginPanelInfo) { + provider = pluginPanelInfo.provider; + pluginPanelName = pluginPanelInfo.name; + } + } else { + panelType = type; + } + + return { + name, + type: panelType, + provider, + pluginPanelName, + meta, + }; +} diff --git a/web/src/components/modals/GroupPanel/types.ts b/web/src/components/modals/GroupPanel/types.ts new file mode 100644 index 00000000..95b84600 --- /dev/null +++ b/web/src/components/modals/GroupPanel/types.ts @@ -0,0 +1,7 @@ +import type { GroupPanelType } from 'tailchat-shared'; + +export interface GroupPanelValues { + name: string; + type: string | GroupPanelType; + [key: string]: unknown; +} diff --git a/web/src/components/modals/CreateGroupPanel.tsx b/web/src/components/modals/GroupPanel/useGroupPanelFields.tsx similarity index 50% rename from web/src/components/modals/CreateGroupPanel.tsx rename to web/src/components/modals/GroupPanel/useGroupPanelFields.tsx index 68df4fbb..5c9f5c50 100644 --- a/web/src/components/modals/CreateGroupPanel.tsx +++ b/web/src/components/modals/GroupPanel/useGroupPanelFields.tsx @@ -1,29 +1,18 @@ -import { pluginGroupPanel } from '@/plugin/common'; -import { findPluginPanelInfoByName } from '@/utils/plugin-helper'; -import React, { useMemo, useState } from 'react'; +import { UserSelector } from '@/components/UserSelector'; +import React from 'react'; +import { useMemo } from 'react'; import { FastFormFieldMeta, GroupPanelType, + isDevelopment, t, - useAsyncRequest, - createGroupPanel, - createFastFormSchema, - fieldSchema, - showToasts, + useFastFormContext, useGroupMemberUUIDs, - isDevelopment, } from 'tailchat-shared'; -import { ModalWrapper } from '../Modal'; -import { WebFastForm } from '../WebFastForm'; +import type { GroupPanelValues } from './types'; import _compact from 'lodash/compact'; -import { UserSelector } from '../UserSelector'; -import { useFastFormContext } from 'tailchat-shared/components/FastForm/context'; - -interface Values { - name: string; - type: string | GroupPanelType; - [key: string]: unknown; -} +import { pluginGroupPanel } from '@/plugin/common'; +import { findPluginPanelInfoByName } from '@/utils/plugin-helper'; const baseFields: FastFormFieldMeta[] = [ { type: 'text', name: 'name', label: t('面板名') }, @@ -48,59 +37,13 @@ const baseFields: FastFormFieldMeta[] = [ }, ]; -const schema = createFastFormSchema({ - name: fieldSchema - .string() - .required(t('面板名不能为空')) - .max(20, t('面板名过长')), - type: fieldSchema.string().required(t('面板类型不能为空')), -}); - -/** - * 创建群组面板 - */ -export const ModalCreateGroupPanel: React.FC<{ - groupId: string; - onCreateSuccess: () => void; -}> = React.memo((props) => { - const [currentValues, setValues] = useState>({}); - - const [, handleSubmit] = useAsyncRequest( - async (values: Values) => { - const { name, type, ...meta } = values; - let panelType: number; - let provider: string | undefined = undefined; - let pluginPanelName: string | undefined = undefined; - - if (typeof type === 'string') { - // 创建一个来自插件的面板 - const panelName = type; - panelType = GroupPanelType.PLUGIN; - const pluginPanelInfo = findPluginPanelInfoByName(panelName); - if (pluginPanelInfo) { - provider = pluginPanelInfo.provider; - pluginPanelName = pluginPanelInfo.name; - } - } else { - panelType = type; - } - - await createGroupPanel(props.groupId, { - name, - type: panelType, - provider, - pluginPanelName, - meta, - }); - showToasts(t('创建成功'), 'success'); - props.onCreateSuccess(); - }, - [props.groupId, props.onCreateSuccess] - ); - +export function useGroupPanelFields( + groupId: string, + currentValues: Partial +) { const disableSendMessageWithoutRender = useMemo(() => { const DisableSendMessageWithoutComponent: React.FC = () => { - const groupMemberUUIDs = useGroupMemberUUIDs(props.groupId); + const groupMemberUUIDs = useGroupMemberUUIDs(groupId); const context = useFastFormContext(); return ( @@ -119,9 +62,9 @@ export const ModalCreateGroupPanel: React.FC<{ 'DisableSendMessageWithoutComponent'; return DisableSendMessageWithoutComponent; - }, [props.groupId]); + }, [groupId]); - const field = useMemo(() => { + const fields = useMemo(() => { // NOTICE: 仅开发环境有这个配置 if (isDevelopment && currentValues.type === GroupPanelType.TEXT) { return _compact([ @@ -152,15 +95,5 @@ export const ModalCreateGroupPanel: React.FC<{ return baseFields; }, [currentValues]); - return ( - - - - ); -}); -ModalCreateGroupPanel.displayName = 'ModalCreateGroupPanel'; + return fields; +}