Browse Source

feat: 完成首页

dev-zw-home
zhaowei 6 months ago
parent
commit
24ca5ffa4c
73 changed files with 967 additions and 9 deletions
  1. +2
    -0
      react-ui/config/config.ts
  2. +4
    -4
      react-ui/config/proxy.ts
  3. +14
    -1
      react-ui/config/routes.ts
  4. BIN
      react-ui/public/fonts/WenYiHei.ttf
  5. BIN
      react-ui/public/fonts/YouSheBiaoTiHei.ttf
  6. +14
    -1
      react-ui/public/fonts/font.css
  7. +52
    -0
      react-ui/public/scripts/resize-breakpoint.js
  8. +44
    -0
      react-ui/public/scripts/resize.js
  9. BIN
      react-ui/src/assets/img/home/code.png
  10. BIN
      react-ui/src/assets/img/home/dataset-arrow-right.png
  11. BIN
      react-ui/src/assets/img/home/dataset-item-bg-hover.png
  12. BIN
      react-ui/src/assets/img/home/dataset-item-bg.png
  13. BIN
      react-ui/src/assets/img/home/dataset.png
  14. BIN
      react-ui/src/assets/img/home/header-bg.png
  15. BIN
      react-ui/src/assets/img/home/image.png
  16. BIN
      react-ui/src/assets/img/home/model-between-dataset.png
  17. BIN
      react-ui/src/assets/img/home/model-bg.png
  18. BIN
      react-ui/src/assets/img/home/model-item-bg-hover.png
  19. BIN
      react-ui/src/assets/img/home/model-item-bg.png
  20. BIN
      react-ui/src/assets/img/home/model.png
  21. BIN
      react-ui/src/assets/img/home/right-arrow-hover.png
  22. BIN
      react-ui/src/assets/img/home/right-arrow.png
  23. BIN
      react-ui/src/assets/img/home/service-bg.png
  24. BIN
      react-ui/src/assets/img/home/service.png
  25. BIN
      react-ui/src/assets/img/home/service1.png
  26. BIN
      react-ui/src/assets/img/home/service2.png
  27. BIN
      react-ui/src/assets/img/home/service3.png
  28. BIN
      react-ui/src/assets/img/home/service4.png
  29. BIN
      react-ui/src/assets/img/home/statistics-bg.png
  30. BIN
      react-ui/src/assets/img/home/user-avatar-big.png
  31. BIN
      react-ui/src/assets/img/home/user-avatar.png
  32. BIN
      react-ui/src/assets/img/home/图像 638@2x.png
  33. BIN
      react-ui/src/assets/img/home/底座.png
  34. BIN
      react-ui/src/assets/img/home/底部(2)@2x.png
  35. BIN
      react-ui/src/assets/img/home/更多(1)@2x.png
  36. BIN
      react-ui/src/assets/img/home/点赞icon(1)@2x.png
  37. BIN
      react-ui/src/assets/img/home/点赞icon(10)@2x.png
  38. BIN
      react-ui/src/assets/img/home/点赞icon(11)@2x.png
  39. BIN
      react-ui/src/assets/img/home/点赞icon(2)@2x.png
  40. BIN
      react-ui/src/assets/img/home/点赞icon(3)@2x.png
  41. BIN
      react-ui/src/assets/img/home/点赞icon(4)@2x.png
  42. BIN
      react-ui/src/assets/img/home/点赞icon(5)@2x.png
  43. BIN
      react-ui/src/assets/img/home/点赞icon(6)@2x.png
  44. BIN
      react-ui/src/assets/img/home/点赞icon(7)@2x.png
  45. BIN
      react-ui/src/assets/img/home/点赞icon(8)@2x.png
  46. BIN
      react-ui/src/assets/img/home/点赞icon(9)@2x.png
  47. BIN
      react-ui/src/assets/img/home/点赞icon@2x.png
  48. BIN
      react-ui/src/assets/img/home/默认头像男@2x.png
  49. +2
    -0
      react-ui/src/enums/pagesEnums.ts
  50. +20
    -0
      react-ui/src/global.tsx
  51. +4
    -1
      react-ui/src/pages/Authorize/index.tsx
  52. +13
    -0
      react-ui/src/pages/Home/components/BlockTitle/index.less
  53. +24
    -0
      react-ui/src/pages/Home/components/BlockTitle/index.tsx
  54. +71
    -0
      react-ui/src/pages/Home/components/Dataset/index.less
  55. +95
    -0
      react-ui/src/pages/Home/components/Dataset/index.tsx
  56. +53
    -0
      react-ui/src/pages/Home/components/Intro/index.less
  57. +24
    -0
      react-ui/src/pages/Home/components/Intro/index.tsx
  58. +67
    -0
      react-ui/src/pages/Home/components/Model/index.less
  59. +89
    -0
      react-ui/src/pages/Home/components/Model/index.tsx
  60. +7
    -0
      react-ui/src/pages/Home/components/NavBar/index.less
  61. +12
    -0
      react-ui/src/pages/Home/components/NavBar/index.tsx
  62. +75
    -0
      react-ui/src/pages/Home/components/Service/index.less
  63. +81
    -0
      react-ui/src/pages/Home/components/Service/index.tsx
  64. +30
    -0
      react-ui/src/pages/Home/components/Statistics/index.less
  65. +54
    -0
      react-ui/src/pages/Home/components/Statistics/index.tsx
  66. +34
    -0
      react-ui/src/pages/Home/components/ViewMore/index.less
  67. +29
    -0
      react-ui/src/pages/Home/components/ViewMore/index.tsx
  68. +15
    -0
      react-ui/src/pages/Home/index.less
  69. +23
    -0
      react-ui/src/pages/Home/index.tsx
  70. +6
    -1
      react-ui/src/styles/theme.less
  71. +4
    -1
      react-ui/src/utils/index.ts
  72. +2
    -0
      react-ui/src/utils/sessionStorage.ts
  73. +3
    -0
      react-ui/src/utils/ui.tsx

+ 2
- 0
react-ui/config/config.ts View File

@@ -127,6 +127,8 @@ export default defineConfig({
headScripts: [ headScripts: [
// 解决首次加载时白屏的问题 // 解决首次加载时白屏的问题
{ src: '/scripts/loading.js', async: true }, { src: '/scripts/loading.js', async: true },
{ src: '/scripts/resize.js', async: true },
// { src: '/scripts/resize-breakpoint.js', async: true },
], ],
// links: [ // links: [
// { // {


+ 4
- 4
react-ui/config/proxy.ts View File

@@ -20,14 +20,14 @@ export default {
// localhost:8000/api/** -> https://preview.pro.ant.design/api/** // localhost:8000/api/** -> https://preview.pro.ant.design/api/**
'/api/': { '/api/': {
// 要代理的地址 // 要代理的地址
// target: 'http://172.20.32.197:31213', // 开发环境
target: 'http://172.20.32.197:31213', // 开发环境
// target: 'http://172.20.32.235:31213', // 测试环境 // target: 'http://172.20.32.235:31213', // 测试环境
target: 'http://172.20.32.44:8082',
// target: 'http://172.20.32.150:8082',
// target: 'http://172.20.32.44:8082',
// target: 'http://172.20.32.164:8082',
// 配置了这个可以从 http 代理到 https // 配置了这个可以从 http 代理到 https
// 依赖 origin 的功能可能需要这个,比如 cookie // 依赖 origin 的功能可能需要这个,比如 cookie
changeOrigin: true, changeOrigin: true,
pathRewrite: { '^/api': '' },
// pathRewrite: { '^/api': '' },
}, },
'/profile/avatar/': { '/profile/avatar/': {
target: 'http://172.20.32.235:31213', target: 'http://172.20.32.235:31213',


+ 14
- 1
react-ui/config/routes.ts View File

@@ -13,7 +13,20 @@
export default [ export default [
{ {
path: '/', path: '/',
redirect: '/workspace',
redirect: '/home',
},
{
name: '首页',
path: '/home',
layout: false,
routes: [
{
name: '首页',
path: '',
key: 'home',
component: './Home/index',
},
],
}, },
{ {
name: '工作空间', name: '工作空间',


BIN
react-ui/public/fonts/WenYiHei.ttf View File


BIN
react-ui/public/fonts/YouSheBiaoTiHei.ttf View File


+ 14
- 1
react-ui/public/fonts/font.css View File

@@ -1,6 +1,6 @@
@font-face { @font-face {
font-family: Alibaba; font-family: Alibaba;
src: url('./ALIBABA-PUHUITI-MEDIUM.TTF');
src: url('./ALIBABA-PUHUITI-REGULAR.TTF');
font-display: swap; font-display: swap;
} }


@@ -10,4 +10,17 @@
url('./DingTalk-JinBuTi.woff') format('woff'), /* 兼容性较好的 woff */ url('./DingTalk-JinBuTi.woff') format('woff'), /* 兼容性较好的 woff */
url('./DingTalk-JinBuTi.ttf') format('truetype'); /* ttf 作为备选 */ url('./DingTalk-JinBuTi.ttf') format('truetype'); /* ttf 作为备选 */
font-display: swap; /* 优化页面加载时的字体显示 */ font-display: swap; /* 优化页面加载时的字体显示 */
}

@font-face {
font-family: 'WenYiHei';
src: url('./WenYiHei.ttf');
font-display: swap; /* 优化页面加载时的字体显示 */
}


@font-face {
font-family: 'YouSheBiaoTiHei';
src: url('./YouSheBiaoTiHei.ttf');
font-display: swap; /* 优化页面加载时的字体显示 */
} }

+ 52
- 0
react-ui/public/scripts/resize-breakpoint.js View File

@@ -0,0 +1,52 @@
(function (doc, win) {
'use strict';

// 配置项
const config = {
// 断点设置(单位:px)
// 1440 1560 1680 1800 1920 2040 2160 2280 2400 2520
breakpoints: [
{ minWidth: 2520, fontSize: 22 }, // 21
{ minWidth: 2280, fontSize: 20 }, // 19
{ minWidth: 2040, fontSize: 18 }, // 17
{ minWidth: 1800, fontSize: 16 }, // 15
{ minWidth: 1560, fontSize: 14 }, // 13
{ minWidth: 0, fontSize: 12 },
],
delay: 300 // 防抖延迟(ms)
};

const docEl = doc.documentElement;
const resizeEvt = 'orientationchange' in win ? 'orientationchange' : 'resize';
let resizeTimeout;

// 计算当前宽度对应的字体大小
function calculateFontSize() {
const clientWidth = docEl.clientWidth || win.innerWidth;
if (!clientWidth) return;

// 从大到小匹配断点
const targetBreakpoint = config.breakpoints.find(
bp => clientWidth >= bp.minWidth
);

// 设置字体大小
docEl.style.fontSize = targetBreakpoint.fontSize + 'px';

// 调试输出(可选)
console.debug('[REM-Resize]',
'Width:', clientWidth + 'px',
'Font-Size:', targetBreakpoint.fontSize + 'px');
}

// 防抖处理
function handleResize() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(calculateFontSize, config.delay);
}

calculateFontSize();

// 初始化监听
win.addEventListener(resizeEvt, handleResize, false);
})(document, window);

+ 44
- 0
react-ui/public/scripts/resize.js View File

@@ -0,0 +1,44 @@
// rem-resize.js
(function (doc, win) {
'use strict';

// 配置项
const config = {
designWidth: 1920, // 设计稿宽度
baseFontSize: 16, // 基础字体大小(设计稿下1rem = 16px)
minFontSize: 12, // 最小字体限制
maxFontSize: 24, // 最大字体限制
delay: 300, // 窗口变化时的延迟执行(ms)
};

const docEl = doc.documentElement;
const resizeEvt = 'orientationchange' in win ? 'orientationchange' : 'resize';
let resizeTimeout;

function calculateFontSize() {
const clientWidth = docEl.clientWidth || win.innerWidth;
if (!clientWidth) return;

const fontSize = Math.min(
Math.max((clientWidth / config.designWidth) * config.baseFontSize, config.minFontSize),
config.maxFontSize,
);

docEl.style.fontSize = fontSize + 'px';

// 可选:调试输出
if (win.console) {
console.debug('[REM-Resize]', 'width:', clientWidth, 'font-size:', fontSize + 'px');
}
}

function resizeHandler() {
clearTimeout(resizeTimeout);
resizeTimeout = setTimeout(calculateFontSize, config.delay);
}

calculateFontSize();

// 初始化监听
win.addEventListener(resizeEvt, resizeHandler, false);
})(document, window);

BIN
react-ui/src/assets/img/home/code.png View File

Before After
Width: 144  |  Height: 144  |  Size: 22 kB

BIN
react-ui/src/assets/img/home/dataset-arrow-right.png View File

Before After
Width: 50  |  Height: 34  |  Size: 978 B

BIN
react-ui/src/assets/img/home/dataset-item-bg-hover.png View File

Before After
Width: 1366  |  Height: 350  |  Size: 116 kB

BIN
react-ui/src/assets/img/home/dataset-item-bg.png View File

Before After
Width: 1366  |  Height: 350  |  Size: 117 kB

BIN
react-ui/src/assets/img/home/dataset.png View File

Before After
Width: 144  |  Height: 144  |  Size: 24 kB

BIN
react-ui/src/assets/img/home/header-bg.png View File

Before After
Width: 5760  |  Height: 1551  |  Size: 3.8 MB

BIN
react-ui/src/assets/img/home/image.png View File

Before After
Width: 144  |  Height: 144  |  Size: 26 kB

BIN
react-ui/src/assets/img/home/model-between-dataset.png View File

Before After
Width: 3120  |  Height: 268  |  Size: 58 kB

BIN
react-ui/src/assets/img/home/model-bg.png View File

Before After
Width: 3840  |  Height: 1748  |  Size: 3.6 MB

BIN
react-ui/src/assets/img/home/model-item-bg-hover.png View File

Before After
Width: 894  |  Height: 416  |  Size: 142 kB

BIN
react-ui/src/assets/img/home/model-item-bg.png View File

Before After
Width: 894  |  Height: 416  |  Size: 106 kB

BIN
react-ui/src/assets/img/home/model.png View File

Before After
Width: 144  |  Height: 144  |  Size: 25 kB

BIN
react-ui/src/assets/img/home/right-arrow-hover.png View File

Before After
Width: 50  |  Height: 34  |  Size: 996 B

BIN
react-ui/src/assets/img/home/right-arrow.png View File

Before After
Width: 35  |  Height: 35  |  Size: 691 B

BIN
react-ui/src/assets/img/home/service-bg.png View File

Before After
Width: 3840  |  Height: 1376  |  Size: 473 kB

BIN
react-ui/src/assets/img/home/service.png View File

Before After
Width: 144  |  Height: 144  |  Size: 25 kB

BIN
react-ui/src/assets/img/home/service1.png View File

Before After
Width: 590  |  Height: 342  |  Size: 275 kB

BIN
react-ui/src/assets/img/home/service2.png View File

Before After
Width: 590  |  Height: 342  |  Size: 369 kB

BIN
react-ui/src/assets/img/home/service3.png View File

Before After
Width: 590  |  Height: 342  |  Size: 383 kB

BIN
react-ui/src/assets/img/home/service4.png View File

Before After
Width: 590  |  Height: 342  |  Size: 193 kB

BIN
react-ui/src/assets/img/home/statistics-bg.png View File

Before After
Width: 4200  |  Height: 362  |  Size: 1.0 MB

BIN
react-ui/src/assets/img/home/user-avatar-big.png View File

Before After
Width: 88  |  Height: 88  |  Size: 15 kB

BIN
react-ui/src/assets/img/home/user-avatar.png View File

Before After
Width: 42  |  Height: 42  |  Size: 4.2 kB

BIN
react-ui/src/assets/img/home/图像 638@2x.png View File

Before After
Width: 32  |  Height: 32  |  Size: 2.4 kB

BIN
react-ui/src/assets/img/home/底座.png View File

Before After
Width: 5760  |  Height: 939  |  Size: 449 kB

BIN
react-ui/src/assets/img/home/底部(2)@2x.png View File

Before After
Width: 162  |  Height: 66  |  Size: 9.4 kB

BIN
react-ui/src/assets/img/home/更多(1)@2x.png View File

Before After
Width: 40  |  Height: 40  |  Size: 695 B

BIN
react-ui/src/assets/img/home/点赞icon(1)@2x.png View File

Before After
Width: 28  |  Height: 28  |  Size: 768 B

BIN
react-ui/src/assets/img/home/点赞icon(10)@2x.png View File

Before After
Width: 28  |  Height: 28  |  Size: 756 B

BIN
react-ui/src/assets/img/home/点赞icon(11)@2x.png View File

Before After
Width: 28  |  Height: 28  |  Size: 768 B

BIN
react-ui/src/assets/img/home/点赞icon(2)@2x.png View File

Before After
Width: 28  |  Height: 28  |  Size: 756 B

BIN
react-ui/src/assets/img/home/点赞icon(3)@2x.png View File

Before After
Width: 28  |  Height: 28  |  Size: 768 B

BIN
react-ui/src/assets/img/home/点赞icon(4)@2x.png View File

Before After
Width: 28  |  Height: 28  |  Size: 756 B

BIN
react-ui/src/assets/img/home/点赞icon(5)@2x.png View File

Before After
Width: 28  |  Height: 28  |  Size: 770 B

BIN
react-ui/src/assets/img/home/点赞icon(6)@2x.png View File

Before After
Width: 28  |  Height: 28  |  Size: 756 B

BIN
react-ui/src/assets/img/home/点赞icon(7)@2x.png View File

Before After
Width: 28  |  Height: 28  |  Size: 768 B

BIN
react-ui/src/assets/img/home/点赞icon(8)@2x.png View File

Before After
Width: 28  |  Height: 28  |  Size: 756 B

BIN
react-ui/src/assets/img/home/点赞icon(9)@2x.png View File

Before After
Width: 28  |  Height: 28  |  Size: 768 B

BIN
react-ui/src/assets/img/home/点赞icon@2x.png View File

Before After
Width: 28  |  Height: 28  |  Size: 756 B

BIN
react-ui/src/assets/img/home/默认头像男@2x.png View File

Before After
Width: 72  |  Height: 72  |  Size: 3.9 kB

+ 2
- 0
react-ui/src/enums/pagesEnums.ts View File

@@ -1,4 +1,6 @@
export enum PageEnum { export enum PageEnum {
Root = '/',
LOGIN = '/user/login', LOGIN = '/user/login',
Authorize = '/authorize', Authorize = '/authorize',
Home = '/home',
} }

+ 20
- 0
react-ui/src/global.tsx View File

@@ -19,6 +19,24 @@ const clearCache = () => {
} }
}; };


const doubleTexxt = () => {
if (process.env.NODE_ENV === 'development') {
document.body.addEventListener('click', (e) => {
const target = e.target;
if (
e.altKey &&
e.ctrlKey &&
target &&
target.innerText &&
target.nodeType === Node.ELEMENT_NODE
) {
const times = 2;
target.innerText = target.innerText.repeat(times);
}
});
}
};

// if pwa is true // if pwa is true
if (pwa) { if (pwa) {
// Notify user if offline now // Notify user if offline now
@@ -89,3 +107,5 @@ if (pwa) {


clearCache(); clearCache();
} }

doubleTexxt();

+ 4
- 1
react-ui/src/pages/Authorize/index.tsx View File

@@ -1,6 +1,7 @@
import { setSessionToken } from '@/access'; import { setSessionToken } from '@/access';
import { loginByOauth2Req } from '@/services/auth'; import { loginByOauth2Req } from '@/services/auth';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import SessionStorage from '@/utils/sessionStorage';
import { history, useModel, useSearchParams } from '@umijs/max'; import { history, useModel, useSearchParams } from '@umijs/max';
import { message } from 'antd'; import { message } from 'antd';
import { useCallback, useEffect } from 'react'; import { useCallback, useEffect } from 'react';
@@ -36,7 +37,9 @@ function Authorize() {
setSessionToken(access_token, access_token, expires_in); setSessionToken(access_token, access_token, expires_in);
message.success('登录成功!'); message.success('登录成功!');
await fetchUserInfo(); await fetchUserInfo();
history.replace(redirect || '/');
const redierctUrl = SessionStorage.getItem(SessionStorage.redirectUrl);
history.replace(redirect || redierctUrl || '/workspace');
SessionStorage.removeItem(SessionStorage.redirectUrl);
} }
}, [fetchUserInfo, redirect, code]); }, [fetchUserInfo, redirect, code]);




+ 13
- 0
react-ui/src/pages/Home/components/BlockTitle/index.less View File

@@ -0,0 +1,13 @@
.block-title {
display: flex;
align-items: center;
justify-content: center;
width: 100%;

&__title {
color: #020814;
font-weight: 500;
font-size: 2.25rem;
text-align: center;
}
}

+ 24
- 0
react-ui/src/pages/Home/components/BlockTitle/index.tsx View File

@@ -0,0 +1,24 @@
import classNames from 'classnames';
import ViewMore from '../ViewMore';
import styles from './index.less';

type BlockTitleProps = {
/** 自定义类名 */
className?: string;
/** 自定义样式 */
style?: React.CSSProperties;
/** 标题 */
title: string;
onClick?: () => void;
};

function BlockTitle({ title, onClick, className, style }: BlockTitleProps) {
return (
<div className={classNames(styles['block-title'], className)} style={style}>
<div className={styles['block-title__title']}>{title}</div>
<ViewMore onClick={onClick}></ViewMore>
</div>
);
}

export default BlockTitle;

+ 71
- 0
react-ui/src/pages/Home/components/Dataset/index.less View File

@@ -0,0 +1,71 @@
.dataset {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
padding: 0 16.25rem 3.125rem;
background-image: url(@/assets/img/home/model-bg.png);
background-repeat: no-repeat;
background-position: top 6.375rem left 0;
background-size: 100% 100%;

&__item {
position: relative;
width: 42.75rem;
padding: 1.875rem 1.25rem;
color: #8284a4;
font-size: 0.8125rem;
background-color: transparent;
border-radius: 11px;
cursor: pointer;
.backgroundFullImage(url(@/assets/img/home/dataset-item-bg.png));

&:hover {
.backgroundFullImage(url(@/assets/img/home/dataset-item-bg-hover.png));
}

&__user-avatar {
flex: none;
width: 2.75rem;
height: 2.75rem;
margin-right: 1rem;
}

&__title {
flex: 1;
color: #020814;
font-size: 1rem;
.singleLine();
}

&:hover &__title {
color: @primary-color;
}

&__arrow {
display: none;
flex: none;
width: 1.5625rem;
margin-left: 0.75rem;
}

&:hover &__arrow {
display: block;
}

&__desc {
height: 2.75rem;
margin-bottom: 0.875rem;
font-size: 0.875rem;
line-height: 1.375rem;
.multiLine(2);
}

&__user-divider {
height: 0.625rem;
margin-right: 0.75rem;
margin-left: 0.75rem;
background-color: #8284a4;
}
}
}

+ 95
- 0
react-ui/src/pages/Home/components/Dataset/index.tsx View File

@@ -0,0 +1,95 @@
import { useNavigate } from '@umijs/max';
import { Divider, Flex } from 'antd';
import BlockTitle from '../BlockTitle';
import styles from './index.less';

const datasetData = [
{
id: 1,
title: '材料大数据与机器学习',
desc: '在材料科学与人工智能交叉融合的当下',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 2,
title: '材料大数据与机器学习',
desc: '在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具。',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 3,
title: '材料大数据与机器学习材料大数据与机器学习材料大数据与机器学习',
desc: '在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具。在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 4,
title: '材料大数据与机器学习',
desc: '在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具。本课程为2025年新',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 5,
title: '材料大数据与机器学习',
desc: '在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具。本课程为2025年新',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 6,
title: '材料大数据与机器学习',
desc: '在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具。本课程为2025年新',
user: '陈绮贞',
date: '18小时前更新',
},
];

function DatasetBlock() {
const navigate = useNavigate();
return (
<div className={styles.dataset}>
<BlockTitle
title="热门数据集"
style={{ marginBottom: '6.75rem' }}
onClick={() => navigate('/dataset/dataset')}
></BlockTitle>
<Flex align="center" justify="space-between" style={{ width: '100%' }} wrap gap="1.875rem 0">
{datasetData.map((item) => {
return (
<Flex className={styles['dataset__item']} key={item.id}>
<img
src={require('@/assets/img/home/user-avatar-big.png')}
className={styles['dataset__item__user-avatar']}
></img>
<div style={{ flex: 1, minWidth: 0 }}>
<Flex align="center" style={{ marginBottom: '0.625rem' }}>
<div className={styles['dataset__item__title']}>{item.title}</div>
<img
className={styles['dataset__item__arrow']}
src={require('@/assets/img/home/dataset-arrow-right.png')}
></img>
</Flex>
<div className={styles['dataset__item__desc']}>{item.desc}</div>
<Flex align="center">
<div>{item.user}</div>
<Divider
type="vertical"
className={styles['dataset__item__user-divider']}
></Divider>
<div>{item.date}</div>
<div></div>
</Flex>
</div>
</Flex>
);
})}
</Flex>
</div>
);
}

export default DatasetBlock;

+ 53
- 0
react-ui/src/pages/Home/components/Intro/index.less View File

@@ -0,0 +1,53 @@
.intro {
position: relative;
z-index: 10;
display: flex;
flex-direction: column;
align-items: center;
padding-top: 8.375rem;
background-image: url(@/assets/img/home/header-bg.png);
background-repeat: no-repeat;
background-position: left top;
background-size: 100% 100%;

&__title {
margin-bottom: 1.125rem;
color: #ffffff;
font-size: 2.375rem;
font-family: WenYiHei;
}

&__desc {
width: 54.5rem;
margin-bottom: 1.875rem;
color: #ffffff;
font-size: 1rem;
line-height: 1.75rem;
text-align: center;
}

&__button {
margin-bottom: 4.375rem;
padding: 0.625rem 2.375rem;
color: #ffffff;
font-size: 1rem;
text-align: center;
background: linear-gradient(
108.54deg,
#5eb4ff 3.72%,
rgba(42, 92, 255, 0.01) 49.49%,
rgba(232, 239, 255, 0.33) 98.01%
);
border: 1px solid rgba(255, 255, 255, 0.38);
border-radius: 0.5rem;
cursor: pointer;

&:hover {
background: linear-gradient(
108.54deg,
rgba(183, 131, 255, 0.81) 3.72%,
rgba(119, 208, 255, 0.31) 98.01%
);
}
}
}

+ 24
- 0
react-ui/src/pages/Home/components/Intro/index.tsx View File

@@ -0,0 +1,24 @@
// import NavBar from '../NavBar';
import { useNavigate } from '@umijs/max';
import StatisticsBlock from '../Statistics';
import styles from './index.less';

function IntroBlock() {
const navigate = useNavigate();
return (
<div className={styles.intro}>
{/* <NavBar></NavBar> */}
<div className={styles['intro__title']}>智能材料科研平台</div>
<div className={styles['intro__desc']}>
智能材料科研平台是用于材料研究和开发的技术平台,它旨在提供实验数据收集、分析和可视化等功能,
以支持材料工程师、科学家和研究人员在材料设计、性能评估和工艺优化方面的工作。
</div>
<div className={styles['intro__button']} onClick={() => navigate('/workspace')}>
进入首页
</div>
<StatisticsBlock></StatisticsBlock>
</div>
);
}

export default IntroBlock;

+ 67
- 0
react-ui/src/pages/Home/components/Model/index.less View File

@@ -0,0 +1,67 @@
.model {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
padding: 5.375rem 16.25rem 9.125rem;
.backgroundFullImage(url(@/assets/img/home/model-bg.png));

&__item {
position: relative;
width: 27.875rem;
padding: 1.875rem 1.25rem;
color: #8284a4;
font-size: 0.8125rem;
background-color: transparent;
border-radius: 11px;
box-shadow: 0rem 0.0625rem 0.75rem rgba(33, 73, 212, 0.09);
cursor: pointer;
.backgroundFullImage(url(@/assets/img/home/model-item-bg.png));

&:hover {
color: white;
.backgroundFullImage(url(@/assets/img/home/model-item-bg-hover.png));
}

&:nth-child(3n + 2) {
top: -3.75rem;
}

&__user-avatar {
flex: none;
width: 2.75rem;
height: 2.75rem;
margin-right: 0.875rem;
}

&__title {
margin-bottom: 0.625rem;
color: #020814;
font-size: 1rem;
.singleLine();
}

&:hover &__title {
color: white;
}

&__desc {
height: 2.75rem;
margin-bottom: 0.875rem;
font-size: 0.875rem;
line-height: 1.375rem;
.multiLine(2);
}

&__user-divider {
height: 0.625rem;
margin-right: 0.75rem;
margin-left: 0.75rem;
background-color: #8284a4;
}

&:hover &__user-divider {
background-color: white;
}
}
}

+ 89
- 0
react-ui/src/pages/Home/components/Model/index.tsx View File

@@ -0,0 +1,89 @@
import { useNavigate } from '@umijs/max';
import { Divider, Flex } from 'antd';
import BlockTitle from '../BlockTitle';
import styles from './index.less';

const modelData = [
{
id: 1,
title: '材料大数据与机器学习',
desc: '在材料科学与人工智能交叉融合的当下',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 2,
title: '材料大数据与机器学习',
desc: '在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具。',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 3,
title: '材料大数据与机器学习材料大数据与机器学习材料大数据与机器学习',
desc: '在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具。在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 4,
title: '材料大数据与机器学习',
desc: '在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具。本课程为2025年新',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 5,
title: '材料大数据与机器学习',
desc: '在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具。本课程为2025年新',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 6,
title: '材料大数据与机器学习',
desc: '在材料科学与人工智能交叉融合的当下,机器学习技术正逐步成为材料研究的重要工具。本课程为2025年新',
user: '陈绮贞',
date: '18小时前更新',
},
];

function ModelBlock() {
const navigate = useNavigate();
return (
<div className={styles.model}>
<BlockTitle
title="热门模型"
style={{ marginBottom: '8.125rem' }}
onClick={() => navigate('/dataset/model')}
></BlockTitle>
<Flex align="center" justify="space-between" style={{ width: '100%' }} wrap gap="3.125rem 0">
{modelData.map((item) => {
return (
<Flex className={styles['model__item']} key={item.id}>
<img
src={require('@/assets/img/home/user-avatar-big.png')}
className={styles['model__item__user-avatar']}
></img>
<div style={{ flex: 1, minWidth: 0 }}>
<div className={styles['model__item__title']}>{item.title}</div>
<div className={styles['model__item__desc']}>{item.desc}</div>
<Flex align="center">
<div>{item.user}</div>
<Divider
type="vertical"
className={styles['model__item__user-divider']}
></Divider>
<div>{item.date}</div>
<div></div>
</Flex>
</div>
</Flex>
);
})}
</Flex>
</div>
);
}

export default ModelBlock;

+ 7
- 0
react-ui/src/pages/Home/components/NavBar/index.less View File

@@ -0,0 +1,7 @@
.nav-bar {
display: flex;
align-items: center;
padding: 1.25rem 15.625rem;

}

+ 12
- 0
react-ui/src/pages/Home/components/NavBar/index.tsx View File

@@ -0,0 +1,12 @@
import styles from './index.less';

function NavBar() {
return (
<div className={styles['nav-bar']}>
<div>智能材料科研平台</div>
<div>首页</div>
</div>
);
}

export default NavBar;

+ 75
- 0
react-ui/src/pages/Home/components/Service/index.less View File

@@ -0,0 +1,75 @@
.service {
position: relative;
display: flex;
flex-direction: column;
align-items: center;
width: 100%;
margin-top: -4rem;
padding: 9.625rem 16.25rem 6.25rem;
.backgroundFullImage(url(@/assets/img/home/service-bg.png));

&__item {
width: 21rem;
padding: 1.25rem 1.25rem 1.5625rem;
background: #ffffff;
border-radius: 1.25rem;
box-shadow: 0rem 0rem 0.75rem rgba(33, 73, 212, 0.06);
cursor: pointer;

&:hover {
box-shadow: 0rem 0rem 0.75rem rgba(33, 73, 212, 0.12);
}

&__image-container {
width: 18.4375rem;
height: 10.6875rem;
margin-bottom: 0.75rem;
overflow: hidden;
border-radius: 1.875rem;
}

&__image {
width: 100%;
height: 100%;
background-repeat: no-repeat;
background-position: top left;
background-size: 100% 100%;
transform: scale(1);
transition: transform 0.3s linear;
}

&:hover &__image {
transform: scale(1.1);
}

&__title {
height: 2.625rem;
margin-bottom: 0.875rem;
color: #020814;
font-size: 0.9375rem;
.multiLine(2);
}

&:hover &__title {
color: @primary-color;
}

&__user-avatar {
width: 1.3125rem;
height: 1.3125rem;
margin-right: 0.5rem;
}

&__user-name {
margin-right: 0.5rem;
color: #191919;
font-size: 0.875rem;
}

&__date {
color: #8284a4;
font-size: 0.8125rem;
text-align: right;
}
}
}

+ 81
- 0
react-ui/src/pages/Home/components/Service/index.tsx View File

@@ -0,0 +1,81 @@
import ServiceImg1 from '@/assets/img/home/service1.png';
import ServiceImg2 from '@/assets/img/home/service2.png';
import ServiceImg3 from '@/assets/img/home/service3.png';
import ServiceImg4 from '@/assets/img/home/service4.png';
import { useNavigate } from '@umijs/max';
import { Flex } from 'antd';
import BlockTitle from '../BlockTitle';
import styles from './index.less';

const serviceData = [
{
id: 1,
img: ServiceImg1,
title: 'MD是研究原子间相互作用的基本工具',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 2,
img: ServiceImg2,
title: 'MD是研究原子间相互作用的基本工具 原子间相互作用势函数 通常基于力场或者量子',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 3,
img: ServiceImg3,
title: 'MD是研究原子间相互作用的基本工具 原子间相互作用势函数 通常基于力场或者量子',
user: '陈绮贞',
date: '18小时前更新',
},
{
id: 4,
img: ServiceImg4,
title:
'MD是研究原子间相互作用的基本工具 原子间相互作用势函数 通常基于力场或者量子 通常基于力场或者量子 通常基于力场或者量子',
user: '陈绮贞',
date: '18小时前更新',
},
];

function ServiceBlock() {
const navigate = useNavigate();
return (
<div className={styles.service}>
<BlockTitle
title="热门APP"
style={{ marginBottom: '5rem' }}
onClick={() => navigate('dataset/modelDeployment')}
></BlockTitle>
<Flex align="center" justify="space-between" style={{ width: '100%' }}>
{serviceData.map((item) => {
return (
<div className={styles['service__item']} key={item.id}>
<div className={styles['service__item__image-container']}>
<img
src={item.img}
draggable={false}
className={styles['service__item__image']}
></img>
</div>
<div className={styles['service__item__title']}>{item.title}</div>
<Flex align="center" justify="space-between">
<Flex align="center">
<img
src={require('@/assets/img/home/user-avatar.png')}
className={styles['service__item__user-avatar']}
></img>
<div className={styles['service__item__user-name']}>{item.user}</div>
</Flex>
<div className={styles['service__item__date']}>{item.date}</div>
</Flex>
</div>
);
})}
</Flex>
</div>
);
}

export default ServiceBlock;

+ 30
- 0
react-ui/src/pages/Home/components/Statistics/index.less View File

@@ -0,0 +1,30 @@
.statistics {
display: flex;
align-items: center;
justify-content: space-evenly;
width: 87.5rem;
height: 7.5rem;
.backgroundFullImage(url(@/assets/img/home/statistics-bg.png));

&__item {
display: flex;
align-items: center;

&__icon {
width: 3rem;
height: 3rem;
margin-right: 1rem;
}

&__count {
color: #ffffff;
font-size: 2.25rem;
font-family: YouSheBiaoTiHei;
}

&__name {
color: #ffffff;
font-size: 0.875rem;
}
}
}

+ 54
- 0
react-ui/src/pages/Home/components/Statistics/index.tsx View File

@@ -0,0 +1,54 @@
import CodeIcon from '@/assets/img/home/code.png';
import DatasetIcon from '@/assets/img/home/dataset.png';
import ImageIcon from '@/assets/img/home/image.png';
import ModelIcon from '@/assets/img/home/model.png';
import ServiceIcon from '@/assets/img/home/service.png';
import styles from './index.less';

const dataList = [
{
icon: DatasetIcon,
name: '数据集',
count: 30,
},
{
icon: ModelIcon,
name: '模型',
count: 30,
},
{
icon: ImageIcon,
name: '镜像',
count: 30,
},
{
icon: CodeIcon,
name: '代码',
count: 30,
},
{
icon: ServiceIcon,
name: '服务',
count: 30,
},
];

function StatisticsBlock() {
return (
<div className={styles['statistics']}>
{dataList.map((item) => {
return (
<div key={item.name} className={styles['statistics__item']}>
<img src={item.icon} draggable={false} className={styles['statistics__item__icon']} />
<div>
<div className={styles['statistics__item__count']}>{item.count}</div>
<div className={styles['statistics__item__name']}>{item.name}</div>
</div>
</div>
);
})}
</div>
);
}

export default StatisticsBlock;

+ 34
- 0
react-ui/src/pages/Home/components/ViewMore/index.less View File

@@ -0,0 +1,34 @@
.view-more {
position: absolute;
right: 16.25rem;
display: flex;
align-items: center;
color: .addAlpha(#020814, 0.7) [];
font-size: 0.9375rem;
cursor: pointer;

&:hover {
color: #020814;
}

&__img {
display: inline;
width: 1.125rem;
height: 1.125rem;
margin-left: 0.75rem;
}

&__hover-img {
display: none;
width: 1.5625rem;
margin-left: 0.625rem;
}

&:hover &__img {
display: none;
}

&:hover &__hover-img {
display: inline;
}
}

+ 29
- 0
react-ui/src/pages/Home/components/ViewMore/index.tsx View File

@@ -0,0 +1,29 @@
import classNames from 'classnames';
import styles from './index.less';

type ViewMoreProps = {
/** 自定义类名 */
className?: string;
/** 自定义样式 */
style?: React.CSSProperties;
/** 自定义样式 */
onClick?: () => void;
};

function ViewMore({ className, style, onClick }: ViewMoreProps) {
return (
<div className={classNames(styles['view-more'], className)} style={style} onClick={onClick}>
<span>查看更多</span>
<img
className={styles['view-more__img']}
src={require('@/assets/img/home/right-arrow.png')}
></img>
<img
className={styles['view-more__hover-img']}
src={require('@/assets/img/home/right-arrow-hover.png')}
></img>
</div>
);
}

export default ViewMore;

+ 15
- 0
react-ui/src/pages/Home/index.less View File

@@ -0,0 +1,15 @@
.home {
height: 100%;
overflow-y: auto;
font-family: Alibaba;

&__separator {
position: relative;
z-index: 10;
display: block;
width: 97.5rem;
height: 8.375rem;
margin: 0 auto;
margin-top: -5.875rem;
}
}

+ 23
- 0
react-ui/src/pages/Home/index.tsx View File

@@ -0,0 +1,23 @@
import DatasetBlock from './components/Dataset';
import IntroBlock from './components/Intro';
import ModelBlock from './components/Model';
import ServiceBlock from './components/Service';
import styles from './index.less';

function Home() {
return (
<div className={styles.home}>
<IntroBlock></IntroBlock>
<ServiceBlock></ServiceBlock>
<ModelBlock></ModelBlock>
<img
src={require('@/assets/img/home/model-between-dataset.png')}
draggable={false}
className={styles['home__separator']}
></img>
<DatasetBlock></DatasetBlock>
</div>
);
}

export default Home;

+ 6
- 1
react-ui/src/styles/theme.less View File

@@ -51,6 +51,11 @@
@result: rgba(@red, @green, @blue, @alpha); @result: rgba(@red, @green, @blue, @alpha);
} }


// 转换为 rem
.rem(@px) {
@result: (@px / 16) * 1rem;
}

// 混合 // 混合
// 单行 // 单行
.singleLine() { .singleLine() {
@@ -73,7 +78,7 @@
.backgroundFullImage(@url) { .backgroundFullImage(@url) {
background-image: @url; background-image: @url;
background-repeat: no-repeat; background-repeat: no-repeat;
background-position: top center;
background-position: top left;
background-size: 100% 100%; background-size: 100% 100%;
} }




+ 4
- 1
react-ui/src/utils/index.ts View File

@@ -7,6 +7,9 @@
import { PageEnum } from '@/enums/pagesEnums'; import { PageEnum } from '@/enums/pagesEnums';
import G6 from '@antv/g6'; import G6 from '@antv/g6';


// 白名单,不需要登录
const whiteList = [PageEnum.Root, PageEnum.LOGIN, PageEnum.Authorize, PageEnum.Home];

/** /**
* 生成 8 位随机数 * 生成 8 位随机数
* @returns 8 位随机数 * @returns 8 位随机数
@@ -295,7 +298,7 @@ export const getGitUrl = (url?: string, branch?: string): string => {
* @return {boolean} true if the pathname needs to be authorized, false otherwise * @return {boolean} true if the pathname needs to be authorized, false otherwise
*/ */
export const needAuth = (pathname: string): boolean => { export const needAuth = (pathname: string): boolean => {
return pathname !== PageEnum.LOGIN && pathname !== PageEnum.Authorize;
return !whiteList.includes(pathname);
}; };


/** /**


+ 2
- 0
react-ui/src/utils/sessionStorage.ts View File

@@ -13,6 +13,8 @@ export default class SessionStorage {
static readonly aimUrlKey = 'aim-url'; static readonly aimUrlKey = 'aim-url';
/** tensorBoard url */ /** tensorBoard url */
static readonly tensorBoardUrlKey = 'tensor-board-url'; static readonly tensorBoardUrlKey = 'tensor-board-url';
/** 登录之前的地址 */
static readonly redirectUrl = 'redirect-url';


/** /**
* 获取 SessionStorage 值 * 获取 SessionStorage 值


+ 3
- 0
react-ui/src/utils/ui.tsx View File

@@ -77,6 +77,9 @@ export const gotoLoginPage = (toHome: boolean = true) => {
if (pathname !== PageEnum.LOGIN) { if (pathname !== PageEnum.LOGIN) {
closeAllModals(); closeAllModals();
removeAllPageCacheState(); removeAllPageCacheState();
if (newSearch) {
SessionStorage.setItem(newSearch, SessionStorage.redirectUrl);
}
history.replace({ history.replace({
pathname: PageEnum.LOGIN, pathname: PageEnum.LOGIN,
search: newSearch, search: newSearch,


Loading…
Cancel
Save