feat: Implement character avatar upload and refactor character form fields and API calls.

This commit is contained in:
liqupan
2026-02-02 22:48:11 +08:00
parent 6c32d845a7
commit dec5748cca
15 changed files with 369 additions and 197 deletions

View File

@@ -19,13 +19,13 @@ import {
} from '@/components/ui/form';
import { Input } from '@/components/ui/input';
import { Button } from '@/components/ui/button';
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
import { Checkbox } from '@/components/ui/checkbox';
import { Textarea } from '@/components/ui/textarea';
import { useCharacterDialog } from './character-dialog-context';
import { Character, characterSchema } from '../data/schema';
import { createCharacter, updateCharacter } from '../data/api';
import { useQueryClient } from '@tanstack/react-query';
import { ImageUpload } from './image-upload';
export function CharacterDialog() {
const { open, setOpen, character } = useCharacterDialog();
@@ -36,12 +36,10 @@ export function CharacterDialog() {
resolver: zodResolver(characterSchema),
defaultValues: {
name: '',
status: 'online',
compatibility: 0,
is_active: true,
is_locked: false,
sort_order: 0,
tagline: '',
avatar_path: '',
description: '',
ai_system_prompt: '',
ai_greeting: '',
@@ -56,12 +54,10 @@ export function CharacterDialog() {
} else {
form.reset({
name: '',
status: 'online',
compatibility: 0,
is_active: true,
is_locked: false,
sort_order: 0,
tagline: '',
avatar_path: '',
description: '',
ai_system_prompt: '',
ai_greeting: '',
@@ -74,7 +70,7 @@ export function CharacterDialog() {
console.log('📝 表单值:', values);
console.log('✅ 表单验证状态:', form.formState.isValid);
console.log('❌ 表单错误:', form.formState.errors);
try {
// 确保 JSONB 字段有默认值
const sanitizedValues = {
@@ -82,28 +78,28 @@ export function CharacterDialog() {
ai_personality: values.ai_personality || {},
ai_voice_config: values.ai_voice_config || {},
};
console.log('🔧 处理后的数据:', sanitizedValues);
if (isEdit) {
console.log('🔄 更新角色ID:', character.id);
await updateCharacter({ ...sanitizedValues, id: character.id });
await updateCharacter({ ...sanitizedValues, id: character.id } as any);
toast.success('角色更新成功');
} else {
console.log(' 创建新角色');
await createCharacter(sanitizedValues);
await createCharacter(sanitizedValues as any);
toast.success('角色创建成功');
}
setOpen(false);
queryClient.invalidateQueries({ queryKey: ['characters'] });
} catch (error) {
console.error('❌ 保存角色失败,详细错误:', error);
// 改进错误信息显示
const errorMessage = error instanceof Error
? error.message
const errorMessage = error instanceof Error
? error.message
: JSON.stringify(error);
toast.error(`保存角色失败: ${errorMessage}`);
}
};
@@ -120,7 +116,7 @@ export function CharacterDialog() {
</DialogDescription>
</DialogHeader>
<Form {...form}>
<form
<form
onSubmit={(e) => {
console.log('📋 Form onSubmit 事件触发', e);
console.log('📊 当前表单状态:', form.formState);
@@ -133,10 +129,10 @@ export function CharacterDialog() {
toast.error('请检查表单输入');
}
)(e);
}}
}}
className='space-y-4'
>
<div className='grid grid-cols-2 gap-4'>
<div className='grid grid-cols-1 gap-4'>
<FormField
control={form.control}
name='name'
@@ -150,38 +146,19 @@ export function CharacterDialog() {
</FormItem>
)}
/>
<FormField
control={form.control}
name='status'
render={({ field }) => (
<FormItem>
<FormLabel></FormLabel>
<Select onValueChange={field.onChange} defaultValue={field.value}>
<FormControl>
<SelectTrigger>
<SelectValue placeholder='选择状态' />
</SelectTrigger>
</FormControl>
<SelectContent>
<SelectItem value='online'>线</SelectItem>
<SelectItem value='busy'></SelectItem>
<SelectItem value='offline'>线</SelectItem>
</SelectContent>
</Select>
<FormMessage />
</FormItem>
)}
/>
</div>
<FormField
control={form.control}
name='tagline'
name='avatar_path'
render={({ field }) => (
<FormItem>
<FormLabel></FormLabel>
<FormLabel></FormLabel>
<FormControl>
<Input placeholder='简短描述' {...field} value={field.value || ''} />
<ImageUpload
value={field.value}
onChange={field.onChange}
/>
</FormControl>
<FormMessage />
</FormItem>
@@ -203,25 +180,6 @@ export function CharacterDialog() {
/>
<div className='grid grid-cols-2 gap-4'>
<FormField
control={form.control}
name='compatibility'
render={({ field }) => (
<FormItem>
<FormLabel> (%)</FormLabel>
<FormControl>
<Input
type='number'
min={0}
max={100}
{...field}
onChange={e => field.onChange(parseInt(e.target.value))}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
<FormField
control={form.control}
name='sort_order'
@@ -315,7 +273,7 @@ export function CharacterDialog() {
<Button type='button' variant='outline' onClick={() => setOpen(false)}>
</Button>
<Button
<Button
type='submit'
disabled={form.formState.isSubmitting}
onClick={() => console.log('💾 保存按钮被点击')}