用DMTK(dicom)实现DR设备的剂量报告(RDSR)

最近公司跟西门子合作,开发他们需要的DR采集工作站的软件。接到一个需求是新的法规标准需要生成累计剂量报告的功能,需求描述是:“该系统的辐射剂量结构报告应包含IEC 61910-1:2014之5.1.2中要求(应)的数据元素;辐射剂量结构报告宜包含IEC 61910-1:2014之5.1.2中要求(宜)的数据元素。”

看到需求时不明所以,找来标准的条款看,如下图所示,英文的看不太明白。于是再找来对应的中文翻译版本来看,还是不知道这个报告应该长什么样。

后面再问西门子,要他们的CT设备生成的剂量报告来作参考,是一个DCM文件。用软件打开来看,跟dcm格式的图像还是不一样的,如下图。 

这下终于有点眉目了,就要把标准里说的那个信息写到一个DCM文件里。接下来就是要研究用哪些DICOM标签来存放这些信息了。因为之前的软件能生成DCM格式的图像,知道一张图像里要用DICOM写入哪些数据,也用代码调用了哪些DCMTK函数可参考,于是信心大增。

用软件查看所有的DICOM标签,如下图。发现实在太多了,这么多要一个个写入,还要研究哪个标签要可以写入什么数据,标签要怎么嵌套。查了一下DICOM标准,看了一些标签的意思,如果要每个标签都自己写将会是很大的工作量。于在网上找看有没有实现类似报告的代码。还真找到了2个。链接如下:

Howto MammoCADSR - DCMTK - OFFIS DCMTK and DICOM ProjectsRedminehttps://support.dcmtk.org/redmine/projects/dcmtk/wiki/howto_mammocadsr#Howto-Create-a-Mammography-CAD-SR-DocumentDCMTK:使用dcmsr API创建示例结构化报告_C和C++技术博客-CSDN博客DCMTK:使用dcmsr API创建示例结构化报告使用dcmsr API创建示例结构化报告使用dcmsr API创建示例结构化报告#include "dcmtk/config/osconfig.h" #include "dcmtk/ofstd/ofconsol.h" #include "dcmtk/dcmsr/dsrdoc.h" #include "dcmtk/dcmsr/codes/ucum.h"#include "dcmtk/dcmdata/dctk.h" //https://cplusplus.blog.csdn.net/article/details/116811257?spm=1001.2101.3001.6650.6&utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-6.no_search_link&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromBaidu~default-6.no_search_link

 其中第2个链接里的代码非常有用,后面就基于它来改的。后面还遇到2个问题,就是不能显示中文,另一个是怎么打开已生成的报告文件并追加新的内容。第一个问题是要把字符集设为DSRTypes::CS_UTF8,不能用例子里的DSRTypes::CS_Latin1。第2个问题就看代码吧。


#include 
#include "DoseStructuredReport.h"// 写入剂量报告
void  DoseStructuredReport::WriteDSRDocument(DoseStructuredReport& DoseInfo, CString sFilePath)
{LOG_DEBUGGING("%s", sFilePath);// 剂量报告已经存在,就打开它,往后追加if (FileUtility::FileExists(sFilePath)){AppendDSRDocument(DoseInfo, sFilePath);return;}DSRDocument* pDoseDocument = new DSRDocument();if (pDoseDocument == NULL){LOG_DEBUGGING("pDoseDocument == NULL");return;}WriteDSRDocumentHeadInfo(pDoseDocument, DoseInfo);WriteDSRDocumentAccumulatedDoseInfo(pDoseDocument, DoseInfo);StoreDSRDocumentToDcmFile(pDoseDocument, sFilePath);delete pDoseDocument;pDoseDocument = NULL;
}// 追加内容到已有的剂量报告里
void DoseStructuredReport::AppendDSRDocument(DoseStructuredReport& DoseInfo, CString sFilePath)
{LOG_DEBUGGING("");DSRDocument* pDoseDocument = new DSRDocument();if (pDoseDocument == NULL){LOG_DEBUGGING("pDoseDocument == NULL");return;}ReadDSRDocumentDcmFile(pDoseDocument, sFilePath);WriteDSRDocumentAccumulatedDoseInfo(pDoseDocument, DoseInfo, TRUE);StoreDSRDocumentToDcmFile(pDoseDocument, sFilePath);delete pDoseDocument;pDoseDocument = NULL;
}// 读取剂量报告DCM文件
BOOL DoseStructuredReport::ReadDSRDocumentDcmFile(DSRDocument* pDoseDocument, CString sFilePath)
{LOG_DEBUGGING("");ASSERT(pDoseDocument != NULL);DcmFileFormat *pDcmFileFormat = new DcmFileFormat();if (pDcmFileFormat == NULL){LOG_DEBUGGING("pDcmFileFormat == NULL");return FALSE;}if (pDcmFileFormat->loadFile(CT2A(sFilePath)).bad()){LOG_ERROR("加载文件失败");return FALSE;}BOOL bRet = FALSE;DcmDataset *pDcmDataset = pDcmFileFormat->getDataset();if (pDcmDataset != NULL){pDoseDocument->getCodingSchemeIdentification().addPrivateDcmtkCodingScheme();OFCondition Condition = pDoseDocument->read(*pDcmDataset,DSRTypes::RF_readDigitalSignatures | DSRTypes::RF_acceptUnknownRelationshipType| DSRTypes::RF_ignoreRelationshipConstraints | DSRTypes::RF_ignoreContentItemErrors| DSRTypes::RF_skipInvalidContentItems);if (Condition.good()){//StoreDSRDocumentToDcmFile(pDoseDocument, sFilePath + "22");//测试用bRet = TRUE;}else{LOG_DEBUGGING("ERROR: could not read pDcmDataset into SR document [%s]", Condition.text());}}else{LOG_DEBUGGING("pDcmDataset == NULL");}delete pDcmFileFormat;pDcmFileFormat = NULL;return bRet;
}// 把剂量报告保存到DCM文件中
BOOL DoseStructuredReport::StoreDSRDocumentToDcmFile(DSRDocument* pDoseDocument, CString sFilePath)
{LOG_DEBUGGING("%s", sFilePath);ASSERT(pDoseDocument != NULL);DcmFileFormat *pDcmFileFormat = new DcmFileFormat();if (pDcmFileFormat == NULL){LOG_DEBUGGING("pDcmFileFormat == NULL");return FALSE;}BOOL bRet = FALSE;DcmDataset *pDcmDataset = pDcmFileFormat->getDataset();if (pDcmDataset != NULL){pDoseDocument->getCodingSchemeIdentification().addPrivateDcmtkCodingScheme();if (pDoseDocument->write(*pDcmDataset).good()){//CString sSpecificCharacterSet;//LANGID lid = GetSystemDefaultLangID();是中文系统就改变语言字符集,不然显示中文乱码//if (lid == 0x0804)//{//	sSpecificCharacterSet = _T("GB18030");//	pDcmDataset->putAndInsertString(DCM_SpecificCharacterSet, CT2A(sSpecificCharacterSet));//}//else//case 0x0409//{//	sSpecificCharacterSet = _T("ISO_IR 100");//}if (pDcmFileFormat->saveFile(CT2A(sFilePath), EXS_LittleEndianExplicit).good()){bRet = TRUE;}else{LOG_DEBUGGING("ERROR: could not save pDcmDataset to file");}}else{LOG_DEBUGGING("ERROR: could not write SR document into pDcmDataset");}}else{LOG_DEBUGGING("pDcmDataset == NULL");}delete pDcmFileFormat;pDcmFileFormat = NULL;return bRet;
}// 写入剂量报告的头信息,从病人图像的DCM信息里获取
void DoseStructuredReport::WriteDSRDocumentHeadInfo(DSRDocument* pDoseDocument, DoseStructuredReport& DoseInfo)
{LOG_DEBUGGING("");ASSERT(pDoseDocument != NULL);pDoseDocument->createNewDocument(DSRTypes::DT_XRayRadiationDoseSR);// 默认字符集, 这里要设为UTF8不然没法显示中文, 不能设为CS_Latin1pDoseDocument->setSpecificCharacterSetType(DSRTypes::CS_UTF8);// Study Instance UIDpDoseDocument->createNewSeriesInStudy(ConvertCStringToUTF8(DoseInfo.StudyInstanceUid).c_str());// 如果送诊医院为空就写入操作医生if (DoseInfo.ReferringPhysiciansName.IsEmpty()){pDoseDocument->setReferringPhysicianName(ConvertCStringToUTF8(DoseInfo.OperatorsName).c_str());}else{pDoseDocument->setReferringPhysicianName(ConvertCStringToUTF8(DoseInfo.ReferringPhysiciansName).c_str());}//pDoseDocument->setSeriesDescription(DoseInfo.SeriesDescription).c_str());pDoseDocument->setSeriesDescription("Radiation Dose Information");// 如果检查描述为空,就写入检查部位if (DoseInfo.StudyDescription.IsEmpty()){pDoseDocument->setStudyDescription(ConvertCStringToUTF8(DoseInfo.BodyPartExamined).c_str());}else{pDoseDocument->setStudyDescription(ConvertCStringToUTF8(DoseInfo.StudyDescription).c_str());}pDoseDocument->setManufacturer(ConvertCStringToUTF8(DoseInfo.Manufacturer).c_str());pDoseDocument->setManufacturerModelName(ConvertCStringToUTF8(DoseInfo.ManufacturersModelName).c_str());pDoseDocument->setDeviceSerialNumber(ConvertCStringToUTF8(DoseInfo.DeviceSerialNumber).c_str());pDoseDocument->setSoftwareVersions(ConvertCStringToUTF8(DoseInfo.SoftwareVersions).c_str());pDoseDocument->setPatientName(ConvertCStringToUTF8(DoseInfo.PatientName).c_str());pDoseDocument->setPatientSex(ConvertCStringToUTF8(DoseInfo.PatientSex).c_str());pDoseDocument->setPatientBirthDate(ConvertCStringToUTF8(DoseInfo.PatientBirthDate).c_str());pDoseDocument->setPatientID(ConvertCStringToUTF8(DoseInfo.PatientID).c_str());
}// 写入累计剂量信息
void DoseStructuredReport::WriteDSRDocumentAccumulatedDoseInfo(DSRDocument* pDoseDocument, DoseStructuredReport& DoseInfo, BOOL bIsAppend)
{LOG_DEBUGGING("");ASSERT(pDoseDocument != NULL);OFString sPosition;if (!bIsAppend){pDoseDocument->getTree().addContentItem(DSRTypes::RT_isRoot, DSRTypes::VT_Container);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("DT.01", "DCM", "X-Ray Radiation Dose Report"));// 观察员内容 Observation ContextpDoseDocument->getTree().addContentItem(DSRTypes::RT_hasObsContext, DSRTypes::VT_PName, DSRTypes::AM_belowCurrent);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("IHE.02", OFFIS_CODING_SCHEME_DESIGNATOR, "Person Observer's Role in this Procedure"));pDoseDocument->getTree().getCurrentContentItem().setStringValue("Irradiation Administering");pDoseDocument->getTree().addContentItem(DSRTypes::RT_hasObsContext, DSRTypes::VT_Text);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("IHE.04", OFFIS_CODING_SCHEME_DESIGNATOR, "Device Observer Manufacturer"));pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(DoseInfo.Manufacturer).c_str());pDoseDocument->getTree().addContentItem(DSRTypes::RT_hasObsContext, DSRTypes::VT_Text);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("IHE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Recording Observer's Organization Name"));pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(DoseInfo.InstitutionName).c_str());}else{pDoseDocument->getTree().gotoRoot();pDoseDocument->getTree().goDown();size_t tt = pDoseDocument->getTree().gotoNode("1.3");// 由于医院名称是中文,读取后再写入就丢掉了,这里要重新写入pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("IHE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Recording Observer's Organization Name"));pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(DoseInfo.InstitutionName).c_str());LOG_DEBUGGING("追加剂量报告: %d", tt);}LOG_DEBUGGING("NodeID=%d, Level=%d, Position=%s, sPosition=%s", pDoseDocument->getTree().getNodeID(),pDoseDocument->getTree().getLevel(), pDoseDocument->getTree().getPosition(sPosition).c_str(), ConvertUTF8ToCString(sPosition.c_str()));// 累积投射的X射线剂量pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Container);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("SH.06", OFFIS_CODING_SCHEME_DESIGNATOR,ConvertCStringToUTF8(StringUtility::Format("Accumulated X - Ray Dose Data (%s, %s)", DoseInfo.SeriesDate, DoseInfo.SeriesTime)).c_str()));pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text, DSRTypes::AM_belowCurrent);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Dose (RP) Total"));pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(StringUtility::Format(_T("%.10f Gy"), DoseInfo.DoseTotal)).c_str());pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Dose Area Product Total"));pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(StringUtility::Format(_T("%.10f Gy.m2"), DoseInfo.DoseAreaProductTotal)).c_str());pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Distance Source to Reference Point"));pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(StringUtility::Format(_T("%d mm"), DoseInfo.DistanceSourceToReferencePoint)).c_str());pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Reference Point Definition"));pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(DoseInfo.ReferencePointDefinition).c_str());pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Total Number of Radiographic Frames"));pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(StringUtility::Format(_T("%d"), DoseInfo.TotalNumOfRadiographicFrames)).c_str());pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Total Fluoroscopy Time"));pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(StringUtility::Format(_T("%d s"), DoseInfo.TotalFluoroscopyTime)).c_str());pDoseDocument->getTree().goUp();// 辐照事件X射线数据pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Container);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("SH.06", OFFIS_CODING_SCHEME_DESIGNATOR,ConvertCStringToUTF8(StringUtility::Format("Irradiation Event X - Ray Data (%s, %s)", DoseInfo.SeriesDate, DoseInfo.SeriesTime)).c_str()));// 采集协议,这里只写部位pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text, DSRTypes::AM_belowCurrent);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Acquisition Protocol"));pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(DoseInfo.BodyPartExamined).c_str());// 开始的日期和时间pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "DateTime Started"));pDoseDocument->getTree().getCurrentContentItem().setStringValue((ConvertCStringToUTF8(DoseInfo.SeriesDate + _T(" ") + DoseInfo.SeriesTime)).c_str());// 辐照事件类型pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Text);pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("RE.05", OFFIS_CODING_SCHEME_DESIGNATOR, "Irradiation Event Type"));CString IrradiationEventType;IrradiationEventType.Format(_T("%s %s %s"),(DoseInfo.IrradiationEventType & 0x01) == 0x01 ? "Radiography," : "",(DoseInfo.IrradiationEventType & 0x02) == 0x02 ? "SerialRadiography," : "",(DoseInfo.IrradiationEventType & 0x04) == 0x04 ? "Fluoroscopy" : "");IrradiationEventType.TrimRight(_T(", "));pDoseDocument->getTree().getCurrentContentItem().setStringValue(ConvertCStringToUTF8(IrradiationEventType).c_str());LOG_DEBUGGING("NodeID=%d, Level=%d, Position=%s, sPosition=%s", pDoseDocument->getTree().getNodeID(),pDoseDocument->getTree().getLevel(), pDoseDocument->getTree().getPosition(sPosition).c_str(), ConvertUTF8ToCString(sPosition.c_str()));//pDoseDocument->getTree().addContentItem(DSRTypes::RT_contains, DSRTypes::VT_Image);//pDoseDocument->getTree().getCurrentContentItem().setConceptName(DSRCodedEntryValue("IR.02", OFFIS_CODING_SCHEME_DESIGNATOR, "Acquired Image"));//pDoseDocument->getTree().getCurrentContentItem().setImageReference(DSRImageReferenceValue(UID_SecondaryCaptureImageStorage, "1.3.12.2.1107.5.8.1.123456789.199507271803030521934"));//pDoseDocument->getCurrentRequestedProcedureEvidence().addItem("1.3.12.2.1107.5.8.1.123456789.199507271803030520282", "1.3.12.2.1107.5.8.1.123456789.199507271803030521007", UID_SecondaryCaptureImageStorage, "1.3.12.2.1107.5.8.1.123456789.199507271803030521934");//pDoseDocument->completeDocument();
}// CString转为UTF8
std::string DoseStructuredReport::ConvertCStringToUTF8(CString strValue)
{std::wstring wbuffer;int length = 0;#ifdef _UNICODEwbuffer.assign(strValue.GetString(), strValue.GetLength());
#else// 预转换ANSI到UNICODE, 获取转换后长度length = ::MultiByteToWideChar(CP_ACP, MB_ERR_INVALID_CHARS, (LPCTSTR)strValue, -1, NULL, 0);wbuffer.resize(length);// 转换 MultiByteToWideChar(CP_ACP, 0, (LPCTSTR)strValue, -1, (LPWSTR)(wbuffer.data()), wbuffer.length());
#endif// 预转换UNICODE到UTF8, 获取转换后长度length = WideCharToMultiByte(CP_UTF8, 0, wbuffer.data(), wbuffer.size(), NULL, 0, NULL, NULL);// 转换UNICODE到UTF8, 获取转换后内容std::string buffer;buffer.resize(length);WideCharToMultiByte(CP_UTF8, 0, wbuffer.c_str(), -1, (LPSTR)(buffer.data()), length, NULL, NULL);return(buffer);
}// UTF8转为CString
CString DoseStructuredReport::ConvertUTF8ToCString(std::string utf8str)
{// 预转换,得到所需空间的大小int nLen = ::MultiByteToWideChar(CP_UTF8, NULL, utf8str.data(), utf8str.size(), NULL, 0);// UTF8转换为Unicodestd::wstring wbuffer;wbuffer.resize(nLen);::MultiByteToWideChar(CP_UTF8, NULL, utf8str.data(), utf8str.size(), (LPWSTR)(wbuffer.data()), wbuffer.length());#ifdef UNICODEreturn (CString(wbuffer.data(), wbuffer.length()));
#else// Unicode转换为ANSI  得到转换后长度nLen = WideCharToMultiByte(CP_ACP, 0, wbuffer.data(), wbuffer.length(), NULL, 0, NULL, NULL);std::string ansistr;ansistr.resize(nLen);// unicode转成ansiWideCharToMultiByte(CP_ACP, 0, (LPWSTR)(wbuffer.data()), wbuffer.length(),(LPSTR)(ansistr.data()), ansistr.size(), NULL, NULL);return (CString(ansistr.data(), ansistr.length()));
#endif
}
#pragma once
#include "dcmtk/config/osconfig.h"    
#include "dcmtk/ofstd/ofconsol.h"    
#include "dcmtk/dcmsr/dsrdoc.h"    
#include "dcmtk/dcmdata/dctk.h"
#include // 存储在报告里的一些剂量参数
class DoseStructuredReport : public CDcmImageInfo
{
public:// 写入剂量报告void WriteDSRDocument(DoseStructuredReport& DoseInfo, CString sFilePath);private:// 追加内容到已有的剂量报告里void AppendDSRDocument(DoseStructuredReport& DoseInfo, CString sFilePath);// 读取剂量报告DCM文件BOOL ReadDSRDocumentDcmFile(DSRDocument* pDoseDocument, CString sFilePath);// 把剂量报告保存到DCM文件中BOOL StoreDSRDocumentToDcmFile(DSRDocument* pDoseDocument, CString sFilePath);// 写入剂量报告的头信息,从病人图像的DCM信息里获取void WriteDSRDocumentHeadInfo(DSRDocument* pDoseDocument, DoseStructuredReport& DoseInfo);// 写入累计剂量信息void WriteDSRDocumentAccumulatedDoseInfo(DSRDocument* pDoseDocument, DoseStructuredReport& DoseInfo, BOOL bIsAppend = FALSE);// CString转为UTF8std::string ConvertCStringToUTF8(CString strValue);// UTF8转为CStringCString ConvertUTF8ToCString(std::string utf8str);public:// 累计剂量,单位:Gydouble DoseTotal = 0;// 累计DAP,单位:Gy.m2 double DoseAreaProductTotal = 0;// 射线源到基准点的距离,单位:mmUINT DistanceSourceToReferencePoint = 850;// 基准点定义,单位:cmCString ReferencePointDefinition = _T("30cm above table");// 辐照总帧数UINT TotalNumOfRadiographicFrames = 0;// 总透视时间,单位:sUINT TotalFluoroscopyTime = 0;// 辐照事件类型,包括3种及它们组合:Radiography,SerialRadiography,Fluoroscopy,// bit0 = 1表示Radiography,bit1 = 1表示SerialRadiography,bit2 = 1表示Fluoroscopychar IrradiationEventType = 0;
};


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部