irc_dicom_service/app/controller/pacs.js

547 lines
19 KiB
JavaScript

const dicomParser = require("dicom-parser");
const BaseController = require("./base");
const fs = require("fs");
const path = require("path");
function getObjectMkdir (url) {
let index = url.lastIndexOf("/")
let a = url.substring(0,index);
return a
}
function getObjectName (url) {
var value = url
var str = value.split("/"); //https://进行分割,
var name = str[str.length - 1]
return name
}
function parseDicomFile(file, uploadQueues, path) {
return new Promise(function(resolve, reject) {
try {
var data = dicomParser.parseDicom(file)
var studyUid = data.string('x0020000d')
var studyIndex = 0
while (
studyIndex < uploadQueues.length &&
uploadQueues[studyIndex].dicomInfo.studyUid !== studyUid
) {
++studyIndex
}
if (studyIndex >= uploadQueues.length) {
var date = data.string('x00080020')
var time = data.string('x00080030')
var studyTime = ''
if (date) {
// date = `${date.substr(0, 4)}-${date.substr(4, 2)}-${date.substr(6, 2)}`
date = `${date.substring(0, 4)}-${date.substring(4, 6)}-${date.substring(6, 8)}`
}
if (time) {
time = `${time.substring(0, 2)}:${time.substring(2, 4)}:${time.substring(4, 6)}`
}
if(date){
studyTime = time ? `${date} ${time}` : `${date} 00:00:00`
}
uploadQueues.push({
studyIndex: studyIndex,
seriesList: [],
fileList: [],
dicomInfo: {
studyUid: studyUid,
patientId: data.string('x00100020'),
patientName: data.string('x00100010') ? data.string('x00100010') : '',
patientAge: data.string('x00101010') ? data.string('x00101010') : '',
patientSex: data.string('x00100040') ? data.string('x00100040') : '',
patientBirthDate: data.string('x00100030'),
hospitalName: data.string('x00080080'),
accNumber: data.string('x00080050'),
bodyPart: data.string('x00180015'),
modality: [],
institutionName: data.string('x00080080'),
description: data.string('x00081030'),
studyTime: studyTime,
VisitInfo: {},
SubjectInfo: {}
},
uploadState: {
selected: false,
stateCode: '',
beginUploadTime: {},
progressValue: 0
}
})
}
var modality = uploadQueues[studyIndex].dicomInfo.modality
var currentModality = data.string('x00080060')
if (!(modality.indexOf(currentModality) > -1)) {
modality.push(currentModality)
}
var fileList = uploadQueues[studyIndex].fileList
var instanceUid = data.string('x00080018')
var instanceIndex = 0
while (
instanceIndex < fileList.length &&
fileList[instanceIndex].instanceUid !== instanceUid
) {
++instanceIndex
}
if (instanceIndex >= fileList.length) {
fileList.push({
instanceUid: instanceUid,
file: file
})
}
var seriesUid = data.string('x0020000e')
var seriesList = uploadQueues[studyIndex].seriesList
var seriesItem = seriesList.find(function(item) {
return item.seriesUid === seriesUid
})
if (!seriesItem) {
seriesItem = {
seriesUid: seriesUid,
seriesNumber: data.intString('x00200011') || 1,
modality: data.string('x00080060'),
description: data.string('x0008103e'),
instanceList: []
}
seriesList.push(seriesItem)
}
var instanceList = seriesItem.instanceList
var instanceItem = instanceList.find(function(item) {
return item.instanceUid === instanceUid
})
if (!instanceItem) {
instanceItem = {
instanceUid: instanceUid,
path: path,
modality: data.string('x00080060'),
instanceNumber: data.intString('x00200013') || 1,
frameCount: data.intString('x00280008') || 1,
file: file
}
instanceList.push(instanceItem)
}
resolve(uploadQueues)
} catch (error) {
console.log(error)
resolve()
}
})
}
class PacsController extends BaseController {
constructor(props) {
super(props);
}
//获取pacs位置
async getPACS(){
try{
console.log(this.ctx.request.query)
let pacs = await this.ctx.model.Pacs.find(this.ctx.request.query).select("_id aet host port mode description")
return this.success(pacs)
}catch (error) {
return this.error(error)
}
}
async findReading() {
try {
this.ctx.validate({
trialCode: 'string',
subjectCode: 'string',
TaskCode: 'string',
})
let config = await this.service.config.getConfig();
let a = await this.ctx.service.pacs.findFromPacs(this.ctx.request.body, config)
if (a) {
let $in = a.map(v => {return v.SeriesInstanceUID})
console.log($in)
let list = await this.ctx.model.Series.find({SeriesInstanceUID: {$in: $in}})
// let list = await this.ctx.model.Pacs.find({})
console.log(list)
let newA = a.map(v => {
let i = list.find(o => {
return o.SeriesInstanceUID == v.SeriesInstanceUID
})
return {
...v,
...i._doc
}
})
return this.success(newA)
} else {
return this.error('找不到影像')
}
} catch (e) {
return this.error(e)
}
}
async pullImage() {
try {
this.ctx.validate({
pacs_id: 'string',
userName: 'string',
userId: 'string',
task_id: 'string',
trialCode: 'string',
trialId: 'string',
siteId: 'string',
subjectId: 'string',
subjectVisitId: 'string',
subjectCode: 'string',
TaskCode: 'string',
seriesList: 'array'
})
let {pacs_id, seriesList,trialId,siteId,subjectId,subjectVisitId, userName, userId, task_id, trialCode, subjectCode, TaskCode} = this.ctx.request.body
let config = await this.service.config.getConfig();
for (let i = 0; i < seriesList.length; i++) {
let series = seriesList[i]
await this.ctx.service.pacs.movescu(this.ctx.request.body, series, config)
await this.ctx.model.Series.findOneAndUpdate({
SeriesInstanceUID: series,
}, {
$set: {
// 拉取中
status: 1,
userName: userName,
userId: userId
}
}, {upsert: true, new: true})
}
let directoryPath = config.ossPacsPath + `/${trialCode}/${subjectCode}/${TaskCode}/${userId}/`
let pathList = fs.readdirSync(directoryPath)
let uploadQueues = []
for (let i = 0; i < pathList.length; i++) {
let item = path.join(directoryPath, pathList[i])
let file = fs.readFileSync(item)
await parseDicomFile(file, uploadQueues, item)
}
console.log(uploadQueues)
const Authorization = this.ctx.get('Authorization');
let arr = []
for (let i = 0; i < uploadQueues.length; ++i) {
let info = {
trialId: trialId,
siteId: siteId,
subjectId: subjectId,
subjectVisitId: subjectVisitId,
fileSize: uploadQueues[i].dicomInfo.fileSize,
fileCount: uploadQueues[i].dicomInfo.fileCount,
IsDicomReUpload: uploadQueues[i].uploadState.AllowReUpload,
visitTaskId: task_id,
Authorization: Authorization,
}
arr.push(this.ctx.service.pacs.archiveStudy(uploadQueues, i ,info, config))
}
let a = await Promise.all(arr)
// 获取
return this.success(a)
} catch (e) {
return this.error(e)
}
}
async pushImage() {
try{
this.ctx.validate({
pacs_id: 'string',
imagesList: 'array',
task_id: 'string',
trialCode: 'string',
subjectCode: 'string',
TaskCode: 'string',
})
let {
pacs_id, imagesList, task_id, trialCode, subjectCode, TaskCode
} = this.ctx.request.body
let pacs = await this.ctx.model.Pacs.findOne({_id: pacs_id})
let config = await this.service.config.getConfig();
let downloadErrorList = [], downloadsuccessList = []
let studyList = []
for (let i = 0; i < imagesList.length; i++) {
let image = imagesList[i]
fs.mkdirSync(config.ossPacsPath + getObjectMkdir(`/${trialCode}/${subjectCode}/${TaskCode}/initial_data/1`), { recursive: true });
await this.service.oss.downloadImage(image.InstancePath, `${config.ossPacsPath}/${trialCode}/${subjectCode}/${TaskCode}/initial_data/${getObjectName(image.InstancePath)}`, config)
let status_result = await this.ctx.model.Status.findOneAndUpdate({
task_id: task_id
}, {
$set: {
downloadNum: i + 1,
status: '下载中',
downloadCount: imagesList.length
}
}, {upsert: true, new: true})
if (!~studyList.indexOf(`${config.ossPacsPath}/${trialCode}/${subjectCode}/${TaskCode}/initial_data`)) {
studyList.push(`${config.ossPacsPath}/${trialCode}/${subjectCode}/${TaskCode}/initial_data`)
}
}
console.log(studyList)
let status_result = await this.ctx.model.Status.findOneAndUpdate({
task_id: task_id
}, {
$set: {
status: '下载完成',
}
}, {upsert: true, new: true})
// 开始推送
for (let i = 0; i < studyList.length; i++) {
let study = studyList[i]
let a = await this.ctx.service.pacs.storescu(pacs, config, study)
let status_result = await this.ctx.model.Status.findOneAndUpdate({
task_id: task_id
}, {
$set: {
status: '推送中',
}
}, {upsert: true, new: true})
}
await this.ctx.model.Status.findOneAndUpdate({
task_id: task_id
}, {
$set: {
status: '推送完成',
}
}, {upsert: true, new: true})
return this.success({downloadErrorList, downloadsuccessList})
}catch (error) {
return this.error(error)
}
}
//新增pacs位置
async addPACS(){
try {
this.ctx.validate({
trialId: 'string',
host: 'string',
port: 'string',
aet: 'string',
})
let {
host,port,aet,trialId
} = this.ctx.request.body
let para = this.ctx.request.body
let pacs = await this.ctx.model.Pacs.findOne({
host,port,aet,trialId
})
if(pacs){
return this.error("PACS位置已存在",60001)
}else{
pacs = this.ctx.model.Pacs(para)
let result = await pacs.save()
return this.success(result)
}
} catch (error) {
return this.error(error)
}
}
async editPacs() {
this.ctx.validate({
trialId: 'string',
host: 'string',
port: 'string',
aet: 'string',
})
let {
_id, host,port,aet,mode, trialId, description
} = this.ctx.request.body
let para = this.ctx.request.body
let result
await this.ctx.model.Pacs.findOneAndUpdate({
_id: _id
}, {
$set: {
// 拉取中
host: host,
port: port,
aet: aet,
mode: mode,
description: description
}
}, {upsert: true, new: true})
return this.success(result)
}
//删除pacs位置
async delPACS(){
try {
this.ctx.validate({
pacs_id: {
type: 'string',
format: this.config.regexp.objectId
}
})
let {
pacs_id
} = this.ctx.request.body
let pacs = await this.ctx.model.Pacs.findOne({
_id:pacs_id
});
if (!pacs) throw '未找到该PACS'
await this.ctx.model.Pacs.deleteOne({
_id:pacs_id
});
return this.success()
} catch (e) {
return this.error(e);
}
}
//测试连接
async testConnection() {
try {
this.ctx.validate({
pacs_ids:"array"
})
} catch (error) {
return this.error(error)
}
try {
let { pacs_ids } = this.ctx.request.body
if(!pacs_ids.length) return this.error("参数为空")
let result = await this.ctx.service.pacs.testConnection(pacs_ids)
return this.success(result)
} catch (error) {
let msg = error
if (error.message) {
msg = error.message.split('\n')
}
return this.error(msg)
}
}
async wxFindFromPacs () {
try {
let {
PatientID
} = this.ctx.request.body
if (!PatientID) {
throw 'PatientID必填'
}
let result = await this.ctx.service.pacs.findFromPacs({PatientID: PatientID})
if (result.length > 0) {
let item = result[0]
let isHas = await this.ctx.model.Dcmtemp.findOne({StudyInstanceUID: item.StudyInstanceUID})
if (isHas) {
this.ctx.model.Dcmtemp.findOneAndUpdate({
_id: isHas._id
}, {
$set: {
host: item.host,
port: item.port,
aet: item.aet,
done: 0,
NumberOfStudyRelatedInstances: item.NumberOfStudyRelatedInstances,
StudyInstanceUID: item.StudyInstanceUID,
status: 0
}
}).exec()
} else {
let params = {
host: item.host,
port: item.port,
aet: item.aet,
done: 0,
NumberOfStudyRelatedInstances: item.NumberOfStudyRelatedInstances,
StudyInstanceUID: item.StudyInstanceUID,
status: 0
}
let m = new this.ctx.model.Dcmtemp(params)
m.save()
}
}
return this.success(result)
} catch (error) {
let msg = error
if (error.message) {
msg = error.message.split('\n')
}
return this.error(msg)
}
}
//查询
async findFromPacs() {
try {
let result = await this.ctx.service.pacs.findFromPacs(this.ctx.request.body)
return this.success(result)
} catch (error) {
let msg = error
if (error.message) {
msg = error.message.split('\n')
}
return this.error(msg)
}
}
//获取下载进度
async percent(){
try {
this.ctx.validate({
task_ids:"array"
})
} catch (error) {
return this.error(error)
}
let { task_ids } = this.ctx.request.body
let result = await this.ctx.model.Status.find({task_id: {$in: task_ids}})
return this.success(result)
}
//下载
async moveFromPacs() {
// 验证数据
try {
this.ctx.validate({
para: "array"
})
} catch (e) {
return this.error(e)
}
let { para } = this.ctx.request.body
try {
for (let i = 0; i < para.length; i++) {
let item = para[i]
let isHas = await this.ctx.model.Dcmtemp.findOne({StudyInstanceUID: item.StudyInstanceUID})
if (isHas) {
this.ctx.model.Dcmtemp.findOneAndUpdate({
_id: isHas._id
}, {
$set: {
host: item.host,
port: item.port,
aet: item.aet,
done: 0,
NumberOfStudyRelatedInstances: item.NumberOfStudyRelatedInstances,
StudyInstanceUID: item.StudyInstanceUID,
status: 0
}
}).exec()
} else {
let params = {
host: item.host,
port: item.port,
aet: item.aet,
done: 0,
NumberOfStudyRelatedInstances: item.NumberOfStudyRelatedInstances,
StudyInstanceUID: item.StudyInstanceUID,
status: 0
}
let m = new this.ctx.model.Dcmtemp(params)
m.save()
}
}
return this.success()
} catch (error) {
return this.error(error)
}
}
//study抽取report
async getLocalPort () {
return this.success({port: this.config.site.PACS_SCP_PORT, aet: this.config.site.PACS_SCP_AET})
}
}
module.exports = PacsController;