11// src/feature/channel/components/ChannelForm.tsx
2- import { useState } from 'react'
2+ import { useEffect , useState } from 'react'
33import { useForm } from 'react-hook-form'
44import { zodResolver } from '@hookform/resolvers/zod'
55import { Input } from '@/components/ui/input'
@@ -13,7 +13,7 @@ import {
1313 FormMessage ,
1414} from '@/components/ui/form'
1515import { channelCreateSchema } from '@/validation/channel'
16- import { useChannelTypeMetas , useCreateChannel , useUpdateChannel , useTestChannelPreviewAll , useChannelDefaultModels } from '../hooks'
16+ import { useChannelTypeMetas , useCreateChannel , useUpdateChannel , useUpdateChannelStatus , useTestChannelPreviewAll , useChannelDefaultModels } from '../hooks'
1717import { useModels } from '@/feature/model/hooks'
1818import { useTranslation } from 'react-i18next'
1919import { ChannelCreateForm } from '@/validation/channel'
@@ -26,7 +26,7 @@ import { AdvancedErrorDisplay } from '@/components/common/error/errorDisplay'
2626import { Skeleton } from "@/components/ui/skeleton"
2727import { AnimatedContainer } from '@/components/ui/animation/components/animated-container'
2828import { toast } from 'sonner'
29- import { FlaskConical , Loader2 , Info } from 'lucide-react'
29+ import { FlaskConical , Loader2 , Info , Power , PowerOff } from 'lucide-react'
3030import { ChannelTestDialog } from './ChannelTestDialog'
3131import { DefaultModelsDialog } from './DefaultModelsDialog'
3232import { ChannelConfigEditor } from './ChannelConfigEditor'
@@ -53,7 +53,7 @@ interface ChannelFormProps {
5353export function ChannelForm ( {
5454 mode = 'create' ,
5555 channelId,
56- channel : _channel ,
56+ channel,
5757 onSuccess,
5858 defaultValues = {
5959 type : 0 ,
@@ -73,6 +73,7 @@ export function ChannelForm({
7373 const isCreateLikeMode = mode === 'create' || mode === 'copy'
7474 const [ defaultModelsDialogOpen , setDefaultModelsDialogOpen ] = useState ( false )
7575 const [ configsError , setConfigsError ] = useState < string | null > ( null )
76+ const [ currentStatus , setCurrentStatus ] = useState ( channel ?. status ?? 1 )
7677
7778 // Determine initial useDefaultModels state
7879 const initialUseDefault = mode === 'create'
@@ -101,6 +102,8 @@ export function ChannelForm({
101102 clearError : clearUpdateError
102103 } = useUpdateChannel ( )
103104
105+ const { updateStatus, isLoading : isStatusUpdating } = useUpdateChannelStatus ( )
106+
104107 // Test channel hook
105108 const {
106109 testChannelPreviewAll,
@@ -112,6 +115,10 @@ export function ChannelForm({
112115
113116 const [ testDialogOpen , setTestDialogOpen ] = useState ( false )
114117
118+ useEffect ( ( ) => {
119+ setCurrentStatus ( channel ?. status ?? 1 )
120+ } , [ channel ?. status , channel ?. id ] )
121+
115122 // 动态状态
116123 const isLoading = isCreateLikeMode ? isCreating : isUpdating
117124 const error = isCreateLikeMode ? createError : updateError
@@ -225,6 +232,22 @@ export function ChannelForm({
225232 setIsUserSubmitting ( true )
226233 }
227234
235+ const handleStatusToggle = ( ) => {
236+ if ( mode !== 'update' || ! channelId ) {
237+ return
238+ }
239+
240+ const nextStatus = currentStatus === 2 ? 1 : 2
241+ updateStatus (
242+ { id : channelId , status : { status : nextStatus } } ,
243+ {
244+ onSuccess : ( ) => {
245+ setCurrentStatus ( nextStatus )
246+ } ,
247+ }
248+ )
249+ }
250+
228251 // Handle toggle between default and custom models
229252 const handleToggleDefaultModels = ( useDefault : boolean ) => {
230253 setUseDefaultModels ( useDefault )
@@ -883,29 +906,57 @@ export function ChannelForm({
883906 />
884907
885908 { /* 提交和测试按钮 */ }
886- < div className = "flex justify-between items-center" >
887- < Button
888- type = "button"
889- variant = "outline"
890- onClick = { handleTestClick }
891- disabled = { isTesting || isLoading }
892- className = "flex items-center gap-2"
893- >
894- { isTesting ? (
895- < >
896- < Loader2 className = "h-4 w-4 animate-spin" />
897- { t ( "channel.testing" ) }
898- </ >
899- ) : (
900- < >
901- < FlaskConical className = "h-4 w-4" />
902- { t ( "channel.test" ) }
903- </ >
904- ) }
905- </ Button >
909+ < div className = "flex justify-between items-center gap-3" >
910+ < div className = "flex items-center gap-2" >
911+ < Button
912+ type = "button"
913+ variant = "outline"
914+ onClick = { handleTestClick }
915+ disabled = { isTesting || isLoading || isStatusUpdating }
916+ className = "flex items-center gap-2"
917+ >
918+ { isTesting ? (
919+ < >
920+ < Loader2 className = "h-4 w-4 animate-spin" />
921+ { t ( "channel.testing" ) }
922+ </ >
923+ ) : (
924+ < >
925+ < FlaskConical className = "h-4 w-4" />
926+ { t ( "channel.test" ) }
927+ </ >
928+ ) }
929+ </ Button >
930+ { mode === 'update' && channelId ? (
931+ < Button
932+ type = "button"
933+ variant = "outline"
934+ onClick = { handleStatusToggle }
935+ disabled = { isLoading || isTesting || isStatusUpdating }
936+ className = "flex items-center gap-2"
937+ >
938+ { isStatusUpdating ? (
939+ < >
940+ < Loader2 className = "h-4 w-4 animate-spin" />
941+ { currentStatus === 2 ? t ( "channel.enable" ) : t ( "channel.disable" ) }
942+ </ >
943+ ) : currentStatus === 2 ? (
944+ < >
945+ < Power className = "h-4 w-4 text-emerald-600 dark:text-emerald-500" />
946+ { t ( "channel.enable" ) }
947+ </ >
948+ ) : (
949+ < >
950+ < PowerOff className = "h-4 w-4 text-yellow-600 dark:text-yellow-500" />
951+ { t ( "channel.disable" ) }
952+ </ >
953+ ) }
954+ </ Button >
955+ ) : null }
956+ </ div >
906957 < Button
907958 type = "submit"
908- disabled = { isLoading || isTesting }
959+ disabled = { isLoading || isTesting || isStatusUpdating }
909960 onClick = { handleSubmitClick }
910961 >
911962 { isLoading ? t ( "channel.dialog.submitting" ) : isCreateLikeMode ? t ( "channel.dialog.create" ) : t ( "channel.dialog.update" ) }
0 commit comments