feat: 标签分类
This commit is contained in:
parent
61a874ca6f
commit
f902254909
10
apps/dmp/core/domain/Label/entities/labelCategory.ts
Normal file
10
apps/dmp/core/domain/Label/entities/labelCategory.ts
Normal file
|
@ -0,0 +1,10 @@
|
|||
export type LabelCategoryType = {
|
||||
name: string;
|
||||
};
|
||||
|
||||
export class LabelCategory {
|
||||
name: string;
|
||||
constructor(props: LabelCategoryType) {
|
||||
this.name = props.name;
|
||||
}
|
||||
}
|
8
apps/dmp/core/domain/Label/labelRepository.ts
Normal file
8
apps/dmp/core/domain/Label/labelRepository.ts
Normal file
|
@ -0,0 +1,8 @@
|
|||
import { Apis } from "@@/infra/api";
|
||||
import { LabelCategory } from "./entities/labelCategory";
|
||||
|
||||
export class LabelRepository {
|
||||
async createNewLabelCategory(labelCategory: LabelCategory) {
|
||||
return await Apis.createNewLabelCategory(labelCategory);
|
||||
}
|
||||
}
|
13
apps/dmp/core/domain/Label/labelService.ts
Normal file
13
apps/dmp/core/domain/Label/labelService.ts
Normal file
|
@ -0,0 +1,13 @@
|
|||
import { LabelCategory } from "./entities/labelCategory";
|
||||
import { LabelRepository } from "./labelRepository";
|
||||
|
||||
export class LabelService {
|
||||
constructor(private labelRepository: LabelRepository) {}
|
||||
|
||||
async createNewLabelCategory(labelCategory: LabelCategory) {
|
||||
const { code } = await this.labelRepository.createNewLabelCategory(
|
||||
labelCategory
|
||||
);
|
||||
return { code };
|
||||
}
|
||||
}
|
36
apps/dmp/core/infra/api/dto.ts
Normal file
36
apps/dmp/core/infra/api/dto.ts
Normal file
|
@ -0,0 +1,36 @@
|
|||
import { Study } from "@/modules/Admin/Dicom/Upload/DicomUploader/util";
|
||||
import { User } from "@@/domain/User/entities/User";
|
||||
|
||||
export type ResponseType = Promise<{
|
||||
code?: number | string;
|
||||
data?: unknown;
|
||||
msg?: string;
|
||||
}>;
|
||||
|
||||
export type ResponsePacsType = Promise<{
|
||||
ID: string;
|
||||
ParentPatient: string;
|
||||
ParentSeries: string;
|
||||
ParentStudy: string;
|
||||
Path: string;
|
||||
Status: string;
|
||||
}>;
|
||||
|
||||
export type ExistInPacsDTO = {
|
||||
StudyInstanceUID: string;
|
||||
SeriesInstanceUID: string;
|
||||
};
|
||||
|
||||
export type ArchiveTaskCreateDto = {
|
||||
user: User;
|
||||
study: Study[];
|
||||
};
|
||||
|
||||
export type DownloadArchiveDTO = {
|
||||
ID: string;
|
||||
Type: "study" | "series" | "Study" | "Series";
|
||||
};
|
||||
|
||||
export type labelCategoryDTO = {
|
||||
name: string;
|
||||
};
|
|
@ -1,43 +1,20 @@
|
|||
import { User } from "@@/domain/User/entities/User";
|
||||
import { Request } from "./Request";
|
||||
import { Study } from "@/modules/Admin/Dicom/Upload/DicomUploader/util";
|
||||
import axios from "axios";
|
||||
import { saveAs } from "file-saver";
|
||||
import {
|
||||
ArchiveTaskCreateDto,
|
||||
DownloadArchiveDTO,
|
||||
ExistInPacsDTO,
|
||||
ResponsePacsType,
|
||||
ResponseType,
|
||||
labelCategoryDTO,
|
||||
} from "./dto";
|
||||
|
||||
const PREFIX = "/api/dmp";
|
||||
const PREFIX_CERT = "/cert";
|
||||
const PREFIX_PACS = "/dicom-web";
|
||||
|
||||
type ResponseType = Promise<{
|
||||
code?: number | string;
|
||||
data?: unknown;
|
||||
msg?: string;
|
||||
}>;
|
||||
|
||||
type ResponsePacsType = Promise<{
|
||||
ID: string;
|
||||
ParentPatient: string;
|
||||
ParentSeries: string;
|
||||
ParentStudy: string;
|
||||
Path: string;
|
||||
Status: string;
|
||||
}>;
|
||||
|
||||
export type ExistInPacsDTO = {
|
||||
StudyInstanceUID: string;
|
||||
SeriesInstanceUID: string;
|
||||
};
|
||||
|
||||
export type ArchiveTaskCreateDto = {
|
||||
user: User;
|
||||
study: Study[];
|
||||
};
|
||||
|
||||
export type DownloadArchiveDTO = {
|
||||
ID: string;
|
||||
Type: "study" | "series" | "Study" | "Series";
|
||||
};
|
||||
|
||||
export const Apis = {
|
||||
/**
|
||||
* 用户登录
|
||||
|
@ -105,4 +82,9 @@ export const Apis = {
|
|||
.catch((error) => {
|
||||
console.error("Download error:", error);
|
||||
}),
|
||||
/**
|
||||
* 创建新的标签分类
|
||||
*/
|
||||
createNewLabelCategory: (p: labelCategoryDTO): ResponseType =>
|
||||
Request.post(PREFIX + "/dicom/label/category/create", p),
|
||||
};
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
import { DicomRepository } from "@@/domain/Dicom/DicomRepository";
|
||||
import { DicomService } from "@@/domain/Dicom/DicomService";
|
||||
import { LabelRepository } from "@@/domain/Label/labelRepository";
|
||||
import { LabelService } from "@@/domain/Label/labelService";
|
||||
import { UserRepository } from "@@/domain/User/UserRepository";
|
||||
import { UserService } from "@@/domain/User/UserService";
|
||||
import { createContext } from "react";
|
||||
|
@ -7,11 +9,13 @@ import { createContext } from "react";
|
|||
export type Services = {
|
||||
userDomainService: UserService;
|
||||
dicomDomainService: DicomService;
|
||||
labelDomainService: LabelService;
|
||||
};
|
||||
|
||||
const defaultServiceMap = {
|
||||
userDomainService: new UserService(new UserRepository()),
|
||||
dicomDomainService: new DicomService(new DicomRepository()),
|
||||
labelDomainService: new LabelService(new LabelRepository()),
|
||||
};
|
||||
|
||||
export const DomainServiceContext = createContext<Services>(defaultServiceMap);
|
||||
|
|
|
@ -6,5 +6,42 @@
|
|||
aside {
|
||||
padding: 20px 20px 0 20px;
|
||||
border-right: 1px solid rgba(5, 5, 5, 0.06);
|
||||
|
||||
.label-category-header {
|
||||
padding: 6px !important;
|
||||
background: transparent !important;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.label-category-item {
|
||||
margin-bottom: 10px;
|
||||
border: none;
|
||||
background: transparent;
|
||||
|
||||
// &.ant-collapse-item-active {
|
||||
// background: rgba(204, 204, 204, .1);
|
||||
// }
|
||||
}
|
||||
|
||||
.label-catalog {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
list-style: none;
|
||||
|
||||
li {
|
||||
margin-bottom: 2px;
|
||||
padding: 6px 0 6px 10px;
|
||||
border-radius: 6px;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background: rgba(204, 204, 204, .1);
|
||||
}
|
||||
|
||||
&.active {
|
||||
background: rgba(204, 204, 204, .2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,56 +1,105 @@
|
|||
import { CSSProperties } from "react";
|
||||
import { useState } from "react";
|
||||
import "./index.less";
|
||||
import { Collapse, CollapseProps, theme } from "antd";
|
||||
import { CaretRightOutlined } from "@ant-design/icons";
|
||||
import {
|
||||
Button,
|
||||
Collapse,
|
||||
CollapseProps,
|
||||
Form,
|
||||
Input,
|
||||
Modal,
|
||||
theme,
|
||||
Typography,
|
||||
} from "antd";
|
||||
import { CaretRightOutlined, PlusOutlined } from "@ant-design/icons";
|
||||
import { useDomain } from "@/hook/useDomain";
|
||||
|
||||
const { Text } = Typography;
|
||||
|
||||
interface LabelProps {
|
||||
children?: JSX.Element;
|
||||
}
|
||||
|
||||
const content = (
|
||||
<ul>
|
||||
<ul className="label-catalog">
|
||||
<li>切片太少</li>
|
||||
<li>{"层厚>1.0mm"}</li>
|
||||
<li className="active">{"层厚>1.0mm"}</li>
|
||||
</ul>
|
||||
);
|
||||
const getItems: (panelStyle: CSSProperties) => CollapseProps["items"] = (
|
||||
panelStyle
|
||||
) => [
|
||||
const getItems = (): CollapseProps["items"] =>
|
||||
[
|
||||
{
|
||||
key: "1",
|
||||
label: "影像质量",
|
||||
children: content,
|
||||
style: panelStyle,
|
||||
},
|
||||
{
|
||||
key: "2",
|
||||
label: "其他",
|
||||
children: <p>1</p>,
|
||||
style: panelStyle,
|
||||
},
|
||||
];
|
||||
].map((i) => ({
|
||||
...i,
|
||||
headerClass: "label-category-header",
|
||||
className: "label-category-item",
|
||||
}));
|
||||
|
||||
export const Label = (props: LabelProps) => {
|
||||
const { token } = theme.useToken();
|
||||
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||
const [createLabelCategoryForm] = Form.useForm<{ name: string }>();
|
||||
const { labelDomainService } = useDomain();
|
||||
|
||||
const panelStyle: React.CSSProperties = {
|
||||
marginBottom: 12,
|
||||
background: token.colorFillAlter,
|
||||
borderRadius: token.borderRadiusLG,
|
||||
border: "none",
|
||||
const handleOk = async () => {
|
||||
try {
|
||||
await createLabelCategoryForm.validateFields();
|
||||
const { name } = createLabelCategoryForm.getFieldsValue();
|
||||
labelDomainService.createNewLabelCategory({ name });
|
||||
} catch (error) {
|
||||
console.log(error);
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="label-container">
|
||||
<aside>
|
||||
<Button
|
||||
block
|
||||
type="dashed"
|
||||
icon={<PlusOutlined />}
|
||||
style={{ marginBottom: 10 }}
|
||||
onClick={() => setIsModalOpen(true)}
|
||||
>
|
||||
新增标签分类
|
||||
</Button>
|
||||
<Modal
|
||||
title="新增标签分类"
|
||||
open={isModalOpen}
|
||||
onOk={handleOk}
|
||||
width={350}
|
||||
okText="确认"
|
||||
cancelText="再想想"
|
||||
onCancel={() => setIsModalOpen(false)}
|
||||
>
|
||||
<Form form={createLabelCategoryForm} style={{ marginTop: 20 }}>
|
||||
<Form.Item
|
||||
name="name"
|
||||
rules={[
|
||||
{ required: true, message: "标签分类名称不能为空" },
|
||||
{ max: 10, message: "不能超过十个字符" },
|
||||
]}
|
||||
>
|
||||
<Input placeholder="请输入标签分类名称" autoComplete="off" />
|
||||
</Form.Item>
|
||||
</Form>
|
||||
</Modal>
|
||||
<Collapse
|
||||
bordered={false}
|
||||
defaultActiveKey={[]}
|
||||
expandIcon={({ isActive }) => (
|
||||
<CaretRightOutlined rotate={isActive ? 90 : 0} />
|
||||
)}
|
||||
style={{ background: token.colorBgContainer }}
|
||||
items={getItems(panelStyle)}
|
||||
style={{ background: token.colorBgContainer, color: token.colorText }}
|
||||
items={getItems()}
|
||||
/>
|
||||
</aside>
|
||||
<main>标签相关数据</main>
|
||||
|
|
|
@ -2,11 +2,9 @@ import { Module } from '@nestjs/common';
|
|||
import { LabelController } from './label.controller';
|
||||
import { LabelService } from './label.service';
|
||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||
import { LabelCategory } from './entity/category.entity';
|
||||
import { Label } from './entity/label.entity';
|
||||
import { LabelCategory } from './entity/label.category.entity';
|
||||
|
||||
@Module({
|
||||
controllers: [LabelController],
|
||||
imports: [
|
||||
TypeOrmModule.forRoot({
|
||||
type: 'mysql',
|
||||
|
@ -21,6 +19,7 @@ import { LabelCategory } from './entity/label.category.entity';
|
|||
}),
|
||||
TypeOrmModule.forFeature([Label, LabelCategory]),
|
||||
],
|
||||
controllers: [LabelController],
|
||||
providers: [LabelService],
|
||||
})
|
||||
export class LabelModule {}
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
|||
import { InjectRepository } from '@nestjs/typeorm';
|
||||
import { Label } from './entity/label.entity';
|
||||
import { Repository } from 'typeorm';
|
||||
import { LabelCategory } from './entity/label.category.entity';
|
||||
import { LabelCategory } from './entity/category.entity';
|
||||
|
||||
@Injectable()
|
||||
export class LabelService {
|
||||
|
@ -13,11 +13,8 @@ export class LabelService {
|
|||
private readonly labelCategoryRepository: Repository<LabelCategory>,
|
||||
) {}
|
||||
|
||||
async createLabelCategory(payload) {
|
||||
console.log(payload);
|
||||
return await this.labelCategoryRepository.save({
|
||||
name: '默认',
|
||||
});
|
||||
async createLabelCategory({ name }) {
|
||||
return await this.labelCategoryRepository.save({ name });
|
||||
}
|
||||
|
||||
async createLabel(payload) {
|
||||
|
|
|
@ -25,4 +25,13 @@ export class DicomController {
|
|||
return { code: 1, msg: error };
|
||||
}
|
||||
}
|
||||
|
||||
@Post('label/category/create')
|
||||
async createLabelCategory(@Body() body) {
|
||||
const { name } = body;
|
||||
const { data } = await firstValueFrom(
|
||||
this.client.send({ cmd: 'dicom.label.category.create' }, { name }),
|
||||
);
|
||||
return { code: 0, data };
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user