Browse Source

feat: 完成积分功能

pull/187/head
cp3hnu 10 months ago
parent
commit
f7b207877b
31 changed files with 587 additions and 58 deletions
  1. +12
    -1
      react-ui/config/routes.ts
  2. BIN
      react-ui/public/fonts/DingTalk-JinBuTi.ttf
  3. BIN
      react-ui/public/fonts/DingTalk-JinBuTi.woff
  4. BIN
      react-ui/public/fonts/DingTalk-JinBuTi.woff2
  5. BIN
      react-ui/public/fonts/TaoBaoMaiCaiTi-Regular.otf
  6. BIN
      react-ui/public/fonts/TaoBaoMaiCaiTi-Regular.ttf
  7. BIN
      react-ui/public/fonts/TaoBaoMaiCaiTi-Regular.woff
  8. BIN
      react-ui/public/fonts/TaoBaoMaiCaiTi-Regular.woff2
  9. +22
    -4
      react-ui/public/fonts/font.css
  10. BIN
      react-ui/src/assets/img/user-points-bg.png
  11. BIN
      react-ui/src/assets/img/workspace-experiment.png
  12. BIN
      react-ui/src/assets/img/workspace-pipeline.png
  13. +31
    -0
      react-ui/src/pages/Points/components/Statistics/index.less
  14. +38
    -0
      react-ui/src/pages/Points/components/Statistics/index.tsx
  15. +19
    -0
      react-ui/src/pages/Points/index.less
  16. +256
    -0
      react-ui/src/pages/Points/index.tsx
  17. +15
    -6
      react-ui/src/pages/System/User/edit.tsx
  18. +5
    -0
      react-ui/src/pages/System/User/index.tsx
  19. +1
    -0
      react-ui/src/pages/Workspace/components/ExperimentChart/index.less
  20. +5
    -5
      react-ui/src/pages/Workspace/components/ExperimentTable/index.less
  21. +4
    -16
      react-ui/src/pages/Workspace/components/TotalStatistics/index.less
  22. +3
    -3
      react-ui/src/pages/Workspace/components/TotalStatistics/index.tsx
  23. +36
    -0
      react-ui/src/pages/Workspace/components/UserPoints/index.less
  24. +40
    -0
      react-ui/src/pages/Workspace/components/UserPoints/index.tsx
  25. +11
    -2
      react-ui/src/pages/Workspace/index.less
  26. +34
    -20
      react-ui/src/pages/Workspace/index.tsx
  27. +22
    -0
      react-ui/src/services/points/index.ts
  28. +8
    -0
      react-ui/src/styles/theme.less
  29. +1
    -0
      react-ui/src/types/system/user.d.ts
  30. +23
    -0
      react-ui/src/utils/statusTableCell.tsx
  31. +1
    -1
      react-ui/src/utils/table.tsx

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

@@ -345,7 +345,6 @@ export default [
}, },
], ],
}, },

{ {
name: '应用开发', name: '应用开发',
path: '/appsDeployment', path: '/appsDeployment',
@@ -498,6 +497,18 @@ export default [
}, },
], ],
}, },
{
name: '算力积分',
path: '/points',
routes: [
{
name: '算力积分',
path: '',
key: 'points',
component: './Points/index',
},
],
},
{ {
path: '*', path: '*',
layout: false, layout: false,


BIN
react-ui/public/fonts/DingTalk-JinBuTi.ttf View File


BIN
react-ui/public/fonts/DingTalk-JinBuTi.woff View File


BIN
react-ui/public/fonts/DingTalk-JinBuTi.woff2 View File


BIN
react-ui/public/fonts/TaoBaoMaiCaiTi-Regular.otf View File


BIN
react-ui/public/fonts/TaoBaoMaiCaiTi-Regular.ttf View File


BIN
react-ui/public/fonts/TaoBaoMaiCaiTi-Regular.woff View File


BIN
react-ui/public/fonts/TaoBaoMaiCaiTi-Regular.woff2 View File


+ 22
- 4
react-ui/public/fonts/font.css View File

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

@font-face {
font-family: 'TaoBaoMaiCaiTi';
src: url('./TaoBaoMaiCaiTi-Regular.woff2') format('woff2'), /* 最优先使用 woff2 */
url('./TaoBaoMaiCaiTi-Regular.woff') format('woff'), /* 兼容性较好的 woff */
url('./TaoBaoMaiCaiTi-Regular.ttf') format('truetype'), /* ttf 作为备选 */
url('./TaoBaoMaiCaiTi-Regular.otf') format('opentype'); /* otf 作为最后选项 */
font-display: swap; /* 优化页面加载时的字体显示 */
}


@font-face {
font-family: 'DingTalk-JinBuTi';
src: url('./DingTalk-JinBuTi.woff2') format('woff2'), /* 最优先使用 woff2 */
url('./DingTalk-JinBuTi.woff') format('woff'), /* 兼容性较好的 woff */
url('./DingTalk-JinBuTi.ttf') format('truetype'); /* ttf 作为备选 */
font-display: swap; /* 优化页面加载时的字体显示 */
}

BIN
react-ui/src/assets/img/user-points-bg.png View File

Before After
Width: 981  |  Height: 672  |  Size: 220 kB

BIN
react-ui/src/assets/img/workspace-experiment.png View File

Before After
Width: 147  |  Height: 148  |  Size: 17 kB Width: 216  |  Height: 216  |  Size: 24 kB

BIN
react-ui/src/assets/img/workspace-pipeline.png View File

Before After
Width: 169  |  Height: 159  |  Size: 21 kB Width: 219  |  Height: 216  |  Size: 31 kB

+ 31
- 0
react-ui/src/pages/Points/components/Statistics/index.less View File

@@ -0,0 +1,31 @@
.statistics {
display: flex;
align-items: center;
width: 100%;
padding: 20px 0;
background-color: @background-color;
border-radius: 8px;

&__item {
display: flex;
flex: 1;
flex-direction: column;
align-items: center;

&--border {
border-right: 1px solid @border-color;
}

&__value {
margin-bottom: 8px;
color: @text-color;
font-weight: bold;
font-size: 30px;
}

&__title {
color: #999999;
font-size: @font-size-input;
}
}
}

+ 38
- 0
react-ui/src/pages/Points/components/Statistics/index.tsx View File

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

type StatisticsProps = {
remaining?: number;
consuming?: number;
};

function Statistics({ remaining, consuming }: StatisticsProps) {
const items = [
{
title: '当前可用算力积分(分)',
value: remaining ?? '-',
},
{
title: '总消耗算力积分(分)',
value: consuming ?? '-',
},
];

return (
<div className={styles['statistics']}>
{items.map((item, index) => (
<div
key={item.title}
className={classNames(styles['statistics__item'], {
[styles['statistics__item--border']]: index === 0,
})}
>
<span className={styles['statistics__item__value']}>{item.value}</span>
<span className={styles['statistics__item__title']}>{item.title}</span>
</div>
))}
</div>
);
}

export default Statistics;

+ 19
- 0
react-ui/src/pages/Points/index.less View File

@@ -0,0 +1,19 @@
.points-detail {
height: 100%;
&__content {
height: calc(100% - 60px);
margin-top: 10px;
padding: 20px 30px 0;
background-color: white;
border-radius: 10px;

&__top {
width: 100%;
}

&__table {
height: calc(100% - 117px - 28px);
margin-top: 28px;
}
}
}

+ 256
- 0
react-ui/src/pages/Points/index.tsx View File

@@ -0,0 +1,256 @@
/*
* @Author: 赵伟
* @Date: 2024-04-16 13:58:08
* @Description: 模型部署服务列表
*/
import PageTitle from '@/components/PageTitle';
import { getPointsConsumptionReq, getPointsStatisticsReq } from '@/services/points';
import themes from '@/styles/theme.less';
import { to } from '@/utils/promise';
import statusTableCell from '@/utils/statusTableCell';
import tableCellRender, { TableCellValueType } from '@/utils/table';
import { Link } from '@umijs/max';
import { Table, type TablePaginationConfig, type TableProps } from 'antd';
import classNames from 'classnames';
import { useEffect, useState } from 'react';
import Statistics from './components/Statistics';
import styles from './index.less';

enum TaskType {
DevEnvironment = 'dev_environment',
Workflow = 'workflow',
Ray = 'ray',
Service = 'service',
}

const taskTypeOptions = [
{
value: 'dev_environment',
label: '开发环境',
},
{
value: 'workflow',
label: '实验',
},
{
value: 'ray',
label: '超参数自动寻优',
},
{
value: 'service',
label: '服务',
},
];

export type PointsData = {
computing_resource_id: number;
credit_per_hour: number; // 每小时消耗的积分
deduce_credit: number;
deduce_last_time: string;
description: string;
id: number;
node_id: string;
start_time: string;
state: number;
workflow_id?: number; // 流水线id
task_id: number; // 实验id
task_ins_id: number; // 实例id
task_type: string;
user_id: number;
};

export type PointsStatistics = {
deduceCredit: number;
userCredit: number;
};

// 格式化任务
const formatTask = (value: string, record: PointsData) => {
let url;
switch (record.task_type) {
case TaskType.DevEnvironment:
url = `/developmentEnvironment`;
break;
case TaskType.Workflow:
if (record.workflow_id && record.task_ins_id) {
url = `/pipeline/experiment/instance/${record.workflow_id}/${record.task_ins_id}`;
}
break;
case TaskType.Ray:
if (record.task_id && record.task_ins_id) {
url = `/pipeline/hyperparameter/instance/${record.task_id}/${record.task_ins_id}`;
}
break;
case TaskType.Service:
if (record.task_id && record.task_ins_id) {
url = `/dataset/modelDeployment/serviceInfo/${record.task_id}/versionInfo/${record.task_ins_id}`;
}
break;
default:
break;
}

if (url) {
return <Link to={url}>{value}</Link>;
} else {
return <span>{value}</span>;
}
};

function PointsDetail() {
const [tableData, setTableData] = useState<PointsData[]>([]);
const [total, setTotal] = useState(0);
const [statistics, setStatistics] = useState<PointsStatistics>();
const [pagination, setPagination] = useState<TablePaginationConfig>({
current: 1,
pageSize: 10,
});

useEffect(() => {
// 获取积分统计
const getPointsStatistics = async () => {
const [res] = await to(getPointsStatisticsReq());
if (res && res.data) {
setStatistics(res.data);
}
};

getPointsStatistics();
}, []);

useEffect(() => {
// 获取积分消费明细
const getPointsConsumption = async () => {
const params: Record<string, any> = {
page: pagination.current! - 1,
size: pagination.pageSize,
};
const [res] = await to(getPointsConsumptionReq(params));
if (res && res.data) {
const { content = [], totalElements = 0 } = res.data;
setTableData(content);
setTotal(totalElements);
}
};

getPointsConsumption();
}, [pagination]);

// 分页切换
const handleTableChange: TableProps<PointsData>['onChange'] = (
pagination,
_filters,
_sorter,
{ action },
) => {
if (action === 'paginate') {
setPagination(pagination);
}
};

const columns: TableProps<PointsData>['columns'] = [
{
title: '序号',
dataIndex: 'index',
key: 'index',
width: 80,
render: tableCellRender(false, TableCellValueType.Index, {
page: pagination.current! - 1,
pageSize: pagination.pageSize!,
}),
},
{
title: '任务',
dataIndex: 'task_name',
key: 'task_name',
width: '15%',
render: formatTask,
},
{
title: '任务类型',
dataIndex: 'task_type',
key: 'task_type',
width: '10%',
render: statusTableCell(taskTypeOptions),
},
{
title: '积分/小时',
dataIndex: 'credit_per_hour',
key: 'credit_per_hour',
width: '10%',
render: tableCellRender(),
},
{
title: '消耗的积分(分)',
dataIndex: 'deduce_credit',
key: 'deduce_credit',
width: '12%',
render: tableCellRender(),
},
{
title: '描述',
dataIndex: 'description',
key: 'description',
render: tableCellRender(true),
},
{
title: '开始时间',
dataIndex: 'start_time',
key: 'start_time',
width: '15%',
render: tableCellRender(false, TableCellValueType.Date),
},
{
title: '状态',
dataIndex: 'state',
key: 'state',
width: '8%',
render: statusTableCell([
{
value: 0,
label: '已结束',
color: themes['textColor'],
},
{
value: 1,
label: '进行中',
color: themes['primaryColor'],
},
]),
},
];

return (
<div className={styles['points-detail']}>
<PageTitle title="算力积分明细"></PageTitle>
<div className={styles['points-detail__content']}>
<div className={styles['points-detail__content__top']}>
<Statistics
remaining={statistics?.userCredit}
consuming={statistics?.deduceCredit}
></Statistics>
</div>
<div
className={classNames('vertical-scroll-table', styles['points-detail__content__table'])}
>
<Table
dataSource={tableData}
columns={columns}
scroll={{ y: 'calc(100% - 55px)' }}
pagination={{
...pagination,
total: total,
showSizeChanger: true,
showQuickJumper: true,
showTotal: () => `共${total}条`,
}}
onChange={handleTableChange}
rowKey="id"
/>
</div>
</div>
</div>
);
}

export default PointsDetail;

+ 15
- 6
react-ui/src/pages/System/User/edit.tsx View File

@@ -2,6 +2,7 @@ import { DictValueEnumObj } from '@/components/DictTag';
import KFModal from '@/components/KFModal'; import KFModal from '@/components/KFModal';
import { import {
ProForm, ProForm,
ProFormDigit,
ProFormRadio, ProFormRadio,
ProFormSelect, ProFormSelect,
ProFormText, ProFormText,
@@ -64,6 +65,7 @@ const UserForm: React.FC<UserFormProps> = (props) => {
remark: props.values.remark, remark: props.values.remark,
gitLinkUsername: props.values.gitLinkUsername, gitLinkUsername: props.values.gitLinkUsername,
gitLinkPassword: props.values.gitLinkPassword, gitLinkPassword: props.values.gitLinkPassword,
credit: props.values.credit,
}); });
}, [form, props, statusOptions]); }, [form, props, statusOptions]);


@@ -219,12 +221,7 @@ const UserForm: React.FC<UserFormProps> = (props) => {
autoComplete: 'new-password', autoComplete: 'new-password',
}} }}
allowClear allowClear
rules={[
{
required: true,
message: <FormattedMessage id="请输入密码!" defaultMessage="请输入密码!" />,
},
]}
rules={props.values.userId ? [] : [{ required: true, message: '请输入密码!' }]}
/> />
<ProFormSelect <ProFormSelect
valueEnum={sexOptions} valueEnum={sexOptions}
@@ -304,6 +301,18 @@ const UserForm: React.FC<UserFormProps> = (props) => {
}} }}
rules={props.values.userId ? [] : [{ required: true, message: '请输入 Git 密码!' }]} rules={props.values.userId ? [] : [{ required: true, message: '请输入 Git 密码!' }]}
/> />
<ProFormDigit
name="credit"
label="算力积分"
placeholder="请输入算力积分"
colProps={{ xs: 24, md: 12, xl: 12 }}
rules={[
{
required: true,
message: '请输入算力积分',
},
]}
/>
<ProFormTextArea <ProFormTextArea
name="remark" name="remark"
label={intl.formatMessage({ label={intl.formatMessage({


+ 5
- 0
react-ui/src/pages/System/User/index.tsx View File

@@ -259,6 +259,11 @@ const UserTableList: React.FC = () => {
dataIndex: 'phonenumber', dataIndex: 'phonenumber',
valueType: 'text', valueType: 'text',
}, },
{
title: <FormattedMessage id="system.user.credit" defaultMessage="算力积分" />,
dataIndex: 'credit',
valueType: 'text',
},
{ {
title: <FormattedMessage id="system.user.status" defaultMessage="帐号状态" />, title: <FormattedMessage id="system.user.status" defaultMessage="帐号状态" />,
dataIndex: 'status', dataIndex: 'status',


+ 1
- 0
react-ui/src/pages/Workspace/components/ExperimentChart/index.less View File

@@ -1,4 +1,5 @@
.experiment-chart { .experiment-chart {
flex: none;
width: 295px; width: 295px;
min-width: 295px; min-width: 295px;
height: 140px; height: 140px;


+ 5
- 5
react-ui/src/pages/Workspace/components/ExperimentTable/index.less View File

@@ -1,8 +1,8 @@
.experiment-table { .experiment-table {
flex: 1; flex: 1;
min-width: 500px;
min-width: 378px;
height: 140px; height: 140px;
padding: 12px 24px;
padding: 12px;
background: @workspace-background; background: @workspace-background;
border-radius: 4px; border-radius: 4px;


@@ -32,15 +32,15 @@
} }


&__status { &__status {
width: 20%;
width: 15%;
} }


&__duration { &__duration {
width: 30%;
width: 25%;
} }


&__date { &__date {
width: calc(50% - 60px);
width: calc(60% - 60px);
} }


&__operation { &__operation {


+ 4
- 16
react-ui/src/pages/Workspace/components/TotalStatistics/index.less View File

@@ -1,16 +1,12 @@
.total-statistics { .total-statistics {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center;
width: 400px;
height: 140px; height: 140px;
background: @workspace-background;
border-radius: 4px;
padding: 0 16px;


&__icon { &__icon {
width: 85px;
height: 80px;
margin-right: 40px;
width: 63px;
margin-right: 15px;
} }


&__title { &__title {
@@ -20,18 +16,10 @@
font-size: @font-size-content; font-size: @font-size-content;
} }


&__title-shadow {
position: absolute;
bottom: 6px;
left: 0;
width: 79px;
height: 6px;
background: linear-gradient(87.07deg, rgba(22, 100, 255, 0.6) 0%, rgba(22, 100, 255, 0) 100%);
}

&__count { &__count {
color: @text-color; color: @text-color;
font-weight: 700; font-weight: 700;
font-size: 25px; font-size: 25px;
font-family: DingTalk-JinBuTi;
} }
} }

+ 3
- 3
react-ui/src/pages/Workspace/components/TotalStatistics/index.tsx View File

@@ -1,3 +1,4 @@
import { Flex } from 'antd';
import styles from './index.less'; import styles from './index.less';


type TotalStatisticsProps = { type TotalStatisticsProps = {
@@ -11,13 +12,12 @@ function TotalStatistics({ icon = '', title = '', count = 0, style }: TotalStati
return ( return (
<div className={styles['total-statistics']} style={style}> <div className={styles['total-statistics']} style={style}>
<img className={styles['total-statistics__icon']} src={icon} draggable={false} alt="" /> <img className={styles['total-statistics__icon']} src={icon} draggable={false} alt="" />
<div>
<Flex vertical align="center">
<div className={styles['total-statistics__title']}> <div className={styles['total-statistics__title']}>
<span>{title}</span> <span>{title}</span>
<div className={styles['total-statistics__title-shadow']}></div>
</div> </div>
<div className={styles['total-statistics__count']}>{count ?? '--'}</div> <div className={styles['total-statistics__count']}>{count ?? '--'}</div>
</div>
</Flex>
</div> </div>
); );
} }


+ 36
- 0
react-ui/src/pages/Workspace/components/UserPoints/index.less View File

@@ -0,0 +1,36 @@
.user-points {
display: flex;
flex: none;
flex-direction: column;
align-items: center;

width: 326px;
height: 228px;
.backgroundFullImage(url(@/assets/img/user-points-bg.png));

&__label {
margin-top: 60px;
color: @text-color;
font-size: @font-size-title;
font-family: DingTalk-JinBuTi;
}

&__value {
margin-top: 8px;
margin-bottom: 12px;
color: @primary-color;
font-size: 36px;
font-family: DingTalk-JinBuTi;
line-height: 43px;
}

&__button {
padding: 8px 20px;
color: @primary-color;
font-size: @font-size-content;
background: rgba(255, 255, 255, 0.3);
border: 1px solid #ffffff;
border-radius: 8px;
cursor: pointer;
}
}

+ 40
- 0
react-ui/src/pages/Workspace/components/UserPoints/index.tsx View File

@@ -0,0 +1,40 @@
import { PointsStatistics } from '@/pages/Points/index';
import { getPointsStatisticsReq } from '@/services/points';
import { to } from '@/utils/promise';
import { useNavigate } from '@umijs/max';
import { useEffect, useState } from 'react';
import styles from './index.less';

function UserPoints() {
const [statistics, setStatistics] = useState<PointsStatistics>();
const navigate = useNavigate();

useEffect(() => {
// 获取积分统计
const getPointsStatistics = async () => {
const [res] = await to(getPointsStatisticsReq());
if (res && res.data) {
setStatistics(res.data);
}
};

getPointsStatistics();
}, []);

return (
<div className={styles['user-points']}>
<span className={styles['user-points__label']}>当前可用算力积分</span>
<span className={styles['user-points__value']}>{statistics?.userCredit ?? '--'}</span>
<div
className={styles['user-points__button']}
onClick={() => {
navigate('/points');
}}
>
查看详情
</div>
</div>
);
}

export default UserPoints;

+ 11
- 2
react-ui/src/pages/Workspace/index.less View File

@@ -6,6 +6,7 @@
background: linear-gradient(#ecf2fe, #f9fafb); background: linear-gradient(#ecf2fe, #f9fafb);


&__overview { &__overview {
flex: 1;
gap: 15px; gap: 15px;
margin-bottom: 16px; margin-bottom: 16px;
padding: 20px 30px; padding: 20px 30px;
@@ -21,11 +22,19 @@


&__content { &__content {
display: flex; display: flex;

flex-wrap: wrap;
gap: 15px; gap: 15px;
align-items: center; align-items: center;


@media screen and (max-width: 1800px) {
flex-wrap: wrap;
&__statistics {
flex: none;
background: linear-gradient(
123.08deg,
rgba(138, 138, 138, 0.06) 1.32%,
rgba(22, 100, 255, 0.02) 58.35%
);
border-radius: 4px;
} }
} }
} }


+ 34
- 20
react-ui/src/pages/Workspace/index.tsx View File

@@ -2,6 +2,7 @@ import { useDraggable } from '@/hooks/draggable';
import { getWorkspaceOverviewReq } from '@/services/workspace'; import { getWorkspaceOverviewReq } from '@/services/workspace';
import { ExperimentInstance } from '@/types'; import { ExperimentInstance } from '@/types';
import { to } from '@/utils/promise'; import { to } from '@/utils/promise';
import { Divider, Flex } from 'antd';
import { useEffect, useState } from 'react'; import { useEffect, useState } from 'react';
import Draggable from 'react-draggable'; import Draggable from 'react-draggable';
import AssetsManagement from './components/AssetsManagement'; import AssetsManagement from './components/AssetsManagement';
@@ -10,6 +11,7 @@ import ExperitableTable from './components/ExperimentTable';
import QuickStart from './components/QuickStart'; import QuickStart from './components/QuickStart';
import RobotFrame from './components/RobotFrame'; import RobotFrame from './components/RobotFrame';
import TotalStatistics from './components/TotalStatistics'; import TotalStatistics from './components/TotalStatistics';
import UserPoints from './components/UserPoints';
import UserSpace from './components/UserSpace'; import UserSpace from './components/UserSpace';
import WorkspaceIntro from './components/WorkspaceIntro'; import WorkspaceIntro from './components/WorkspaceIntro';
import styles from './index.less'; import styles from './index.less';
@@ -28,6 +30,7 @@ function Workspace() {
setRobotFrameVisible((prev) => !prev), setRobotFrameVisible((prev) => !prev),
); );
const users: number[] = new Array(8).fill(0); const users: number[] = new Array(8).fill(0);

useEffect(() => { useEffect(() => {
getWorkspaceOverview(); getWorkspaceOverview();
}, []); }, []);
@@ -43,27 +46,38 @@ function Workspace() {
return ( return (
<div className={styles.workspace}> <div className={styles.workspace}>
<WorkspaceIntro></WorkspaceIntro> <WorkspaceIntro></WorkspaceIntro>
<div className={styles['workspace__overview']}>
<div className={styles['workspace__overview__title']}>运行概览</div>
<div className={styles['workspace__overview__content']}>
<TotalStatistics
icon={require('@/assets/img/workspace-pipeline.png')}
title="流水线总数"
count={overviewData?.workflowCount}
/>
<TotalStatistics
icon={require('@/assets/img/workspace-experiment.png')}
title="正在运行实例总数"
count={overviewData?.runningExperimentInsCount}
/>
<ExperitableTable
tableData={overviewData?.latestExperimentInsList || []}
></ExperitableTable>
{overviewData?.experimentInsStatus && (
<ExperimentChart chartData={overviewData?.experimentInsStatus}></ExperimentChart>
)}
<Flex gap={'0 15px'} wrap>
<div className={styles['workspace__overview']}>
<div className={styles['workspace__overview__title']}>运行概览</div>
<div className={styles['workspace__overview__content']}>
<Flex align="center" className={styles['workspace__overview__content__statistics']}>
<TotalStatistics
icon={require('@/assets/img/workspace-pipeline.png')}
title="流水线总数"
count={overviewData?.workflowCount}
/>
<Divider
type="vertical"
dashed
style={{ color: '1px dashed rgba(96, 107, 122, 0.19)', height: 68 }}
/>
<TotalStatistics
icon={require('@/assets/img/workspace-experiment.png')}
title="正在运行实例总数"
count={overviewData?.runningExperimentInsCount}
/>
</Flex>

<ExperitableTable
tableData={overviewData?.latestExperimentInsList || []}
></ExperitableTable>
{overviewData?.experimentInsStatus && (
<ExperimentChart chartData={overviewData?.experimentInsStatus}></ExperimentChart>
)}
</div>
</div> </div>
</div>
<UserPoints />
</Flex>
<div className={styles['workspace__quick-start']}> <div className={styles['workspace__quick-start']}>
<QuickStart></QuickStart> <QuickStart></QuickStart>
<div className={styles['workspace__user']}> <div className={styles['workspace__user']}>


+ 22
- 0
react-ui/src/services/points/index.ts View File

@@ -0,0 +1,22 @@
/*
* @Author: 赵伟
* @Date: 2025-03-20 13:48:53
* @Description: 积分
*/

import { request } from '@umijs/max';

// 分页查询积分消费明细
export function getPointsConsumptionReq(params: any) {
return request(`/api/mmp/computingResource/resouceOccupy`, {
method: 'GET',
params,
});
}

// 分页查询积分消费明细
export function getPointsStatisticsReq() {
return request(`/api/mmp/computingResource/credit`, {
method: 'GET',
});
}

+ 8
- 0
react-ui/src/styles/theme.less View File

@@ -69,6 +69,14 @@
-webkit-line-clamp: @line; -webkit-line-clamp: @line;
} }


// 背景
.backgroundFullImage(@url) {
background-image: @url;
background-repeat: no-repeat;
background-position: top center;
background-size: 100% 100%;
}

// 导出变量 // 导出变量
:export { :export {
primaryColor: @primary-color; primaryColor: @primary-color;


+ 1
- 0
react-ui/src/types/system/user.d.ts View File

@@ -21,6 +21,7 @@ declare namespace API.System {
remark: string; remark: string;
gitLinkUsername?: string; gitLinkUsername?: string;
gitLinkPassword?: string; gitLinkPassword?: string;
credit?: number;
} }


export interface UserListParams { export interface UserListParams {


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

@@ -0,0 +1,23 @@
/*
* @Author: 赵伟
* @Date: 2025-03-20 14:33:01
* @Description: 通用的 Table 状态单元格
*/

export type StatusInfo = {
value: number | string;
label: string;
color?: string;
};

function statusTableCell(infos: StatusInfo[]) {
return function (status?: string | number | null) {
const info = infos.find((item) => item.value === status);
if (status === null || status === undefined || !info) {
return <span>--</span>;
}
return <span style={{ color: info.color }}>{info.label}</span>;
};
}

export default statusTableCell;

+ 1
- 1
react-ui/src/utils/table.tsx View File

@@ -1,7 +1,7 @@
/* /*
* @Author: 赵伟 * @Author: 赵伟
* @Date: 2024-06-26 10:05:52 * @Date: 2024-06-26 10:05:52
* @Description: Table cell 自定义 render
* @Description: Table Cell 自定义 render
*/ */


import { isEmpty } from '@/utils'; import { isEmpty } from '@/utils';


Loading…
Cancel
Save