diff --git a/react-ui/config/config.ts b/react-ui/config/config.ts
index 515b79cb..c10b23b6 100644
--- a/react-ui/config/config.ts
+++ b/react-ui/config/config.ts
@@ -1,6 +1,5 @@
// https://umijs.org/config/
import { defineConfig } from '@umijs/max';
-import { join } from 'path';
import defaultSettings from './defaultSettings';
import proxy from './proxy';
import routes from './routes';
@@ -145,20 +144,7 @@ export default defineConfig({
* @description 基于 openapi 的规范生成serve 和mock,能减少很多样板代码
* @doc https://pro.ant.design/zh-cn/docs/openapi/
*/
- openAPI: [
- {
- requestLibPath: "import { request } from '@umijs/max'",
- // 或者使用在线的版本
- // schemaPath: "https://gw.alipayobjects.com/os/antfincdn/M%24jrzTTYJN/oneapi.json"
- schemaPath: join(__dirname, 'oneapi.json'),
- mock: false,
- },
- {
- requestLibPath: "import { request } from '@umijs/max'",
- schemaPath: 'https://gw.alipayobjects.com/os/antfincdn/CA1dOm%2631B/openapi.json',
- projectName: 'swagger',
- },
- ],
+ // openAPI: [],
// mfsu: {
// strategy: 'normal',
// },
diff --git a/react-ui/config/oneapi.json b/react-ui/config/oneapi.json
deleted file mode 100644
index c77d988b..00000000
--- a/react-ui/config/oneapi.json
+++ /dev/null
@@ -1,593 +0,0 @@
-{
- "openapi": "3.0.1",
- "info": {
- "title": "Ant Design Pro",
- "version": "1.0.0"
- },
- "servers": [
- {
- "url": "http://localhost:8000/"
- },
- {
- "url": "https://localhost:8000/"
- }
- ],
- "paths": {
- "/api/currentUser": {
- "get": {
- "tags": ["api"],
- "description": "获取当前的用户",
- "operationId": "currentUser",
- "responses": {
- "200": {
- "description": "Success",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/CurrentUser"
- }
- }
- }
- },
- "401": {
- "description": "Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ErrorResponse"
- }
- }
- }
- }
- }
- },
- "x-swagger-router-controller": "api"
- },
- "/api/login/captcha": {
- "post": {
- "description": "发送验证码",
- "operationId": "getFakeCaptcha",
- "tags": ["login"],
- "parameters": [
- {
- "name": "phone",
- "in": "query",
- "description": "手机号",
- "schema": {
- "type": "string"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Success",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/FakeCaptcha"
- }
- }
- }
- }
- }
- }
- },
- "/api/login/outLogin": {
- "post": {
- "description": "登录接口",
- "operationId": "outLogin",
- "tags": ["login"],
- "responses": {
- "200": {
- "description": "Success",
- "content": {
- "application/json": {
- "schema": {
- "type": "object"
- }
- }
- }
- },
- "401": {
- "description": "Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ErrorResponse"
- }
- }
- }
- }
- }
- },
- "x-swagger-router-controller": "api"
- },
- "/api/login/account": {
- "post": {
- "tags": ["login"],
- "description": "登录接口",
- "operationId": "login",
- "requestBody": {
- "description": "登录系统",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/LoginParams"
- }
- }
- },
- "required": true
- },
- "responses": {
- "200": {
- "description": "Success",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/LoginResult"
- }
- }
- }
- },
- "401": {
- "description": "Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ErrorResponse"
- }
- }
- }
- }
- },
- "x-codegen-request-body-name": "body"
- },
- "x-swagger-router-controller": "api"
- },
- "/api/notices": {
- "summary": "getNotices",
- "description": "NoticeIconItem",
- "get": {
- "tags": ["api"],
- "operationId": "getNotices",
- "responses": {
- "200": {
- "description": "Success",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/NoticeIconList"
- }
- }
- }
- }
- }
- }
- },
- "/api/rule": {
- "get": {
- "tags": ["rule"],
- "description": "获取规则列表",
- "operationId": "rule",
- "parameters": [
- {
- "name": "current",
- "in": "query",
- "description": "当前的页码",
- "schema": {
- "type": "number"
- }
- },
- {
- "name": "pageSize",
- "in": "query",
- "description": "页面的容量",
- "schema": {
- "type": "number"
- }
- }
- ],
- "responses": {
- "200": {
- "description": "Success",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/RuleList"
- }
- }
- }
- },
- "401": {
- "description": "Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ErrorResponse"
- }
- }
- }
- }
- }
- },
- "post": {
- "tags": ["rule"],
- "description": "新建规则",
- "operationId": "addRule",
- "responses": {
- "200": {
- "description": "Success",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/RuleListItem"
- }
- }
- }
- },
- "401": {
- "description": "Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ErrorResponse"
- }
- }
- }
- }
- }
- },
- "put": {
- "tags": ["rule"],
- "description": "新建规则",
- "operationId": "updateRule",
- "responses": {
- "200": {
- "description": "Success",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/RuleListItem"
- }
- }
- }
- },
- "401": {
- "description": "Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ErrorResponse"
- }
- }
- }
- }
- }
- },
- "delete": {
- "tags": ["rule"],
- "description": "删除规则",
- "operationId": "removeRule",
- "responses": {
- "200": {
- "description": "Success",
- "content": {
- "application/json": {
- "schema": {
- "type": "object"
- }
- }
- }
- },
- "401": {
- "description": "Error",
- "content": {
- "application/json": {
- "schema": {
- "$ref": "#/components/schemas/ErrorResponse"
- }
- }
- }
- }
- }
- },
- "x-swagger-router-controller": "api"
- },
- "/swagger": {
- "x-swagger-pipe": "swagger_raw"
- }
- },
- "components": {
- "schemas": {
- "CurrentUser": {
- "type": "object",
- "properties": {
- "name": {
- "type": "string"
- },
- "avatar": {
- "type": "string"
- },
- "userid": {
- "type": "string"
- },
- "email": {
- "type": "string"
- },
- "signature": {
- "type": "string"
- },
- "title": {
- "type": "string"
- },
- "group": {
- "type": "string"
- },
- "tags": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "key": {
- "type": "string"
- },
- "label": {
- "type": "string"
- }
- }
- }
- },
- "notifyCount": {
- "type": "integer",
- "format": "int32"
- },
- "unreadCount": {
- "type": "integer",
- "format": "int32"
- },
- "country": {
- "type": "string"
- },
- "access": {
- "type": "string"
- },
- "geographic": {
- "type": "object",
- "properties": {
- "province": {
- "type": "object",
- "properties": {
- "label": {
- "type": "string"
- },
- "key": {
- "type": "string"
- }
- }
- },
- "city": {
- "type": "object",
- "properties": {
- "label": {
- "type": "string"
- },
- "key": {
- "type": "string"
- }
- }
- }
- }
- },
- "address": {
- "type": "string"
- },
- "phone": {
- "type": "string"
- }
- }
- },
- "LoginResult": {
- "type": "object",
- "properties": {
- "status": {
- "type": "string"
- },
- "type": {
- "type": "string"
- },
- "currentAuthority": {
- "type": "string"
- }
- }
- },
- "PageParams": {
- "type": "object",
- "properties": {
- "current": {
- "type": "number"
- },
- "pageSize": {
- "type": "number"
- }
- }
- },
- "RuleListItem": {
- "type": "object",
- "properties": {
- "key": {
- "type": "integer",
- "format": "int32"
- },
- "disabled": {
- "type": "boolean"
- },
- "href": {
- "type": "string"
- },
- "avatar": {
- "type": "string"
- },
- "name": {
- "type": "string"
- },
- "owner": {
- "type": "string"
- },
- "desc": {
- "type": "string"
- },
- "callNo": {
- "type": "integer",
- "format": "int32"
- },
- "status": {
- "type": "integer",
- "format": "int32"
- },
- "updatedAt": {
- "type": "string",
- "format": "datetime"
- },
- "createdAt": {
- "type": "string",
- "format": "datetime"
- },
- "progress": {
- "type": "integer",
- "format": "int32"
- }
- }
- },
- "RuleList": {
- "type": "object",
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/RuleListItem"
- }
- },
- "total": {
- "type": "integer",
- "description": "列表的内容总数",
- "format": "int32"
- },
- "success": {
- "type": "boolean"
- }
- }
- },
- "FakeCaptcha": {
- "type": "object",
- "properties": {
- "code": {
- "type": "integer",
- "format": "int32"
- },
- "status": {
- "type": "string"
- }
- }
- },
- "LoginParams": {
- "type": "object",
- "properties": {
- "username": {
- "type": "string"
- },
- "password": {
- "type": "string"
- },
- "autoLogin": {
- "type": "boolean"
- },
- "type": {
- "type": "string"
- }
- }
- },
- "ErrorResponse": {
- "required": ["errorCode"],
- "type": "object",
- "properties": {
- "errorCode": {
- "type": "string",
- "description": "业务约定的错误码"
- },
- "errorMessage": {
- "type": "string",
- "description": "业务上的错误信息"
- },
- "success": {
- "type": "boolean",
- "description": "业务上的请求是否成功"
- }
- }
- },
- "NoticeIconList": {
- "type": "object",
- "properties": {
- "data": {
- "type": "array",
- "items": {
- "$ref": "#/components/schemas/NoticeIconItem"
- }
- },
- "total": {
- "type": "integer",
- "description": "列表的内容总数",
- "format": "int32"
- },
- "success": {
- "type": "boolean"
- }
- }
- },
- "NoticeIconItemType": {
- "title": "NoticeIconItemType",
- "description": "已读未读列表的枚举",
- "type": "string",
- "properties": {},
- "enum": ["notification", "message", "event"]
- },
- "NoticeIconItem": {
- "type": "object",
- "properties": {
- "id": {
- "type": "string"
- },
- "extra": {
- "type": "string",
- "format": "any"
- },
- "key": { "type": "string" },
- "read": {
- "type": "boolean"
- },
- "avatar": {
- "type": "string"
- },
- "title": {
- "type": "string"
- },
- "status": {
- "type": "string"
- },
- "datetime": {
- "type": "string",
- "format": "date"
- },
- "description": {
- "type": "string"
- },
- "type": {
- "extensions": {
- "x-is-enum": true
- },
- "$ref": "#/components/schemas/NoticeIconItemType"
- }
- }
- }
- }
- }
-}
diff --git a/react-ui/src/app.tsx b/react-ui/src/app.tsx
index e6a09fb5..4f911013 100644
--- a/react-ui/src/app.tsx
+++ b/react-ui/src/app.tsx
@@ -118,18 +118,10 @@ export const layout: RuntimeConfig['layout'] = ({ initialState }) => {
width: '331px',
},
],
- // links: isDev
- // ? [
- //
- //
- // OpenAPI 文档
- // ,
- // ]
- // : [],
// 自定义 403 页面
// unAccessible:
unAccessible
,
- // 增加一个 loading 的状态
childrenRender: (children) => {
+ // 增加一个 loading 的状态
// if (initialState?.loading) return ;
return (
@@ -236,6 +228,7 @@ export const antd: RuntimeAntdConfig = (memo) => {
memo.theme.components.Table = {
headerBg: 'rgba(242, 244, 247, 0.36)',
headerBorderRadius: 4,
+ rowSelectedBg: 'rgba(22, 100, 255, 0.05)',
};
memo.theme.components.Tabs = {
titleFontSize: 16,
diff --git a/react-ui/src/assets/img/metrics-title-icon.png b/react-ui/src/assets/img/metrics-title-icon.png
new file mode 100644
index 00000000..66cd461f
Binary files /dev/null and b/react-ui/src/assets/img/metrics-title-icon.png differ
diff --git a/react-ui/src/assets/img/model-metrics.png b/react-ui/src/assets/img/model-metrics.png
new file mode 100644
index 00000000..3379db8a
Binary files /dev/null and b/react-ui/src/assets/img/model-metrics.png differ
diff --git a/react-ui/src/components/BasicInfo/index.less b/react-ui/src/components/BasicInfo/index.less
index 53fcb46c..ffeb3d3d 100644
--- a/react-ui/src/components/BasicInfo/index.less
+++ b/react-ui/src/components/BasicInfo/index.less
@@ -5,48 +5,54 @@
gap: 20px 40px;
align-items: flex-start;
width: 80%;
-}
-.kf-basic-info-item {
- display: flex;
- align-items: flex-start;
- width: calc(50% - 20px);
- font-size: 16px;
- line-height: 1.6;
-
- &__label {
- position: relative;
- flex: none;
- color: @text-color-secondary;
- text-align: justify;
- text-align-last: justify;
-
- &::after {
- position: absolute;
- content: ':';
+ &__item {
+ display: flex;
+ align-items: flex-start;
+ width: calc(50% - 20px);
+
+ &__label {
+ position: relative;
+ flex: none;
+ color: @text-color-secondary;
+ font-size: @font-size-content;
+ line-height: 1.6;
+ text-align: justify;
+ text-align-last: justify;
+
+ &::after {
+ position: absolute;
+ content: ':';
+ }
}
- }
- &__list-value {
- display: flex;
- flex: 1;
- flex-direction: column;
- gap: 5px 0;
- }
+ &__value-container {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ gap: 5px 0;
+ }
- &__value {
- flex: 1;
- margin-left: 16px;
- white-space: pre-line;
- word-break: break-all;
- }
+ &__value {
+ flex: 1;
+ margin-left: 16px;
+ font-size: @font-size-content;
+ line-height: 1.6;
+ white-space: pre-line;
+ word-break: break-all;
- &__text {
- color: @text-color;
- }
+ &--ellipsis {
+ .singleLine();
+ }
+
+ &__text {
+ color: @text-color;
+ }
- &__link:hover {
- text-decoration: underline @underline-color;
- text-underline-offset: 3px;
+ &__link:hover {
+ text-decoration: underline @underline-color;
+ text-underline-offset: 3px;
+ }
+ }
}
}
diff --git a/react-ui/src/components/BasicInfo/index.tsx b/react-ui/src/components/BasicInfo/index.tsx
index af56ded0..60cd5b57 100644
--- a/react-ui/src/components/BasicInfo/index.tsx
+++ b/react-ui/src/components/BasicInfo/index.tsx
@@ -1,4 +1,5 @@
import { Link } from '@umijs/max';
+import { Typography } from 'antd';
import classNames from 'classnames';
import './index.less';
@@ -11,6 +12,7 @@ export type BasicInfoLink = {
export type BasicInfoData = {
label: string;
value?: any;
+ ellipsis?: boolean;
format?: (_value?: any) => string | BasicInfoLink | BasicInfoLink[] | undefined;
};
@@ -18,45 +20,73 @@ type BasicInfoProps = {
datas: BasicInfoData[];
className?: string;
style?: React.CSSProperties;
- labelWidth?: number;
+ labelWidth: number;
};
-function BasicInfo({ datas, className, style, labelWidth = 100 }: BasicInfoProps) {
+type BasicInfoItemProps = {
+ data: BasicInfoData;
+ labelWidth: number;
+ classPrefix: string;
+};
+
+type BasicInfoItemValueProps = BasicInfoLink & {
+ ellipsis?: boolean;
+ classPrefix: string;
+};
+
+export default function BasicInfo({ datas, className, style, labelWidth }: BasicInfoProps) {
return (
{datas.map((item) => (
-
+
))}
);
}
-type BasicInfoItemProps = {
- data: BasicInfoData;
- labelWidth?: number;
-};
-function BasicInfoItem({ data, labelWidth = 100 }: BasicInfoItemProps) {
- const { label, value, format } = data;
+export function BasicInfoItem({ data, labelWidth, classPrefix }: BasicInfoItemProps) {
+ const { label, value, format, ellipsis } = data;
const formatValue = format ? format(value) : value;
+ const myClassName = `${classPrefix}__item`;
let valueComponent = undefined;
if (Array.isArray(formatValue)) {
valueComponent = (
-
+
{formatValue.map((item: BasicInfoLink) => (
-
+
))}
);
} else if (typeof formatValue === 'object' && formatValue) {
valueComponent = (
-
+
);
} else {
- valueComponent =
;
+ valueComponent = (
+
+ );
}
return (
-
-
+
+
{label}
{valueComponent}
@@ -64,35 +94,39 @@ function BasicInfoItem({ data, labelWidth = 100 }: BasicInfoItemProps) {
);
}
-type BasicInfoItemValueProps = {
- value: string;
- link?: string;
- url?: string;
-};
-
-function BasicInfoItemValue({ value, link, url }: BasicInfoItemValueProps) {
+export function BasicInfoItemValue({
+ value,
+ link,
+ url,
+ ellipsis,
+ classPrefix,
+}: BasicInfoItemValueProps) {
+ const myClassName = `${classPrefix}__item__value`;
+ let component = undefined;
if (url && value) {
- return (
-
+ component = (
+
{value}
);
} else if (link && value) {
- return (
-
+ component = (
+
{value}
);
} else {
- return (
-
{value ?? '--'}
- );
+ component =
{value ?? '--'};
}
-}
-export default BasicInfo;
+ return (
+
+ {component}
+
+ );
+}
diff --git a/react-ui/src/components/BasicTableInfo/index.less b/react-ui/src/components/BasicTableInfo/index.less
new file mode 100644
index 00000000..cc3d0984
--- /dev/null
+++ b/react-ui/src/components/BasicTableInfo/index.less
@@ -0,0 +1,64 @@
+.kf-basic-table-info {
+ display: flex;
+ flex-direction: row;
+ flex-wrap: wrap;
+ align-items: stretch;
+ width: 100%;
+ border: 1px solid @border-color-base;
+ border-bottom: none;
+ border-radius: 4px;
+
+ &__item {
+ display: flex;
+ align-items: stretch;
+ width: 25%;
+ border-bottom: 1px solid @border-color-base;
+
+ &__label {
+ flex: none;
+ padding: 12px 20px;
+ color: @text-color-secondary;
+ font-size: 14px;
+ text-align: left;
+ background-color: .addAlpha(#606b7a, 0.05) [];
+ }
+
+ &__value-container {
+ display: flex;
+ flex: 1;
+ flex-direction: column;
+ align-items: flex-start;
+ min-width: 0;
+ }
+
+ &__value {
+ flex: 1;
+ margin: 0 !important;
+ padding: 12px 20px 4px;
+ font-size: @font-size;
+ white-space: pre-line;
+ word-break: break-all;
+
+ & + & {
+ padding-top: 0;
+ }
+
+ &:last-child {
+ padding-bottom: 12px;
+ }
+
+ &--ellipsis {
+ .singleLine();
+ }
+
+ &__text {
+ color: @text-color;
+ }
+
+ &__link:hover {
+ text-decoration: underline @underline-color;
+ text-underline-offset: 3px;
+ }
+ }
+ }
+}
diff --git a/react-ui/src/components/BasicTableInfo/index.tsx b/react-ui/src/components/BasicTableInfo/index.tsx
new file mode 100644
index 00000000..df167ae2
--- /dev/null
+++ b/react-ui/src/components/BasicTableInfo/index.tsx
@@ -0,0 +1,43 @@
+import classNames from 'classnames';
+import { BasicInfoItem, type BasicInfoData, type BasicInfoLink } from '../BasicInfo';
+import './index.less';
+export type { BasicInfoData, BasicInfoLink };
+
+type BasicTableInfoProps = {
+ datas: BasicInfoData[];
+ className?: string;
+ style?: React.CSSProperties;
+ labelWidth: number;
+};
+
+export default function BasicTableInfo({
+ datas,
+ className,
+ style,
+ labelWidth,
+}: BasicTableInfoProps) {
+ const remainder = datas.length % 4;
+ const array = [];
+ if (remainder > 0) {
+ for (let i = 0; i < 4 - remainder; i++) {
+ array.push({
+ label: '',
+ value: '',
+ });
+ }
+ }
+ const showDatas = [...datas, ...array];
+
+ return (
+
+ {showDatas.map((item) => (
+
+ ))}
+
+ );
+}
diff --git a/react-ui/src/components/CommonTableCell/index.tsx b/react-ui/src/components/CommonTableCell/index.tsx
deleted file mode 100644
index c86ef9a9..00000000
--- a/react-ui/src/components/CommonTableCell/index.tsx
+++ /dev/null
@@ -1,25 +0,0 @@
-/*
- * @Author: 赵伟
- * @Date: 2024-04-28 14:18:11
- * @Description: 自定义 Table 单元格,没有数据时展示 --
- */
-
-import { Tooltip } from 'antd';
-
-function renderCell(text?: any | null) {
- return
{text ?? '--'};
-}
-
-function CommonTableCell(ellipsis: boolean = false) {
- if (ellipsis) {
- return (text?: any | null) => (
-
- {renderCell(text)}
-
- );
- } else {
- return renderCell;
- }
-}
-
-export default CommonTableCell;
diff --git a/react-ui/src/components/DateTableCell/index.tsx b/react-ui/src/components/DateTableCell/index.tsx
deleted file mode 100644
index ea629ba7..00000000
--- a/react-ui/src/components/DateTableCell/index.tsx
+++ /dev/null
@@ -1,20 +0,0 @@
-/*
- * @Author: 赵伟
- * @Date: 2024-04-28 14:18:11
- * @Description: 自定义 Table 日期类单元格
- */
-
-import { formatDate } from '@/utils/date';
-import dayjs from 'dayjs';
-
-function DateTableCell(text?: string | null) {
- if (text === undefined || text === null || text === '') {
- return
--;
- }
- if (!dayjs(text).isValid()) {
- return
无效的日期;
- }
- return
{formatDate(text)};
-}
-
-export default DateTableCell;
diff --git a/react-ui/src/components/RobotFrame/index.less b/react-ui/src/components/RobotFrame/index.less
index e3e5662e..a203ecc3 100644
--- a/react-ui/src/components/RobotFrame/index.less
+++ b/react-ui/src/components/RobotFrame/index.less
@@ -23,7 +23,7 @@
width: 100%;
height: 60px;
padding: 0 15px;
- border-bottom: 1px solid #e8e8e8;
+ border-bottom: 1px solid @border-color-base;
}
&__iframe {
diff --git a/react-ui/src/components/SubAreaTitle/index.tsx b/react-ui/src/components/SubAreaTitle/index.tsx
index 0458f715..cd07b206 100644
--- a/react-ui/src/components/SubAreaTitle/index.tsx
+++ b/react-ui/src/components/SubAreaTitle/index.tsx
@@ -9,7 +9,7 @@ import './index.less';
type SubAreaTitleProps = {
title: string;
- image: string;
+ image?: string;
style?: React.CSSProperties;
className?: string;
};
@@ -17,8 +17,10 @@ type SubAreaTitleProps = {
function SubAreaTitle({ title, image, style, className }: SubAreaTitleProps) {
return (
-

-
{title}
+ {image && (
+

+ )}
+
{title}
);
}
diff --git a/react-ui/src/hooks/index.ts b/react-ui/src/hooks/index.ts
index adf61e7d..6f5bdbbc 100644
--- a/react-ui/src/hooks/index.ts
+++ b/react-ui/src/hooks/index.ts
@@ -5,7 +5,7 @@
*/
import { FormInstance } from 'antd';
import { debounce } from 'lodash';
-import { useCallback, useEffect, useRef, useState } from 'react';
+import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
/**
* 生成具有初始值的状态引用
*
@@ -156,3 +156,45 @@ export const useEffectWhen = (effect: () => void, deps: React.DependencyList, wh
}
}, [when]);
};
+
+// 选择、全选操作
+export const useCheck =
(list: T[]) => {
+ const [selected, setSelected] = useState([]);
+
+ const checked = useMemo(() => {
+ return selected.length === list.length;
+ }, [selected, list]);
+
+ const indeterminate = useMemo(() => {
+ return selected.length > 0 && selected.length < list.length;
+ }, [selected, list]);
+
+ const checkAll = useCallback(() => {
+ setSelected(checked ? [] : list);
+ }, [list, checked]);
+
+ const isSingleChecked = useCallback((item: T) => selected.includes(item), [selected]);
+
+ const checkSingle = useCallback(
+ (item: T) => {
+ setSelected((prev) => {
+ if (isSingleChecked(item)) {
+ return prev.filter((i) => i !== item);
+ } else {
+ return [...prev, item];
+ }
+ });
+ },
+ [selected, isSingleChecked],
+ );
+
+ return [
+ selected,
+ setSelected,
+ checked,
+ indeterminate,
+ checkAll,
+ isSingleChecked,
+ checkSingle,
+ ] as const;
+};
diff --git a/react-ui/src/hooks/pageCacheState.ts b/react-ui/src/hooks/pageCacheState.ts
index 9268a07a..e320b0a6 100644
--- a/react-ui/src/hooks/pageCacheState.ts
+++ b/react-ui/src/hooks/pageCacheState.ts
@@ -4,6 +4,7 @@
* @Description: 页面状态缓存,pop 回到这个页面的时候,重新构建之前的状态
*/
+import { parseJsonText } from '@/utils';
import { useCallback, useState } from 'react';
const pageKeys: string[] = [];
@@ -14,11 +15,7 @@ const getCacheState = (key: string) => {
const jsonStr = sessionStorage.getItem(key);
if (jsonStr) {
removeCacheState(key);
- try {
- return JSON.parse(jsonStr);
- } catch (error) {
- return undefined;
- }
+ return parseJsonText(jsonStr);
}
return undefined;
};
diff --git a/react-ui/src/overrides.less b/react-ui/src/overrides.less
index af9591fe..9e4b34cc 100644
--- a/react-ui/src/overrides.less
+++ b/react-ui/src/overrides.less
@@ -79,6 +79,12 @@
background-color: #fff;
}
+.ant-table-row-selected {
+ .ant-table-cell {
+ color: @primary-color;
+ }
+}
+
.ant-pro-page-container {
overflow-y: auto;
}
diff --git a/react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.less b/react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.less
index 1f1a9a92..c5d4abaa 100644
--- a/react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.less
+++ b/react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.less
@@ -39,7 +39,7 @@
}
&__url {
- margin-bottom: 10px;
+ margin-bottom: 10px !important;
color: @text-color-secondary;
font-size: 14px;
}
diff --git a/react-ui/src/pages/Dataset/components/ResourceInfo/index.less b/react-ui/src/pages/Dataset/components/ResourceInfo/index.less
index 6103b602..8cbba3d6 100644
--- a/react-ui/src/pages/Dataset/components/ResourceInfo/index.less
+++ b/react-ui/src/pages/Dataset/components/ResourceInfo/index.less
@@ -38,10 +38,6 @@
&__bottom {
position: relative;
height: calc(100% - 135px);
- padding: 8px 30px 20px;
- background: #ffffff;
- border-radius: 10px;
- box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09);
&__legend {
position: absolute;
@@ -52,6 +48,12 @@
:global {
.ant-tabs {
height: 100%;
+ .ant-tabs-nav-wrap {
+ padding-top: 8px;
+ padding-left: 30px;
+ background-color: white;
+ border-radius: 10px 10px 0 0;
+ }
.ant-tabs-content-holder {
height: 100%;
.ant-tabs-content {
diff --git a/react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx b/react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx
index fe1e9a86..159ba9f1 100644
--- a/react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx
+++ b/react-ui/src/pages/Dataset/components/ResourceInfo/index.tsx
@@ -164,7 +164,16 @@ const ResourceInfo = ({ resourceType }: ResourceInfoProps) => {
key: ResourceInfoTabKeys.Introduction,
label: `${typeName}简介`,
icon: ,
- children: ,
+ children: (
+
+ ),
},
{
key: ResourceInfoTabKeys.Version,
diff --git a/react-ui/src/pages/Dataset/components/ResourceIntro/index.less b/react-ui/src/pages/Dataset/components/ResourceIntro/index.less
index 57d40216..6ac9223b 100644
--- a/react-ui/src/pages/Dataset/components/ResourceIntro/index.less
+++ b/react-ui/src/pages/Dataset/components/ResourceIntro/index.less
@@ -1,10 +1,25 @@
.resource-intro {
width: 100%;
- margin-top: 24px;
- &__basic {
- width: 100%;
- }
- &__usage {
- width: 100%;
+
+ &__top {
+ padding: 20px 30px;
+ background: white;
+ border-radius: 0 0 10px 10px;
+ box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09);
+
+ pre {
+ margin-bottom: 0 !important;
+ }
+
+ &__title {
+ margin: 15px 0;
+ color: @text-color-secondary;
+ font-size: 14px;
+ }
+
+ &__desc {
+ color: @text-color;
+ font-size: @font-size;
+ }
}
}
diff --git a/react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx b/react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx
index 2ee7fb24..0aa3b7e3 100644
--- a/react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx
+++ b/react-ui/src/pages/Dataset/components/ResourceIntro/index.tsx
@@ -1,4 +1,4 @@
-import BasicInfo, { BasicInfoData } from '@/components/BasicInfo';
+import BasicTableInfo, { BasicInfoData } from '@/components/BasicTableInfo';
import SubAreaTitle from '@/components/SubAreaTitle';
import { ResourceInfoTabKeys } from '@/pages/Dataset/components/ResourceInfo';
import {
@@ -8,13 +8,19 @@ import {
ProjectDependency,
ResourceType,
TrainTask,
+ resourceConfig,
} from '@/pages/Dataset/config';
+import ModelMetrics from '@/pages/Model/components/ModelMetrics';
import { getGitUrl } from '@/utils';
import styles from './index.less';
type ResourceIntroProps = {
resourceType: ResourceType;
info: DatasetData | ModelData;
+ resourceId: number;
+ identifier: string;
+ owner: string;
+ version?: string;
};
const formatDataset = (datasets?: DatasetData[]) => {
@@ -27,29 +33,6 @@ const formatDataset = (datasets?: DatasetData[]) => {
}));
};
-const formatParams = (map?: Record, space: string = '') => {
- if (!map || Object.keys(map).length === 0) {
- return undefined;
- }
- return Object.entries(map)
- .map(([key, value]) => `${space}${key} : ${value}`)
- .join('\n');
-};
-
-const formatMetrics = (map?: Record) => {
- if (!map || Object.keys(map).length === 0) {
- return undefined;
- }
- return Object.entries(map)
- .map(([key, value]) => {
- if (typeof value === 'object' && value !== null) {
- return `${key} : \n${formatParams(value, ' ')}`;
- }
- return `${key} : ${value}`;
- })
- .join('\n');
-};
-
const getProjectUrl = (project?: ProjectDependency) => {
if (!project || !project.url || !project.branch) {
return undefined;
@@ -93,49 +76,50 @@ const getDatasetDatas = (data: DatasetData): BasicInfoData[] => [
{
label: '数据集名称',
value: data.name,
+ ellipsis: true,
},
{
label: '版本',
value: data.version,
+ ellipsis: true,
},
{
label: '创建人',
value: data.create_by,
+ ellipsis: true,
},
{
label: '更新时间',
value: data.update_time,
+ ellipsis: true,
},
{
label: '数据来源',
value: data.dataset_source,
format: formatSource,
+ ellipsis: true,
},
{
label: '训练任务',
value: data.train_task,
format: formatTrainTask,
+ ellipsis: true,
},
{
label: '处理代码',
value: data.processing_code,
format: formatProject,
+ ellipsis: true,
},
{
label: '数据集分类',
value: data.data_type,
+ ellipsis: true,
},
{
label: '研究方向',
value: data.data_tag,
- },
- {
- label: '数据集描述',
- value: data.description,
- },
- {
- label: '版本描述',
- value: data.version_desc,
+ ellipsis: true,
},
];
@@ -143,77 +127,79 @@ const getModelDatas = (data: ModelData): BasicInfoData[] => [
{
label: '模型名称',
value: data.name,
+ ellipsis: true,
},
{
label: '版本',
value: data.version,
+ ellipsis: true,
},
{
label: '创建人',
value: data.create_by,
+ ellipsis: true,
},
{
label: '更新时间',
value: data.update_time,
+ ellipsis: true,
},
{
label: '训练镜像',
value: data.image,
+ ellipsis: true,
},
{
label: '训练代码',
value: data.project_depency,
format: formatProject,
+ ellipsis: true,
},
{
label: '训练数据集',
value: data.train_datasets,
format: formatDataset,
+ ellipsis: true,
},
{
label: '测试数据集',
value: data.test_datasets,
format: formatDataset,
- },
- {
- label: '参数',
- value: data.params,
- format: formatParams,
- },
- {
- label: '指标',
- value: data.metrics,
- format: formatMetrics,
+ ellipsis: true,
},
{
label: '模型来源',
value: data.model_source,
format: formatSource,
+ ellipsis: true,
},
{
label: '训练任务',
value: data.train_task,
format: formatTrainTask,
+ ellipsis: true,
},
{
label: '模型框架',
value: data.model_type,
+ ellipsis: true,
},
{
label: '模型能力',
value: data.model_tag,
- },
- {
- label: '模型描述',
- value: data.description,
- },
- {
- label: '版本描述',
- value: data.version_desc,
+ ellipsis: true,
},
];
-function ResourceIntro({ resourceType, info }: ResourceIntroProps) {
+function ResourceIntro({
+ resourceType,
+ info,
+ resourceId,
+ identifier,
+ owner,
+ version,
+}: ResourceIntroProps) {
+ const config = resourceConfig[resourceType];
const basicDatas: BasicInfoData[] =
resourceType === ResourceType.Dataset
? getDatasetDatas(info as DatasetData)
@@ -221,23 +207,37 @@ function ResourceIntro({ resourceType, info }: ResourceIntroProps) {
return (
-
-
-
+
+
+
+
+
+
{`${config.name}描述`}
+
{info.description ?? '暂无描述'}
+
版本描述
+
{info.version_desc ?? '暂无描述'}
+
+
-
-
+ {resourceType === ResourceType.Model && version && (
+
+ )}
);
}
diff --git a/react-ui/src/pages/Dataset/components/ResourceVersion/index.less b/react-ui/src/pages/Dataset/components/ResourceVersion/index.less
index d36c5ab6..e40591bd 100644
--- a/react-ui/src/pages/Dataset/components/ResourceVersion/index.less
+++ b/react-ui/src/pages/Dataset/components/ResourceVersion/index.less
@@ -1,4 +1,9 @@
.resource-version {
+ min-height: 100%;
+ padding: 20px 30px;
color: @text-color;
font-size: @font-size-content;
+ background: white;
+ border-radius: 0 0 10px 10px;
+ box-shadow: 0px 2px 12px rgba(180, 182, 191, 0.09);
}
diff --git a/react-ui/src/pages/Dataset/components/ResourceVersion/index.tsx b/react-ui/src/pages/Dataset/components/ResourceVersion/index.tsx
index b357ee00..44c54320 100644
--- a/react-ui/src/pages/Dataset/components/ResourceVersion/index.tsx
+++ b/react-ui/src/pages/Dataset/components/ResourceVersion/index.tsx
@@ -1,5 +1,3 @@
-import CommonTableCell from '@/components/CommonTableCell';
-import DateTableCell from '@/components/DateTableCell';
import KFIcon from '@/components/KFIcon';
import {
ResourceData,
@@ -8,7 +6,8 @@ import {
resourceConfig,
} from '@/pages/Dataset/config';
import { downLoadZip } from '@/utils/downloadfile';
-import { Button, Flex, Table } from 'antd';
+import tableCellRender, { TableCellValueType } from '@/utils/table';
+import { Button, Flex, Table, TableProps } from 'antd';
import styles from './index.less';
type ResourceVersionProps = {
@@ -38,37 +37,33 @@ function ResourceVersion({ resourceType, info }: ResourceVersionProps) {
downLoadZip(url, { url: record.url });
};
- const columns = [
+ const columns: TableProps
['columns'] = [
{
title: '序号',
dataIndex: 'index',
key: 'index',
width: 80,
- render(_text: string, _record: ResourceFileData, index: number) {
- return {index + 1};
- },
+ render: tableCellRender(false, TableCellValueType.Index),
},
{
title: '文件名称',
dataIndex: 'file_name',
key: 'file_name',
- render: (text: string, record: ResourceFileData) => (
- downloadAlone(record)}>
- {text}
-
- ),
+ render: tableCellRender(false, TableCellValueType.Link, {
+ onClick: downloadAlone,
+ }),
},
{
title: '文件大小',
dataIndex: 'file_size',
key: 'file_size',
- render: CommonTableCell(),
+ render: tableCellRender(),
},
{
title: '更新时间',
dataIndex: 'update_time',
key: 'update_time',
- render: DateTableCell,
+ render: tableCellRender(false, TableCellValueType.Date),
},
{
title: '操作',
@@ -91,7 +86,7 @@ function ResourceVersion({ resourceType, info }: ResourceVersionProps) {
return (
-
+