jinyaqiu 0c98b399b9
Some checks failed
Dev Deploy / Explore-Gitea-Actions (push) Failing after 14s
feat: 修改
2025-07-07 14:58:49 +08:00

196 lines
6.4 KiB
TypeScript

import ReturnArrow from "@/assets/icons/svg/returnArrow.svg";
import Chat from "@/components/ask/chat";
import AskHello from "@/components/ask/hello";
import SendMessage from "@/components/ask/send";
import { ThemedText } from "@/components/ThemedText";
import { fetchApi } from "@/lib/server-api-util";
import { Message } from "@/types/ask";
import { router, useLocalSearchParams } from "expo-router";
import { useCallback, useEffect, useRef, useState } from 'react';
import { KeyboardAvoidingView, Platform, ScrollView, StyleSheet, TouchableOpacity, View } from 'react-native';
import { useSafeAreaInsets } from "react-native-safe-area-context";
export default function AskScreen() {
const insets = useSafeAreaInsets();
// 在组件内部添加 ref
const scrollViewRef = useRef<ScrollView>(null);
// 用于控制是否显示问候页面
const [isHello, setIsHello] = useState(true);
// 获取对话id
const [conversationId, setConversationId] = useState<string | null>(null);
// 用户对话信息收集
const [userMessages, setUserMessages] = useState<Message[]>([]);
const createNewConversation = useCallback(async () => {
// TODO 用户未输入时,显示提示信息
setUserMessages([{
content: {
text: "请输入您的问题,寻找,请稍等..."
},
role: 'Assistant',
timestamp: new Date().toISOString()
}]);
const data = await fetchApi<string>("/chat/new", {
method: "POST",
});
setConversationId(data);
}, []);
// 获取路由参数
const { sessionId, newSession } = useLocalSearchParams<{
sessionId: string;
newSession: string;
}>();
// 添加自动滚动到底部的效果
useEffect(() => {
if (scrollViewRef.current && !isHello) {
scrollViewRef.current.scrollToEnd({ animated: true });
}
}, [userMessages, isHello]);
useEffect(() => {
if (sessionId) {
setConversationId(sessionId)
setIsHello(false)
fetchApi<Message[]>(`/chats/${sessionId}/message-history`).then((res) => {
setUserMessages(res)
})
}
if (newSession) {
setIsHello(false)
createNewConversation()
}
}, [sessionId, newSession])
return (
<View style={{ flex: 1, backgroundColor: 'white', paddingTop: insets.top }}>
{/* 导航栏 - 保持在顶部 */}
<View style={isHello ? "" : styles.navbar} className="relative w-full flex flex-row items-center justify-between pb-3 pt-[2rem]">
{/* 点击去memo list 页面 */}
<TouchableOpacity
style={styles.backButton}
onPress={() => {
router.replace('/memo-list');
}}
>
<ReturnArrow />
</TouchableOpacity>
<ThemedText className={`!text-textSecondary font-semibold text-3xl w-full text-center flex-1 ${isHello ? "opacity-0" : ""}`}>MemoWake</ThemedText>
<View />
</View>
<KeyboardAvoidingView
style={{ flex: 1 }}
behavior={Platform.OS === "ios" ? "padding" : "height"}
keyboardVerticalOffset={Platform.OS === "ios" ? 0 : 20}
>
<ScrollView
ref={scrollViewRef}
contentContainerStyle={{ flexGrow: 1 }}
keyboardShouldPersistTaps="handled"
showsVerticalScrollIndicator={false}
bounces={false}
onContentSizeChange={() => {
if (scrollViewRef.current && !isHello) {
scrollViewRef.current.scrollToEnd({ animated: true });
}
}}
>
{/* 内容区域 */}
<View className="flex-1">
{isHello ? <AskHello /> : <Chat userMessages={userMessages} sessionId={sessionId} />}
</View>
</ScrollView>
{/* 功能区 - 放在 KeyboardAvoidingView 内但在 ScrollView 外 */}
<View className="w-full px-[1.5rem] mb-[2rem]">
<SendMessage setUserMessages={setUserMessages} setConversationId={setConversationId} setIsHello={setIsHello} conversationId={conversationId} />
</View>
</KeyboardAvoidingView>
</View>
);
}
const styles = StyleSheet.create({
navbar: {
boxShadow: '0 4px 6px -1px rgba(0, 0, 0, 0.1)',
backgroundColor: 'white',
zIndex: 10,
},
container: {
flex: 1,
backgroundColor: 'white',
borderTopLeftRadius: 20,
borderTopRightRadius: 20,
paddingTop: 60
},
backButton: {
marginLeft: 16,
padding: 12
},
content: {
flex: 1,
padding: 20,
alignItems: 'center',
justifyContent: 'center',
},
description: {
fontSize: 16,
color: '#666',
textAlign: 'center',
marginBottom: 40,
paddingHorizontal: 20,
lineHeight: 24,
},
chipsContainer: {
width: "100%",
flexDirection: 'row',
flexWrap: 'nowrap',
justifyContent: 'center',
marginBottom: 40,
display: "flex",
alignItems: "center",
overflow: "scroll",
},
chip: {
flexDirection: 'row',
alignItems: 'center',
backgroundColor: '#FFF5E6',
paddingVertical: 10,
paddingHorizontal: 16,
borderRadius: 20,
margin: 5,
},
chipText: {
marginLeft: 6,
color: '#FF9500',
fontSize: 14,
},
inputContainer: {
flexDirection: 'row',
padding: 16,
paddingBottom: 30,
backgroundColor: 'white',
},
input: {
flex: 1,
borderColor: '#FF9500',
borderWidth: 1,
borderRadius: 25,
paddingHorizontal: 20,
paddingVertical: 12,
fontSize: 16,
width: '100%', // 确保输入框宽度撑满
},
voiceButton: {
width: 40,
height: 40,
borderRadius: 20,
backgroundColor: '#FF9500',
justifyContent: 'center',
alignItems: 'center',
marginRight: 8, // 添加一点右边距
},
});