From 2ebbc7374ad03bbbe8c4c875aef4560a233fa294 Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Fri, 19 Jul 2024 10:12:50 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=8E=A5=E5=85=A5=E6=9C=BA=E5=99=A8?= =?UTF-8?q?=E4=BA=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/package.json | 1 + react-ui/src/assets/img/robot.png | Bin 0 -> 1789 bytes react-ui/src/components/RobotFrame/index.less | 34 ++++++++++++++++ react-ui/src/components/RobotFrame/index.tsx | 30 ++++++++++++++ react-ui/src/hooks/draggable.ts | 37 ++++++++++++++++++ react-ui/src/pages/Workspace/index.less | 11 ++++++ react-ui/src/pages/Workspace/index.tsx | 20 ++++++++++ 7 files changed, 133 insertions(+) create mode 100644 react-ui/src/assets/img/robot.png create mode 100644 react-ui/src/components/RobotFrame/index.less create mode 100644 react-ui/src/components/RobotFrame/index.tsx create mode 100644 react-ui/src/hooks/draggable.ts diff --git a/react-ui/package.json b/react-ui/package.json index cab066e..e7651de 100644 --- a/react-ui/package.json +++ b/react-ui/package.json @@ -76,6 +76,7 @@ "react-cropper": "^2.3.3", "react-dev-inspector": "^1.8.1", "react-dom": "^18.2.0", + "react-draggable": "^4.4.6", "react-helmet-async": "^1.3.0", "react-highlight": "^0.15.0" }, diff --git a/react-ui/src/assets/img/robot.png b/react-ui/src/assets/img/robot.png new file mode 100644 index 0000000000000000000000000000000000000000..e91be9ac1d1a3b443719ca963cb959685b057580 GIT binary patch literal 1789 zcmVPx*w@E}nRCr$Poo#O1I1GlR?FHHsCAq>D3*+dtoi z?jrI_0`UCv&Th&Pvm;ms*+iMrs8&O~q1$qGR^c!(p$!cDr001Z{swG>OC~yG);op+)O4ar4 z`&aJ~{!7Ve(9UP~1ON>Btz4D6lYjpA_b()Nl#|qyCGXAvz?8=dSGEV>CkB9pWwm1t z0NC+Wt(qbN)Kb=nT>xOjQMIZG0BR{~#4Z3Z;;35H1OT;^HDVV47;#jsY65^-${Mk& z7l5z{vW2~e%G;p}fFRa?-D#S%X!32Pp>`+&Aijge&XVwk$2X z0W-4!W9`rbK;-GMbwUYd0r_iSD-dW4nWV-UYKNW(Fe*ELg6t-(+Gqy=AU)DKg#bW~ zYT*RL*)eB`0GTopFGB<%3dJvG17te@^l#O=_i+9l-x+tfA{>`H{=%_(03cKKg>Yf* zoOtMA<_(Kq)~{JC>a4XZQy&3}dq>D103ZubTTdsOQ&JEBkR1U4$Wj$3h%TUjh!hiu z02Gz_GKc_VsR|TC1SlXP#RMV%MWxGJpYy?kV77l@bmt%CEdFVgdI0(Wr|WY%IwC;g z9s1I@iSowzN`#x$Yb6bw5|A`NAPfL+z^6g5m}9vx_mMz2 z&ruWru3+S3%JI``1^Qc#EkaJQnM_e*4rl=YWwb=XwxVBF0RS|Ya>oFP zCphUe&h&9tZa)AJ0U)`tgwq880GbbXl`0$oTx<}?dHO@6cG*G%pmD(kfaJtm@i~2e zYIQF;0|*8%3!wQw_LQwzAc=pykh6G0sV?J~m(*BfwQX1jpm;%k*)&~Ce)z{UFsD<4qb_0Mr5di=gLbo_O000aCa^9$M z%uAF708G_eivj?E2>|zXG1vUP%S*2I#oDTG5IC!CI}1esVAmsO8w3ptK6a*o(Rg(^ zDsC4{6)sMkVy5-!SF{pX!6|n$xn~o}-72|xBjsZNd4b|JNPXx^_Dvr}Jpe#aX|;@f z=c5bAaXumaOY@*_*40|(8Mnh%_bSG~$of)1ip+I-?!ORifdzX-_ zH5(ygdH{g)J)PE6IBa`{Jc$8-=x5Llt5D+&p8$X;(73Nxns?nW(?!-^!QZ(0D-i# zO5cBbZ^R}5fS|M!r0m5v#zX-C1X4~bb>H-^s3ZV?)(G6AyPu#h78IIotz_fY8x(O<+ f&fR;7FRlF#rKRb>YEsXK00000NkvXXu0mjf+5aEo literal 0 HcmV?d00001 diff --git a/react-ui/src/components/RobotFrame/index.less b/react-ui/src/components/RobotFrame/index.less new file mode 100644 index 0000000..e3e5662 --- /dev/null +++ b/react-ui/src/components/RobotFrame/index.less @@ -0,0 +1,34 @@ +.robot-frame { + position: fixed; + top: 55px; + right: -610px; + z-index: 100; + width: 600px; + height: calc(100% - 55px); + background-color: #fff; + box-shadow: -6px 0 16px 0 rgba(0, 0, 0, 0.08), -3px 0 6px -4px rgba(0, 0, 0, 0.12), + -9px 0 28px 8px rgba(0, 0, 0, 0.05); + transition: right 0.3s ease-in-out; + + // 增加优先级 + &&--visible { + right: 0; + } + + &__header { + display: flex; + gap: 10px; + align-items: center; + justify-content: flex-end; + width: 100%; + height: 60px; + padding: 0 15px; + border-bottom: 1px solid #e8e8e8; + } + + &__iframe { + width: 100%; + height: calc(100% - 60px); + border: 0; + } +} diff --git a/react-ui/src/components/RobotFrame/index.tsx b/react-ui/src/components/RobotFrame/index.tsx new file mode 100644 index 0000000..49789aa --- /dev/null +++ b/react-ui/src/components/RobotFrame/index.tsx @@ -0,0 +1,30 @@ +import { CloseOutlined, ExpandOutlined } from '@ant-design/icons'; +import { Button } from 'antd'; +import classNames from 'classnames'; +import styles from './index.less'; + +type RobotFrameProps = { + onClose: () => void; + visible: boolean; +}; + +function RobotFrame({ onClose, visible }: RobotFrameProps) { + const url = 'http://172.20.32.181:30080/chat/l4S79c4rly0o1pn7'; + const openUrl = () => { + window.open(url, '_blank'); + }; + + return ( +
+
+ + +
+ +
+ ); +} + +export default RobotFrame; diff --git a/react-ui/src/hooks/draggable.ts b/react-ui/src/hooks/draggable.ts new file mode 100644 index 0000000..b093ea6 --- /dev/null +++ b/react-ui/src/hooks/draggable.ts @@ -0,0 +1,37 @@ +// 处理 react-draggable 组件拖动结束时,响应了点击事件的 +import { useState } from 'react'; + +export const useDraggable = (onClick: () => void) => { + const [isDragging, setIsDragging] = useState(false); + + const handleStart = () => { + setIsDragging(false); + }; + + const handleDrag = () => { + if (!isDragging) { + setIsDragging(true); + } + }; + + const handleStop = () => { + // 延迟设置 isDragging 为 false 是为了确保在点击事件触发之前它仍然为 true + setTimeout(() => setIsDragging(false), 0); + }; + + const handleClick = (e: React.MouseEvent) => { + if (isDragging) { + e.preventDefault(); + e.stopPropagation(); + } else { + onClick(); + } + }; + + return { + handleStart, + handleDrag, + handleStop, + handleClick, + }; +}; diff --git a/react-ui/src/pages/Workspace/index.less b/react-ui/src/pages/Workspace/index.less index f7f95a2..3c7bd42 100644 --- a/react-ui/src/pages/Workspace/index.less +++ b/react-ui/src/pages/Workspace/index.less @@ -1,4 +1,5 @@ .workspace { + position: relative; height: 100%; padding: 20px 30px 10px; overflow-y: auto; @@ -43,4 +44,14 @@ min-width: 326px; height: 700px; } + + &__robot-img { + position: fixed; + right: 30px; + bottom: 20px; + width: 64px; + height: 64px; + background-color: white; + cursor: pointer; + } } diff --git a/react-ui/src/pages/Workspace/index.tsx b/react-ui/src/pages/Workspace/index.tsx index 55acd26..f5e6fe9 100644 --- a/react-ui/src/pages/Workspace/index.tsx +++ b/react-ui/src/pages/Workspace/index.tsx @@ -1,7 +1,10 @@ +import RobotFrame from '@/components/RobotFrame'; +import { useDraggable } from '@/hooks/draggable'; import { getWorkspaceOverviewReq } from '@/services/workspace'; import { ExperimentInstance } from '@/types'; import { to } from '@/utils/promise'; import { useEffect, useState } from 'react'; +import Draggable from 'react-draggable'; import AssetsManagement from './components/AssetsManagement'; import ExperimentChart, { type ExperimentStatistics } from './components/ExperimentChart'; import ExperitableTable from './components/ExperimentTable'; @@ -20,6 +23,10 @@ type OverviewData = { function Workspace() { const [overviewData, setOverviewData] = useState(); + const [robotFrameVisible, setRobotFrameVisible] = useState(false); + const { handleStart, handleStop, handleDrag, handleClick } = useDraggable(() => + setRobotFrameVisible((prev) => !prev), + ); const users: number[] = new Array(8).fill(0); useEffect(() => { getWorkspaceOverview(); @@ -64,6 +71,19 @@ function Workspace() { + + e.preventDefault()} + > + + + setRobotFrameVisible(false)} + > ); }