fix: bug
This commit is contained in:
parent
30fa29b0ac
commit
b46ad76161
|
|
@ -154,6 +154,7 @@ export default function HomeScreen() {
|
|||
<TemplateCard
|
||||
id={item.id}
|
||||
title={item.title}
|
||||
titleEn={item.titleEn}
|
||||
previewUrl={item.previewUrl}
|
||||
webpPreviewUrl={item.webpPreviewUrl}
|
||||
coverImageUrl={item.coverImageUrl}
|
||||
|
|
|
|||
|
|
@ -178,9 +178,11 @@ export const DynamicForm = forwardRef<DynamicFormRef, DynamicFormProps>(
|
|||
const handlePickAndUploadImage = useCallback(async (nodeId: string) => {
|
||||
try {
|
||||
const [imageUri] = await imgPicker({ maxImages: 1 })
|
||||
console.log('[DynamicForm] 选择图片成功:', imageUri)
|
||||
|
||||
// 上传图片
|
||||
const url = await uploadFile({ uri: imageUri })
|
||||
console.log('[DynamicForm] 上传成功,URL:', url)
|
||||
updateFormData(nodeId, url)
|
||||
setPreviewImages((prev) => ({ ...prev, [nodeId]: imageUri }))
|
||||
} catch (error: any) {
|
||||
|
|
@ -188,7 +190,7 @@ export const DynamicForm = forwardRef<DynamicFormRef, DynamicFormProps>(
|
|||
if (error?.message === '未选择任何图片') {
|
||||
return
|
||||
}
|
||||
console.error('Pick and upload failed:', error)
|
||||
console.error('[DynamicForm] 上传失败:', { error, message: error?.message, stack: error?.stack })
|
||||
Toast.show(t('dynamicForm.uploadFailed') || '上传失败,请重试')
|
||||
}
|
||||
}, [t, updateFormData])
|
||||
|
|
|
|||
|
|
@ -77,4 +77,50 @@ describe('TemplateCard Component', () => {
|
|||
expect(typeof TemplateCard).toBe('object')
|
||||
})
|
||||
})
|
||||
|
||||
describe('Multi-language support', () => {
|
||||
it('should display Chinese title when language is zh-CN', () => {
|
||||
const title = '测试模板'
|
||||
const titleEn = 'Test Template'
|
||||
const language = 'zh-CN'
|
||||
|
||||
// 根据语言选择显示的标题
|
||||
const displayTitle = language === 'en-US' ? titleEn : title
|
||||
|
||||
expect(displayTitle).toBe('测试模板')
|
||||
})
|
||||
|
||||
it('should display English title when language is en-US', () => {
|
||||
const title = '测试模板'
|
||||
const titleEn = 'Test Template'
|
||||
const language = 'en-US'
|
||||
|
||||
// 根据语言选择显示的标题
|
||||
const displayTitle = language === 'en-US' ? titleEn : title
|
||||
|
||||
expect(displayTitle).toBe('Test Template')
|
||||
})
|
||||
|
||||
it('should fallback to Chinese title when titleEn is missing', () => {
|
||||
const title = '测试模板'
|
||||
const titleEn = undefined
|
||||
const language = 'en-US'
|
||||
|
||||
// 当 titleEn 不存在时,回退到中文标题
|
||||
const displayTitle = language === 'en-US' && titleEn ? titleEn : title
|
||||
|
||||
expect(displayTitle).toBe('测试模板')
|
||||
})
|
||||
|
||||
it('should fallback to Chinese title when titleEn is empty string', () => {
|
||||
const title = '测试模板'
|
||||
const titleEn = ''
|
||||
const language = 'en-US'
|
||||
|
||||
// 当 titleEn 为空字符串时,回退到中文标题
|
||||
const displayTitle = language === 'en-US' && titleEn ? titleEn : title
|
||||
|
||||
expect(displayTitle).toBe('测试模板')
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -2,10 +2,12 @@ import React, { memo, useCallback, useMemo } from 'react'
|
|||
import { Pressable, StyleSheet, Text, View, ViewStyle, ImageStyle } from 'react-native'
|
||||
import { Image } from 'expo-image'
|
||||
import { LinearGradient } from 'expo-linear-gradient'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export interface TemplateCardProps {
|
||||
id?: string
|
||||
title: string
|
||||
titleEn?: string
|
||||
previewUrl?: string
|
||||
webpPreviewUrl?: string
|
||||
coverImageUrl?: string
|
||||
|
|
@ -49,6 +51,7 @@ const GRADIENT_END = { x: 0, y: 1 }
|
|||
const TemplateCardComponent: React.FC<TemplateCardProps> = ({
|
||||
id,
|
||||
title,
|
||||
titleEn,
|
||||
previewUrl,
|
||||
webpPreviewUrl,
|
||||
coverImageUrl,
|
||||
|
|
@ -57,9 +60,16 @@ const TemplateCardComponent: React.FC<TemplateCardProps> = ({
|
|||
onPress,
|
||||
testID,
|
||||
}) => {
|
||||
const { i18n } = useTranslation()
|
||||
const aspectRatio = useMemo(() => parseAspectRatio(aspectRatioString), [aspectRatioString])
|
||||
const imageUri = useMemo(() => getImageUri(webpPreviewUrl, previewUrl, coverImageUrl), [webpPreviewUrl, previewUrl, coverImageUrl])
|
||||
|
||||
// Select display title based on current language
|
||||
const displayTitle = useMemo(() => {
|
||||
const isEnglish = i18n.language === 'en-US'
|
||||
return isEnglish && titleEn ? titleEn : title
|
||||
}, [i18n.language, title, titleEn])
|
||||
|
||||
// 使用 useCallback 缓存 onPress 回调
|
||||
const handlePress = useCallback(() => {
|
||||
if (id) {
|
||||
|
|
@ -105,7 +115,7 @@ const TemplateCardComponent: React.FC<TemplateCardProps> = ({
|
|||
style={styles.cardImageGradient}
|
||||
/>
|
||||
<Text style={styles.cardTitle} numberOfLines={1}>
|
||||
{title}
|
||||
{displayTitle}
|
||||
</Text>
|
||||
</View>
|
||||
</Pressable>
|
||||
|
|
|
|||
|
|
@ -103,6 +103,13 @@ const mockCategories: Category[] = [
|
|||
{ id: 'cat-3', name: 'Category 3', templates: [] },
|
||||
]
|
||||
|
||||
// Test data with multi-language support
|
||||
const mockCategoriesWithI18n: Array<Category & { nameEn: string }> = [
|
||||
{ id: 'cat-1', name: '分类1', nameEn: 'Category 1', templates: [] },
|
||||
{ id: 'cat-2', name: '分类2', nameEn: 'Category 2', templates: [] },
|
||||
{ id: 'cat-3', name: '分类3', nameEn: 'Category 3', templates: [] },
|
||||
]
|
||||
|
||||
describe('useTabNavigation - core logic', () => {
|
||||
describe('initialization', () => {
|
||||
it('should select first category when initialCategoryId is empty', () => {
|
||||
|
|
@ -256,4 +263,41 @@ describe('useTabNavigation - core logic', () => {
|
|||
expect(state.currentCategory).toBeUndefined()
|
||||
})
|
||||
})
|
||||
|
||||
describe('multi-language support', () => {
|
||||
it('should generate tabs with Chinese names when language is zh-CN', () => {
|
||||
// 模拟中文环境
|
||||
const language = 'zh-CN'
|
||||
const tabs = mockCategoriesWithI18n.map(cat =>
|
||||
language === 'en-US' ? cat.nameEn : cat.name
|
||||
)
|
||||
|
||||
expect(tabs).toEqual(['分类1', '分类2', '分类3'])
|
||||
})
|
||||
|
||||
it('should generate tabs with English names when language is en-US', () => {
|
||||
// 模拟英文环境
|
||||
const language = 'en-US'
|
||||
const tabs = mockCategoriesWithI18n.map(cat =>
|
||||
language === 'en-US' ? cat.nameEn : cat.name
|
||||
)
|
||||
|
||||
expect(tabs).toEqual(['Category 1', 'Category 2', 'Category 3'])
|
||||
})
|
||||
|
||||
it('should fallback to Chinese name when nameEn is missing', () => {
|
||||
const categoriesWithMissingEn = [
|
||||
{ id: 'cat-1', name: '分类1', nameEn: 'Category 1' },
|
||||
{ id: 'cat-2', name: '分类2', nameEn: '' }, // nameEn 为空
|
||||
{ id: 'cat-3', name: '分类3' }, // 没有 nameEn 字段
|
||||
]
|
||||
|
||||
const language = 'en-US'
|
||||
const tabs = categoriesWithMissingEn.map(cat =>
|
||||
language === 'en-US' && cat.nameEn ? cat.nameEn : cat.name
|
||||
)
|
||||
|
||||
expect(tabs).toEqual(['Category 1', '分类2', '分类3'])
|
||||
})
|
||||
})
|
||||
})
|
||||
|
|
|
|||
|
|
@ -1,9 +1,11 @@
|
|||
import { useState, useMemo, useCallback, useEffect } from 'react'
|
||||
import { CategoryTemplate } from '@repo/sdk'
|
||||
import { useTranslation } from 'react-i18next'
|
||||
|
||||
export interface Category {
|
||||
id: string
|
||||
name: string
|
||||
nameEn?: string
|
||||
templates?: CategoryTemplate[]
|
||||
}
|
||||
|
||||
|
|
@ -23,6 +25,7 @@ export interface UseTabNavigationReturn {
|
|||
|
||||
export function useTabNavigation(options: UseTabNavigationOptions): UseTabNavigationReturn {
|
||||
const { categories, initialCategoryId } = options
|
||||
const { i18n } = useTranslation()
|
||||
|
||||
// State for active tab index
|
||||
const [activeIndex, setActiveIndex] = useState<number>(() => {
|
||||
|
|
@ -52,10 +55,14 @@ export function useTabNavigation(options: UseTabNavigationOptions): UseTabNaviga
|
|||
}
|
||||
}, [categories, selectedCategoryId])
|
||||
|
||||
// Generate tabs array from category names
|
||||
// Generate tabs array from category names with i18n support
|
||||
const tabs = useMemo(() => {
|
||||
return categories.map(category => category.name)
|
||||
}, [categories])
|
||||
const isEnglish = i18n.language === 'en-US'
|
||||
return categories.map(category => {
|
||||
// Use English name if available and language is English, otherwise use Chinese name
|
||||
return isEnglish && category.nameEn ? category.nameEn : category.name
|
||||
})
|
||||
}, [categories, i18n.language])
|
||||
|
||||
// Get current category based on selectedCategoryId
|
||||
const currentCategory = useMemo(() => {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,9 @@ import { handleError } from '@/hooks/use-error'
|
|||
|
||||
export async function uploadFile(params: { uri: string; mimeType?: string; fileName?: string }): Promise<string> {
|
||||
const { uri, mimeType, fileName } = params
|
||||
|
||||
console.log('[uploadFile] 开始上传:', { uri, mimeType, fileName, platform: Platform.OS })
|
||||
|
||||
const formData = new FormData()
|
||||
formData.append('file', {
|
||||
uri: uri,
|
||||
|
|
@ -17,8 +20,10 @@ export async function uploadFile(params: { uri: string; mimeType?: string; fileN
|
|||
const { data, error } = await handleError(async () => await fileController.uploadS3(formData))
|
||||
|
||||
if (error || !data?.data) {
|
||||
console.error('[uploadFile] 上传失败:', { error, data, uri })
|
||||
throw error || new Error('上传失败')
|
||||
}
|
||||
|
||||
console.log('[uploadFile] 上传成功:', data.data)
|
||||
return data.data
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue