feat: 添加tabber

This commit is contained in:
2025-10-22 14:06:06 +08:00
parent ae8e5cf384
commit daf2bf503e
7 changed files with 64 additions and 39 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 106 KiB

After

Width:  |  Height:  |  Size: 110 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

View File

@@ -1,11 +1,14 @@
.main-layout { .main-layout {
height: 100%; height: 100%;
.layout-content { .layout-content {
--bottom: 0;
--bottom: constant(safe-area-inset-bottom);
--bottom: env(safe-area-inset-bottom);
height: 100%; height: 100%;
overflow-y: auto; overflow-y: auto;
// padding-bottom: 150px; // padding-bottom: constant(safe-area-inset-bottom); /*兼容 IOS<11.2*/
padding-bottom: constant(safe-area-inset-bottom); /*兼容 IOS<11.2*/ // padding-bottom: env(safe-area-inset-bottom); /*兼容 IOS>11.2*/
padding-bottom: env(safe-area-inset-bottom); /*兼容 IOS>11.2*/ padding-bottom: calc(var(--bottom) + 44px);
} }
.layout-tab { .layout-tab {

View File

@@ -1,7 +1,8 @@
import React from "react"; import React from "react";
import { NavBar, SafeArea } from "antd-mobile"; import { NavBar, SafeArea, TabBar } from "antd-mobile";
import { useNavigate } from "react-router-dom"; import { useNavigate } from "react-router-dom";
import "./index.less"; import "./index.less";
import { Translate, Electrocardiogram, GithubOne, Blossom, User } from "@icon-park/react";
interface MainLayoutProps { interface MainLayoutProps {
children: React.ReactNode; children: React.ReactNode;
@@ -20,30 +21,42 @@ const MainLayout: React.FC<MainLayoutProps> = ({
}) => { }) => {
const navigate = useNavigate(); const navigate = useNavigate();
// const location = useLocation(); // const location = useLocation();
const [pathname, setPathname] = React.useState(location.pathname);
// const tabs = [ const tabs = [
{
key: "/translate",
title: "宠物翻译",
icon: <Translate />,
},
{
key: "/translate/archives",
title: "情绪监控",
icon: <Electrocardiogram />,
},
{
key: "/translate/mood",
title: "我的宠物",
icon: <GithubOne />,
},
// { // {
// key: "/", // key: "/translate/mood",
// title: "宠物翻译", // title: "宠物服务",
// icon: <CattleZodiac />, // icon: <Blossom />,
// }, // },
// { // {
// key: "/set", // key: "/translate/mood",
// title: "待办", // title: "个人中心",
// icon: <User />, // icon: <User />,
// }, // },
// { ];
// key: "/message",
// title: "消息",
// icon: <User />,
// },
// {
// key: "/me",
// title: "我的",
// icon: <User size="24" />, const setRouteActive = (value: string) => {
// }, console.log(value);
// ];
setPathname(value);
navigate(value);
};
const goBack = () => { const goBack = () => {
// 打印路由栈 // 打印路由栈
@@ -68,15 +81,11 @@ const MainLayout: React.FC<MainLayoutProps> = ({
<div className="layout-content">{children}</div> <div className="layout-content">{children}</div>
<div className="footer layout-tab"> <div className="footer layout-tab">
{/* <TabBar <TabBar activeKey={pathname} onChange={(value) => setRouteActive(value)} safeArea={true}>
activeKey={pathname}
onChange={(value) => setRouteActive(value)}
safeArea={true}
>
{tabs.map((item) => ( {tabs.map((item) => (
<TabBar.Item key={item.key} icon={item.icon} title={item.title} /> <TabBar.Item key={item.key} icon={item.icon} title={item.title} />
))} ))}
</TabBar> */} </TabBar>
</div> </div>
</div> </div>
); );

View File

@@ -1,9 +1,10 @@
import { useRef, useState } from "react"; import { useEffect, useRef, useState } from "react";
import { Avatar, Divider, Space, SpinLoading, Toast } from "antd-mobile"; import { Avatar, Divider, Space, SpinLoading, Toast } from "antd-mobile";
import { VoiceIcon } from "@workspace/shared"; import { VoiceIcon } from "@workspace/shared";
import { Message } from "../../../types"; import { Message } from "../../../types";
import "./index.less"; import "./index.less";
import { Refresh } from "@icon-park/react"; import { Refresh } from "@icon-park/react";
import DefAvatar from "@/assets/translate/def-avatar.png";
interface DefinedProps { interface DefinedProps {
data: Message[]; data: Message[];
@@ -48,7 +49,7 @@ function Index(props: DefinedProps) {
}; };
const renderAvatar = (item: Message) => { const renderAvatar = (item: Message) => {
return <Avatar src={item.petAvatar || ""} style={{ "--border-radius": "32px" }} />; return <Avatar src={item.petAvatar || DefAvatar} style={{ "--border-radius": "32px" }} />;
}; };
const refreshMessage = async (messageId: number, e: React.MouseEvent) => { const refreshMessage = async (messageId: number, e: React.MouseEvent) => {
@@ -107,7 +108,10 @@ function Index(props: DefinedProps) {
<span className="name"> <span className="name">
{item.isTranslating && !item.isRefresh ? "" : item.petName ?? "未知宠物"} {item.isTranslating && !item.isRefresh ? "" : item.petName ?? "未知宠物"}
</span> </span>
{!(item.isTranslating && !item.isRefresh) && (
<Divider direction="vertical" style={{ margin: "0px 8px" }} /> <Divider direction="vertical" style={{ margin: "0px 8px" }} />
)}
<span className="">{item.createTime}</span> <span className="">{item.createTime}</span>
</div> </div>
<div className="voice-container" onClick={() => playAudio(item.id, item.contentText)}> <div className="voice-container" onClick={() => playAudio(item.id, item.contentText)}>
@@ -122,7 +126,7 @@ function Index(props: DefinedProps) {
</div> </div>
))} ))}
<div style={{ height: "80px", width: "100%" }}></div> <div style={{ height: "130px", width: "100%" }}></div>
</div> </div>
); );
} }

View File

@@ -1,4 +1,4 @@
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useMemo, useState } from "react";
import { Image, Toast } from "antd-mobile"; import { Image, Toast } from "antd-mobile";
import MessageCom from "./component/message"; import MessageCom from "./component/message";
import VoiceRecord from "./component/voice"; import VoiceRecord from "./component/voice";
@@ -35,6 +35,15 @@ function Index(props: DefinedProps) {
const [visible, setVisible] = useState<boolean>(false); const [visible, setVisible] = useState<boolean>(false);
const [dialogId, setDialogId] = useState<number>(0); const [dialogId, setDialogId] = useState<number>(0);
// 创建稳定化的消息字符串(排除 isTranslating 字段变化的影响)
const stableMessagesString = useMemo(() => {
const stableMessages = messages.map((msg) => {
const { isTranslating, isRefresh, ...rest } = msg;
return rest;
});
return JSON.stringify(stableMessages);
}, [messages]);
useEffect(() => { useEffect(() => {
setCurrentLanguage(menuItems[0]); setCurrentLanguage(menuItems[0]);
fetchInitialMessages(); fetchInitialMessages();
@@ -75,7 +84,7 @@ function Index(props: DefinedProps) {
scrollToBottom(); scrollToBottom();
}); });
} }
}, [messages, scrollToBottom]); }, [stableMessagesString, scrollToBottom]);
//完成录音 //完成录音
const onRecordingComplete = useCallback( const onRecordingComplete = useCallback(

View File

@@ -7,7 +7,7 @@ export default defineConfig({
// basicSsl() // basicSsl()
// target: "https://petshy.tashowz.com", // target: "https://petshy.tashowz.com",
// http://192.168.1.231:48080 // http://192.168.1.231:48080
plugins: [react(), basicSsl()], plugins: [react()],
server: { server: {
port: 3000, port: 3000,
host: "0.0.0.0", host: "0.0.0.0",