| @@ -64,4 +64,4 @@ mvnw | |||||
| /react-ui/docs | /react-ui/docs | ||||
| /react-ui/types/tsconfig.tsbuildinfo | /react-ui/types/tsconfig.tsbuildinfo | ||||
| /react-ui/storybook-static | /react-ui/storybook-static | ||||
| /react-ui/.storybook/deploy.sh | |||||
| /react-ui/.storybook/scripts | |||||
| @@ -0,0 +1,3 @@ | |||||
| # Dockerfile | |||||
| FROM nginx:alpine | |||||
| COPY storybook-static/ /usr/share/nginx/html | |||||
| @@ -40,7 +40,7 @@ | |||||
| "start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev max dev", | "start:test": "cross-env REACT_APP_ENV=test MOCK=none UMI_ENV=dev max dev", | ||||
| "storybook": "storybook dev -p 6006", | "storybook": "storybook dev -p 6006", | ||||
| "storybook-build": "storybook build", | "storybook-build": "storybook build", | ||||
| "storybook-deploy": "./.storybook/deploy.sh", | |||||
| "storybook-deploy": "./.storybook/scripts/upload-deploy.sh", | |||||
| "storybook-docs": "storybook dev --docs", | "storybook-docs": "storybook dev --docs", | ||||
| "storybook-docs-build": "storybook build --docs", | "storybook-docs-build": "storybook build --docs", | ||||
| "test": "jest", | "test": "jest", | ||||
| @@ -137,7 +137,6 @@ export const layout: RuntimeConfig['layout'] = ({ initialState }) => { | |||||
| onClick: () => { | onClick: () => { | ||||
| // 点击菜单项,删除所有的页面 state 缓存 | // 点击菜单项,删除所有的页面 state 缓存 | ||||
| removeAllPageCacheState(); | removeAllPageCacheState(); | ||||
| // console.log('click menu'); | |||||
| }, | }, | ||||
| }, | }, | ||||
| ...initialState?.settings, | ...initialState?.settings, | ||||
| @@ -3,7 +3,7 @@ import { setRemoteMenu } from '@/services/session'; | |||||
| import { logout } from '@/services/system/auth'; | import { logout } from '@/services/system/auth'; | ||||
| import { ClientInfo } from '@/types'; | import { ClientInfo } from '@/types'; | ||||
| import SessionStorage from '@/utils/sessionStorage'; | import SessionStorage from '@/utils/sessionStorage'; | ||||
| import { gotoLoginPage } from '@/utils/ui'; | |||||
| import { gotoLoginPage, oauthLogout } from '@/utils/ui'; | |||||
| import { LogoutOutlined, UserOutlined } from '@ant-design/icons'; | import { LogoutOutlined, UserOutlined } from '@ant-design/icons'; | ||||
| import { setAlpha } from '@ant-design/pro-components'; | import { setAlpha } from '@ant-design/pro-components'; | ||||
| import { useEmotionCss } from '@ant-design/use-emotion-css'; | import { useEmotionCss } from '@ant-design/use-emotion-css'; | ||||
| @@ -62,6 +62,7 @@ const AvatarDropdown: React.FC<GlobalHeaderRightProps> = ({ menu }) => { | |||||
| * 退出登录,并且将当前的 url 保存 | * 退出登录,并且将当前的 url 保存 | ||||
| */ | */ | ||||
| const loginOut = async () => { | const loginOut = async () => { | ||||
| oauthLogout('http://172.20.32.197:31209/oauth/logout'); | |||||
| await logout(); | await logout(); | ||||
| clearSessionToken(); | clearSessionToken(); | ||||
| setRemoteMenu(null); | setRemoteMenu(null); | ||||
| @@ -160,3 +160,8 @@ ol { | |||||
| input:-webkit-autofill { | input:-webkit-autofill { | ||||
| transition: background-color 5000s ease-in-out 0s; | transition: background-color 5000s ease-in-out 0s; | ||||
| } | } | ||||
| .ant-typography { | |||||
| color: inherit; | |||||
| font-size: inherit; | |||||
| } | |||||
| @@ -261,8 +261,3 @@ | |||||
| } | } | ||||
| } | } | ||||
| } | } | ||||
| .ant-typography { | |||||
| color: inherit; | |||||
| font-size: inherit; | |||||
| } | |||||
| @@ -104,16 +104,16 @@ function EditorCreate() { | |||||
| <Row gutter={10}> | <Row gutter={10}> | ||||
| <Col span={10}> | <Col span={10}> | ||||
| <Form.Item | <Form.Item | ||||
| label="任务名称" | |||||
| label="编辑器名称" | |||||
| name="name" | name="name" | ||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: true, | required: true, | ||||
| message: '请输入任务名称', | |||||
| message: '请输入编辑器名称', | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Input placeholder="请输入任务名称" maxLength={64} showCount allowClear /> | |||||
| <Input placeholder="请输入编辑器名称" maxLength={64} showCount allowClear /> | |||||
| </Form.Item> | </Form.Item> | ||||
| </Col> | </Col> | ||||
| </Row> | </Row> | ||||
| @@ -7,6 +7,8 @@ | |||||
| import KFIcon from '@/components/KFIcon'; | import KFIcon from '@/components/KFIcon'; | ||||
| import { DevEditorStatus } from '@/enums'; | import { DevEditorStatus } from '@/enums'; | ||||
| import { useCacheState } from '@/hooks/useCacheState'; | import { useCacheState } from '@/hooks/useCacheState'; | ||||
| import { useComputingResource } from '@/hooks/useComputingResource'; | |||||
| import { DatasetData, ModelData } from '@/pages/Dataset/config'; | |||||
| import { | import { | ||||
| deleteEditorReq, | deleteEditorReq, | ||||
| getEditorListReq, | getEditorListReq, | ||||
| @@ -14,6 +16,7 @@ import { | |||||
| stopEditorReq, | stopEditorReq, | ||||
| } from '@/services/developmentEnvironment'; | } from '@/services/developmentEnvironment'; | ||||
| import themes from '@/styles/theme.less'; | import themes from '@/styles/theme.less'; | ||||
| import { parseJsonText } from '@/utils'; | |||||
| import { openAntdModal } from '@/utils/modal'; | import { openAntdModal } from '@/utils/modal'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import SessionStorage from '@/utils/sessionStorage'; | import SessionStorage from '@/utils/sessionStorage'; | ||||
| @@ -42,6 +45,10 @@ export type EditorData = { | |||||
| update_by: string; | update_by: string; | ||||
| create_time: string; | create_time: string; | ||||
| url: string; | url: string; | ||||
| computing_resource_id: number; | |||||
| dataset?: string | DatasetData; | |||||
| model?: string | ModelData; | |||||
| image?: string; | |||||
| }; | }; | ||||
| function EditorList() { | function EditorList() { | ||||
| @@ -56,6 +63,7 @@ function EditorList() { | |||||
| pageSize: 10, | pageSize: 10, | ||||
| }, | }, | ||||
| ); | ); | ||||
| const getResourceDescription = useComputingResource()[1]; | |||||
| // 获取编辑器列表 | // 获取编辑器列表 | ||||
| const getEditorList = useCallback(async () => { | const getEditorList = useCallback(async () => { | ||||
| @@ -66,6 +74,10 @@ function EditorList() { | |||||
| const [res] = await to(getEditorListReq(params)); | const [res] = await to(getEditorListReq(params)); | ||||
| if (res && res.data) { | if (res && res.data) { | ||||
| const { content = [], totalElements = 0 } = res.data; | const { content = [], totalElements = 0 } = res.data; | ||||
| content.forEach((item: EditorData) => { | |||||
| item.dataset = typeof item.dataset === 'string' ? parseJsonText(item.dataset) : null; | |||||
| item.model = typeof item.model === 'string' ? parseJsonText(item.model) : null; | |||||
| }); | |||||
| setTableData(content); | setTableData(content); | ||||
| setTotal(totalElements); | setTotal(totalElements); | ||||
| } | } | ||||
| @@ -102,11 +114,18 @@ function EditorList() { | |||||
| // 停止编辑器 | // 停止编辑器 | ||||
| const stopEditor = async (id: number) => { | const stopEditor = async (id: number) => { | ||||
| const [res] = await to(stopEditorReq(id)); | |||||
| if (res) { | |||||
| message.success('操作成功'); | |||||
| getEditorList(); | |||||
| } | |||||
| modalConfirm({ | |||||
| title: '停止后,该编辑器将不可使用', | |||||
| content: '是否确认停止?', | |||||
| isDelete: false, | |||||
| onOk: async () => { | |||||
| const [res] = await to(stopEditorReq(id)); | |||||
| if (res) { | |||||
| message.success('操作成功'); | |||||
| getEditorList(); | |||||
| } | |||||
| }, | |||||
| }); | |||||
| }; | }; | ||||
| // 制作镜像 | // 制作镜像 | ||||
| @@ -165,44 +184,72 @@ function EditorList() { | |||||
| title: '编辑器名称', | title: '编辑器名称', | ||||
| dataIndex: 'name', | dataIndex: 'name', | ||||
| key: 'name', | key: 'name', | ||||
| width: '30%', | |||||
| render: (text, record) => | |||||
| record.url && record.status === DevEditorStatus.Running ? ( | |||||
| <a className="kf-table-row-link" onClick={(e) => gotoEditorPage(e, record)}> | |||||
| {text} | |||||
| </a> | |||||
| ) : ( | |||||
| <span>{text ?? '--'}</span> | |||||
| ), | |||||
| }, | |||||
| { | |||||
| title: '状态', | |||||
| dataIndex: 'status', | |||||
| key: 'status', | |||||
| width: '10%', | |||||
| render: EditorStatusCell, | |||||
| width: '20%', | |||||
| render: (text, record, index) => | |||||
| record.url && record.status === DevEditorStatus.Running | |||||
| ? tableCellRender<EditorData>(true, TableCellValueType.Link, { | |||||
| onClick: (record, e) => gotoEditorPage(e, record), | |||||
| })(text, record, index) | |||||
| : tableCellRender<EditorData>(true, TableCellValueType.Text)(text, record, index), | |||||
| }, | }, | ||||
| { | { | ||||
| title: '资源', | |||||
| title: '计算资源', | |||||
| dataIndex: 'computing_resource', | dataIndex: 'computing_resource', | ||||
| key: 'computing_resource', | key: 'computing_resource', | ||||
| width: '20%', | |||||
| width: 100, | |||||
| render: tableCellRender(), | render: tableCellRender(), | ||||
| }, | }, | ||||
| { | |||||
| title: '资源规格', | |||||
| dataIndex: 'computing_resource_id', | |||||
| key: 'computing_resource_id', | |||||
| width: '20%', | |||||
| render: tableCellRender(true, TableCellValueType.Custom, { | |||||
| format: getResourceDescription, | |||||
| }), | |||||
| }, | |||||
| { | |||||
| title: '数据集', | |||||
| dataIndex: ['dataset', 'showValue'], | |||||
| key: 'dataset', | |||||
| width: '15%', | |||||
| render: tableCellRender(true), | |||||
| }, | |||||
| { | |||||
| title: '模型', | |||||
| dataIndex: ['model', 'showValue'], | |||||
| key: 'model', | |||||
| width: '15%', | |||||
| render: tableCellRender(true), | |||||
| }, | |||||
| { | |||||
| title: '镜像', | |||||
| dataIndex: ['image'], | |||||
| key: 'image', | |||||
| width: '15%', | |||||
| render: tableCellRender(true), | |||||
| }, | |||||
| { | { | ||||
| title: '创建者', | title: '创建者', | ||||
| dataIndex: 'update_by', | dataIndex: 'update_by', | ||||
| key: 'update_by', | key: 'update_by', | ||||
| width: '20%', | |||||
| render: tableCellRender(), | |||||
| width: '15%', | |||||
| render: tableCellRender(true), | |||||
| }, | }, | ||||
| { | { | ||||
| title: '创建时间', | title: '创建时间', | ||||
| dataIndex: 'create_time', | dataIndex: 'create_time', | ||||
| key: 'create_time', | key: 'create_time', | ||||
| width: '20%', | |||||
| width: 180, | |||||
| render: tableCellRender(false, TableCellValueType.Date), | render: tableCellRender(false, TableCellValueType.Date), | ||||
| }, | }, | ||||
| { | |||||
| title: '状态', | |||||
| dataIndex: 'status', | |||||
| key: 'status', | |||||
| width: 80, | |||||
| render: EditorStatusCell, | |||||
| }, | |||||
| { | { | ||||
| title: '操作', | title: '操作', | ||||
| dataIndex: 'operation', | dataIndex: 'operation', | ||||
| @@ -20,7 +20,7 @@ function CreateMirrorModal({ envId, onOk, ...rest }: CreateMirrorModalProps) { | |||||
| }), | }), | ||||
| ); | ); | ||||
| if (res) { | if (res) { | ||||
| message.success('创建成功,请到 “AI资产” - “个人镜像” 中查看'); | |||||
| message.success('创建成功,请到 “多形态资源库” - “个人镜像” 中查看'); | |||||
| onOk?.(); | onOk?.(); | ||||
| } | } | ||||
| }; | }; | ||||
| @@ -59,12 +59,12 @@ function CreateMirrorModal({ envId, onOk, ...rest }: CreateMirrorModalProps) { | |||||
| <Input placeholder="请输入镜像名称" maxLength={64} showCount allowClear /> | <Input placeholder="请输入镜像名称" maxLength={64} showCount allowClear /> | ||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item | <Form.Item | ||||
| label="镜像Tag" | |||||
| label="镜像版本" | |||||
| name="tag_name" | name="tag_name" | ||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: true, | required: true, | ||||
| message: '请输入镜像Tag', | |||||
| message: '请输入镜像版本', | |||||
| }, | }, | ||||
| { | { | ||||
| pattern: /^[a-zA-Z0-9._-]+$/, | pattern: /^[a-zA-Z0-9._-]+$/, | ||||
| @@ -72,7 +72,7 @@ function CreateMirrorModal({ envId, onOk, ...rest }: CreateMirrorModalProps) { | |||||
| }, | }, | ||||
| ]} | ]} | ||||
| > | > | ||||
| <Input placeholder="请输入镜像Tag" maxLength={64} showCount allowClear /> | |||||
| <Input placeholder="请输入镜像版本" maxLength={64} showCount allowClear /> | |||||
| </Form.Item> | </Form.Item> | ||||
| <Form.Item | <Form.Item | ||||
| label="镜像描述" | label="镜像描述" | ||||
| @@ -87,7 +87,7 @@ function CreateMirrorModal({ envId, onOk, ...rest }: CreateMirrorModalProps) { | |||||
| <Input.TextArea | <Input.TextArea | ||||
| placeholder="请输入镜像描述" | placeholder="请输入镜像描述" | ||||
| autoSize={{ minRows: 3, maxRows: 6 }} | autoSize={{ minRows: 3, maxRows: 6 }} | ||||
| maxLength={256} | |||||
| maxLength={128} | |||||
| showCount | showCount | ||||
| allowClear | allowClear | ||||
| /> | /> | ||||
| @@ -6,14 +6,13 @@ | |||||
| flex-direction: column; | flex-direction: column; | ||||
| height: calc(100% - 60px); | height: calc(100% - 60px); | ||||
| margin-top: 10px; | margin-top: 10px; | ||||
| padding: 30px 30px 0; | |||||
| padding: 10px 30px 0; | |||||
| background-color: white; | background-color: white; | ||||
| border-radius: 10px; | border-radius: 10px; | ||||
| &__tabs { | &__tabs { | ||||
| flex: 1; | flex: 1; | ||||
| min-height: 0; | min-height: 0; | ||||
| margin-top: 20px; | |||||
| padding-bottom: 10px; | padding-bottom: 10px; | ||||
| :global { | :global { | ||||
| @@ -3,9 +3,9 @@ | |||||
| * @Date: 2024-04-16 13:58:08 | * @Date: 2024-04-16 13:58:08 | ||||
| * @Description: 服务版本详情 | * @Description: 服务版本详情 | ||||
| */ | */ | ||||
| import FullScreenFrame from '@/components/FullScreenFrame'; | |||||
| import KFIcon from '@/components/KFIcon'; | import KFIcon from '@/components/KFIcon'; | ||||
| import PageTitle from '@/components/PageTitle'; | import PageTitle from '@/components/PageTitle'; | ||||
| import SubAreaTitle from '@/components/SubAreaTitle'; | |||||
| import { getServiceVersionInfoReq } from '@/services/modelDeployment'; | import { getServiceVersionInfoReq } from '@/services/modelDeployment'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { useParams } from '@umijs/max'; | import { useParams } from '@umijs/max'; | ||||
| @@ -18,6 +18,7 @@ import { ServiceVersionData } from '../types'; | |||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| export enum ModelDeploymentTabKey { | export enum ModelDeploymentTabKey { | ||||
| Basic = 'Basic', // 基本信息 | |||||
| Predict = 'Predict', // 预测 | Predict = 'Predict', // 预测 | ||||
| Guide = 'Guide', // 调用指南 | Guide = 'Guide', // 调用指南 | ||||
| Log = 'Log', // 服务日志 | Log = 'Log', // 服务日志 | ||||
| @@ -43,10 +44,23 @@ function ServiceVersionInfo() { | |||||
| }, [id]); | }, [id]); | ||||
| const tabItems = [ | const tabItems = [ | ||||
| { | |||||
| key: ModelDeploymentTabKey.Basic, | |||||
| label: '基本信息', | |||||
| icon: <KFIcon type="icon-jibenxinxi" />, | |||||
| children: <VersionBasicInfo info={versionInfo} />, | |||||
| }, | |||||
| { | { | ||||
| key: ModelDeploymentTabKey.Predict, | key: ModelDeploymentTabKey.Predict, | ||||
| label: '预测', | label: '预测', | ||||
| icon: <KFIcon type="icon-yuce" />, | icon: <KFIcon type="icon-yuce" />, | ||||
| children: ( | |||||
| <div style={{ height: '100%', width: '100%' }}> | |||||
| {versionInfo?.page_path && ( | |||||
| <FullScreenFrame url={versionInfo?.page_path}></FullScreenFrame> | |||||
| )} | |||||
| </div> | |||||
| ), | |||||
| }, | }, | ||||
| { | { | ||||
| key: ModelDeploymentTabKey.Guide, | key: ModelDeploymentTabKey.Guide, | ||||
| @@ -66,12 +80,6 @@ function ServiceVersionInfo() { | |||||
| <div className={styles['service-version-info']}> | <div className={styles['service-version-info']}> | ||||
| <PageTitle title="服务版本详情"></PageTitle> | <PageTitle title="服务版本详情"></PageTitle> | ||||
| <div className={styles['service-version-info__content']}> | <div className={styles['service-version-info__content']}> | ||||
| <SubAreaTitle | |||||
| title="基本信息" | |||||
| image={require('@/assets/img/mirror-basic.png')} | |||||
| style={{ marginBottom: '26px' }} | |||||
| ></SubAreaTitle> | |||||
| <VersionBasicInfo info={versionInfo} /> | |||||
| <div className={styles['service-version-info__content__tabs']}> | <div className={styles['service-version-info__content__tabs']}> | ||||
| <Tabs items={tabItems} /> | <Tabs items={tabItems} /> | ||||
| </div> | </div> | ||||
| @@ -79,6 +79,10 @@ function VersionBasicInfo({ info }: BasicInfoProps) { | |||||
| label: 'API URL', | label: 'API URL', | ||||
| value: info?.url, | value: info?.url, | ||||
| }, | }, | ||||
| { | |||||
| label: '文档地址', | |||||
| value: info?.doc_path, | |||||
| }, | |||||
| { | { | ||||
| label: '副本数量', | label: '副本数量', | ||||
| value: info?.replicas, | value: info?.replicas, | ||||
| @@ -104,7 +108,14 @@ function VersionBasicInfo({ info }: BasicInfoProps) { | |||||
| }, | }, | ||||
| ]; | ]; | ||||
| return <BasicInfo datas={datas} labelWidth={66} labelAlign="justify"></BasicInfo>; | |||||
| return ( | |||||
| <BasicInfo | |||||
| datas={datas} | |||||
| labelWidth={66} | |||||
| labelAlign="justify" | |||||
| style={{ marginTop: 10 }} | |||||
| ></BasicInfo> | |||||
| ); | |||||
| } | } | ||||
| export default VersionBasicInfo; | export default VersionBasicInfo; | ||||
| @@ -49,6 +49,8 @@ export type ServiceVersionData = { | |||||
| update_time: string; | update_time: string; | ||||
| create_time: string; | create_time: string; | ||||
| created_by: string; | created_by: string; | ||||
| doc_path?: string; // 文档地址 | |||||
| page_path?: string; // 预测地址 | |||||
| }; | }; | ||||
| // 操作类型 | // 操作类型 | ||||
| @@ -188,7 +188,7 @@ function PointsDetail() { | |||||
| render: tableCellRender(), | render: tableCellRender(), | ||||
| }, | }, | ||||
| { | { | ||||
| title: '描述', | |||||
| title: '资源规格', | |||||
| dataIndex: 'description', | dataIndex: 'description', | ||||
| key: 'description', | key: 'description', | ||||
| render: tableCellRender(true), | render: tableCellRender(true), | ||||
| @@ -217,7 +217,7 @@ function PointsDetail() { | |||||
| color: themes['primaryColor'], | color: themes['primaryColor'], | ||||
| }, | }, | ||||
| { | { | ||||
| value: 0, | |||||
| value: 2, | |||||
| label: '准备中', | label: '准备中', | ||||
| color: themes['pendingColor'], | color: themes['pendingColor'], | ||||
| }, | }, | ||||
| @@ -316,11 +316,19 @@ const UserForm: React.FC<UserFormProps> = (props) => { | |||||
| label="算力积分" | label="算力积分" | ||||
| placeholder="请输入算力积分" | placeholder="请输入算力积分" | ||||
| colProps={{ xs: 24, md: 12, xl: 12 }} | colProps={{ xs: 24, md: 12, xl: 12 }} | ||||
| max={100000} | |||||
| min={0} | |||||
| rules={[ | rules={[ | ||||
| { | { | ||||
| required: true, | required: true, | ||||
| message: '请输入算力积分', | message: '请输入算力积分', | ||||
| }, | }, | ||||
| { | |||||
| type: 'number', | |||||
| min: 0, | |||||
| max: 100000, | |||||
| message: '请输入0 ~ 100000之间的数', | |||||
| }, | |||||
| ]} | ]} | ||||
| /> | /> | ||||
| <ProFormTextArea | <ProFormTextArea | ||||
| @@ -3,9 +3,9 @@ | |||||
| flex: none; | flex: none; | ||||
| flex-direction: column; | flex-direction: column; | ||||
| align-items: center; | align-items: center; | ||||
| width: 326px; | width: 326px; | ||||
| height: 228px; | height: 228px; | ||||
| padding: 0 20px; | |||||
| .backgroundFullImage(url(@/assets/img/user-points-bg.png)); | .backgroundFullImage(url(@/assets/img/user-points-bg.png)); | ||||
| &__label { | &__label { | ||||
| @@ -16,12 +16,15 @@ | |||||
| } | } | ||||
| &__value { | &__value { | ||||
| width: 100%; | |||||
| margin-top: 8px; | margin-top: 8px; | ||||
| margin-bottom: 12px; | margin-bottom: 12px; | ||||
| color: @primary-color; | color: @primary-color; | ||||
| font-size: 36px; | font-size: 36px; | ||||
| font-family: DingTalk-JinBuTi; | font-family: DingTalk-JinBuTi; | ||||
| line-height: 43px; | line-height: 43px; | ||||
| text-align: center; | |||||
| .singleLine(); | |||||
| } | } | ||||
| &__button { | &__button { | ||||
| @@ -2,6 +2,7 @@ import { PointsStatistics } from '@/pages/Points/index'; | |||||
| import { getPointsStatisticsReq } from '@/services/points'; | import { getPointsStatisticsReq } from '@/services/points'; | ||||
| import { to } from '@/utils/promise'; | import { to } from '@/utils/promise'; | ||||
| import { useNavigate } from '@umijs/max'; | import { useNavigate } from '@umijs/max'; | ||||
| import { Typography } from 'antd'; | |||||
| import { useEffect, useState } from 'react'; | import { useEffect, useState } from 'react'; | ||||
| import styles from './index.less'; | import styles from './index.less'; | ||||
| @@ -23,8 +24,13 @@ function UserPoints() { | |||||
| return ( | return ( | ||||
| <div className={styles['user-points']}> | <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__label']}>当前可用算力积分</div> | |||||
| <Typography.Paragraph | |||||
| className={styles['user-points__value']} | |||||
| ellipsis={{ tooltip: statistics?.userCredit ?? '--' }} | |||||
| > | |||||
| {statistics?.userCredit ?? '--'} | |||||
| </Typography.Paragraph> | |||||
| <div | <div | ||||
| className={styles['user-points__button']} | className={styles['user-points__button']} | ||||
| onClick={() => { | onClick={() => { | ||||
| @@ -226,3 +226,14 @@ export const removeFormListItem = ( | |||||
| }, | }, | ||||
| }); | }); | ||||
| }; | }; | ||||
| /** | |||||
| * 退出子系统 | |||||
| * @param url - 退出登录的地址 | |||||
| */ | |||||
| export const oauthLogout = (url: string) => { | |||||
| const iframe = document.createElement('iframe'); | |||||
| iframe.style.display = 'none'; | |||||
| iframe.src = url; | |||||
| document.body.appendChild(iframe); | |||||
| }; | |||||