Browse Source

fix: 镜像地址添加复制功能

pull/189/head
cp3hnu 10 months ago
parent
commit
30e7c6193a
5 changed files with 55 additions and 29 deletions
  1. +12
    -1
      react-ui/config/routes.ts
  2. +10
    -10
      react-ui/src/pages/Mirror/Create/index.tsx
  3. +13
    -6
      react-ui/src/pages/Mirror/Info/index.tsx
  4. +3
    -3
      react-ui/src/pages/Mirror/List/index.tsx
  5. +17
    -9
      react-ui/src/utils/table.tsx

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

@@ -271,7 +271,18 @@ export default [
{ {
name: '镜像详情', name: '镜像详情',
path: 'info/:id', path: 'info/:id',
component: './Mirror/Info',
routes: [
{
name: '镜像详情',
path: '',
component: './Mirror/Info',
},
{
name: '新增镜像版本',
path: 'add-version',
component: './Mirror/Create',
},
],
}, },
{ {
name: '创建镜像', name: '创建镜像',


+ 10
- 10
react-ui/src/pages/Mirror/Create/index.tsx View File

@@ -44,7 +44,7 @@ const mirrorRadioItems: KFRadioItem[] = [
function MirrorCreate() { function MirrorCreate() {
const navigate = useNavigate(); const navigate = useNavigate();
const [form] = Form.useForm(); const [form] = Form.useForm();
const [nameDisabled, setNameDisabled] = useState(false);
const [isAddVersion, setIsAddVersion] = useState(false); // 是制作镜像还是新增镜像版本
const { message } = App.useApp(); const { message } = App.useApp();


const uploadProps: UploadProps = { const uploadProps: UploadProps = {
@@ -60,7 +60,7 @@ function MirrorCreate() {
const name = SessionStorage.getItem(SessionStorage.mirrorNameKey); const name = SessionStorage.getItem(SessionStorage.mirrorNameKey);
if (name) { if (name) {
form.setFieldValue('name', name); form.setFieldValue('name', name);
setNameDisabled(true);
setIsAddVersion(true);
} }
return () => { return () => {
SessionStorage.removeItem(SessionStorage.mirrorNameKey); SessionStorage.removeItem(SessionStorage.mirrorNameKey);
@@ -120,7 +120,7 @@ function MirrorCreate() {


return ( return (
<div className={styles['mirror-create']}> <div className={styles['mirror-create']}>
<PageTitle title="创建镜像"></PageTitle>
<PageTitle title={!isAddVersion ? '创建镜像' : '新增镜像版本'}></PageTitle>
<div className={styles['mirror-create__content']}> <div className={styles['mirror-create__content']}>
<div> <div>
<Form <Form
@@ -142,7 +142,7 @@ function MirrorCreate() {
<Row gutter={10}> <Row gutter={10}>
<Col span={10}> <Col span={10}>
<Form.Item <Form.Item
label="镜像名称及Tag"
label="镜像名称和版本"
name="name" name="name"
rules={[ rules={[
{ {
@@ -158,7 +158,7 @@ function MirrorCreate() {
<Input <Input
placeholder="请输入镜像名称" placeholder="请输入镜像名称"
maxLength={64} maxLength={64}
disabled={nameDisabled}
disabled={isAddVersion}
showCount showCount
allowClear allowClear
/> />
@@ -174,22 +174,22 @@ function MirrorCreate() {
rules={[ rules={[
{ {
required: true, required: true,
message: '请输入镜像Tag',
message: '请输入镜像版本',
}, },
{ {
pattern: /^[a-zA-Z0-9._-]+$/, pattern: /^[a-zA-Z0-9._-]+$/,
message: '版本只支持字母、数字、点(.)、下划线(_)、中横线(-)',
message: '镜像版本只支持字母、数字、点(.)、下划线(_)、中横线(-)',
}, },
]} ]}
> >
<Input placeholder="请输入镜像Tag" maxLength={64} showCount allowClear />
<Input placeholder="请输入镜像版本" maxLength={64} showCount allowClear />
</Form.Item> </Form.Item>
</Col> </Col>
</Row> </Row>
<Row gutter={10}> <Row gutter={10}>
<Col span={20}> <Col span={20}>
<Form.Item <Form.Item
label="镜像描述"
label={isAddVersion ? '镜像版本描述' : '镜像描述'}
name="description" name="description"
rules={[ rules={[
{ {
@@ -303,7 +303,7 @@ function MirrorCreate() {


<Form.Item wrapperCol={{ offset: 0, span: 16 }}> <Form.Item wrapperCol={{ offset: 0, span: 16 }}>
<Button type="primary" htmlType="submit"> <Button type="primary" htmlType="submit">
创建镜像
确定
</Button> </Button>
<Button <Button
type="default" type="default"


+ 13
- 6
react-ui/src/pages/Mirror/Info/index.tsx View File

@@ -155,7 +155,7 @@ function MirrorInfo() {
}; };


const createMirrorVersion = () => { const createMirrorVersion = () => {
navigate(`/dataset/mirror/create`);
navigate(`add-version`);
SessionStorage.setItem(SessionStorage.mirrorNameKey, mirrorInfo.name || ''); SessionStorage.setItem(SessionStorage.mirrorNameKey, mirrorInfo.name || '');
setCacheState({ setCacheState({
pagination, pagination,
@@ -167,27 +167,34 @@ function MirrorInfo() {
title: '镜像版本', title: '镜像版本',
dataIndex: 'tag_name', dataIndex: 'tag_name',
key: 'tag_name', key: 'tag_name',
width: '25%',
width: '20%',
render: tableCellRender(), render: tableCellRender(),
}, },
{ {
title: '镜像地址', title: '镜像地址',
dataIndex: 'url', dataIndex: 'url',
key: 'url', key: 'url',
render: tableCellRender(),
width: '20%',
render: tableCellRender('auto', TableCellValueType.Text, { copyable: true }),
},
{
title: '版本描述',
dataIndex: 'description',
key: 'description',
render: tableCellRender(true),
}, },
{ {
title: '状态', title: '状态',
dataIndex: 'status', dataIndex: 'status',
key: 'status', key: 'status',
width: 150,
width: 100,
render: MirrorStatusCell, render: MirrorStatusCell,
}, },
{ {
title: '镜像大小', title: '镜像大小',
dataIndex: 'file_size', dataIndex: 'file_size',
key: 'file_size', key: 'file_size',
width: 150,
width: 120,
render: tableCellRender(), render: tableCellRender(),
}, },
{ {
@@ -200,7 +207,7 @@ function MirrorInfo() {
{ {
title: '操作', title: '操作',
dataIndex: 'operation', dataIndex: 'operation',
width: 150,
width: 120,
key: 'operation', key: 'operation',
hidden: isPublic, hidden: isPublic,
render: (_: any, record: MirrorVersionData) => ( render: (_: any, record: MirrorVersionData) => (


+ 3
- 3
react-ui/src/pages/Mirror/List/index.tsx View File

@@ -128,7 +128,7 @@ function MirrorList() {


// 查看详情 // 查看详情
const toDetail = (record: MirrorData) => { const toDetail = (record: MirrorData) => {
navigate(`/dataset/mirror/info/${record.id}`);
navigate(`info/${record.id}`);
setCacheState({ setCacheState({
activeTab, activeTab,
pagination, pagination,
@@ -149,7 +149,7 @@ function MirrorList() {


// 创建镜像 // 创建镜像
const createMirror = () => { const createMirror = () => {
navigate(`/dataset/mirror/create`);
navigate(`create`);
SessionStorage.setItem(SessionStorage.mirrorNameKey, ''); SessionStorage.setItem(SessionStorage.mirrorNameKey, '');
setCacheState({ setCacheState({
activeTab, activeTab,
@@ -262,7 +262,7 @@ function MirrorList() {
onClick={createMirror} onClick={createMirror}
icon={<KFIcon type="icon-xinjian2" />} icon={<KFIcon type="icon-xinjian2" />}
> >
制作镜像
创建镜像
</Button> </Button>
)} )}
<Button <Button


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

@@ -25,6 +25,7 @@ export type TableCellValueOptions<T> = {
dateFormat?: string; // 类型为 Date 时有效 dateFormat?: string; // 类型为 Date 时有效
onClick?: (record: T, e: React.MouseEvent) => void; // 类型为 Link 时有效 onClick?: (record: T, e: React.MouseEvent) => void; // 类型为 Link 时有效
format?: (value: any | undefined | null, record: T, index: number) => string | undefined | null; // 类型为 Custom 时有效 format?: (value: any | undefined | null, record: T, index: number) => string | undefined | null; // 类型为 Custom 时有效
copyable?: boolean; // 省略时是否可以复制
}; };


type TableCellFormatter = (value: any | undefined | null) => string | undefined | null; type TableCellFormatter = (value: any | undefined | null) => string | undefined | null;
@@ -93,17 +94,17 @@ function tableCellRender<T>(
} }


if (ellipsis === 'auto' && text) { if (ellipsis === 'auto' && text) {
return renderCell(type, text, 'auto', record, options?.onClick);
return renderCell(type, text, 'auto', record, options);
} else if (ellipsis && text) { } else if (ellipsis && text) {
const tooltipProps = typeof ellipsis === 'object' ? ellipsis : {}; const tooltipProps = typeof ellipsis === 'object' ? ellipsis : {};
const { overlayStyle, ...rest } = tooltipProps; const { overlayStyle, ...rest } = tooltipProps;
return ( return (
<Tooltip {...rest} overlayStyle={{ maxWidth: 400, ...overlayStyle }} title={text}> <Tooltip {...rest} overlayStyle={{ maxWidth: 400, ...overlayStyle }} title={text}>
{renderCell(type, text, true, record, options?.onClick)}
{renderCell(type, text, true, record, options)}
</Tooltip> </Tooltip>
); );
} else { } else {
return renderCell(type, text, false, record, options?.onClick);
return renderCell(type, text, false, record, options);
} }
}; };
} }
@@ -113,31 +114,38 @@ function renderCell<T>(
text: any | undefined | null, text: any | undefined | null,
ellipsis: boolean | 'auto', ellipsis: boolean | 'auto',
record: T, record: T,
onClick?: (record: T, e: React.MouseEvent) => void,
options?: TableCellValueOptions<T>,
) { ) {
return type === TableCellValueType.Link return type === TableCellValueType.Link
? renderLink(text, ellipsis, record, onClick)
: renderText(text, ellipsis);
? renderLink(text, ellipsis, record, options)
: renderText(text, ellipsis, options);
} }


function renderLink<T>( function renderLink<T>(
text: any | undefined | null, text: any | undefined | null,
ellipsis: boolean | 'auto', ellipsis: boolean | 'auto',
record: T, record: T,
onClick?: (record: T, e: React.MouseEvent) => void,
options?: TableCellValueOptions<T>,
) { ) {
const { onClick } = options ?? {};
return ( return (
<a className="kf-table-row-link" onClick={(e) => onClick?.(record, e)}> <a className="kf-table-row-link" onClick={(e) => onClick?.(record, e)}>
{renderText(text, ellipsis)}
{renderText(text, ellipsis, options)}
</a> </a>
); );
} }


function renderText(text: any | undefined | null, ellipsis: boolean | 'auto') {
function renderText<T>(
text: any | undefined | null,
ellipsis: boolean | 'auto',
options?: TableCellValueOptions<T>,
) {
const { copyable } = options ?? {};
if (ellipsis === 'auto') { if (ellipsis === 'auto') {
return ( return (
<Typography.Paragraph <Typography.Paragraph
style={{ marginBottom: 0 }} style={{ marginBottom: 0 }}
copyable={copyable}
ellipsis={{ ellipsis={{
tooltip: { tooltip: {
title: text, title: text,


Loading…
Cancel
Save