diff --git a/react-ui/package.json b/react-ui/package.json index a4e0635c..7bee9125 100644 --- a/react-ui/package.json +++ b/react-ui/package.json @@ -8,7 +8,7 @@ "build": "max build", "deploy": "npm run build && npm run gh-pages", "dev": "npm run start:dev", - "dev-no-sso": "cross-env NO_SSO=true PORT=8001 npm run start:mock", + "dev-no-sso": "cross-env NO_SSO=true npm run start:mock", "docker-hub:build": "docker build -f Dockerfile.hub -t ant-design-pro ./", "docker-prod:build": "docker-compose -f ./docker/docker-compose.yml build", "docker-prod:dev": "docker-compose -f ./docker/docker-compose.yml up", diff --git a/react-ui/src/assets/img/workspace/echart-bg.png b/react-ui/src/assets/img/workspace/echart-bg.png index 55a53973..4a1851f3 100644 Binary files a/react-ui/src/assets/img/workspace/echart-bg.png and b/react-ui/src/assets/img/workspace/echart-bg.png differ diff --git a/react-ui/src/hooks/useRootFontSize.ts b/react-ui/src/hooks/useRootFontSize.ts index a8887b24..e577162e 100644 --- a/react-ui/src/hooks/useRootFontSize.ts +++ b/react-ui/src/hooks/useRootFontSize.ts @@ -18,8 +18,6 @@ export function useRootFontSize() { const html = document.documentElement; const observer = new MutationObserver(() => { const size = getHtmlFontSize(); - console.log('zzz', size); - setFontSize(size); }); observer.observe(html, { diff --git a/react-ui/src/pages/Welcome.tsx b/react-ui/src/pages/Welcome.tsx deleted file mode 100644 index d0c49f7a..00000000 --- a/react-ui/src/pages/Welcome.tsx +++ /dev/null @@ -1,164 +0,0 @@ -import { PageContainer } from '@ant-design/pro-components'; -import { useModel } from '@umijs/max'; -import { Card, theme } from 'antd'; -import React from 'react'; - -/** - * 每个单独的卡片,为了复用样式抽成了组件 - * @param param0 - * @returns - */ -const InfoCard: React.FC<{ - title: string; - index: number; - desc: string; - href: string; -}> = ({ title, href, index, desc }) => { - const { useToken } = theme; - - const { token } = useToken(); - - return ( -
-
-
- {index} -
-
- {title} -
-
-
- {desc} -
- - 了解更多 {'>'} - -
- ); -}; - -const Welcome: React.FC = () => { - const { token } = theme.useToken(); - const { initialState } = useModel('@@initialState'); - return ( - - -
-
- 欢迎使用 Ant Design Pro -
-

- Ant Design Pro 是一个整合了 umi,Ant Design 和 ProComponents - 的脚手架方案。致力于在设计规范和基础组件的基础上,继续向上构建,提炼出典型模板/业务组件/配套设计资源,进一步提升企业级中后台产品设计研发过程中的『用户』和『设计者』的体验。 -

-
- - - -
-
-
-
- ); -}; - -export default Welcome; diff --git a/react-ui/src/pages/Workspace/components/ExperimentChart/charts.js b/react-ui/src/pages/Workspace/components/ExperimentChart/charts.js index 09337704..e9bceeb0 100644 --- a/react-ui/src/pages/Workspace/components/ExperimentChart/charts.js +++ b/react-ui/src/pages/Workspace/components/ExperimentChart/charts.js @@ -8,32 +8,6 @@ * @param opacity 饼或者环的透明度 */ -const setSeriesItem = (item, k) => { - const seriesItem = { - name: - typeof item.name === 'undefined' - ? `series${item}` - : item.name, - type: 'surface', - parametric: true, - wireframe: { - show: false - }, - pieData: item, - pieStatus: { - selected: false, - hovered: false, - k: k - }, - center: ['10%', '50%'] - } - if ( item.color) { - seriesItem.itemStyle = { color: item.color } - } - - return seriesItem -} - export const getPie3D = (pieData, internalDiameterRatio, distance, alpha, pieHeight, opacity = 1) => { const series = [] let sumValue = 0 @@ -255,7 +229,7 @@ export const getParametricEquation = (startRatio, endRatio, isSelected, isHovere /** * 获取3d丙图的最高扇区的高度 */ -const getHeight3D = (series, height) => { +export const getHeight3D = (series, height) => { series.sort((a, b) => { return b.pieData.value - a.pieData.value }) @@ -265,7 +239,7 @@ const getHeight3D = (series, height) => { /** * 格式化浮点数 */ -const fomatFloat = (num, n) => { +export const fomatFloat = (num, n) => { let f = parseFloat(num) if (isNaN(f)) { return false @@ -283,3 +257,30 @@ const fomatFloat = (num, n) => { } return s } + +export const setSeriesItem = (item, k) => { + const seriesItem = { + name: + typeof item.name === 'undefined' + ? `series${item}` + : item.name, + type: 'surface', + parametric: true, + wireframe: { + show: false + }, + pieData: item, + pieStatus: { + selected: false, + hovered: false, + k: k + }, + center: ['10%', '50%'], + } + if ( item.color) { + seriesItem.itemStyle = { color: item.color } + } + + return seriesItem +} + diff --git a/react-ui/src/pages/Workspace/components/ExperimentChart/index.less b/react-ui/src/pages/Workspace/components/ExperimentChart/index.less index 4643bfb6..1c15fa4c 100644 --- a/react-ui/src/pages/Workspace/components/ExperimentChart/index.less +++ b/react-ui/src/pages/Workspace/components/ExperimentChart/index.less @@ -1,6 +1,5 @@ .experiment-chart { - display: flex; - flex-direction: column; + flex: none; width: 100%; height: 15rem; margin-top: 1.25rem; @@ -11,4 +10,9 @@ font-weight: 700; font-size: 1rem; } + + &__canvas { + height: calc(15rem - 1.53rem - 1.25rem); + .backgroundFullImage(url(@/assets/img/workspace/echart-bg.png)); + } } diff --git a/react-ui/src/pages/Workspace/components/ExperimentChart/new.tsx b/react-ui/src/pages/Workspace/components/ExperimentChart/new.tsx new file mode 100644 index 00000000..5b012a6f --- /dev/null +++ b/react-ui/src/pages/Workspace/components/ExperimentChart/new.tsx @@ -0,0 +1,167 @@ +import { useRootFontSize } from '@/hooks/useRootFontSize'; +import * as echarts from 'echarts'; +import 'echarts-gl'; +import React, { useEffect, useMemo, useRef } from 'react'; +import { getParametricEquation, setSeriesItem } from './charts'; +import styles from './index.less'; + +export type ExperimentStatistics = { + Failed: number; + Pending: number; + Running: number; + Succeeded: number; + Terminated: number; +}; + +type ExperimentChartProps = { + style?: React.CSSProperties; + chartData: { name: string; value: number; color?: string }[]; +}; + +function ExperimentChart({ chartData, style }: ExperimentChartProps) { + const fontSize = useRootFontSize(); + const chartRef = useRef(null); + + const series = useMemo(() => { + const series = []; + let startValue = 0; + let endValue = 0; + let legendData = []; + let legendBfb = []; + const k = 1 - 0.86; + const sumValue = chartData.reduce((res, item) => res + item.value, 0); + + // 为每一个饼图数据,生成一个 series-surface 配置 + for (let i = 0; i < chartData.length; i++) { + const seriesItem = setSeriesItem(chartData[i], k); + series.push(seriesItem); + } + + // 使用上一次遍历时,计算出的数据和 sumValue,调用 getParametricEquation 函数, + // 向每个 series-surface 传入不同的参数方程 series-surface.parametricEquation,也就是实现每一个扇形。 + legendData = []; + legendBfb = []; + for (let i = 0; i < series.length; i++) { + endValue = startValue + series[i].pieData.value; + series[i].pieData.startRatio = startValue / sumValue; + series[i].pieData.endRatio = endValue / sumValue; + //@ts-ignore + series[i].parametricEquation = getParametricEquation( + series[i].pieData.startRatio, + series[i].pieData.endRatio, + false, + false, + k, + series[i].pieData.value, + ); + startValue = endValue; + const bfb = series[i].pieData.value / sumValue; + legendData.push({ + name: series[i].name, + value: bfb, + }); + legendBfb.push({ + name: series[i].name, + value: bfb, + }); + } + + return series; + }, [chartData]); + + // @ts-ignore + const options: echarts.EChartsOption = useMemo( + () => ({ + tooltip: { + backgroundColor: 'white', + textStyle: { + color: '#494a6f', + fontSize: 14, + }, + formatter: (params: any) => { + if (params.seriesName !== 'mouseoutSeries' && params.seriesName !== 'pie2d') { + const value = chartData[params.seriesIndex].value; + return ( + `` + + `${params.seriesName}` + + `${value}` + ); + } + }, + }, + xAxis3D: { + min: -1, + max: 1, + }, + yAxis3D: { + min: -1, + max: 1, + }, + zAxis3D: { + min: -1, + max: 1, + }, + grid3D: { + top: -2 * fontSize, + show: false, + boxHeight: 8, // 圆环的高度 + viewControl: { + // 3d效果可以放大、旋转等,请自己去查看官方配置 + alpha: 20, // 角度 + distance: 150, // 调整视角到主体的距离,类似调整zoom + rotateSensitivity: 0, // 设置为0无法旋转 + zoomSensitivity: 0, // 设置为0无法缩放 + panSensitivity: 0, // 设置为0无法平移 + autoRotate: false, // 自动旋转 + }, + }, + series: series, + legend: { + bottom: fontSize, + left: 'center', + orient: 'horizontal', + icon: 'rect', + itemWidth: 0.75 * fontSize, + itemHeight: 0.75 * fontSize, + itemGap: 1.25 * fontSize, + textStyle: { + fontSize: 0.75 * fontSize, + }, + selectedMode: false, + }, + }), + [chartData, series, fontSize], + ); + + useEffect(() => { + // 创建一个echarts实例,返回echarts实例 + const chart = echarts.init(chartRef.current); + + // 设置图表实例的配置项和数据 + chart.setOption(options); + + // 改变大小 + const chartResize = () => { + chart.resize(); + }; + + window.addEventListener('resize', chartResize); + + // 组件卸载 + return () => { + window.removeEventListener('resize', chartResize); + chart.dispose(); + }; + }, [options]); + + return ( +
+
实验统计
+
+
+
+
+ ); +} + +export default ExperimentChart; diff --git a/react-ui/src/pages/Workspace/components/ExperimentChart/test.tsx b/react-ui/src/pages/Workspace/components/ExperimentChart/test.tsx deleted file mode 100644 index 6c559729..00000000 --- a/react-ui/src/pages/Workspace/components/ExperimentChart/test.tsx +++ /dev/null @@ -1,125 +0,0 @@ -import * as echarts from 'echarts'; -import React from 'react'; -import styles from './index.less'; -import ThreePieChart from './threePieChart'; - -const color1 = new echarts.graphic.LinearGradient( - 0, - 0, - 0, - 1, - [ - { offset: 0, color: '#c73131' }, - { offset: 1, color: '#ff7e96' }, - ], - false, -); - -const color2 = new echarts.graphic.LinearGradient( - 0, - 0, - 0, - 1, - [ - { offset: 0, color: '#6ac21d' }, - { offset: 1, color: '#96e850' }, - ], - false, -); -const color3 = new echarts.graphic.LinearGradient( - 0, - 0, - 0, - 1, - [ - { offset: 0, color: '#8c8c8c' }, - { offset: 1, color: '#c8c6c6' }, - ], - false, -); -const color4 = new echarts.graphic.LinearGradient( - 0, - 0, - 0, - 1, - [ - { offset: 0, color: '#ecb934' }, - { offset: 1, color: '#f0864d' }, - ], - false, -); - -const color5 = new echarts.graphic.LinearGradient( - 0, - 0, - 0, - 1, - [ - { offset: 0, color: '#7ea9fe' }, - { offset: 1, color: '#1664ff' }, - ], - false, -); - -const color6 = new echarts.graphic.LinearGradient( - 0, - 0, - 0, - 1, - [ - { offset: 0, color: 'rgba(255, 255, 255, 0.62)' }, - { offset: 1, color: '#ebf2ff ' }, - ], - false, -); - -export type ExperimentStatistics = { - Failed: number; - Pending: number; - Running: number; - Succeeded: number; - Terminated: number; -}; - -type ExperimentChartProps = { - style?: React.CSSProperties; - chartData: ExperimentStatistics; -}; - -function ExperimentChart({ chartData, style }: ExperimentChartProps) { - // useEffect(() => { - // // 创建一个echarts实例,返回echarts实例 - // const chart = echarts.init(chartRef.current); - - // // 设置图表实例的配置项和数据 - // chart.setOption(options); - - // // 组件卸载 - // return () => { - // // myChart.dispose() 销毁实例 - // chart.dispose(); - // }; - // }, [options]); - - const pieData = [ - { name: '销售业务', value: 77.56, color: '#f00' }, - { name: '技术服务', value: 18.21, color: '#0f0' }, - { name: '配送业务', value: 3.67, color: '#00f' }, - { name: '其他业务', value: 0.17, color: '#ff0' }, - ]; - - return ( -
-
实验统计
-
- -
-
- ); -} - -export default ExperimentChart; diff --git a/react-ui/src/pages/Workspace/components/ExperimentChart/threePieChart.jsx b/react-ui/src/pages/Workspace/components/ExperimentChart/threePieChart.jsx deleted file mode 100644 index 734f6477..00000000 --- a/react-ui/src/pages/Workspace/components/ExperimentChart/threePieChart.jsx +++ /dev/null @@ -1,84 +0,0 @@ -import * as echarts from 'echarts'; -import { useEffect } from 'react'; -import { getPie3D } from './charts'; -function PieEchart({ id, data, style }) { - useEffect(() => { - if (data && data.length > 0) { - init(setLabel(data)); - } - }, [data]); - - const init = (data) => { - let huan_val = document.getElementById(id); - let myEcharts = echarts.init(huan_val); - - let options = getOption(data); - console.log(options); - options.color = ['#4154f1', '#ffa900', '#00aa82', '#a296fd', '#40acfc']; - options.legend = { - orient: 'horizontal', - right: 'center', - bottom: 40, - width: '100%', - itemWidth: 11, - itemHeight: 11, - }; - options.grid3D.top = -50; - options.series.map((item) => { - item.radius = [30, 120]; - item.height = 20; - }); - console.log(options); - myEcharts.setOption(options); - }; - const getOption = (data) => { - console.log(data); - let option = getPie3D(data, 0.86, 150, 20, 20, 1); - return option; - }; - const setLabel = (data) => { - console.log(data, 'data'); - - data.forEach((item, index) => { - item.itemStyle = { - color: item.color, - }; - item.label = { - normal: { - show: true, - color: item.color, - rich: { - b: { - color: '#fff', - lineHeight: 25, - align: 'left', - }, - c: { - fontSize: 22, - color: '#fff', - textShadowColor: '#1c90a6', - textShadowOffsetX: 0, - textShadowOffsetY: 2, - textShadowBlur: 5, - }, - d: { - color: item.color, - align: 'left', - }, - }, - }, - }; - item.labelLine = { - normal: { - lineStyle: { - width: 1, - color: 'rgba(255,255,255,0.7)', - }, - }, - }; - }); - return data; - }; - return
; -} -export default PieEchart; diff --git a/react-ui/src/pages/Workspace/components/Experiments/index.tsx b/react-ui/src/pages/Workspace/components/Experiments/index.tsx index d5be9dd2..bb37748e 100644 --- a/react-ui/src/pages/Workspace/components/Experiments/index.tsx +++ b/react-ui/src/pages/Workspace/components/Experiments/index.tsx @@ -11,24 +11,28 @@ type ExperimentsProps = { const testData = [ { + id: 1, name: '基于pytorch的XXXX开发', description: '基于pytorch的XXXX开发基于pytorch的XXXX开发', status: 'Running', date: new Date(), }, { + id: 2, name: '基于pytorch的XXXX开发', description: '基于pytorch的XXXX开发基于pytorch的XXXX开发', status: 'Running', date: new Date(), }, { + id: 3, name: '基于pytorch的XXXX开发', description: '基于pytorch的XXXX开发基于pytorch的XXXX开发', status: 'Running', date: new Date(), }, { + id: 4, name: '基于pytorch的XXXX开发', description: '基于pytorch的XXXX开发基于pytorch的XXXX开发', status: 'Running', diff --git a/react-ui/src/pages/Workspace/components/Messages/index.less b/react-ui/src/pages/Workspace/components/Messages/index.less index e7a228d4..3949021c 100644 --- a/react-ui/src/pages/Workspace/components/Messages/index.less +++ b/react-ui/src/pages/Workspace/components/Messages/index.less @@ -1,5 +1,8 @@ .messages { + display: flex; flex: 1; + flex-direction: column; + min-height: 0; margin-top: 1.25rem; &__title { @@ -21,6 +24,7 @@ } &__content { + flex: 1; width: 100%; margin-top: 1.25rem; padding: 1rem 1.25rem; diff --git a/react-ui/src/pages/Workspace/components/Messages/index.tsx b/react-ui/src/pages/Workspace/components/Messages/index.tsx index a10c6de0..78127067 100644 --- a/react-ui/src/pages/Workspace/components/Messages/index.tsx +++ b/react-ui/src/pages/Workspace/components/Messages/index.tsx @@ -66,7 +66,7 @@ function Messages() { return (
- +
消息通知
消息中心 diff --git a/react-ui/src/pages/Workspace/components/Search/index.tsx b/react-ui/src/pages/Workspace/components/Search/index.tsx index 251b6800..0d6196c3 100644 --- a/react-ui/src/pages/Workspace/components/Search/index.tsx +++ b/react-ui/src/pages/Workspace/components/Search/index.tsx @@ -1,5 +1,6 @@ import KFIcon from '@/components/KFIcon'; import { Button, Flex, Input } from 'antd'; +import { useState } from 'react'; import styles from './index.less'; const hotQuestions = [ @@ -22,6 +23,11 @@ const hotQuestions = [ ]; function WorkspaceSearch() { + const [question, setQuestion] = useState(''); + const handle = () => { + console.log(question); + }; + return (
@@ -37,6 +43,8 @@ function WorkspaceSearch() {
setQuestion(e.target.value)} autoSize={{ minRows: 5, maxRows: 5 }} placeholder="请输入科学问题进行搜索" allowClear @@ -46,6 +54,7 @@ function WorkspaceSearch() { color="default" variant="solid" shape="round" + onClick={handle} > 开始搜索 diff --git a/react-ui/src/pages/Workspace/components/UserPoints/index.less b/react-ui/src/pages/Workspace/components/UserPoints/index.less index 24c49c80..ffdbe4cf 100644 --- a/react-ui/src/pages/Workspace/components/UserPoints/index.less +++ b/react-ui/src/pages/Workspace/components/UserPoints/index.less @@ -1,4 +1,5 @@ .user-points { + flex: none; &__title { margin-bottom: 1.25rem; color: @text-color; diff --git a/react-ui/src/pages/Workspace/index.less b/react-ui/src/pages/Workspace/index.less index b090799d..c5d62ef8 100644 --- a/react-ui/src/pages/Workspace/index.less +++ b/react-ui/src/pages/Workspace/index.less @@ -9,6 +9,7 @@ display: flex; flex-direction: column; width: calc(25% - 1.25rem); + height: 44.75rem; padding: 1.25rem; .backgroundFullImage(url(@/assets/img/workspace/points-bg.png)); } diff --git a/react-ui/src/pages/Workspace/index.tsx b/react-ui/src/pages/Workspace/index.tsx index 166c697e..2c75964d 100644 --- a/react-ui/src/pages/Workspace/index.tsx +++ b/react-ui/src/pages/Workspace/index.tsx @@ -8,7 +8,8 @@ import { type ExperimentStatistics } from './components/ExperimentChart'; // import RobotFrame from './components/RobotFrame'; import { Flex } from 'antd'; import AssetsManagement from './components/AssetsManagement'; -import ExperimentChart from './components/ExperimentChart'; +// import ExperimentChart from './components/ExperimentChart'; +import ExperimentChart from '@/pages/Workspace/components/ExperimentChart/new'; import Experiments from './components/Experiments'; import Messages from './components/Messages'; import Notebooks from './components/Notebooks'; @@ -25,6 +26,35 @@ type OverviewData = { function Workspace() { const [overviewData, setOverviewData] = useState(); + const chartData = overviewData?.experimentInsStatus + ? [ + { + value: overviewData.experimentInsStatus.Failed, + name: '失败', + color: 'rgba(217, 71, 71, 1)', + }, + { + value: overviewData.experimentInsStatus.Succeeded, + name: '成功', + color: 'rgba(0, 180, 42, 1)', + }, + { + value: overviewData.experimentInsStatus.Terminated, + name: '中止', + color: 'rgba(122, 123, 178, 1)', + }, + { + value: overviewData.experimentInsStatus.Pending, + name: '等待', + color: 'rgba(253, 174, 83, 1)', + }, + { + value: overviewData.experimentInsStatus.Running, + name: '运行中', + color: 'rgba(50, 135, 251, 1)', + }, + ] + : []; useEffect(() => { getWorkspaceOverview(); @@ -41,19 +71,17 @@ function Workspace() { return (
- +
- +
- {overviewData?.experimentInsStatus && ( - - )} +