diff --git a/react-ui/config/routes.ts b/react-ui/config/routes.ts index c2b1c2a..8838c75 100644 --- a/react-ui/config/routes.ts +++ b/react-ui/config/routes.ts @@ -198,6 +198,17 @@ export default [ }, ], }, + { + name: '代码配置', + path: 'codeConfig', + routes: [ + { + name: '代码配置', + path: '', + component: './CodeConfig/List', + }, + ], + }, ], }, { diff --git a/react-ui/src/enums/index.ts b/react-ui/src/enums/index.ts index b75eeca..5585725 100644 --- a/react-ui/src/enums/index.ts +++ b/react-ui/src/enums/index.ts @@ -10,6 +10,12 @@ export enum CommonTabKeys { Public = 'Public', // 公开 } +// 公开还是私有 +export enum AvailableRange { + Public = 1, // 公开 + Private = 0, // 私有 +} + // 实验状态 export enum ExperimentStatus { Running = 'Running', // 运行中 diff --git a/react-ui/src/pages/CodeConfig/List/index.less b/react-ui/src/pages/CodeConfig/List/index.less new file mode 100644 index 0000000..4108b48 --- /dev/null +++ b/react-ui/src/pages/CodeConfig/List/index.less @@ -0,0 +1,47 @@ +.code-config-list { + display: flex; + flex: 1; + flex-direction: column; + height: 100%; + height: 100%; + padding: 20px 0; + background: white; + box-shadow: 0px 3px 6px rgba(146, 146, 146, 0.09); + + &__header { + display: flex; + align-items: center; + justify-content: space-between; + height: 32px; + margin-bottom: 30px; + padding: 0 30px; + color: @text-color; + font-size: 15px; + } + + &__content { + display: flex; + flex: 1; + flex-wrap: wrap; + gap: 20px; + align-content: flex-start; + width: 100%; + margin-bottom: 30px; + padding: 0 30px; + overflow-y: auto; + } + + &__empty { + display: flex; + flex: 1; + align-items: center; + justify-content: center; + } + + :global { + .ant-pagination { + margin-right: 30px; + text-align: right; + } + } +} diff --git a/react-ui/src/pages/CodeConfig/List/index.tsx b/react-ui/src/pages/CodeConfig/List/index.tsx new file mode 100644 index 0000000..b5aec9b --- /dev/null +++ b/react-ui/src/pages/CodeConfig/List/index.tsx @@ -0,0 +1,173 @@ +import KFIcon from '@/components/KFIcon'; +import { deleteCodeConfigReq, getCodeConfigListReq } from '@/services/codeConfig'; +import { openAntdModal } from '@/utils/modal'; +import { to } from '@/utils/promise'; +import { modalConfirm } from '@/utils/ui'; +import { App, Button, Empty, Input, Pagination, PaginationProps } from 'antd'; +import { useEffect, useState } from 'react'; +import AddCodeConfigModal, { OperationType } from '../components/AddCodeConfigModal'; +import CodeConfigItem from '../components/CodeConfigItem'; +import styles from './index.less'; + +// 代码配置数据 +export type CodeConfigData = { + id: number; + code_repo_name: string; + code_repo_vis: number; + git_url: string; + git_branch: string; + git_user_name: string; + git_password: string; + ssh_key: string; + verify_mode: number; + create_by: string; + create_time: string; + update_by: string; + update_time: string; +}; + +export type ResourceListRef = { + reset: () => void; +}; + +function CodeConfigList() { + const [dataList, setDataList] = useState([]); + const [total, setTotal] = useState(0); + const [pagination, setPagination] = useState({ + current: 1, + pageSize: 20, + }); + const [searchText, setSearchText] = useState(undefined); + const [inputText, setInputText] = useState(undefined); + const { message } = App.useApp(); + + useEffect(() => { + getDataList(); + }, [pagination, searchText]); + + // 获取数据请求 + const getDataList = async () => { + const params = { + page: pagination.current! - 1, + size: pagination.pageSize, + code_repo_name: searchText !== '' ? searchText : undefined, + }; + const [res] = await to(getCodeConfigListReq(params)); + if (res && res.data && res.data.content) { + setDataList(res.data.content); + setTotal(res.data.totalElements); + } + }; + + // 删除请求 + const deleteRecord = async (id: number) => { + const [res] = await to(deleteCodeConfigReq(id)); + if (res) { + getDataList(); + message.success('删除成功'); + } + }; + + // 搜索 + const handleSearch = (value: string) => { + setSearchText(value); + }; + + // 删除 + const handleRemove = (record: CodeConfigData) => { + modalConfirm({ + title: '确定删除这个代码配置吗?', + onOk: () => { + deleteRecord(record.id); + }, + }); + }; + + // 修改 + const handleClick = (record: CodeConfigData) => { + const { close } = openAntdModal(AddCodeConfigModal, { + opType: OperationType.Update, + codeConfigData: record, + onOk: () => { + getDataList(); + close(); + }, + }); + }; + + // 新建 + const createCodeConfig = () => { + const { close } = openAntdModal(AddCodeConfigModal, { + opType: OperationType.Create, + onOk: () => { + getDataList(); + close(); + }, + }); + }; + + // 分页切换 + const handlePageChange: PaginationProps['onChange'] = (page, pageSize) => { + setPagination({ + current: page, + pageSize: pageSize, + }); + }; + + return ( +
+
+ 数据总数:{total}个 +
+ setInputText(e.target.value)} + value={inputText} + /> + +
+
+ {dataList?.length !== 0 ? ( + <> +
+ {dataList?.map((item) => ( + + ))} +
+ + + ) : ( +
+ +
+ )} +
+ ); +} + +export default CodeConfigList; diff --git a/react-ui/src/pages/CodeConfig/components/AddCodeConfigModal/index.less b/react-ui/src/pages/CodeConfig/components/AddCodeConfigModal/index.less new file mode 100644 index 0000000..e69de29 diff --git a/react-ui/src/pages/CodeConfig/components/AddCodeConfigModal/index.tsx b/react-ui/src/pages/CodeConfig/components/AddCodeConfigModal/index.tsx new file mode 100644 index 0000000..975e4f2 --- /dev/null +++ b/react-ui/src/pages/CodeConfig/components/AddCodeConfigModal/index.tsx @@ -0,0 +1,244 @@ +import KFModal from '@/components/KFModal'; +import { AvailableRange } from '@/enums'; +import { type CodeConfigData } from '@/pages/CodeConfig/List'; +import { addCodeConfigReq, updateCodeConfigReq } from '@/services/codeConfig'; +import { to } from '@/utils/promise'; +import { Form, Input, Radio, message, type ModalProps } from 'antd'; +import { omit } from 'lodash'; + +export enum VerifyMode { + Password = 0, // 用户名密码 + SSH = 1, // SSH Key +} + +export enum OperationType { + Create = 0, // 新建 + Update = 1, // 更新 +} + +type FormData = Partial; + +interface AddCodeConfigModalProps extends Omit { + opType: OperationType; + codeConfigData?: CodeConfigData; + onOk: () => void; +} + +function AddCodeConfigModal({ opType, codeConfigData, onOk, ...rest }: AddCodeConfigModalProps) { + // 上传请求 + const createCodeConfig = async (formData: FormData) => { + const params: FormData & { id?: number } = { + ...formData, + }; + // 清除多余的信息 + if (formData.code_repo_vis === AvailableRange.Public) { + omit(params, ['verify_mode', 'git_user_name', 'git_password', 'ssh_key']); + } + if (formData.verify_mode === VerifyMode.Password) { + omit(params, ['ssh_key']); + } else if (formData.verify_mode === VerifyMode.SSH) { + omit(params, ['git_user_name', 'git_password']); + } + if (opType === OperationType.Update) { + params.id = codeConfigData?.id; + } + const request = opType === OperationType.Create ? addCodeConfigReq : updateCodeConfigReq; + const [res] = await to(request(params)); + if (res) { + message.success(opType === OperationType.Create ? '创建成功' : '修改成功'); + onOk?.(); + } + }; + + // 提交 + const onFinish = (formData: FormData) => { + createCodeConfig(formData); + }; + + // 设置初始值 + const initialValues: FormData = codeConfigData ?? { + code_repo_vis: AvailableRange.Public, + verify_mode: VerifyMode.Password, + }; + if (initialValues.verify_mode === undefined || initialValues.verify_mode === null) { + initialValues.verify_mode = VerifyMode.Password; + } + + return ( + +
+ {/* 禁止 Chrome 自动填充 */} + {/* + */} + + + + + + 公开 + 私有 + + + + + + + + + + prevValues?.code_repo_vis !== currentValues?.code_repo_vis + } + > + {({ getFieldValue }) => { + return getFieldValue('code_repo_vis') === AvailableRange.Private ? ( + <> + + + 用户名/密码 + SSH Key + + + + prevValues?.verify_mode !== currentValues?.verify_mode + } + > + {({ getFieldValue }) => { + return getFieldValue('verify_mode') === VerifyMode.Password ? ( + <> + + + + + + + + ) : ( + + + + ); + }} + + + ) : null; + }} + +
+
+ ); +} + +export default AddCodeConfigModal; diff --git a/react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.less b/react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.less new file mode 100644 index 0000000..42d054a --- /dev/null +++ b/react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.less @@ -0,0 +1,68 @@ +.code-config-item { + position: relative; + width: calc(25% - 15px); + padding: 20px; + background: white; + border: 1px solid #eaeaea; + border-radius: 4px; + cursor: pointer; + + @media screen and (max-width: 1860px) { + & { + width: calc(33.33% - 13.33px); + } + } + + &__name { + position: relative; + display: inline-block; + height: 24px; + margin: 0 10px 0 0 !important; + color: @text-color; + font-size: 16px; + } + + &__url { + margin-bottom: 10px; + color: @text-color-secondary; + font-size: 14px; + } + + &__description { + height: 44px; + margin-bottom: 20px; + color: @text-color-secondary; + font-size: 14px; + .multiLine(2); + } + + &__time { + display: flex; + flex: 0 1 content; + align-items: center; + width: 100%; + color: #808080; + font-size: 13px; + } + + &:hover { + border-color: @primary-color; + box-shadow: 0px 0px 6px 1px rgba(0, 0, 0, 0.1); + + .resource-item__name { + color: @primary-color; + } + } +} + +.resource-item__name { + &::after { + position: absolute; + top: 14px; + left: 0; + width: 100%; + height: 6px; + background: linear-gradient(to right, rgba(22, 100, 255, 0.3) 0, rgba(22, 100, 255, 0) 100%); + content: ''; + } +} diff --git a/react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.tsx b/react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.tsx new file mode 100644 index 0000000..237719a --- /dev/null +++ b/react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.tsx @@ -0,0 +1,51 @@ +import clock from '@/assets/img/clock.png'; +import creatByImg from '@/assets/img/creatBy.png'; +import KFIcon from '@/components/KFIcon'; +import { type CodeConfigData } from '@/pages/CodeConfig/List'; +import { formatDate } from '@/utils/date'; +import { Button, Flex, Typography } from 'antd'; +import styles from './index.less'; + +type CodeConfigItemProps = { + item: CodeConfigData; + onClick: (item: CodeConfigData) => void; + onRemove: (item: CodeConfigData) => void; +}; + +function CodeConfigItem({ item, onClick, onRemove }: CodeConfigItemProps) { + return ( +
onClick(item)}> + + + {item.code_repo_name} + + + +
{item.git_url}
+ +
+ + {item.create_by} +
+
+ + 最近更新: {formatDate(item.update_time, 'YYYY-MM-DD')} +
+
+
+ ); +} + +export default CodeConfigItem; diff --git a/react-ui/src/pages/Dataset/components/Resourcetem/index.less b/react-ui/src/pages/Dataset/components/ResourceItem/index.less similarity index 100% rename from react-ui/src/pages/Dataset/components/Resourcetem/index.less rename to react-ui/src/pages/Dataset/components/ResourceItem/index.less diff --git a/react-ui/src/pages/Dataset/components/Resourcetem/index.tsx b/react-ui/src/pages/Dataset/components/ResourceItem/index.tsx similarity index 100% rename from react-ui/src/pages/Dataset/components/Resourcetem/index.tsx rename to react-ui/src/pages/Dataset/components/ResourceItem/index.tsx diff --git a/react-ui/src/pages/Dataset/components/ResourceList/index.tsx b/react-ui/src/pages/Dataset/components/ResourceList/index.tsx index 60626fa..53df0e3 100644 --- a/react-ui/src/pages/Dataset/components/ResourceList/index.tsx +++ b/react-ui/src/pages/Dataset/components/ResourceList/index.tsx @@ -9,7 +9,7 @@ import { App, Button, Input, Pagination, PaginationProps } from 'antd'; import { Ref, forwardRef, useEffect, useImperativeHandle, useState } from 'react'; import { CategoryData, ResourceData, ResourceType, resourceConfig } from '../../config'; import AddDatasetModal from '../AddDatasetModal'; -import ResourceItem from '../Resourcetem'; +import ResourceItem from '../ResourceItem'; import styles from './index.less'; export type ResourceListRef = { @@ -161,7 +161,7 @@ function ResourceList( 数据总数:{total}个
- record.url ? ( + record.url && record.status === DevEditorStatus.Running ? ( gotoEditorPage(e, record)}> {text} diff --git a/react-ui/src/services/codeConfig/index.js b/react-ui/src/services/codeConfig/index.js new file mode 100644 index 0000000..24f73c2 --- /dev/null +++ b/react-ui/src/services/codeConfig/index.js @@ -0,0 +1,39 @@ +import { request } from '@umijs/max'; + +// 分页查询代码配置 +export function getCodeConfigListReq(params) { + return request(`/api/mmp/codeConfig`, { + method: 'GET', + params, + }); +} + +// 新增代码配置 +export function addCodeConfigReq(data) { + return request(`/api/mmp/codeConfig`, { + method: 'POST', + data, + }); +} + +// 更新代码配置 +export function updateCodeConfigReq(data) { + return request(`/api/mmp/codeConfig`, { + method: 'PUT', + data, + }); +} + +// 删除代码配置 +export function deleteCodeConfigReq(id) { + return request(`/api/mmp/codeConfig/${id}`, { + method: 'DELETE', + }); +} + +// 查询代码配置详情 +export function getCodeConfigDetailReq(id) { + return request(`/api/mmp/codeConfig/${id}`, { + method: 'GET' + }); +} \ No newline at end of file