feat: 标签、分类增删改查
This commit is contained in:
parent
25ea7c14d9
commit
0bb16c94ae
10
apps/dmp/core/domain/Label/entities/label.ts
Normal file
10
apps/dmp/core/domain/Label/entities/label.ts
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
export type LabelType = {
|
||||||
|
name: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export class Label {
|
||||||
|
name: string;
|
||||||
|
constructor(props: LabelType) {
|
||||||
|
this.name = props.name;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,5 +1,11 @@
|
||||||
import { Apis } from "@@/infra/api";
|
import { Apis } from "@@/infra/api";
|
||||||
import { LabelCategory } from "./entities/labelCategory";
|
import { LabelCategory } from "./entities/labelCategory";
|
||||||
|
import {
|
||||||
|
LabelCategoryUpdateDTO,
|
||||||
|
LabelCreateDTO,
|
||||||
|
LabelDeleteDTO,
|
||||||
|
LabelUpdateDTO,
|
||||||
|
} from "@@/infra/api/dto";
|
||||||
|
|
||||||
export class LabelRepository {
|
export class LabelRepository {
|
||||||
async createNewLabelCategory(labelCategory: LabelCategory) {
|
async createNewLabelCategory(labelCategory: LabelCategory) {
|
||||||
|
@ -9,4 +15,20 @@ export class LabelRepository {
|
||||||
async findLabelCategory() {
|
async findLabelCategory() {
|
||||||
return await Apis.findLabelCategory();
|
return await Apis.findLabelCategory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createLabel(p: LabelCreateDTO) {
|
||||||
|
return await Apis.createLabel(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateLabel(p: LabelUpdateDTO) {
|
||||||
|
return await Apis.updateLabel(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteLabel(p: LabelDeleteDTO) {
|
||||||
|
return await Apis.deleteLabel(p);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateCategory(p: LabelCategoryUpdateDTO) {
|
||||||
|
return await Apis.updateCategory(p);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,3 +1,9 @@
|
||||||
|
import {
|
||||||
|
LabelCategoryUpdateDTO,
|
||||||
|
LabelCreateDTO,
|
||||||
|
LabelDeleteDTO,
|
||||||
|
LabelUpdateDTO,
|
||||||
|
} from "@@/infra/api/dto";
|
||||||
import { LabelCategory } from "./entities/labelCategory";
|
import { LabelCategory } from "./entities/labelCategory";
|
||||||
import { LabelRepository } from "./labelRepository";
|
import { LabelRepository } from "./labelRepository";
|
||||||
|
|
||||||
|
@ -14,4 +20,24 @@ export class LabelService {
|
||||||
async findLabelCategory() {
|
async findLabelCategory() {
|
||||||
return await this.labelRepository.findLabelCategory();
|
return await this.labelRepository.findLabelCategory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async createNewLabel(p: LabelCreateDTO) {
|
||||||
|
const { code } = await this.labelRepository.createLabel(p);
|
||||||
|
return { code };
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateLabel(p: LabelUpdateDTO) {
|
||||||
|
const { code } = await this.labelRepository.updateLabel(p);
|
||||||
|
return { code };
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteLabel(p: LabelDeleteDTO) {
|
||||||
|
const { code } = await this.labelRepository.deleteLabel(p);
|
||||||
|
return { code };
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateCategory(p: LabelCategoryUpdateDTO) {
|
||||||
|
const { code } = await this.labelRepository.updateCategory(p);
|
||||||
|
return { code };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,3 +34,22 @@ export type DownloadArchiveDTO = {
|
||||||
export type labelCategoryDTO = {
|
export type labelCategoryDTO = {
|
||||||
name: string;
|
name: string;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export type LabelCreateDTO = {
|
||||||
|
name: string;
|
||||||
|
categoryId: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LabelUpdateDTO = {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LabelDeleteDTO = {
|
||||||
|
id: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LabelCategoryUpdateDTO = {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
};
|
||||||
|
|
|
@ -6,10 +6,14 @@ import {
|
||||||
ArchiveTaskCreateDto,
|
ArchiveTaskCreateDto,
|
||||||
DownloadArchiveDTO,
|
DownloadArchiveDTO,
|
||||||
ExistInPacsDTO,
|
ExistInPacsDTO,
|
||||||
|
LabelCreateDTO,
|
||||||
|
LabelDeleteDTO,
|
||||||
|
LabelUpdateDTO,
|
||||||
ResponsePacsType,
|
ResponsePacsType,
|
||||||
ResponseType,
|
ResponseType,
|
||||||
labelCategoryDTO,
|
labelCategoryDTO,
|
||||||
} from "./dto";
|
} from "./dto";
|
||||||
|
import { Label } from "@@/domain/Label/entities/label";
|
||||||
|
|
||||||
const PREFIX = "/api/dmp";
|
const PREFIX = "/api/dmp";
|
||||||
const PREFIX_CERT = "/cert";
|
const PREFIX_CERT = "/cert";
|
||||||
|
@ -93,4 +97,28 @@ export const Apis = {
|
||||||
*/
|
*/
|
||||||
findLabelCategory: (): ResponseType =>
|
findLabelCategory: (): ResponseType =>
|
||||||
Request.get(PREFIX + "/dicom/label/category/find/all"),
|
Request.get(PREFIX + "/dicom/label/category/find/all"),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建新标签
|
||||||
|
*/
|
||||||
|
createLabel: (p: LabelCreateDTO): ResponseType =>
|
||||||
|
Request.post(PREFIX + "/dicom/label/create", p),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改标签
|
||||||
|
*/
|
||||||
|
updateLabel: (p: LabelUpdateDTO): ResponseType =>
|
||||||
|
Request.post(PREFIX + "/dicom/label/update", p),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 删除标签
|
||||||
|
*/
|
||||||
|
deleteLabel: (p: LabelDeleteDTO): ResponseType =>
|
||||||
|
Request.post(PREFIX + "/dicom/label/delete", p),
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 修改标签分类
|
||||||
|
*/
|
||||||
|
updateCategory: (p: labelCategoryDTO): ResponseType =>
|
||||||
|
Request.post(PREFIX + "/dicom/label/category/update", p),
|
||||||
};
|
};
|
||||||
|
|
28
apps/dmp/src/modules/Admin/Label/LabelTree/config.tsx
Normal file
28
apps/dmp/src/modules/Admin/Label/LabelTree/config.tsx
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
import { ModalType } from "./interface";
|
||||||
|
|
||||||
|
type ModalConfigType = {
|
||||||
|
[key in ModalType]: {
|
||||||
|
title: string;
|
||||||
|
placeholder: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export const modalConfig: ModalConfigType = {
|
||||||
|
createLabel: {
|
||||||
|
title: "添加新标签",
|
||||||
|
placeholder: "新标签名称",
|
||||||
|
},
|
||||||
|
updateLabel: {
|
||||||
|
title: "编辑",
|
||||||
|
placeholder: "新标签名称",
|
||||||
|
},
|
||||||
|
updateCategory: {
|
||||||
|
title: "编辑分类名称",
|
||||||
|
placeholder: "新标签分类名称",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
export const defaultModalConfig = {
|
||||||
|
title: "",
|
||||||
|
placeholder: "",
|
||||||
|
};
|
192
apps/dmp/src/modules/Admin/Label/LabelTree/index.tsx
Normal file
192
apps/dmp/src/modules/Admin/Label/LabelTree/index.tsx
Normal file
|
@ -0,0 +1,192 @@
|
||||||
|
import {
|
||||||
|
Button,
|
||||||
|
Col,
|
||||||
|
Collapse,
|
||||||
|
CollapseProps,
|
||||||
|
Form,
|
||||||
|
Input,
|
||||||
|
Modal,
|
||||||
|
Row,
|
||||||
|
Space,
|
||||||
|
Tooltip,
|
||||||
|
theme,
|
||||||
|
} from "antd";
|
||||||
|
import {
|
||||||
|
CategoryItemType,
|
||||||
|
LabelTreeProps,
|
||||||
|
LabelType,
|
||||||
|
ModalType,
|
||||||
|
} from "./interface";
|
||||||
|
import { useEffect, useState } from "react";
|
||||||
|
import { defaultModalConfig, modalConfig } from "./config";
|
||||||
|
import {
|
||||||
|
CaretRightOutlined,
|
||||||
|
CloseOutlined,
|
||||||
|
EditOutlined,
|
||||||
|
TagOutlined,
|
||||||
|
} from "@ant-design/icons";
|
||||||
|
|
||||||
|
export const LabelTree = (props: LabelTreeProps) => {
|
||||||
|
const { token } = theme.useToken();
|
||||||
|
const [modalType, setModalType] = useState<ModalType | null>(null);
|
||||||
|
const [form] = Form.useForm<{ name: string }>();
|
||||||
|
const [activeLabel, setActiveLabel] = useState<LabelType | null>(null);
|
||||||
|
const [activeCategory, setActiveCategory] = useState<CategoryItemType | null>(
|
||||||
|
null
|
||||||
|
);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
switch (modalType) {
|
||||||
|
case "updateLabel":
|
||||||
|
form.setFieldsValue({ name: activeLabel?.name });
|
||||||
|
break;
|
||||||
|
case "updateCategory":
|
||||||
|
form.setFieldsValue({ name: activeCategory?.name });
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}, [activeLabel, activeCategory, form, modalType]);
|
||||||
|
|
||||||
|
const { title, placeholder } = !modalType
|
||||||
|
? defaultModalConfig
|
||||||
|
: modalConfig[modalType];
|
||||||
|
|
||||||
|
const handleConfirm = async () => {
|
||||||
|
try {
|
||||||
|
await form.validateFields();
|
||||||
|
const { name } = form.getFieldsValue();
|
||||||
|
switch (modalType) {
|
||||||
|
case "createLabel":
|
||||||
|
activeCategory &&
|
||||||
|
props.onCreateLabel?.({ name, categoryId: activeCategory.id });
|
||||||
|
break;
|
||||||
|
case "updateLabel":
|
||||||
|
activeLabel && props.onUpdateLabel?.({ name, id: activeLabel.id });
|
||||||
|
break;
|
||||||
|
case "updateCategory":
|
||||||
|
activeCategory &&
|
||||||
|
props.onUpdateCategory?.({ name, id: activeCategory.id });
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
form.resetFields();
|
||||||
|
setModalType(null);
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const getItems = (dataList: CategoryItemType[]): CollapseProps["items"] =>
|
||||||
|
dataList
|
||||||
|
.map((item) => {
|
||||||
|
return {
|
||||||
|
key: item.id,
|
||||||
|
label: (
|
||||||
|
<Row>
|
||||||
|
<Col span={18}>{item.name}</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Space>
|
||||||
|
<Tooltip title={`编辑 ${item.name} 分类`}>
|
||||||
|
<EditOutlined
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setActiveCategory(item);
|
||||||
|
setModalType("updateCategory");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title={`删除 ${item.name} 分类`}>
|
||||||
|
<CloseOutlined />
|
||||||
|
</Tooltip>
|
||||||
|
</Space>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
),
|
||||||
|
children: (
|
||||||
|
<ul className="label-catalog">
|
||||||
|
{item.labels?.map((label) => (
|
||||||
|
<li key={label.id}>
|
||||||
|
<Row>
|
||||||
|
<Col span={18}>{label.name}</Col>
|
||||||
|
<Col span={6}>
|
||||||
|
<Space>
|
||||||
|
<Tooltip title={`编辑 ${label.name} 标签`}>
|
||||||
|
<EditOutlined
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
setActiveLabel(label);
|
||||||
|
setModalType("updateLabel");
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
<Tooltip title={`删除 ${label.name} 标签`}>
|
||||||
|
<CloseOutlined
|
||||||
|
onClick={(e) => {
|
||||||
|
e.stopPropagation();
|
||||||
|
props.onDeleteLabel?.(label);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
|
</Space>
|
||||||
|
</Col>
|
||||||
|
</Row>
|
||||||
|
</li>
|
||||||
|
))}
|
||||||
|
<Button
|
||||||
|
type="dashed"
|
||||||
|
block
|
||||||
|
icon={<TagOutlined />}
|
||||||
|
onClick={() => {
|
||||||
|
setActiveCategory(item);
|
||||||
|
setModalType("createLabel");
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
添加标签
|
||||||
|
</Button>
|
||||||
|
</ul>
|
||||||
|
),
|
||||||
|
};
|
||||||
|
})
|
||||||
|
.map((i) => ({
|
||||||
|
...i,
|
||||||
|
headerClass: "label-category-header",
|
||||||
|
className: "label-category-item",
|
||||||
|
}));
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
<Collapse
|
||||||
|
bordered={false}
|
||||||
|
defaultActiveKey={[]}
|
||||||
|
expandIcon={({ isActive }) => (
|
||||||
|
<CaretRightOutlined rotate={isActive ? 90 : 0} />
|
||||||
|
)}
|
||||||
|
style={{ background: token.colorBgContainer, color: token.colorText }}
|
||||||
|
items={getItems(props.data)}
|
||||||
|
/>
|
||||||
|
<Modal
|
||||||
|
open={modalType !== null}
|
||||||
|
title={title}
|
||||||
|
cancelText="再想想"
|
||||||
|
okText="确认"
|
||||||
|
width={350}
|
||||||
|
onCancel={() => setModalType(null)}
|
||||||
|
onOk={handleConfirm}
|
||||||
|
>
|
||||||
|
<Form form={form}>
|
||||||
|
<Form.Item
|
||||||
|
name="name"
|
||||||
|
rules={[
|
||||||
|
{ required: true, message: `${title}不能为空` },
|
||||||
|
{ max: 10, message: "不能超过十个字符" },
|
||||||
|
]}
|
||||||
|
>
|
||||||
|
<Input placeholder={placeholder} />
|
||||||
|
</Form.Item>
|
||||||
|
</Form>
|
||||||
|
</Modal>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
};
|
47
apps/dmp/src/modules/Admin/Label/LabelTree/interface.tsx
Normal file
47
apps/dmp/src/modules/Admin/Label/LabelTree/interface.tsx
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
export type ModalType = "createLabel" | "updateLabel" | "updateCategory";
|
||||||
|
|
||||||
|
export type CategoryItemType = {
|
||||||
|
id: number;
|
||||||
|
name: string;
|
||||||
|
labels?: { id: number; name: string }[];
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LabelCategoryType = {
|
||||||
|
name: string;
|
||||||
|
id: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type LabelType = {
|
||||||
|
name: string;
|
||||||
|
id?: number;
|
||||||
|
categoryId?: number;
|
||||||
|
};
|
||||||
|
|
||||||
|
export interface LabelTreeProps {
|
||||||
|
children?: JSX.Element;
|
||||||
|
data: CategoryItemType[];
|
||||||
|
/**
|
||||||
|
* 编辑标签分类名称
|
||||||
|
* @param {string} name 更新后的标签分类名
|
||||||
|
* @param {number} id 标签分类id
|
||||||
|
*/
|
||||||
|
onUpdateCategory?: (p: LabelCategoryType) => void;
|
||||||
|
/**
|
||||||
|
* 编辑标签分类名称
|
||||||
|
* @param {string} name 更新后的标签分类名
|
||||||
|
* @param {number} categoryId 标签分类id
|
||||||
|
*/
|
||||||
|
onCreateLabel?: (p: LabelType) => void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 编辑标签名称
|
||||||
|
* @param {string} name 更新后的标签名
|
||||||
|
* @param {number} id 标签id
|
||||||
|
*/
|
||||||
|
onUpdateLabel?: (p: LabelType) => void;
|
||||||
|
/**
|
||||||
|
* 删除标签
|
||||||
|
* @param {number} id 标签id
|
||||||
|
*/
|
||||||
|
onDeleteLabel?: (p: LabelType) => void;
|
||||||
|
}
|
|
@ -1,84 +1,111 @@
|
||||||
import { useEffect, useState } from "react";
|
import { useCallback, useEffect, useState } from "react";
|
||||||
import "./index.less";
|
import "./index.less";
|
||||||
import {
|
import { Button, Form, Input, Modal, message } from "antd";
|
||||||
Button,
|
import { PlusOutlined } from "@ant-design/icons";
|
||||||
Collapse,
|
|
||||||
CollapseProps,
|
|
||||||
Form,
|
|
||||||
Input,
|
|
||||||
Modal,
|
|
||||||
theme,
|
|
||||||
Typography,
|
|
||||||
} from "antd";
|
|
||||||
import { CaretRightOutlined, PlusOutlined } from "@ant-design/icons";
|
|
||||||
import { useDomain } from "@/hook/useDomain";
|
import { useDomain } from "@/hook/useDomain";
|
||||||
|
import { LabelTree } from "./LabelTree";
|
||||||
const { Text } = Typography;
|
import {
|
||||||
|
CategoryItemType,
|
||||||
|
LabelCategoryType,
|
||||||
|
LabelType,
|
||||||
|
} from "./LabelTree/interface";
|
||||||
|
|
||||||
interface LabelProps {
|
interface LabelProps {
|
||||||
children?: JSX.Element;
|
children?: JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = (
|
|
||||||
<ul className="label-catalog">
|
|
||||||
<li>切片太少</li>
|
|
||||||
<li className="active">{"层厚>1.0mm"}</li>
|
|
||||||
</ul>
|
|
||||||
);
|
|
||||||
const getItems = (): CollapseProps["items"] =>
|
|
||||||
[
|
|
||||||
{
|
|
||||||
key: "1",
|
|
||||||
label: "影像质量",
|
|
||||||
children: content,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "2",
|
|
||||||
label: "其他",
|
|
||||||
children: <p>1</p>,
|
|
||||||
},
|
|
||||||
].map((i) => ({
|
|
||||||
...i,
|
|
||||||
headerClass: "label-category-header",
|
|
||||||
className: "label-category-item",
|
|
||||||
}));
|
|
||||||
|
|
||||||
export const Label = (props: LabelProps) => {
|
export const Label = (props: LabelProps) => {
|
||||||
const { token } = theme.useToken();
|
|
||||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
const [createLabelCategoryForm] = Form.useForm<{ name: string }>();
|
const [createLabelCategoryForm] = Form.useForm<{ name: string }>();
|
||||||
const { labelDomainService } = useDomain();
|
const { labelDomainService } = useDomain();
|
||||||
|
const [labelList, setLabelList] = useState<CategoryItemType[]>([]);
|
||||||
|
const [messageApi, contextHolder] = message.useMessage();
|
||||||
|
|
||||||
const handleOk = async () => {
|
const createLabelHandler = async () => {
|
||||||
try {
|
try {
|
||||||
await createLabelCategoryForm.validateFields();
|
await createLabelCategoryForm.validateFields();
|
||||||
const { name } = createLabelCategoryForm.getFieldsValue();
|
const { name } = createLabelCategoryForm.getFieldsValue();
|
||||||
labelDomainService.createNewLabelCategory({ name });
|
labelDomainService.createNewLabelCategory({ name }).then((res) => {
|
||||||
|
const { code } = res;
|
||||||
|
if (code === 0) {
|
||||||
|
renderLabelList();
|
||||||
|
createLabelCategoryForm.resetFields();
|
||||||
|
setIsModalOpen(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.log(error);
|
console.log(error);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
useEffect(() => {
|
const renderLabelList = useCallback(async () => {
|
||||||
labelDomainService.findLabelCategory();
|
const { code, data } = await labelDomainService.findLabelCategory();
|
||||||
|
if (code === 0) setLabelList(data as CategoryItemType[]);
|
||||||
}, [labelDomainService]);
|
}, [labelDomainService]);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
renderLabelList();
|
||||||
|
}, [renderLabelList]);
|
||||||
|
|
||||||
|
const onCreateLabelHandler = ({ name, categoryId }: LabelType) => {
|
||||||
|
labelDomainService
|
||||||
|
.createNewLabel({ name, categoryId: categoryId! })
|
||||||
|
.then((res) => {
|
||||||
|
const { code } = res;
|
||||||
|
if (code === 0) {
|
||||||
|
renderLabelList();
|
||||||
|
messageApi.success(`标签 ${name} 添加成功`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onUpdateLabelHandler = ({ name, id }: LabelType) => {
|
||||||
|
labelDomainService.updateLabel({ name, id: id! }).then((res) => {
|
||||||
|
const { code } = res;
|
||||||
|
if (code === 0) {
|
||||||
|
renderLabelList();
|
||||||
|
messageApi.success(`标签 ${name} 修改成功`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onDeleteLabelHandler = ({ id, name }: LabelType) => {
|
||||||
|
labelDomainService.deleteLabel({ id: id! }).then((res) => {
|
||||||
|
const { code } = res;
|
||||||
|
if (code === 0) {
|
||||||
|
renderLabelList();
|
||||||
|
messageApi.success(`标签 ${name} 修改成功`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const onUpdateCategoryHandler = ({ name, id }: LabelCategoryType) => {
|
||||||
|
labelDomainService.updateCategory({ name, id }).then((res) => {
|
||||||
|
const { code } = res;
|
||||||
|
if (code === 0) {
|
||||||
|
renderLabelList();
|
||||||
|
messageApi.success(`${name} 分类修改成功`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="label-container">
|
<div className="label-container">
|
||||||
|
{contextHolder}
|
||||||
<aside>
|
<aside>
|
||||||
<Button
|
<Button
|
||||||
block
|
block
|
||||||
type="dashed"
|
type="primary"
|
||||||
icon={<PlusOutlined />}
|
icon={<PlusOutlined />}
|
||||||
style={{ marginBottom: 10 }}
|
style={{ marginBottom: 10 }}
|
||||||
onClick={() => setIsModalOpen(true)}
|
onClick={() => setIsModalOpen(true)}
|
||||||
>
|
>
|
||||||
新增标签分类
|
标签分类
|
||||||
</Button>
|
</Button>
|
||||||
<Modal
|
<Modal
|
||||||
title="新增标签分类"
|
title="创建标签分类"
|
||||||
open={isModalOpen}
|
open={isModalOpen}
|
||||||
onOk={handleOk}
|
onOk={createLabelHandler}
|
||||||
width={350}
|
width={350}
|
||||||
okText="确认"
|
okText="确认"
|
||||||
cancelText="再想想"
|
cancelText="再想想"
|
||||||
|
@ -96,14 +123,12 @@ export const Label = (props: LabelProps) => {
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</Form>
|
||||||
</Modal>
|
</Modal>
|
||||||
<Collapse
|
<LabelTree
|
||||||
bordered={false}
|
data={labelList}
|
||||||
defaultActiveKey={[]}
|
onCreateLabel={onCreateLabelHandler}
|
||||||
expandIcon={({ isActive }) => (
|
onUpdateLabel={onUpdateLabelHandler}
|
||||||
<CaretRightOutlined rotate={isActive ? 90 : 0} />
|
onDeleteLabel={onDeleteLabelHandler}
|
||||||
)}
|
onUpdateCategory={onUpdateCategoryHandler}
|
||||||
style={{ background: token.colorBgContainer, color: token.colorText }}
|
|
||||||
items={getItems()}
|
|
||||||
/>
|
/>
|
||||||
</aside>
|
</aside>
|
||||||
<main>标签相关数据</main>
|
<main>标签相关数据</main>
|
||||||
|
|
|
@ -15,8 +15,9 @@ const errorMapping = {
|
||||||
@Catch(QueryFailedError)
|
@Catch(QueryFailedError)
|
||||||
export class TypeOrmExceptionFilter implements ExceptionFilter {
|
export class TypeOrmExceptionFilter implements ExceptionFilter {
|
||||||
catch(exception: QueryFailedError, host: ArgumentsHost) {
|
catch(exception: QueryFailedError, host: ArgumentsHost) {
|
||||||
console.log('TypeOrmExceptionFilter 过滤器');
|
console.log('TypeOrmExceptionFilter 过滤器:', exception.driverError);
|
||||||
const message = errorMapping?.[exception.driverError] ?? 'sql操作失败。';
|
const message =
|
||||||
|
errorMapping?.[exception.driverError.code] ?? 'sql操作失败。';
|
||||||
return { statusCode, message };
|
return { statusCode, message };
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,9 +2,11 @@ import {
|
||||||
Column,
|
Column,
|
||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
Entity,
|
Entity,
|
||||||
|
OneToMany,
|
||||||
PrimaryGeneratedColumn,
|
PrimaryGeneratedColumn,
|
||||||
UpdateDateColumn,
|
UpdateDateColumn,
|
||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
|
import { Label } from './label.entity';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class LabelCategory {
|
export class LabelCategory {
|
||||||
|
@ -19,4 +21,7 @@ export class LabelCategory {
|
||||||
|
|
||||||
@UpdateDateColumn({ type: 'timestamp' })
|
@UpdateDateColumn({ type: 'timestamp' })
|
||||||
updateAt: Date;
|
updateAt: Date;
|
||||||
|
|
||||||
|
@OneToMany(() => Label, (label) => label.category)
|
||||||
|
labels: Label[];
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,11 @@ import {
|
||||||
Column,
|
Column,
|
||||||
CreateDateColumn,
|
CreateDateColumn,
|
||||||
Entity,
|
Entity,
|
||||||
|
ManyToOne,
|
||||||
PrimaryGeneratedColumn,
|
PrimaryGeneratedColumn,
|
||||||
UpdateDateColumn,
|
UpdateDateColumn,
|
||||||
} from 'typeorm';
|
} from 'typeorm';
|
||||||
|
import { LabelCategory } from './category.entity';
|
||||||
|
|
||||||
@Entity()
|
@Entity()
|
||||||
export class Label {
|
export class Label {
|
||||||
|
@ -27,4 +29,7 @@ export class Label {
|
||||||
|
|
||||||
@UpdateDateColumn({ type: 'timestamp' })
|
@UpdateDateColumn({ type: 'timestamp' })
|
||||||
updateAt: Date;
|
updateAt: Date;
|
||||||
|
|
||||||
|
@ManyToOne(() => LabelCategory, (category) => category.labels)
|
||||||
|
category: LabelCategory;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { Controller } from '@nestjs/common';
|
import { Controller } from '@nestjs/common';
|
||||||
import { EventPattern, MessagePattern } from '@nestjs/microservices';
|
import { MessagePattern } from '@nestjs/microservices';
|
||||||
import { LabelService } from './label.service';
|
import { LabelService } from './label.service';
|
||||||
|
|
||||||
@Controller()
|
@Controller()
|
||||||
|
@ -12,13 +12,32 @@ export class LabelController {
|
||||||
return { statusCode: 200, data: inserted };
|
return { statusCode: 200, data: inserted };
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventPattern({ cmd: 'dicom.label.create' })
|
@MessagePattern('dicom.label.create')
|
||||||
async createLabel(payload) {
|
async createLabel(payload) {
|
||||||
return this.labelService.createLabel(payload);
|
const data = await this.labelService.createLabel(payload);
|
||||||
|
return { statusCode: 200, data };
|
||||||
|
}
|
||||||
|
|
||||||
|
@MessagePattern('dicom.label.update')
|
||||||
|
async updateLabel(payload) {
|
||||||
|
const data = await this.labelService.updateLabel(payload);
|
||||||
|
return { statusCode: 200, data };
|
||||||
}
|
}
|
||||||
|
|
||||||
@MessagePattern('dicom.label.category.find.all')
|
@MessagePattern('dicom.label.category.find.all')
|
||||||
async findAllLabelCategory() {
|
async findAllLabelCategory() {
|
||||||
return await this.labelService.findAllLabelCategory();
|
return await this.labelService.findAllLabelCategory();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@MessagePattern('dicom.label.delete')
|
||||||
|
async deleteLabel(payload) {
|
||||||
|
const { affected } = await this.labelService.deleteLabel(payload);
|
||||||
|
return { statusCode: affected > 0 ? 200 : -1 };
|
||||||
|
}
|
||||||
|
|
||||||
|
@MessagePattern('dicom.label.category.update')
|
||||||
|
async updateLabelCategory(payload) {
|
||||||
|
const { affected } = await this.labelService.updateLabelCategory(payload);
|
||||||
|
return { statusCode: affected > 0 ? 200 : -1 };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,15 +17,31 @@ export class LabelService {
|
||||||
return await this.labelCategoryRepository.save({ name });
|
return await this.labelCategoryRepository.save({ name });
|
||||||
}
|
}
|
||||||
|
|
||||||
async createLabel(payload) {
|
async createLabel({ categoryId: id, name }) {
|
||||||
console.log(payload);
|
const category = await this.labelCategoryRepository.findOne({
|
||||||
return await this.labelRepository.save({
|
where: { id },
|
||||||
name: '钙化',
|
|
||||||
description: '钙化的关键词',
|
|
||||||
});
|
});
|
||||||
|
const label = new Label();
|
||||||
|
label.name = name;
|
||||||
|
label.category = category;
|
||||||
|
return await this.labelRepository.save(label);
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateLabel({ id, name }) {
|
||||||
|
const label = await this.labelRepository.findOne({ where: { id } });
|
||||||
|
label.name = name;
|
||||||
|
return await this.labelRepository.save(label);
|
||||||
}
|
}
|
||||||
|
|
||||||
async findAllLabelCategory() {
|
async findAllLabelCategory() {
|
||||||
return await this.labelCategoryRepository.find();
|
return await this.labelCategoryRepository.find({ relations: ['labels'] });
|
||||||
|
}
|
||||||
|
|
||||||
|
async deleteLabel({ id }) {
|
||||||
|
return await this.labelRepository.delete({ id });
|
||||||
|
}
|
||||||
|
|
||||||
|
async updateLabelCategory({ name, id }) {
|
||||||
|
return await this.labelCategoryRepository.update(id, { name });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,7 +32,7 @@ export class DicomController {
|
||||||
const { statusCode, message, data } = await firstValueFrom(
|
const { statusCode, message, data } = await firstValueFrom(
|
||||||
this.client.send('dicom.label.category.create', { name }),
|
this.client.send('dicom.label.category.create', { name }),
|
||||||
);
|
);
|
||||||
return { statusCode, message, data };
|
return { code: statusCode === 200 ? 0 : 1, message, data };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Get('label/category/find/all')
|
@Get('label/category/find/all')
|
||||||
|
@ -42,4 +42,40 @@ export class DicomController {
|
||||||
);
|
);
|
||||||
return { code: 0, data };
|
return { code: 0, data };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Post('label/create')
|
||||||
|
async createLabel(@Body() body) {
|
||||||
|
const { name, categoryId } = body;
|
||||||
|
const { statusCode, message, data } = await firstValueFrom(
|
||||||
|
this.client.send('dicom.label.create', { name, categoryId }),
|
||||||
|
);
|
||||||
|
return { code: statusCode === 200 ? 0 : 1, message, data };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('label/update')
|
||||||
|
async updateLabel(@Body() body) {
|
||||||
|
const { name, id } = body;
|
||||||
|
const { statusCode, message, data } = await firstValueFrom(
|
||||||
|
this.client.send('dicom.label.update', { name, id }),
|
||||||
|
);
|
||||||
|
return { code: statusCode === 200 ? 0 : 1, message, data };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('label/delete')
|
||||||
|
async deleteLabel(@Body() body) {
|
||||||
|
const { id } = body;
|
||||||
|
const { statusCode, message, data } = await firstValueFrom(
|
||||||
|
this.client.send('dicom.label.delete', { id }),
|
||||||
|
);
|
||||||
|
return { code: statusCode === 200 ? 0 : 1, message, data };
|
||||||
|
}
|
||||||
|
|
||||||
|
@Post('label/category/update')
|
||||||
|
async updateLabelCategory(@Body() body) {
|
||||||
|
const { name, id } = body;
|
||||||
|
const { statusCode, message, data } = await firstValueFrom(
|
||||||
|
this.client.send('dicom.label.category.update', { name, id }),
|
||||||
|
);
|
||||||
|
return { code: statusCode === 200 ? 0 : 1, message, data };
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user