-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
287 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
25 changes: 25 additions & 0 deletions
25
server/src/main/java/com/jixialunbi/dto/request/TagRequest.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
package com.jixialunbi.dto.request; | ||
|
||
import jakarta.validation.constraints.NotBlank; | ||
import jakarta.validation.constraints.NotNull; | ||
import jakarta.validation.constraints.Size; | ||
import lombok.Data; | ||
|
||
/** | ||
* Data Transfer Object for Profile request | ||
*/ | ||
@Data | ||
public class TagRequest { | ||
|
||
private Long id; | ||
|
||
@NotBlank | ||
@Size(max = 20) | ||
private String name; | ||
|
||
private long order; | ||
|
||
@Size(max = 200) | ||
private String description; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,27 +1,27 @@ | ||
.default { | ||
:global { | ||
.ant-modal-header { | ||
padding: 7px 24px; | ||
color: rgba(0, 0, 0, 0.85); | ||
background: #fff; | ||
border-bottom: 1px solid #f0f0f0; | ||
border-radius: 2px 2px 0 0; | ||
} | ||
// .default { | ||
// :global { | ||
// .ant-modal-header { | ||
// // padding: 7px 24px; | ||
// // color: rgba(0, 0, 0, 0.85); | ||
// // background: #fff; | ||
// // border-bottom: 1px solid #f0f0f0; | ||
// // border-radius: 2px 2px 0 0; | ||
// } | ||
|
||
.ant-modal-close { | ||
top: 22px; | ||
} | ||
// .ant-modal-close { | ||
// top: 22px; | ||
// } | ||
|
||
.ant-modal-body { | ||
padding: 0; | ||
} | ||
// .ant-modal-body { | ||
// // padding: 0; | ||
// } | ||
|
||
.ant-modal-footer { | ||
.ant-btn { | ||
height: 24px; | ||
padding-top: 0; | ||
padding-bottom: 0; | ||
} | ||
} | ||
} | ||
} | ||
// .ant-modal-footer { | ||
// // .ant-btn { | ||
// // height: 24px; | ||
// // padding-top: 0; | ||
// // padding-bottom: 0; | ||
// // } | ||
// } | ||
// } | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import { Form, Input, InputNumber, message } from 'antd'; | ||
import { useForm } from 'antd/lib/form/Form'; | ||
import { noop } from 'lodash'; | ||
import React, { useEffect } from 'react'; | ||
import Modal from '@/components/Modal'; | ||
import { useSWRMutation } from '@/hooks'; | ||
|
||
interface Props { | ||
visible: boolean; | ||
onOk?: () => void; | ||
onCancel?: () => void; | ||
data?: any; | ||
} | ||
|
||
export default function EditModal(props: Props) { | ||
const { visible, onOk = noop, onCancel, data } = props; | ||
const [form] = useForm(); | ||
const { trigger: createCategory, isMutating: createIsMutating } = useSWRMutation({ url: '/api/v1/tags/create' }); | ||
const { trigger: updateCategory } = useSWRMutation({ url: '/api/v1/tags/update' }); | ||
const onFinish = (values: any) => { | ||
form.validateFields().then(async () => { | ||
if (data) { | ||
await updateCategory({ ...data, ...values }).then(() => { | ||
message.success('更新成功'); | ||
}); | ||
} else { | ||
await createCategory({ ...values, order: 0 }).then(() => { | ||
message.success('提交成功'); | ||
}); | ||
} | ||
await onOk(); | ||
}); | ||
}; | ||
const onFinishFailed = (errorInfo: any) => { | ||
console.log('Failed:', errorInfo); | ||
}; | ||
useEffect(() => { | ||
if (data && form) { | ||
form.setFieldsValue(data); | ||
} | ||
}, [data, form]); | ||
return ( | ||
<Modal | ||
title={data ? '编辑标签' : '添加标签'} | ||
open={visible} | ||
width={420} | ||
confirmLoading={createIsMutating} | ||
onOk={() => { | ||
form.submit(); | ||
onOk(); | ||
}} | ||
onCancel={onCancel} | ||
> | ||
<Form | ||
form={form} | ||
name="basic" | ||
labelCol={{ span: 4 }} | ||
wrapperCol={{ span: 20 }} | ||
initialValues={{ remember: true }} | ||
onFinish={onFinish} | ||
onFinishFailed={onFinishFailed} | ||
autoComplete="off" | ||
> | ||
<Form.Item label="名称" name="name" rules={[{ required: true, message: '请输入' }]}> | ||
<Input placeholder="请输入" /> | ||
</Form.Item> | ||
<Form.Item label="顺序" name="order"> | ||
<InputNumber placeholder="请输入" min={0} max={50} /> | ||
</Form.Item> | ||
<Form.Item label="描述" name="description" rules={[{ message: '请输入' }]} style={{ marginBottom: 0 }}> | ||
<Input.TextArea placeholder="请输入" /> | ||
</Form.Item> | ||
</Form> | ||
</Modal> | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
.wrap { | ||
padding-top: 15px; | ||
} | ||
|
||
.title { | ||
margin-bottom: 15px; | ||
} | ||
|
||
.labels { | ||
display: flex; | ||
align-items: center; | ||
flex-wrap: wrap; | ||
button { | ||
padding: 0; | ||
} | ||
} | ||
|
||
.labelsItem { | ||
display: flex; | ||
align-items: center; | ||
gap: 10px; | ||
margin-right: 20px; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,92 @@ | ||
'use client'; | ||
|
||
import TagGroup from '@/components/TagGroup'; | ||
import { Form } from 'antd'; | ||
import { Button, Spin, Space, Popconfirm } from 'antd'; | ||
import Layout from '../Layout'; | ||
import styles from './index.module.scss'; | ||
import { DeleteOutlined, EditOutlined, PlusOutlined } from '@ant-design/icons'; | ||
import { useSWR, useSWRMutation } from '@/hooks'; | ||
import EditModal from './components/EditModal'; | ||
import { useState } from 'react'; | ||
|
||
export default function Setting() { | ||
const { data, isLoading, mutate } = useSWR({ url: '/api/v1/tags' }); | ||
const { trigger: deleteTag, isMutating: delIsMutating } = useSWRMutation({ url: '/api/v1/delete-tag' }); | ||
const tags = data?.data ?? []; | ||
const [editData, setEditData] = useState({ visible: false, data: {} }); | ||
return ( | ||
<Layout> | ||
<Form.Item> | ||
<TagGroup></TagGroup> | ||
</Form.Item> | ||
<div className={styles.wrap}> | ||
<div className={styles.title}>标签管理</div> | ||
<Spin tip="Loading" size="small" spinning={isLoading}> | ||
<div className={styles.labels}> | ||
{tags.map((item) => { | ||
return ( | ||
<div className={styles.labelsItem} key={item.id}> | ||
<div>{item.name}</div> | ||
<Space> | ||
<Button | ||
type="link" | ||
onClick={() => { | ||
setEditData({ | ||
visible: true, | ||
data: item, | ||
}); | ||
}} | ||
> | ||
<EditOutlined></EditOutlined> | ||
编辑 | ||
</Button> | ||
<Popconfirm | ||
title="是否删除该标签?" | ||
onConfirm={async () => { | ||
await deleteTag({ id: item.id } as any).then(() => { | ||
mutate(); | ||
}); | ||
}} | ||
> | ||
<Button type="link" danger loading={delIsMutating}> | ||
<DeleteOutlined></DeleteOutlined> | ||
删除 | ||
</Button> | ||
</Popconfirm> | ||
</Space> | ||
</div> | ||
); | ||
})} | ||
<Button | ||
type="link" | ||
size="small" | ||
onClick={() => | ||
setEditData({ | ||
visible: true, | ||
data: null, | ||
}) | ||
} | ||
> | ||
<PlusOutlined></PlusOutlined>添加标签 | ||
</Button> | ||
{editData.visible && ( | ||
<EditModal | ||
visible={editData.visible} | ||
data={editData.data} | ||
onCancel={() => { | ||
setEditData({ | ||
visible: false, | ||
data: null, | ||
}); | ||
}} | ||
onOk={() => { | ||
mutate(); | ||
setEditData({ | ||
visible: false, | ||
data: null, | ||
}); | ||
}} | ||
></EditModal> | ||
)} | ||
</div> | ||
</Spin> | ||
</div> | ||
</Layout> | ||
); | ||
} |