| @@ -20,9 +20,9 @@ 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.235:31213', // 测试环境 | |||||
| // target: 'http://172.20.32.44:8082', | |||||
| // target: 'http://172.20.32.197:31213', // 开发环境 | |||||
| target: 'http://172.20.32.235:31213', // 测试环境 | |||||
| // target: 'http://36.103.199.74:31213/', // 公网环境 | |||||
| // target: 'http://172.20.32.164:8082', | // target: 'http://172.20.32.164:8082', | ||||
| // 配置了这个可以从 http 代理到 https | // 配置了这个可以从 http 代理到 https | ||||
| // 依赖 origin 的功能可能需要这个,比如 cookie | // 依赖 origin 的功能可能需要这个,比如 cookie | ||||
| @@ -75,6 +75,7 @@ | |||||
| "fabric": "^5.3.0", | "fabric": "^5.3.0", | ||||
| "highlight.js": "^11.7.0", | "highlight.js": "^11.7.0", | ||||
| "lodash": "^4.17.21", | "lodash": "^4.17.21", | ||||
| "motion": "~12.23.12", | |||||
| "omit.js": "^2.0.2", | "omit.js": "^2.0.2", | ||||
| "pnpm": "^8.9.0", | "pnpm": "^8.9.0", | ||||
| "query-string": "^8.1.0", | "query-string": "^8.1.0", | ||||
| @@ -82,6 +83,7 @@ | |||||
| "rc-util": "^5.30.0", | "rc-util": "^5.30.0", | ||||
| "react": "^18.2.0", | "react": "^18.2.0", | ||||
| "react-activation": "^0.12.4", | "react-activation": "^0.12.4", | ||||
| "react-countup": "~6.5.3", | |||||
| "react-cropper": "^2.3.3", | "react-cropper": "^2.3.3", | ||||
| "react-dev-inspector": "^1.8.1", | "react-dev-inspector": "^1.8.1", | ||||
| "react-dom": "^18.2.0", | "react-dom": "^18.2.0", | ||||
| @@ -8,7 +8,7 @@ | |||||
| * - Please do NOT serve this file on production. | * - Please do NOT serve this file on production. | ||||
| */ | */ | ||||
| const PACKAGE_VERSION = '2.7.0' | |||||
| const PACKAGE_VERSION = '2.7.1' | |||||
| const INTEGRITY_CHECKSUM = '00729d72e3b82faf54ca8b9621dbb96f' | const INTEGRITY_CHECKSUM = '00729d72e3b82faf54ca8b9621dbb96f' | ||||
| const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') | const IS_MOCKED_RESPONSE = Symbol('isMockedResponse') | ||||
| const activeClientIds = new Set() | const activeClientIds = new Set() | ||||
| @@ -3,7 +3,7 @@ | |||||
| display: flex; | display: flex; | ||||
| flex-direction: column; | flex-direction: column; | ||||
| align-items: center; | align-items: center; | ||||
| padding: 4.375rem 16.25rem 9.375rem; | |||||
| padding: 4.375rem @home-padding-x 9.375rem; | |||||
| .backgroundFullImage(url(@/assets/img/home/code-bg.png)); | .backgroundFullImage(url(@/assets/img/home/code-bg.png)); | ||||
| &__item { | &__item { | ||||
| @@ -3,7 +3,7 @@ | |||||
| display: flex; | display: flex; | ||||
| flex-direction: column; | flex-direction: column; | ||||
| align-items: center; | align-items: center; | ||||
| padding: 0 16.25rem 11.625rem; | |||||
| padding: 0 @home-padding-x 11.125rem; | |||||
| &__item { | &__item { | ||||
| position: relative; | position: relative; | ||||
| @@ -1,15 +1,28 @@ | |||||
| .intro { | .intro { | ||||
| position: relative; | |||||
| z-index: 10; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| align-items: center; | |||||
| background-image: url(@/assets/img/home/header-bg.png); | |||||
| background-repeat: no-repeat; | |||||
| background-position: left top; | |||||
| background-size: 100% 100%; | |||||
| position: fixed; | |||||
| top: 0; | |||||
| right: 0; | |||||
| left: 0; | |||||
| z-index: 100; | |||||
| height: @home-info-height; | |||||
| overflow: hidden; | |||||
| background-color: red; | |||||
| &__content { | |||||
| position: relative; | |||||
| z-index: 10; | |||||
| display: flex; | |||||
| flex-direction: column; | |||||
| align-items: center; | |||||
| padding: 1.25rem @home-padding-x 0; | |||||
| background-image: url(@/assets/img/home/header-bg.png); | |||||
| background-repeat: no-repeat; | |||||
| background-position: left top; | |||||
| background-size: 100% 100%; | |||||
| } | |||||
| &__title { | &__title { | ||||
| margin-top: 1.25rem; | |||||
| margin-bottom: 1.125rem; | margin-bottom: 1.125rem; | ||||
| color: #ffffff; | color: #ffffff; | ||||
| font-weight: 400; | font-weight: 400; | ||||
| @@ -1,23 +1,60 @@ | |||||
| import { convertRemToPx } from '@/utils'; | |||||
| import { useNavigate } from '@umijs/max'; | import { useNavigate } from '@umijs/max'; | ||||
| import { motion, useMotionTemplate, useScroll, useSpring, useTransform } from 'motion/react'; | |||||
| import NavBar from '../NavBar'; | import NavBar from '../NavBar'; | ||||
| import StatisticsBlock from '../Statistics'; | import StatisticsBlock from '../Statistics'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| function IntroBlock() { | function IntroBlock() { | ||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const { scrollY } = useScroll(); | |||||
| const springValue = useSpring(scrollY, { | |||||
| stiffness: 100, | |||||
| damping: 30, | |||||
| restDelta: 0.001, | |||||
| }); | |||||
| const initialHeight = convertRemToPx(35); | |||||
| console.log(initialHeight); | |||||
| const height = useTransform(() => `max(calc(35rem - ${springValue.get()}px), 5rem)`); | |||||
| // const left = useTransform(() => `min(${springValue.get()}px, 16.25rem)`); | |||||
| const left = useTransform(springValue, [0, initialHeight], [0.0, 16.25]); | |||||
| const leftRem = useMotionTemplate`${left}rem`; | |||||
| const radius = useTransform(springValue, [0, initialHeight], [0.0, 2.5]); | |||||
| const radiusRem = useMotionTemplate`${radius}rem`; | |||||
| const top = useTransform(springValue, [0, initialHeight], [0, 10]); | |||||
| const paddingX = useTransform(springValue, [0, initialHeight], [16.25, 10]); | |||||
| const paddingXRem = useMotionTemplate`1.25rem ${paddingX}rem 0`; | |||||
| return ( | 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> | |||||
| <motion.div | |||||
| className={styles.intro} | |||||
| style={{ | |||||
| height: height, | |||||
| left: leftRem, | |||||
| right: leftRem, | |||||
| borderRadius: radiusRem, | |||||
| top: top, | |||||
| }} | |||||
| transition={{ | |||||
| type: 'spring', | |||||
| duration: 0.3, | |||||
| }} | |||||
| > | |||||
| <motion.div className={styles['intro__content']} style={{ padding: paddingXRem }}> | |||||
| <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> | |||||
| </motion.div> | |||||
| </motion.div> | |||||
| ); | ); | ||||
| } | } | ||||
| @@ -3,7 +3,7 @@ | |||||
| display: flex; | display: flex; | ||||
| flex-direction: column; | flex-direction: column; | ||||
| align-items: center; | align-items: center; | ||||
| padding: 0 16.25rem 11.625rem; | |||||
| padding: 0 @home-padding-x 11.125rem; | |||||
| &__item { | &__item { | ||||
| position: relative; | position: relative; | ||||
| @@ -3,12 +3,21 @@ | |||||
| display: flex; | display: flex; | ||||
| flex-direction: column; | flex-direction: column; | ||||
| align-items: center; | align-items: center; | ||||
| margin-top: 1.25rem; | |||||
| padding: 4.125rem 16.25rem 14.75rem; | |||||
| padding: 4.125rem @home-padding-x 14.75rem; | |||||
| .backgroundFullImage(url(@/assets/img/home/model-bg.png)); | .backgroundFullImage(url(@/assets/img/home/model-bg.png)); | ||||
| &__content { | |||||
| display: flex; | |||||
| flex-wrap: wrap; | |||||
| gap: 1.625rem 1.25rem; | |||||
| align-items: center; | |||||
| width: 100%; | |||||
| } | |||||
| &__item { | &__item { | ||||
| position: relative; | position: relative; | ||||
| display: flex; | |||||
| align-items: center; | |||||
| width: calc((100% - 2 * 1.25rem) / 3); | width: calc((100% - 2 * 1.25rem) / 3); | ||||
| padding: 1.875rem 1.25rem; | padding: 1.875rem 1.25rem; | ||||
| color: @home-text-color-tertiary; | color: @home-text-color-tertiary; | ||||
| @@ -3,10 +3,31 @@ import { getPublicModelsReq } from '@/services/home'; | |||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { useNavigate } from '@umijs/max'; | import { useNavigate } from '@umijs/max'; | ||||
| import { Divider, Flex } from 'antd'; | import { Divider, Flex } from 'antd'; | ||||
| import { motion, type Variants } from 'motion/react'; | |||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import BlockTitle from '../BlockTitle'; | import BlockTitle from '../BlockTitle'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const modelVariants: Variants = { | |||||
| offscreen: (index: number) => ({ | |||||
| y: 0, | |||||
| opacity: 1, | |||||
| transition: { | |||||
| ease: 'linear', | |||||
| duration: 0.1, | |||||
| }, | |||||
| }), | |||||
| onscreen: { | |||||
| y: [0, 200, 0], | |||||
| opacity: [0, 0, 1], | |||||
| transition: { | |||||
| ease: 'easeInOut', | |||||
| duration: 0.5, | |||||
| times: [0, 0, 1], | |||||
| }, | |||||
| }, | |||||
| }; | |||||
| function ModelBlock() { | function ModelBlock() { | ||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const [modelData, setModelData] = useState<ModelData[]>([]); | const [modelData, setModelData] = useState<ModelData[]>([]); | ||||
| @@ -30,10 +51,14 @@ function ModelBlock() { | |||||
| style={{ marginBottom: '5.25rem' }} | style={{ marginBottom: '5.25rem' }} | ||||
| onClick={() => navigate('/dataset/model')} | onClick={() => navigate('/dataset/model')} | ||||
| ></BlockTitle> | ></BlockTitle> | ||||
| <Flex align="center" style={{ width: '100%' }} wrap gap="1.625rem 1.25rem"> | |||||
| <div className={styles['model__content']}> | |||||
| {modelData.map((item, index) => { | {modelData.map((item, index) => { | ||||
| return ( | return ( | ||||
| <Flex | |||||
| <motion.div | |||||
| variants={modelVariants} | |||||
| initial={'offscreen'} | |||||
| whileInView={'onscreen'} | |||||
| custom={index} | |||||
| className={styles['model__item']} | className={styles['model__item']} | ||||
| key={item.id} | key={item.id} | ||||
| onClick={() => { | onClick={() => { | ||||
| @@ -64,10 +89,10 @@ function ModelBlock() { | |||||
| <div className={styles['model__item__category']}>材料研发</div> | <div className={styles['model__item__category']}>材料研发</div> | ||||
| </Flex> */} | </Flex> */} | ||||
| </div> | </div> | ||||
| </Flex> | |||||
| </motion.div> | |||||
| ); | ); | ||||
| })} | })} | ||||
| </Flex> | |||||
| </div> | |||||
| </div> | </div> | ||||
| ); | ); | ||||
| } | } | ||||
| @@ -1,9 +1,9 @@ | |||||
| .nav-bar { | .nav-bar { | ||||
| display: flex; | display: flex; | ||||
| align-items: center; | align-items: center; | ||||
| justify-content: space-between; | |||||
| width: 100%; | width: 100%; | ||||
| margin-bottom: 4.375rem; | margin-bottom: 4.375rem; | ||||
| padding: 1.25rem 15.625rem; | |||||
| color: white; | color: white; | ||||
| font-size: 0.9375rem; | font-size: 0.9375rem; | ||||
| @@ -20,24 +20,30 @@ | |||||
| &__menu-item { | &__menu-item { | ||||
| margin-right: 3.125rem; | margin-right: 3.125rem; | ||||
| padding: 0.25rem 0.5rem; | |||||
| border-radius: 0.375rem; | |||||
| cursor: pointer; | cursor: pointer; | ||||
| &:hover { | |||||
| background-color: rgba(0, 0, 0, 0.06); | |||||
| } | |||||
| &:last-of-type { | &:last-of-type { | ||||
| margin-right: 0; | margin-right: 0; | ||||
| } | } | ||||
| } | } | ||||
| &__avatar { | |||||
| width: 2rem; | |||||
| height: 2rem; | |||||
| margin-right: 0; | |||||
| margin-left: auto; | |||||
| cursor: pointer; | |||||
| } | |||||
| :global { | |||||
| .ant-dropdown-trigger { | |||||
| height: 2.15rem; | |||||
| &__login { | |||||
| margin-right: 0; | |||||
| margin-left: auto; | |||||
| cursor: pointer; | |||||
| .ant-avatar { | |||||
| margin-right: 0 !important; | |||||
| } | |||||
| } | |||||
| .ant-dropdown-trigger > .anticon { | |||||
| display: none; | |||||
| } | |||||
| } | } | ||||
| } | } | ||||
| @@ -2,6 +2,7 @@ import { getAccessToken } from '@/access'; | |||||
| import Avatar from '@/components/RightContent/AvatarDropdown'; | import Avatar from '@/components/RightContent/AvatarDropdown'; | ||||
| import { useNavigate } from '@umijs/max'; | import { useNavigate } from '@umijs/max'; | ||||
| import { Flex } from 'antd'; | import { Flex } from 'antd'; | ||||
| import classNames from 'classnames'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| function NavBar() { | function NavBar() { | ||||
| @@ -47,26 +48,30 @@ function NavBar() { | |||||
| className={styles['nav-bar__app-logo']} | className={styles['nav-bar__app-logo']} | ||||
| ></img> | ></img> | ||||
| <span className={styles['nav-bar__app-name']}>智能材料科研平台</span> | <span className={styles['nav-bar__app-name']}>智能材料科研平台</span> | ||||
| <div className={styles['nav-bar__menu-item']} onClick={() => gotoPage('service')}> | |||||
| 服务 | |||||
| </div> | |||||
| <div className={styles['nav-bar__menu-item']} onClick={() => gotoPage('model')}> | |||||
| 模型 | |||||
| </div> | |||||
| <div className={styles['nav-bar__menu-item']} onClick={() => gotoPage('dataset')}> | |||||
| 数据集 | |||||
| </div> | |||||
| <div className={styles['nav-bar__menu-item']} onClick={() => gotoPage('mirror')}> | |||||
| 镜像 | |||||
| </div> | |||||
| <div className={styles['nav-bar__menu-item']} onClick={() => gotoPage('codeConfig')}> | |||||
| 代码配置 | |||||
| </div> | |||||
| </Flex> | </Flex> | ||||
| <div className={styles['nav-bar__menu-item']} onClick={() => gotoPage('service')}> | |||||
| 服务 | |||||
| </div> | |||||
| <div className={styles['nav-bar__menu-item']} onClick={() => gotoPage('model')}> | |||||
| 模型 | |||||
| </div> | |||||
| <div className={styles['nav-bar__menu-item']} onClick={() => gotoPage('dataset')}> | |||||
| 数据集 | |||||
| </div> | |||||
| <div className={styles['nav-bar__menu-item']} onClick={() => gotoPage('mirror')}> | |||||
| 镜像 | |||||
| </div> | |||||
| <div className={styles['nav-bar__menu-item']} onClick={() => gotoPage('codeConfig')}> | |||||
| 代码配置 | |||||
| </div> | |||||
| {token ? ( | {token ? ( | ||||
| <Avatar menu isHome /> | <Avatar menu isHome /> | ||||
| ) : ( | ) : ( | ||||
| <div className={styles['nav-bar__login']} onClick={() => gotoPage('login')}> | |||||
| <div | |||||
| className={classNames(styles['nav-bar__menu-item'], styles['nav-bar__login'])} | |||||
| onClick={() => gotoPage('login')} | |||||
| > | |||||
| 登录 | 登录 | ||||
| </div> | </div> | ||||
| )} | )} | ||||
| @@ -0,0 +1,25 @@ | |||||
| import { motion, useInView, Variants } from 'motion/react'; | |||||
| import { ReactNode, useRef } from 'react'; | |||||
| type ScrollRevealProps = { | |||||
| children: ReactNode; | |||||
| variants: Variants; | |||||
| }; | |||||
| function ScrollReveal({ children, variants }: ScrollRevealProps) { | |||||
| const ref = useRef<HTMLDivElement>(null); | |||||
| const isInView = useInView(ref, { amount: 'all' }); | |||||
| return ( | |||||
| <motion.div | |||||
| variants={variants} | |||||
| ref={ref} | |||||
| initial="offscreen" | |||||
| animate={isInView ? 'onscreen' : 'offscreen'} | |||||
| > | |||||
| {children} | |||||
| </motion.div> | |||||
| ); | |||||
| } | |||||
| export default ScrollReveal; | |||||
| @@ -4,7 +4,7 @@ | |||||
| flex-direction: column; | flex-direction: column; | ||||
| align-items: center; | align-items: center; | ||||
| width: 100%; | width: 100%; | ||||
| padding: 5.625rem 16.25rem 6.25rem; | |||||
| padding: 5.625rem @home-padding-x 6.25rem; | |||||
| .backgroundFullImage(url(@/assets/img/home/service-bg.png)); | .backgroundFullImage(url(@/assets/img/home/service-bg.png)); | ||||
| &__item { | &__item { | ||||
| @@ -8,10 +8,31 @@ import { formatDate } from '@/utils/date'; | |||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { useNavigate } from '@umijs/max'; | import { useNavigate } from '@umijs/max'; | ||||
| import { Flex } from 'antd'; | import { Flex } from 'antd'; | ||||
| import { motion, type Variants } from 'motion/react'; | |||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import BlockTitle from '../BlockTitle'; | import BlockTitle from '../BlockTitle'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| const serviceVariants: Variants = { | |||||
| offscreen: { | |||||
| y: -100, | |||||
| opacity: 0, | |||||
| transition: { | |||||
| ease: 'linear', | |||||
| duration: 0, | |||||
| }, | |||||
| }, | |||||
| onscreen: (index: number) => ({ | |||||
| y: 0, | |||||
| opacity: 1, | |||||
| transition: { | |||||
| type: 'spring', | |||||
| duration: 1, | |||||
| delay: index * 0.3, | |||||
| }, | |||||
| }), | |||||
| }; | |||||
| function ServiceBlock() { | function ServiceBlock() { | ||||
| const navigate = useNavigate(); | const navigate = useNavigate(); | ||||
| const [serviceData, setServiceData] = useState<ServiceData[]>([]); | const [serviceData, setServiceData] = useState<ServiceData[]>([]); | ||||
| @@ -38,10 +59,14 @@ function ServiceBlock() { | |||||
| <Flex align="center" style={{ width: '100%' }} gap={'0 1.125rem'}> | <Flex align="center" style={{ width: '100%' }} gap={'0 1.125rem'}> | ||||
| {serviceData.map((item, index) => { | {serviceData.map((item, index) => { | ||||
| return ( | return ( | ||||
| <div | |||||
| <motion.div | |||||
| variants={serviceVariants} | |||||
| className={styles['service__item']} | className={styles['service__item']} | ||||
| key={item.id} | key={item.id} | ||||
| onClick={() => navigate(`/dataset/modelDeployment/serviceInfo/${item.id}`)} | onClick={() => navigate(`/dataset/modelDeployment/serviceInfo/${item.id}`)} | ||||
| initial="offscreen" | |||||
| whileInView="onscreen" | |||||
| custom={index} | |||||
| > | > | ||||
| <div className={styles['service__item__image-container']}> | <div className={styles['service__item__image-container']}> | ||||
| <img | <img | ||||
| @@ -59,7 +84,7 @@ function ServiceBlock() { | |||||
| <div className={styles['service__item__user']}>{item.create_by}</div> | <div className={styles['service__item__user']}>{item.create_by}</div> | ||||
| <div className={styles['service__item__date']}>{formatDate(item.create_time)}</div> | <div className={styles['service__item__date']}>{formatDate(item.create_time)}</div> | ||||
| </Flex> | </Flex> | ||||
| </div> | |||||
| </motion.div> | |||||
| ); | ); | ||||
| })} | })} | ||||
| </Flex> | </Flex> | ||||
| @@ -6,6 +6,7 @@ import ServiceIcon from '@/assets/img/home/service.png'; | |||||
| import { getAssetPublicCountReq } from '@/services/home'; | import { getAssetPublicCountReq } from '@/services/home'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import CountUp from 'react-countup'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| function StatisticsBlock() { | function StatisticsBlock() { | ||||
| @@ -84,7 +85,14 @@ function StatisticsBlock() { | |||||
| <div key={item.title} className={styles['statistics__item']}> | <div key={item.title} className={styles['statistics__item']}> | ||||
| <img src={item.icon} draggable={false} className={styles['statistics__item__icon']} /> | <img src={item.icon} draggable={false} className={styles['statistics__item__icon']} /> | ||||
| <div> | <div> | ||||
| <div className={styles['statistics__item__count']}>{item.value ?? '--'}</div> | |||||
| <div className={styles['statistics__item__count']}> | |||||
| {item.value ? ( | |||||
| <CountUp end={item.value} duration={1} enableScrollSpy></CountUp> | |||||
| ) : ( | |||||
| '--' | |||||
| )} | |||||
| </div> | |||||
| <div className={styles['statistics__item__name']}>{item.title}</div> | <div className={styles['statistics__item__name']}>{item.title}</div> | ||||
| </div> | </div> | ||||
| </div> | </div> | ||||
| @@ -1,6 +1,5 @@ | |||||
| .home { | .home { | ||||
| height: 100%; | |||||
| overflow-y: auto; | |||||
| padding-top: @home-info-height; | |||||
| font-family: Alibaba; | font-family: Alibaba; | ||||
| &__separator { | &__separator { | ||||
| @@ -31,6 +31,8 @@ | |||||
| @home-text-color-secondary: @text-color-secondary; | @home-text-color-secondary: @text-color-secondary; | ||||
| @home-text-color-tertiary: #8284a4; | @home-text-color-tertiary: #8284a4; | ||||
| @home-divider-color: #d8d8d8; | @home-divider-color: #d8d8d8; | ||||
| @home-padding-x: 16.25rem; | |||||
| @home-info-height: 35rem; | |||||
| @workspace-background: linear-gradient( | @workspace-background: linear-gradient( | ||||
| 179.03deg, | 179.03deg, | ||||
| @@ -365,3 +365,16 @@ export const trimCharacter = (str: string, ch: string): string => { | |||||
| export const convertEmptyStringToUndefined = (value?: string): string | undefined => { | export const convertEmptyStringToUndefined = (value?: string): string | undefined => { | ||||
| return value === '' ? undefined : value; | return value === '' ? undefined : value; | ||||
| }; | }; | ||||
| /** | |||||
| * Converts rem to px. | |||||
| * | |||||
| * @param {number} rem - The value of rem. | |||||
| * @return {number} The value of px | |||||
| */ | |||||
| export const convertRemToPx = (rem: number): number => { | |||||
| const fontSize = document.documentElement.style.fontSize; | |||||
| const font = parseFloat(fontSize); | |||||
| return font * rem; | |||||
| }; | |||||