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 { User } from "@@/domain/User/entities/User";
|
||||||
import { Request } from "./Request";
|
import { Request } from "./Request";
|
||||||
import { Study } from "@/modules/Admin/Dicom/Upload/DicomUploader/util";
|
|
||||||
import axios from "axios";
|
import axios from "axios";
|
||||||
import { saveAs } from "file-saver";
|
import { saveAs } from "file-saver";
|
||||||
|
import {
|
||||||
|
ArchiveTaskCreateDto,
|
||||||
|
DownloadArchiveDTO,
|
||||||
|
ExistInPacsDTO,
|
||||||
|
ResponsePacsType,
|
||||||
|
ResponseType,
|
||||||
|
labelCategoryDTO,
|
||||||
|
} from "./dto";
|
||||||
|
|
||||||
const PREFIX = "/api/dmp";
|
const PREFIX = "/api/dmp";
|
||||||
const PREFIX_CERT = "/cert";
|
const PREFIX_CERT = "/cert";
|
||||||
const PREFIX_PACS = "/dicom-web";
|
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 = {
|
export const Apis = {
|
||||||
/**
|
/**
|
||||||
* 用户登录
|
* 用户登录
|
||||||
|
@ -105,4 +82,9 @@ export const Apis = {
|
||||||
.catch((error) => {
|
.catch((error) => {
|
||||||
console.error("Download error:", 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 { DicomRepository } from "@@/domain/Dicom/DicomRepository";
|
||||||
import { DicomService } from "@@/domain/Dicom/DicomService";
|
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 { UserRepository } from "@@/domain/User/UserRepository";
|
||||||
import { UserService } from "@@/domain/User/UserService";
|
import { UserService } from "@@/domain/User/UserService";
|
||||||
import { createContext } from "react";
|
import { createContext } from "react";
|
||||||
|
@ -7,11 +9,13 @@ import { createContext } from "react";
|
||||||
export type Services = {
|
export type Services = {
|
||||||
userDomainService: UserService;
|
userDomainService: UserService;
|
||||||
dicomDomainService: DicomService;
|
dicomDomainService: DicomService;
|
||||||
|
labelDomainService: LabelService;
|
||||||
};
|
};
|
||||||
|
|
||||||
const defaultServiceMap = {
|
const defaultServiceMap = {
|
||||||
userDomainService: new UserService(new UserRepository()),
|
userDomainService: new UserService(new UserRepository()),
|
||||||
dicomDomainService: new DicomService(new DicomRepository()),
|
dicomDomainService: new DicomService(new DicomRepository()),
|
||||||
|
labelDomainService: new LabelService(new LabelRepository()),
|
||||||
};
|
};
|
||||||
|
|
||||||
export const DomainServiceContext = createContext<Services>(defaultServiceMap);
|
export const DomainServiceContext = createContext<Services>(defaultServiceMap);
|
||||||
|
|
|
@ -6,5 +6,42 @@
|
||||||
aside {
|
aside {
|
||||||
padding: 20px 20px 0 20px;
|
padding: 20px 20px 0 20px;
|
||||||
border-right: 1px solid rgba(5, 5, 5, 0.06);
|
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 "./index.less";
|
||||||
import { Collapse, CollapseProps, theme } from "antd";
|
import {
|
||||||
import { CaretRightOutlined } from "@ant-design/icons";
|
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 {
|
interface LabelProps {
|
||||||
children?: JSX.Element;
|
children?: JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<ul>
|
<ul className="label-catalog">
|
||||||
<li>切片太少</li>
|
<li>切片太少</li>
|
||||||
<li>{"层厚>1.0mm"}</li>
|
<li className="active">{"层厚>1.0mm"}</li>
|
||||||
</ul>
|
</ul>
|
||||||
);
|
);
|
||||||
const getItems: (panelStyle: CSSProperties) => CollapseProps["items"] = (
|
const getItems = (): CollapseProps["items"] =>
|
||||||
panelStyle
|
[
|
||||||
) => [
|
{
|
||||||
{
|
key: "1",
|
||||||
key: "1",
|
label: "影像质量",
|
||||||
label: "影像质量",
|
children: content,
|
||||||
children: content,
|
},
|
||||||
style: panelStyle,
|
{
|
||||||
},
|
key: "2",
|
||||||
{
|
label: "其他",
|
||||||
key: "2",
|
children: <p>1</p>,
|
||||||
label: "其他",
|
},
|
||||||
children: <p>1</p>,
|
].map((i) => ({
|
||||||
style: panelStyle,
|
...i,
|
||||||
},
|
headerClass: "label-category-header",
|
||||||
];
|
className: "label-category-item",
|
||||||
|
}));
|
||||||
|
|
||||||
export const Label = (props: LabelProps) => {
|
export const Label = (props: LabelProps) => {
|
||||||
const { token } = theme.useToken();
|
const { token } = theme.useToken();
|
||||||
|
const [isModalOpen, setIsModalOpen] = useState(false);
|
||||||
|
const [createLabelCategoryForm] = Form.useForm<{ name: string }>();
|
||||||
|
const { labelDomainService } = useDomain();
|
||||||
|
|
||||||
const panelStyle: React.CSSProperties = {
|
const handleOk = async () => {
|
||||||
marginBottom: 12,
|
try {
|
||||||
background: token.colorFillAlter,
|
await createLabelCategoryForm.validateFields();
|
||||||
borderRadius: token.borderRadiusLG,
|
const { name } = createLabelCategoryForm.getFieldsValue();
|
||||||
border: "none",
|
labelDomainService.createNewLabelCategory({ name });
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="label-container">
|
<div className="label-container">
|
||||||
<aside>
|
<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
|
<Collapse
|
||||||
bordered={false}
|
bordered={false}
|
||||||
defaultActiveKey={[]}
|
defaultActiveKey={[]}
|
||||||
expandIcon={({ isActive }) => (
|
expandIcon={({ isActive }) => (
|
||||||
<CaretRightOutlined rotate={isActive ? 90 : 0} />
|
<CaretRightOutlined rotate={isActive ? 90 : 0} />
|
||||||
)}
|
)}
|
||||||
style={{ background: token.colorBgContainer }}
|
style={{ background: token.colorBgContainer, color: token.colorText }}
|
||||||
items={getItems(panelStyle)}
|
items={getItems()}
|
||||||
/>
|
/>
|
||||||
</aside>
|
</aside>
|
||||||
<main>标签相关数据</main>
|
<main>标签相关数据</main>
|
||||||
|
|
|
@ -2,11 +2,9 @@ import { Module } from '@nestjs/common';
|
||||||
import { LabelController } from './label.controller';
|
import { LabelController } from './label.controller';
|
||||||
import { LabelService } from './label.service';
|
import { LabelService } from './label.service';
|
||||||
import { TypeOrmModule } from '@nestjs/typeorm';
|
import { TypeOrmModule } from '@nestjs/typeorm';
|
||||||
|
import { LabelCategory } from './entity/category.entity';
|
||||||
import { Label } from './entity/label.entity';
|
import { Label } from './entity/label.entity';
|
||||||
import { LabelCategory } from './entity/label.category.entity';
|
|
||||||
|
|
||||||
@Module({
|
@Module({
|
||||||
controllers: [LabelController],
|
|
||||||
imports: [
|
imports: [
|
||||||
TypeOrmModule.forRoot({
|
TypeOrmModule.forRoot({
|
||||||
type: 'mysql',
|
type: 'mysql',
|
||||||
|
@ -21,6 +19,7 @@ import { LabelCategory } from './entity/label.category.entity';
|
||||||
}),
|
}),
|
||||||
TypeOrmModule.forFeature([Label, LabelCategory]),
|
TypeOrmModule.forFeature([Label, LabelCategory]),
|
||||||
],
|
],
|
||||||
|
controllers: [LabelController],
|
||||||
providers: [LabelService],
|
providers: [LabelService],
|
||||||
})
|
})
|
||||||
export class LabelModule {}
|
export class LabelModule {}
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Injectable } from '@nestjs/common';
|
||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { Label } from './entity/label.entity';
|
import { Label } from './entity/label.entity';
|
||||||
import { Repository } from 'typeorm';
|
import { Repository } from 'typeorm';
|
||||||
import { LabelCategory } from './entity/label.category.entity';
|
import { LabelCategory } from './entity/category.entity';
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class LabelService {
|
export class LabelService {
|
||||||
|
@ -13,11 +13,8 @@ export class LabelService {
|
||||||
private readonly labelCategoryRepository: Repository<LabelCategory>,
|
private readonly labelCategoryRepository: Repository<LabelCategory>,
|
||||||
) {}
|
) {}
|
||||||
|
|
||||||
async createLabelCategory(payload) {
|
async createLabelCategory({ name }) {
|
||||||
console.log(payload);
|
return await this.labelCategoryRepository.save({ name });
|
||||||
return await this.labelCategoryRepository.save({
|
|
||||||
name: '默认',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async createLabel(payload) {
|
async createLabel(payload) {
|
||||||
|
|
|
@ -25,4 +25,13 @@ export class DicomController {
|
||||||
return { code: 1, msg: error };
|
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