From 5bdf3d247fd72ab93f2093399a6f34f4ab12effc Mon Sep 17 00:00:00 2001 From: cp3hnu Date: Thu, 29 Aug 2024 17:14:11 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E5=AE=8C=E6=88=90=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E9=85=8D=E7=BD=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- react-ui/config/routes.ts | 11 + react-ui/src/pages/CodeConfig/List/index.less | 47 ++++ react-ui/src/pages/CodeConfig/List/index.tsx | 173 ++++++++++++ .../components/AddCodeConfigModal/index.less | 0 .../components/AddCodeConfigModal/index.tsx | 248 ++++++++++++++++++ .../components/CodeConfigItem/index.less | 68 +++++ .../components/CodeConfigItem/index.tsx | 51 ++++ .../{Resourcetem => ResourceItem}/index.less | 0 .../{Resourcetem => ResourceItem}/index.tsx | 0 .../Dataset/components/ResourceList/index.tsx | 4 +- react-ui/src/services/codeConfig/index.js | 39 +++ 11 files changed, 639 insertions(+), 2 deletions(-) create mode 100644 react-ui/src/pages/CodeConfig/List/index.less create mode 100644 react-ui/src/pages/CodeConfig/List/index.tsx create mode 100644 react-ui/src/pages/CodeConfig/components/AddCodeConfigModal/index.less create mode 100644 react-ui/src/pages/CodeConfig/components/AddCodeConfigModal/index.tsx create mode 100644 react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.less create mode 100644 react-ui/src/pages/CodeConfig/components/CodeConfigItem/index.tsx rename react-ui/src/pages/Dataset/components/{Resourcetem => ResourceItem}/index.less (100%) rename react-ui/src/pages/Dataset/components/{Resourcetem => ResourceItem}/index.tsx (100%) create mode 100644 react-ui/src/services/codeConfig/index.js diff --git a/react-ui/config/routes.ts b/react-ui/config/routes.ts index c2b1c2a0..8838c75a 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/pages/CodeConfig/List/index.less b/react-ui/src/pages/CodeConfig/List/index.less new file mode 100644 index 00000000..4108b486 --- /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 00000000..6b2b6620 --- /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, { OperationTypeEnum } 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: OperationTypeEnum.Update, + codeConfigData: record, + onOk: () => { + getDataList(); + close(); + }, + }); + }; + + // 新建 + const createCodeConfig = () => { + const { close } = openAntdModal(AddCodeConfigModal, { + opType: OperationTypeEnum.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 00000000..e69de29b 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 00000000..4221213c --- /dev/null +++ b/react-ui/src/pages/CodeConfig/components/AddCodeConfigModal/index.tsx @@ -0,0 +1,248 @@ +import KFModal from '@/components/KFModal'; +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 RepoVisibleEnum { + Private = 0, // 私有 + Public = 1, // 公开 +} + +export enum VerifyModeEnum { + Password = 0, // 用户名密码 + SSH = 1, // SSH Key +} + +export enum OperationTypeEnum { + Create = 0, // 新建 + Update = 1, // 更新 +} + +type FormData = Partial; + +interface AddCodeConfigModalProps extends Omit { + opType: OperationTypeEnum; + 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 === RepoVisibleEnum.Public) { + omit(params, ['verify_mode', 'git_user_name', 'git_password', 'ssh_key']); + } + if (formData.verify_mode === VerifyModeEnum.Password) { + omit(params, ['ssh_key']); + } else if (formData.verify_mode === VerifyModeEnum.SSH) { + omit(params, ['git_user_name', 'git_password']); + } + if (opType === OperationTypeEnum.Update) { + params.id = codeConfigData?.id; + } + const request = opType === OperationTypeEnum.Create ? addCodeConfigReq : updateCodeConfigReq; + const [res] = await to(request(params)); + if (res) { + message.success(opType === OperationTypeEnum.Create ? '创建成功' : '修改成功'); + onOk?.(); + } + }; + + // 提交 + const onFinish = (formData: FormData) => { + createCodeConfig(formData); + }; + + // 设置初始值 + const initialValues: FormData = codeConfigData ?? { + code_repo_vis: RepoVisibleEnum.Public, + verify_mode: VerifyModeEnum.Password, + }; + if (initialValues.verify_mode === undefined || initialValues.verify_mode === null) { + initialValues.verify_mode = VerifyModeEnum.Password; + } + + return ( + +
+ {/* 禁止 Chrome 自动填充 */} + {/* + */} + + + + + + 公开 + 私有 + + + + + + + + + + prevValues?.code_repo_vis !== currentValues?.code_repo_vis + } + > + {({ getFieldValue }) => { + return getFieldValue('code_repo_vis') === RepoVisibleEnum.Private ? ( + <> + + + 用户名/密码 + SSH Key + + + + prevValues?.verify_mode !== currentValues?.verify_mode + } + > + {({ getFieldValue }) => { + return getFieldValue('verify_mode') === VerifyModeEnum.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 00000000..42d054ab --- /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 00000000..237719af --- /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 60626faf..53df0e3f 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}个