feat: init
This commit is contained in:
@@ -23,6 +23,7 @@
|
|||||||
"antd-mobile-icons": "^0.3.0",
|
"antd-mobile-icons": "^0.3.0",
|
||||||
"axios": "^1.6.2",
|
"axios": "^1.6.2",
|
||||||
"axios-hooks": "^5.0.2",
|
"axios-hooks": "^5.0.2",
|
||||||
|
"framer-motion": "^12.23.12",
|
||||||
"js-audio-recorder": "^1.0.7",
|
"js-audio-recorder": "^1.0.7",
|
||||||
"jsqr": "^1.4.0",
|
"jsqr": "^1.4.0",
|
||||||
"less": "^4.2.0",
|
"less": "^4.2.0",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// components/ErrorBoundary/index.tsx
|
// components/ErrorBoundary/index.tsx
|
||||||
import React, { Component, ReactNode } from "react";
|
import { Component, ReactNode } from "react";
|
||||||
import { Result, Button } from "antd-mobile";
|
import { Result, Button } from "antd-mobile";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
.actions {
|
.actions {
|
||||||
display: flex;
|
display: flex;
|
||||||
gap: 16px;
|
gap: 12px;
|
||||||
margin-top: 24px;
|
margin-top: 24px;
|
||||||
|
|
||||||
.button {
|
.button {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import React, { useCallback, useState } from "react";
|
import React, { useCallback } from "react";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
|
|
||||||
const VoiceIcon = (props: { isPlaying: boolean; onChange?: () => void }) => {
|
const VoiceIcon = (props: { isPlaying: boolean; onChange?: () => void }) => {
|
||||||
@@ -7,10 +7,7 @@ const VoiceIcon = (props: { isPlaying: boolean; onChange?: () => void }) => {
|
|||||||
props.onChange?.();
|
props.onChange?.();
|
||||||
}, [isPlaying]);
|
}, [isPlaying]);
|
||||||
return (
|
return (
|
||||||
<div
|
<div className={`voice-icon ${isPlaying ? "playing" : ""}`} onClick={onChange}>
|
||||||
className={`voice-icon ${isPlaying ? "playing" : ""}`}
|
|
||||||
onClick={onChange}
|
|
||||||
>
|
|
||||||
<div className="wave wave1"></div>
|
<div className="wave wave1"></div>
|
||||||
<div className="wave wave2"></div>
|
<div className="wave wave2"></div>
|
||||||
<div className="wave wave3"></div>
|
<div className="wave wave3"></div>
|
||||||
|
|||||||
38
pnpm-lock.yaml
generated
38
pnpm-lock.yaml
generated
@@ -41,6 +41,9 @@ importers:
|
|||||||
axios-hooks:
|
axios-hooks:
|
||||||
specifier: ^5.0.2
|
specifier: ^5.0.2
|
||||||
version: 5.1.1(axios@1.11.0)(react@18.3.1)
|
version: 5.1.1(axios@1.11.0)(react@18.3.1)
|
||||||
|
framer-motion:
|
||||||
|
specifier: ^12.23.12
|
||||||
|
version: 12.23.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1)
|
||||||
js-audio-recorder:
|
js-audio-recorder:
|
||||||
specifier: ^1.0.7
|
specifier: ^1.0.7
|
||||||
version: 1.0.7
|
version: 1.0.7
|
||||||
@@ -1481,6 +1484,20 @@ packages:
|
|||||||
resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==}
|
resolution: {integrity: sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==}
|
||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
|
|
||||||
|
framer-motion@12.23.12:
|
||||||
|
resolution: {integrity: sha512-6e78rdVtnBvlEVgu6eFEAgG9v3wLnYEboM8I5O5EXvfKC8gxGQB8wXJdhkMy10iVcn05jl6CNw7/HTsTCfwcWg==}
|
||||||
|
peerDependencies:
|
||||||
|
'@emotion/is-prop-valid': '*'
|
||||||
|
react: ^18.0.0 || ^19.0.0
|
||||||
|
react-dom: ^18.0.0 || ^19.0.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@emotion/is-prop-valid':
|
||||||
|
optional: true
|
||||||
|
react:
|
||||||
|
optional: true
|
||||||
|
react-dom:
|
||||||
|
optional: true
|
||||||
|
|
||||||
fs-extra@11.3.1:
|
fs-extra@11.3.1:
|
||||||
resolution: {integrity: sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==}
|
resolution: {integrity: sha512-eXvGGwZ5CL17ZSwHWd3bbgk7UUpF6IFHtP57NYYakPvHOs8GDgDe5KJI36jIJzDkJ6eJjuzRA8eBQb6SkKue0g==}
|
||||||
engines: {node: '>=14.14'}
|
engines: {node: '>=14.14'}
|
||||||
@@ -1828,6 +1845,12 @@ packages:
|
|||||||
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
|
resolution: {integrity: sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==}
|
||||||
engines: {node: '>=16 || 14 >=14.17'}
|
engines: {node: '>=16 || 14 >=14.17'}
|
||||||
|
|
||||||
|
motion-dom@12.23.12:
|
||||||
|
resolution: {integrity: sha512-RcR4fvMCTESQBD/uKQe49D5RUeDOokkGRmz4ceaJKDBgHYtZtntC/s2vLvY38gqGaytinij/yi3hMcWVcEF5Kw==}
|
||||||
|
|
||||||
|
motion-utils@12.23.6:
|
||||||
|
resolution: {integrity: sha512-eAWoPgr4eFEOFfg2WjIsMoqJTW6Z8MTUCgn/GZ3VRpClWBdnbjryiA3ZSNLyxCTmCQx4RmYX6jX1iWHbenUPNQ==}
|
||||||
|
|
||||||
ms@2.0.0:
|
ms@2.0.0:
|
||||||
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==}
|
||||||
|
|
||||||
@@ -3984,6 +4007,15 @@ snapshots:
|
|||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
|
|
||||||
|
framer-motion@12.23.12(react-dom@18.3.1(react@18.3.1))(react@18.3.1):
|
||||||
|
dependencies:
|
||||||
|
motion-dom: 12.23.12
|
||||||
|
motion-utils: 12.23.6
|
||||||
|
tslib: 2.8.1
|
||||||
|
optionalDependencies:
|
||||||
|
react: 18.3.1
|
||||||
|
react-dom: 18.3.1(react@18.3.1)
|
||||||
|
|
||||||
fs-extra@11.3.1:
|
fs-extra@11.3.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
@@ -4302,6 +4334,12 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
brace-expansion: 2.0.2
|
brace-expansion: 2.0.2
|
||||||
|
|
||||||
|
motion-dom@12.23.12:
|
||||||
|
dependencies:
|
||||||
|
motion-utils: 12.23.6
|
||||||
|
|
||||||
|
motion-utils@12.23.6: {}
|
||||||
|
|
||||||
ms@2.0.0: {}
|
ms@2.0.0: {}
|
||||||
|
|
||||||
ms@2.1.3: {}
|
ms@2.1.3: {}
|
||||||
|
|||||||
@@ -1,28 +1,27 @@
|
|||||||
import {useState, useEffect} from 'react';
|
// import {useState, useEffect} from 'react';
|
||||||
import isEqual from 'lodash.isequal';
|
|
||||||
|
|
||||||
function useSessionStorage<T>(key: string, initialValue: T): [T, (value: T) => void] {
|
// function useSessionStorage<T>(key: string, initialValue: T): [T, (value: T) => void] {
|
||||||
// 初始化状态
|
// // 初始化状态
|
||||||
const [storedValue, setStoredValue] = useState<T>(() => {
|
// const [storedValue, setStoredValue] = useState<T>(() => {
|
||||||
const item = sessionStorage.getItem(key);
|
// const item = sessionStorage.getItem(key);
|
||||||
if (item !== null) {
|
// if (item !== null) {
|
||||||
// 如果 sessionStorage 中有数据,则使用现有数据
|
// // 如果 sessionStorage 中有数据,则使用现有数据
|
||||||
return JSON.parse(item);
|
// return JSON.parse(item);
|
||||||
} else {
|
// } else {
|
||||||
// 当 sessionStorage 中没有相应的键时,使用 initialValue 初始化,并写入 sessionStorage
|
// // 当 sessionStorage 中没有相应的键时,使用 initialValue 初始化,并写入 sessionStorage
|
||||||
sessionStorage.setItem(key, JSON.stringify(initialValue));
|
// sessionStorage.setItem(key, JSON.stringify(initialValue));
|
||||||
return initialValue;
|
// return initialValue;
|
||||||
}
|
// }
|
||||||
});
|
// });
|
||||||
|
|
||||||
// 监听并保存变化到 sessionStorage
|
// // 监听并保存变化到 sessionStorage
|
||||||
useEffect(() => {
|
// useEffect(() => {
|
||||||
if (!isEqual(JSON.parse(sessionStorage.getItem(key) || 'null'), storedValue)) {
|
// if (!isEqual(JSON.parse(sessionStorage.getItem(key) || 'null'), storedValue)) {
|
||||||
sessionStorage.setItem(key, JSON.stringify(storedValue));
|
// sessionStorage.setItem(key, JSON.stringify(storedValue));
|
||||||
}
|
// }
|
||||||
}, [key, storedValue]);
|
// }, [key, storedValue]);
|
||||||
|
|
||||||
return [storedValue, setStoredValue];
|
// return [storedValue, setStoredValue];
|
||||||
}
|
// }
|
||||||
|
|
||||||
export default useSessionStorage;
|
// export default useSessionStorage;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { NavBar, SafeArea, TabBar, Toast } from "antd-mobile";
|
import { NavBar, SafeArea, Toast } from "antd-mobile";
|
||||||
import { useNavigate, useLocation } from "react-router-dom";
|
import { useNavigate, useLocation } from "react-router-dom";
|
||||||
import { User, CattleZodiac } from "@icon-park/react";
|
import { User, CattleZodiac } from "@icon-park/react";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
@@ -13,39 +13,31 @@ interface MainLayoutProps {
|
|||||||
|
|
||||||
const MainLayout: React.FC<MainLayoutProps> = ({ isShowNavBar, children, onLink, title }) => {
|
const MainLayout: React.FC<MainLayoutProps> = ({ isShowNavBar, children, onLink, title }) => {
|
||||||
const navigate = useNavigate();
|
const navigate = useNavigate();
|
||||||
const location = useLocation();
|
// const location = useLocation();
|
||||||
const { pathname } = location;
|
|
||||||
const [activeKey, setActiveKey] = React.useState(pathname);
|
|
||||||
|
|
||||||
const setRouteActive = (value: string) => {
|
// const tabs = [
|
||||||
if (value !== "/") {
|
// {
|
||||||
Toast.show("待开发");
|
// key: "/",
|
||||||
}
|
// title: "宠物翻译",
|
||||||
};
|
// icon: <CattleZodiac />,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// key: "/set",
|
||||||
|
// title: "待办",
|
||||||
|
// icon: <User />,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// key: "/message",
|
||||||
|
// title: "消息",
|
||||||
|
// icon: <User />,
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// key: "/me",
|
||||||
|
// title: "我的",
|
||||||
|
|
||||||
const tabs = [
|
// icon: <User size="24" />,
|
||||||
{
|
// },
|
||||||
key: "/",
|
// ];
|
||||||
title: "宠物翻译",
|
|
||||||
icon: <CattleZodiac />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/set",
|
|
||||||
title: "待办",
|
|
||||||
icon: <User />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/message",
|
|
||||||
title: "消息",
|
|
||||||
icon: <User />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "/me",
|
|
||||||
title: "我的",
|
|
||||||
|
|
||||||
icon: <User size="24" />,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
const goBack = () => {
|
const goBack = () => {
|
||||||
if (onLink) {
|
if (onLink) {
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import React, { useEffect } from "react";
|
import React, { useEffect } from "react";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import { AppRoute } from "./routes";
|
|
||||||
|
|
||||||
interface AuthRouteProps {
|
interface AuthRouteProps {
|
||||||
children: React.ReactNode;
|
children: React.ReactNode;
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ export interface AppRoute {
|
|||||||
const Home = lazy(() => import("@/view/home"));
|
const Home = lazy(() => import("@/view/home"));
|
||||||
const Page404 = lazy(() => import("@/view/error/page404"));
|
const Page404 = lazy(() => import("@/view/error/page404"));
|
||||||
const TranslateDetail = lazy(() => import("@/view/home/detail"));
|
const TranslateDetail = lazy(() => import("@/view/home/detail"));
|
||||||
|
const TranslateMood = lazy(() => import("@/view/home/mood"));
|
||||||
export const routes: AppRoute[] = [
|
export const routes: AppRoute[] = [
|
||||||
{
|
{
|
||||||
path: "/",
|
path: "/",
|
||||||
@@ -31,5 +32,13 @@ export const routes: AppRoute[] = [
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
{ path: "/translate/detail", element: <TranslateDetail />, auth: false },
|
{ path: "/translate/detail", element: <TranslateDetail />, auth: false },
|
||||||
|
{
|
||||||
|
path: "/translate/mood",
|
||||||
|
element: <TranslateMood />,
|
||||||
|
auth: false,
|
||||||
|
meta: {
|
||||||
|
title: "情绪监控",
|
||||||
|
},
|
||||||
|
},
|
||||||
{ path: "*", element: <Page404 />, auth: false },
|
{ path: "*", element: <Page404 />, auth: false },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
import React from "react";
|
|
||||||
import { RenderRoutes } from "@/route/render-routes.tsx";
|
import { RenderRoutes } from "@/route/render-routes.tsx";
|
||||||
import { axiosInstance } from "@/http/axios-instance.ts";
|
import { axiosInstance } from "@/http/axios-instance.ts";
|
||||||
import { configure } from "axios-hooks";
|
import { configure } from "axios-hooks";
|
||||||
|
|||||||
13
projects/translate-h5/src/view/home/archives/index.tsx
Normal file
13
projects/translate-h5/src/view/home/archives/index.tsx
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
// 档案
|
||||||
|
import MainLayout from "@/layout/main/mainLayout";
|
||||||
|
import "./index.less";
|
||||||
|
|
||||||
|
function Index() {
|
||||||
|
return (
|
||||||
|
<MainLayout isShowNavBar={true}>
|
||||||
|
<div className="archives"></div>
|
||||||
|
</MainLayout>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Index;
|
||||||
@@ -1,6 +1,23 @@
|
|||||||
.home {
|
.home {
|
||||||
height: 100%;
|
height: 100%;
|
||||||
|
width: 100%;
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
.home-header {
|
||||||
|
display: flex;
|
||||||
|
padding: 12px;
|
||||||
|
position: sticky;
|
||||||
|
top: 0px;
|
||||||
|
background: #fff;
|
||||||
|
justify-content: space-between;
|
||||||
|
align-items: center;
|
||||||
|
z-index: 99;
|
||||||
|
h3 {
|
||||||
|
font-size: 20px;
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
}
|
||||||
// .adm-tabs {
|
// .adm-tabs {
|
||||||
// display: flex;
|
// display: flex;
|
||||||
// flex-direction: column;
|
// flex-direction: column;
|
||||||
@@ -21,7 +38,7 @@
|
|||||||
|
|
||||||
// .adm-tabs-tab {
|
// .adm-tabs-tab {
|
||||||
// font-size: 20px;
|
// font-size: 20px;
|
||||||
// color: rgba(0, 0, 0, 0.25);
|
// font-size: 20px;
|
||||||
// font-weight: 600;
|
// font-weight: 600;
|
||||||
// &.adm-tabs-tab-active {
|
// &.adm-tabs-tab-active {
|
||||||
// color: #000;
|
// color: #000;
|
||||||
@@ -36,6 +53,7 @@
|
|||||||
flex-direction: column;
|
flex-direction: column;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
.header {
|
.header {
|
||||||
|
padding: 0px 16px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,32 +1,37 @@
|
|||||||
import MainLayout from "@/layout/main/mainLayout";
|
import MainLayout from "@/layout/main/mainLayout";
|
||||||
import { Button, Tabs } from "antd-mobile";
|
import { useState } from "react";
|
||||||
import Translate from "./translate";
|
import { Divider, Space } from "antd-mobile";
|
||||||
|
import Translate from "./translate/index";
|
||||||
|
import { Electrocardiogram, Filter, GithubOne } from "@icon-park/react";
|
||||||
|
import { useNavigate } from "react-router-dom";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
|
|
||||||
function Index() {
|
function Index() {
|
||||||
const handleRecordComplete = (audioData: AudioData): void => {
|
const [visible, setVisible] = useState<boolean>(false);
|
||||||
console.log("录音完成:", audioData);
|
const navigate = useNavigate();
|
||||||
};
|
|
||||||
|
|
||||||
const handleError = (error: Error): void => {
|
const onLink = () => {
|
||||||
console.error("录音错误:", error);
|
navigate("/translate/mood");
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MainLayout>
|
<MainLayout>
|
||||||
<div className="home">
|
<div className="home">
|
||||||
<div className="header">
|
<div className="home-header">
|
||||||
<h3>宠物翻译</h3>
|
<h3>宠物翻译</h3>
|
||||||
<div></div>
|
<Space style={{ fontSize: "20px", "--gap": "16px" }}>
|
||||||
|
<Filter theme="outline" fill="#333" strokeWidth={3} strokeLinecap="butt" />
|
||||||
|
<Divider direction="vertical" />
|
||||||
|
<Electrocardiogram
|
||||||
|
theme="outline"
|
||||||
|
fill="#333"
|
||||||
|
strokeWidth={3}
|
||||||
|
strokeLinecap="butt"
|
||||||
|
onClick={onLink}
|
||||||
|
/>
|
||||||
|
<GithubOne theme="outline" fill="#333" strokeWidth={3} strokeLinecap="butt" />
|
||||||
|
</Space>
|
||||||
</div>
|
</div>
|
||||||
{/* <Tabs stretch={false}>
|
<Translate searchVisible={visible} />
|
||||||
<Tabs.Tab title="宠物翻译" key="1">
|
|
||||||
<Translate />
|
|
||||||
</Tabs.Tab>
|
|
||||||
<Tabs.Tab title="宠物档案" key="2">
|
|
||||||
2
|
|
||||||
</Tabs.Tab>
|
|
||||||
</Tabs> */}
|
|
||||||
</div>
|
</div>
|
||||||
</MainLayout>
|
</MainLayout>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -0,0 +1,3 @@
|
|||||||
|
.mood {
|
||||||
|
padding: 12px;
|
||||||
|
}
|
||||||
11
projects/translate-h5/src/view/home/mood/index.tsx
Normal file
11
projects/translate-h5/src/view/home/mood/index.tsx
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
import MainLayout from "@/layout/main/mainLayout";
|
||||||
|
import styles from "./index.module.less";
|
||||||
|
const Moods = () => {
|
||||||
|
return (
|
||||||
|
<MainLayout isShowNavBar={true} title="情绪">
|
||||||
|
<div className={styles.mood}>心情</div>
|
||||||
|
</MainLayout>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default Moods;
|
||||||
@@ -4,7 +4,7 @@ import { VoiceIcon } from "@workspace/shared";
|
|||||||
import dogSvg from "@/assets/translate/dog.svg";
|
import dogSvg from "@/assets/translate/dog.svg";
|
||||||
import catSvg from "@/assets/translate/cat.svg";
|
import catSvg from "@/assets/translate/cat.svg";
|
||||||
import pigSvg from "@/assets/translate/pig.svg";
|
import pigSvg from "@/assets/translate/pig.svg";
|
||||||
import { Message } from "../../types";
|
import { Message } from "../../../types";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
|
|
||||||
interface DefinedProps {
|
interface DefinedProps {
|
||||||
@@ -89,44 +89,18 @@ function Index(props: DefinedProps) {
|
|||||||
};
|
};
|
||||||
const renderAvatar = (type?: "pig" | "cat" | "dog") => {
|
const renderAvatar = (type?: "pig" | "cat" | "dog") => {
|
||||||
if (type === "pig") {
|
if (type === "pig") {
|
||||||
<Image
|
<Image src={pigSvg} width={40} height={40} fit="cover" style={{ borderRadius: 32 }} />;
|
||||||
src={pigSvg}
|
|
||||||
width={40}
|
|
||||||
height={40}
|
|
||||||
fit="cover"
|
|
||||||
style={{ borderRadius: 32 }}
|
|
||||||
/>;
|
|
||||||
}
|
}
|
||||||
if (type === "cat") {
|
if (type === "cat") {
|
||||||
return (
|
return <Image src={catSvg} width={40} height={40} fit="cover" style={{ borderRadius: 32 }} />;
|
||||||
<Image
|
|
||||||
src={catSvg}
|
|
||||||
width={40}
|
|
||||||
height={40}
|
|
||||||
fit="cover"
|
|
||||||
style={{ borderRadius: 32 }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return (
|
return <Image src={dogSvg} width={40} height={40} fit="cover" style={{ borderRadius: 32 }} />;
|
||||||
<Image
|
|
||||||
src={dogSvg}
|
|
||||||
width={40}
|
|
||||||
height={40}
|
|
||||||
fit="cover"
|
|
||||||
style={{ borderRadius: 32 }}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="message">
|
<div className="message">
|
||||||
{data.map((item, index) => (
|
{data.map((item, index) => (
|
||||||
<div
|
<div className="item" key={index} onClick={() => playAudio(item.id, item.audioUrl)}>
|
||||||
className="item"
|
|
||||||
key={index}
|
|
||||||
onClick={() => playAudio(item.id, item.audioUrl)}
|
|
||||||
>
|
|
||||||
{renderAvatar(item.type)}
|
{renderAvatar(item.type)}
|
||||||
<div className="rig">
|
<div className="rig">
|
||||||
<div>
|
<div>
|
||||||
@@ -163,9 +137,7 @@ function Index(props: DefinedProps) {
|
|||||||
</div>
|
</div>
|
||||||
<div className="voice-container">
|
<div className="voice-container">
|
||||||
<VoiceIcon isPlaying={false} />
|
<VoiceIcon isPlaying={false} />
|
||||||
<div className="tips">
|
<div className="tips">{isRecording ? "录制中..." : "轻点麦克风录制"}</div>
|
||||||
{isRecording ? "录制中..." : "轻点麦克风录制"}
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -1,21 +1,14 @@
|
|||||||
import { DownOne } from "@icon-park/react";
|
import { Dropdown, type DropdownRef, Radio, SearchBar, Space } from "antd-mobile";
|
||||||
import {
|
|
||||||
ActionSheet,
|
|
||||||
Dropdown,
|
|
||||||
type DropdownRef,
|
|
||||||
Popup,
|
|
||||||
Radio,
|
|
||||||
SearchBar,
|
|
||||||
Space,
|
|
||||||
} from "antd-mobile";
|
|
||||||
import { RadioValue } from "antd-mobile/es/components/radio";
|
import { RadioValue } from "antd-mobile/es/components/radio";
|
||||||
import { useRef, useState } from "react";
|
import { useRef, useState } from "react";
|
||||||
|
|
||||||
interface PropsConfig {
|
interface PropsConfig {
|
||||||
handleAllAni: () => void;
|
handleAllAni: () => void;
|
||||||
|
value?: string;
|
||||||
}
|
}
|
||||||
const allAni = ["全部宠物", "丑丑", "胖胖", "可可"];
|
const allAni = ["全部宠物", "丑丑", "胖胖", "可可"];
|
||||||
function SearchCom(props: PropsConfig) {
|
function SearchCom(props: PropsConfig) {
|
||||||
|
const { value } = props;
|
||||||
const [aniName, setAniName] = useState<string>("全部宠物");
|
const [aniName, setAniName] = useState<string>("全部宠物");
|
||||||
const animenuRef = useRef<DropdownRef>(null);
|
const animenuRef = useRef<DropdownRef>(null);
|
||||||
const handleAniSelect = (val: RadioValue) => {
|
const handleAniSelect = (val: RadioValue) => {
|
||||||
@@ -32,6 +25,7 @@ function SearchCom(props: PropsConfig) {
|
|||||||
"--height": "32px",
|
"--height": "32px",
|
||||||
"--padding-left": "12px",
|
"--padding-left": "12px",
|
||||||
}}
|
}}
|
||||||
|
defaultValue={value}
|
||||||
/>
|
/>
|
||||||
<Dropdown className="all" ref={animenuRef}>
|
<Dropdown className="all" ref={animenuRef}>
|
||||||
<Dropdown.Item key="ani" title={aniName}>
|
<Dropdown.Item key="ani" title={aniName}>
|
||||||
@@ -5,8 +5,6 @@ import microphoneSvg from "@/assets/translate/microphone.svg";
|
|||||||
import microphoneDisabledSvg from "@/assets/translate/microphoneDisabledSvg.svg";
|
import microphoneDisabledSvg from "@/assets/translate/microphoneDisabledSvg.svg";
|
||||||
import { createStartRecordSound, createSendSound } from "@/utils/voice";
|
import { createStartRecordSound, createSendSound } from "@/utils/voice";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
import { Message } from "../../types";
|
|
||||||
import { CloseCircleOutline } from "antd-mobile-icons";
|
|
||||||
|
|
||||||
interface DefinedProps {
|
interface DefinedProps {
|
||||||
onRecordingComplete: (url: string, finalDuration: number) => void;
|
onRecordingComplete: (url: string, finalDuration: number) => void;
|
||||||
@@ -80,10 +78,7 @@ function Index(props: DefinedProps) {
|
|||||||
//正在录音中
|
//正在录音中
|
||||||
return (
|
return (
|
||||||
<div onClick={onStopRecording} className="isRecording">
|
<div onClick={onStopRecording} className="isRecording">
|
||||||
<ProgressCircle
|
<ProgressCircle percent={recordingDuration} style={{ "--size": "80px" }}>
|
||||||
percent={recordingDuration}
|
|
||||||
style={{ "--size": "80px" }}
|
|
||||||
>
|
|
||||||
<div className="recording-dot">
|
<div className="recording-dot">
|
||||||
<span className="circle"></span>
|
<span className="circle"></span>
|
||||||
</div>
|
</div>
|
||||||
@@ -95,14 +90,7 @@ function Index(props: DefinedProps) {
|
|||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
//麦克风状态
|
//麦克风状态
|
||||||
return (
|
return <Image height={80} width={80} src={microphoneSvg} onClick={onStartRecording} />;
|
||||||
<Image
|
|
||||||
height={80}
|
|
||||||
width={80}
|
|
||||||
src={microphoneSvg}
|
|
||||||
onClick={onStartRecording}
|
|
||||||
/>
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}, [hasPermission, isRecording, recordingDuration]);
|
}, [hasPermission, isRecording, recordingDuration]);
|
||||||
const checkMicrophonePermission = useCallback(async () => {
|
const checkMicrophonePermission = useCallback(async () => {
|
||||||
@@ -3,7 +3,7 @@ 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";
|
||||||
import { XPopup, FloatingMenu, type FloatMenuItemConfig } from "@workspace/shared";
|
import { XPopup, FloatingMenu, type FloatMenuItemConfig } from "@workspace/shared";
|
||||||
import type { Message } from "./types";
|
import type { Message } from "../types";
|
||||||
|
|
||||||
import { mockTranslateAudio } from "@/utils/voice";
|
import { mockTranslateAudio } from "@/utils/voice";
|
||||||
import dogSvg from "@/assets/translate/dog.svg";
|
import dogSvg from "@/assets/translate/dog.svg";
|
||||||
@@ -11,7 +11,9 @@ import catSvg from "@/assets/translate/cat.svg";
|
|||||||
import pigSvg from "@/assets/translate/pig.svg";
|
import pigSvg from "@/assets/translate/pig.svg";
|
||||||
import { MoreTwo } from "@icon-park/react";
|
import { MoreTwo } from "@icon-park/react";
|
||||||
import SearchCom from "./component/search";
|
import SearchCom from "./component/search";
|
||||||
interface DefinedProps {}
|
interface DefinedProps {
|
||||||
|
searchVisible: boolean;
|
||||||
|
}
|
||||||
const menuItems: FloatMenuItemConfig[] = [
|
const menuItems: FloatMenuItemConfig[] = [
|
||||||
{ icon: <Image src={dogSvg} />, type: "dog" },
|
{ icon: <Image src={dogSvg} />, type: "dog" },
|
||||||
{ icon: <Image src={catSvg} />, type: "cat" },
|
{ icon: <Image src={catSvg} />, type: "cat" },
|
||||||
@@ -22,23 +24,11 @@ const menuItems: FloatMenuItemConfig[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
function Index(props: DefinedProps) {
|
function Index(props: DefinedProps) {
|
||||||
// const data: Message[] = [
|
const { searchVisible } = props;
|
||||||
// {
|
|
||||||
// id: 1,
|
|
||||||
// audioUrl: "",
|
|
||||||
// duration: 0,
|
|
||||||
// translatedText: "",
|
|
||||||
// isTranslating: true,
|
|
||||||
// isPlaying: false,
|
|
||||||
// timestamp: 0,
|
|
||||||
// },
|
|
||||||
// ];
|
|
||||||
const [currentPlayingId, setCurrentPlayingId] = useState<string | null>(null); //当前播放id
|
|
||||||
const [messages, setMessages] = useState<Message[]>([]);
|
const [messages, setMessages] = useState<Message[]>([]);
|
||||||
const [isRecording, setIsRecording] = useState(false); //是否录音中
|
const [isRecording, setIsRecording] = useState(false); //是否录音中
|
||||||
const [currentLanguage, setCurrentLanguage] = useState<FloatMenuItemConfig>();
|
const [currentLanguage, setCurrentLanguage] = useState<FloatMenuItemConfig>();
|
||||||
const [visible, setVisible] = useState<boolean>(false);
|
const [visible, setVisible] = useState<boolean>(false);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
setCurrentLanguage(menuItems[0]);
|
setCurrentLanguage(menuItems[0]);
|
||||||
}, []);
|
}, []);
|
||||||
@@ -111,9 +101,11 @@ function Index(props: DefinedProps) {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="translate-container">
|
<div className="translate-container">
|
||||||
<div className="header">
|
{searchVisible && (
|
||||||
<SearchCom handleAllAni={() => {}} />
|
<div className="header">
|
||||||
</div>
|
<SearchCom handleAllAni={() => {}} />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
<MessageCom data={messages} isRecording={isRecording}></MessageCom>
|
<MessageCom data={messages} isRecording={isRecording}></MessageCom>
|
||||||
<VoiceRecord
|
<VoiceRecord
|
||||||
@@ -12,14 +12,7 @@ export default defineConfig({
|
|||||||
open: true,
|
open: true,
|
||||||
},
|
},
|
||||||
css: {
|
css: {
|
||||||
modules: {
|
modules: {},
|
||||||
generateScopedName: () => {
|
|
||||||
if (process.env.NODE_ENV === "production") {
|
|
||||||
return `[hash:base64:8]`;
|
|
||||||
}
|
|
||||||
return `[name]__[local]___[hash:base64:5]`;
|
|
||||||
},
|
|
||||||
},
|
|
||||||
preprocessorOptions: {
|
preprocessorOptions: {
|
||||||
less: {
|
less: {
|
||||||
// 全局变量
|
// 全局变量
|
||||||
|
|||||||
Reference in New Issue
Block a user