pacs直连、检查查询条件新增
continuous-integration/drone/push Build is passing Details

uat_us
DESKTOP-6C3NK6N\WXS 2024-07-23 11:13:20 +08:00
parent 9b6f8717c3
commit 90e33e1b97
3 changed files with 293 additions and 187 deletions

View File

@ -3810,4 +3810,12 @@ export function submitVisitStudyBinding(data) {
data
})
}
// 获取pacs检查技术
export function getDicomModalityList(params) {
return request({
url: `/Patient/getDicomModalityList`,
method: 'get',
params
})
}

View File

@ -40,25 +40,35 @@
>
<span style="float: left">{{ item.VisitName }}</span>
</el-option>
<el-option key="Other" label="Out of Plan" value="1.11" />
</el-select>
</el-form-item>
<el-form-item :label="$t('trials:studyList:table:isFromPacs')">
<el-select v-model="searchData.IsFromPACS" clearable>
<el-option
key="Other"
label="Out of Plan"
value="1.11"
/>
v-for="item of $d.UploadType"
:key="item.id"
:label="item.label"
:value="item.value"
>
</el-option>
</el-select>
</el-form-item>
<el-form-item>
<!-- 查询 -->
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t('common:button:search') }}
{{ $t("common:button:search") }}
</el-button>
<!-- 重置 -->
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }}
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t("common:button:reset") }}
</el-button>
</el-form-item>
</el-form>
</template>
<!-- 检查列表 -->
@ -104,19 +114,31 @@
<!-- Modality,Body Part Examined,Count,Study Date -->
<!-- Study Info -->
<div slot="content">
{{ `${$t('trials:studyList:table:modality')}, ${$t('trials:studyList:table:bodyPart')}, ${$t('trials:studyList:table:studyDate')}, ${$t('trials:studyList:table:count')}` }}
{{
`${$t("trials:studyList:table:modality")}, ${$t(
"trials:studyList:table:bodyPart"
)}, ${$t("trials:studyList:table:studyDate")}, ${$t(
"trials:studyList:table:count"
)}`
}}
</div>
<span>{{ $t('trials:studyList:table:studyInfo') }}</span>
<span>{{ $t("trials:studyList:table:studyInfo") }}</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<div style="display: flex; align-items: center">
<div v-if="scope.row.Modalities">{{ scope.row.Modalities }}({{ scope.row.Count }}), </div>
<div v-else style="color:#f44336;">N/A, </div>
<div v-if="scope.row.Bodypart" style="margin:0 3px;">{{ scope.row.Bodypart }}, </div>
<div v-else style="color:#f44336;margin:0 3px;">N/A, </div>
<div v-if="scope.row.StudyTime">{{ moment(scope.row.StudyTime).format('YYYY-MM-DD') }} </div>
<div v-else style="color:#f44336;">N/A </div>
<div v-if="scope.row.Modalities">
{{ scope.row.Modalities }}({{ scope.row.Count }}),
</div>
<div v-else style="color: #f44336">N/A,</div>
<div v-if="scope.row.Bodypart" style="margin: 0 3px">
{{ scope.row.Bodypart }},
</div>
<div v-else style="color: #f44336; margin: 0 3px">N/A,</div>
<div v-if="scope.row.StudyTime">
{{ moment(scope.row.StudyTime).format("YYYY-MM-DD") }}
</div>
<div v-else style="color: #f44336">N/A</div>
<div>
<!-- <el-popover v-if="scope.row.Count && scope.row.IsDicom" trigger="click" placement="bottom">
<el-table v-loading="seriesLoading" :data="seriesList" height="200" size="small" class="seriesListOfStudy">
@ -174,29 +196,32 @@
</el-button> -->
<!-- <span>({{ scope.row.Count }})</span> -->
<!-- <span v-else style="color:#f44336;">N/A</span> -->
</div>
</div>
</template>
</el-table-column>
<el-table-column
min-width="120"
show-overflow-tooltip
>
<el-table-column min-width="120" show-overflow-tooltip>
<template slot="header">
<el-tooltip placement="top">
<div slot="content">
{{ `${$t('trials:studyList:table:siteId')}, ${$t('trials:studyList:table:siteName')}` }}
{{
`${$t("trials:studyList:table:siteId")}, ${$t(
"trials:studyList:table:siteName"
)}`
}}
</div>
<span>{{ $t('trials:studyList:table:site') }}</span>
<span>{{ $t("trials:studyList:table:site") }}</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span v-if="scope.row.TrialSiteCode">{{ scope.row.TrialSiteCode }}, </span>
<span v-else style="color:#f44336;">N/A, </span>
<span v-if="scope.row.TrialSiteAliasName">{{ scope.row.TrialSiteAliasName }}</span>
<span v-else style="color:#f44336;">N/A</span>
<span v-if="scope.row.TrialSiteCode"
>{{ scope.row.TrialSiteCode }},
</span>
<span v-else style="color: #f44336">N/A, </span>
<span v-if="scope.row.TrialSiteAliasName">{{
scope.row.TrialSiteAliasName
}}</span>
<span v-else style="color: #f44336">N/A</span>
</template>
</el-table-column>
<el-table-column
@ -205,21 +230,22 @@
sortable="custom"
show-overflow-tooltip
/>
<el-table-column
min-width="90"
show-overflow-tooltip
>
<el-table-column min-width="90" show-overflow-tooltip>
<template slot="header">
<el-tooltip placement="top">
<div slot="content">
{{ `${$t('trials:studyList:table:visitName')}, ${$t('trials:studyList:table:visitNum')}` }}<br>
{{
`${$t("trials:studyList:table:visitName")}, ${$t(
"trials:studyList:table:visitNum"
)}`
}}<br />
</div>
<span>{{ $t('trials:studyList:table:visit') }}</span>
<span>{{ $t("trials:studyList:table:visit") }}</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<span v-if="scope.row.VisitName">{{ scope.row.VisitName }}, </span>
<span v-else style="color:#f44336;">N/A, </span>
<span v-else style="color: #f44336">N/A, </span>
<span>{{ scope.row.VisitNum }}</span>
</template>
</el-table-column>
@ -237,8 +263,24 @@
sortable="custom"
min-width="120"
/>
<el-table-column :label="$t('common:action:action')" min-width="100" fixed="right">
<el-table-column
prop="IsFromPACS"
:label="$t('trials:studyList:table:isFromPacs')"
show-overflow-tooltip
sortable="custom"
min-width="120"
>
<template slot-scope="scope">
<el-tag :type="scope.row.IsFromPACS ? 'warning' : ''">
{{ $fd("UploadType", scope.row.IsFromPACS) }}
</el-tag>
</template>
</el-table-column>
<el-table-column
:label="$t('common:action:action')"
min-width="100"
fixed="right"
>
<template slot-scope="scope">
<!-- 查看 -->
<el-button
@ -262,23 +304,32 @@
</el-table>
<!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
<pagination
class="page"
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/>
</template>
<base-model :config="share_model">
<template slot="dialog-body">
<div>
<i style="color:#428bca;" class="el-icon-success" />
<i style="color: #428bca" class="el-icon-success" />
<span>成功创建分享链接</span>
</div>
<div style="margin:10px 0;">
链接<el-input v-model="shareLink" readonly style="width:420px;" />
<div style="margin: 10px 0">
链接<el-input v-model="shareLink" readonly style="width: 420px" />
</div>
<div style="margin-bottom:20px;">
提取码 <el-input v-model="extractionCode" style="width:100px;" readonly />
<div style="margin-bottom: 20px">
提取码
<el-input v-model="extractionCode" style="width: 100px" readonly />
</div>
<div>
<el-button type="primary" round @click="copyCode"></el-button>
<el-button type="primary" round @click="copyCode"
>复制链接及提取码</el-button
>
</div>
</template>
</base-model>
@ -292,11 +343,16 @@
append-to-body
custom-class="base-dialog-wrapper"
>
<div class="base-modal-body" style="border:2px solid #ccc;padding: 10px">
<NonDicomPreview v-if="previewNonDicomVisible" :none-dicom-id="rowData.Id" />
<div
class="base-modal-body"
style="border: 2px solid #ccc; padding: 10px"
>
<NonDicomPreview
v-if="previewNonDicomVisible"
:none-dicom-id="rowData.Id"
/>
</div>
</el-dialog>
</BaseContainer>
</template>
<script>
@ -305,28 +361,28 @@ import {
getTrialSiteSelect,
getSeriesList,
getTrialVisitStageSelect,
getNoneDicomStudyFileList
} from '@/api/trials'
import { createImageShare } from '@/api/share'
import BaseContainer from '@/components/BaseContainer'
import Pagination from '@/components/Pagination'
import BaseModel from '@/components/BaseModel'
import NonDicomPreview from './components/nonDicomPreview'
import moment from 'moment'
import { getToken } from '@/utils/auth'
getNoneDicomStudyFileList,
} from "@/api/trials";
import { createImageShare } from "@/api/share";
import BaseContainer from "@/components/BaseContainer";
import Pagination from "@/components/Pagination";
import BaseModel from "@/components/BaseModel";
import NonDicomPreview from "./components/nonDicomPreview";
import moment from "moment";
import { getToken } from "@/utils/auth";
const searchDataDefault = () => {
return {
SubjectInfo: '',
SubjectInfo: "",
VisitPlanArray: [],
Status: '',
SiteId: '',
IsFromPACS: null,
Status: "",
SiteId: "",
PageIndex: 1,
PageSize: 20
}
}
PageSize: 20,
};
};
export default {
name: 'StudyList',
name: "StudyList",
components: { BaseContainer, Pagination, BaseModel, NonDicomPreview },
data() {
return {
@ -339,195 +395,217 @@ export default {
seriesList: [],
nonDicomfilesList: [],
rowData: {},
userTypeEnumInt: zzSessionStorage.getItem('userTypeEnumInt') * 1,
share_model: { visible: false, title: '影像分享', showClose: true, width: '500px' },
shareLink: '',
extractionCode: '',
userTypeEnumInt: zzSessionStorage.getItem("userTypeEnumInt") * 1,
share_model: {
visible: false,
title: "影像分享",
showClose: true,
width: "500px",
},
shareLink: "",
extractionCode: "",
moment,
filesLoading: '',
seriesLoading: '',
filesLoading: "",
seriesLoading: "",
previewNonDicomVisible: false,
trialId: this.$route.query.trialId,
tokenKey: getToken(),
openWindow: null,
bp: []
}
bp: [],
};
},
async mounted() {
this.bp = await this.$getBodyPart(this.$route.query.trialId)
this.getSite()
this.getVisitPlanOptions()
this.getList()
this.bp = await this.$getBodyPart(this.$route.query.trialId);
this.getSite();
this.getVisitPlanOptions();
this.getList();
},
methods: {
//
getList() {
this.loading = true
this.searchData.TrialId = this.trialId
this.loading = true;
this.searchData.TrialId = this.trialId;
getDicomAndNoneDicomStudyList(this.searchData)
.then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
this.loading = false;
this.list = res.Result.CurrentPageData;
this.total = res.Result.TotalCount;
})
.catch(() => {
this.loading = false
})
this.loading = false;
});
},
// Dicom
handleGetseriesList(row) {
this.seriesLoading = true
this.seriesList = []
getSeriesList(row.Id).then((res) => {
this.seriesLoading = false
this.seriesList = res.Result
}).catch(() => {
this.seriesLoading = false
this.seriesLoading = true;
this.seriesList = [];
getSeriesList(row.Id)
.then((res) => {
this.seriesLoading = false;
this.seriesList = res.Result;
})
.catch(() => {
this.seriesLoading = false;
});
},
// Dicom
handleGetFilesList(id) {
this.filesLoading = true
getNoneDicomStudyFileList(id).then(res => {
this.nonDicomfilesList = res.Result
this.filesLoading = false
}).catch(() => { this.filesLoading = false })
this.filesLoading = true;
getNoneDicomStudyFileList(id)
.then((res) => {
this.nonDicomfilesList = res.Result;
this.filesLoading = false;
})
.catch(() => {
this.filesLoading = false;
});
},
//
handleViewStudy(row) {
if (this.openWindow) {
this.openWindow.close()
this.openWindow.close();
}
if (row.IsDicom) {
const routeData = this.$router.resolve({
path: `/showdicom?studyId=${row.Id}&TokenKey=${this.tokenKey}&type=Study`
})
this.openWindow = window.open(routeData.href, '_blank')
path: `/showdicom?studyId=${row.Id}&TokenKey=${this.tokenKey}&type=Study`,
});
this.openWindow = window.open(routeData.href, "_blank");
} else {
// this.rowData = { ...row }
// this.previewNonDicomVisible = true
let trialId = this.$route.query.trialId
let trialId = this.$route.query.trialId;
const routeData = this.$router.resolve({
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SubjectVisitId}&studyId=${row.Id}&TokenKey=${this.tokenKey}`
})
this.openWindow = window.open(routeData.href, '_blank')
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SubjectVisitId}&studyId=${row.Id}&TokenKey=${this.tokenKey}`,
});
this.openWindow = window.open(routeData.href, "_blank");
}
},
handlePreviewNonDicom(row) {
if (this.openWindow) {
this.openWindow.close()
this.openWindow.close();
}
let trialId = this.$route.query.trialId
let trialId = this.$route.query.trialId;
const routeData = this.$router.resolve({
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SubjectVisitId}&studyId=${row.Id}&TokenKey=${this.tokenKey}`
})
this.openWindow = window.open(routeData.href, '_blank')
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SubjectVisitId}&studyId=${row.Id}&TokenKey=${this.tokenKey}`,
});
this.openWindow = window.open(routeData.href, "_blank");
},
//
handlePreview(row) {
if (this.openWindow) {
this.openWindow.close()
this.openWindow.close();
}
this.openWindow = window.open(row.FullFilePath, '_blank')
this.openWindow = window.open(row.FullFilePath, "_blank");
},
//
studyStatusFormatter(StudyStatus) {
if (StudyStatus === 5) return 'Uploaded'
else if (StudyStatus === 1) return 'Uploading'
else if (StudyStatus === 7) return 'QA Requested'
else if (StudyStatus === 10) return 'In QA'
else if (StudyStatus === 25) return 'QA-Passed'
else if (StudyStatus === 26) return 'QA-Failed'
else if (StudyStatus === 28) return 'Anonymizing'
else if (StudyStatus === 30) return 'Anonymized'
else if (StudyStatus === 32) return 'Anonymizing Failed'
else if (StudyStatus === 34) return 'Forwarding'
else if (StudyStatus === 36) return 'Forwarded'
else if (StudyStatus === 38) return 'Forwarding Failed'
else return ''
if (StudyStatus === 5) return "Uploaded";
else if (StudyStatus === 1) return "Uploading";
else if (StudyStatus === 7) return "QA Requested";
else if (StudyStatus === 10) return "In QA";
else if (StudyStatus === 25) return "QA-Passed";
else if (StudyStatus === 26) return "QA-Failed";
else if (StudyStatus === 28) return "Anonymizing";
else if (StudyStatus === 30) return "Anonymized";
else if (StudyStatus === 32) return "Anonymizing Failed";
else if (StudyStatus === 34) return "Forwarding";
else if (StudyStatus === 36) return "Forwarded";
else if (StudyStatus === 38) return "Forwarding Failed";
else return "";
},
// site
getSite() {
getTrialSiteSelect(this.trialId).then((res) => {
this.siteOptions = res.Result
})
this.siteOptions = res.Result;
});
},
// visit
getVisitPlanOptions() {
getTrialVisitStageSelect(this.trialId)
.then((res) => {
this.visitPlanOptions = res.Result
})
getTrialVisitStageSelect(this.trialId).then((res) => {
this.visitPlanOptions = res.Result;
});
},
//
handleShareImage(row) {
this.shareLink = ''
this.extractionCode = ''
this.shareLink = "";
this.extractionCode = "";
const params = {
TrialId: row.TrialId,
SiteId: row.SiteId,
SubjectId: row.SubjectId,
StudyId: row.Id
}
this.loading = true
createImageShare(params).then((res) => {
this.loading = false
StudyId: row.Id,
};
this.loading = true;
createImageShare(params)
.then((res) => {
this.loading = false;
if (res.IsSuccess) {
// this.shareLink = `${window.location.origin}${window.location.pathname}#/imagesShare?id=${res.Result.ResourceId}`
this.shareLink = `${window.location.origin}/imagesShare?id=${res.Result.ResourceId}`
this.extractionCode = res.Result.Password
this.share_model.visible = true
this.shareLink = `${window.location.origin}/imagesShare?id=${res.Result.ResourceId}`;
this.extractionCode = res.Result.Password;
this.share_model.visible = true;
}
}).catch(() => { this.loading = false })
})
.catch(() => {
this.loading = false;
});
},
getBodyPart(bodyPart) {
if (!bodyPart) return ''
var separator = ','
if (bodyPart.indexOf('|') > -1) {
separator = '|'
} else if (bodyPart.indexOf(',') > -1) {
separator = ','
} else if (bodyPart.indexOf('') > -1) {
separator = ''
if (!bodyPart) return "";
var separator = ",";
if (bodyPart.indexOf("|") > -1) {
separator = "|";
} else if (bodyPart.indexOf(",") > -1) {
separator = ",";
} else if (bodyPart.indexOf("") > -1) {
separator = "";
}
var arr = bodyPart.split(separator)
var newArr = arr.map(i => {
return this.$fd('Bodypart', i.trim(), 'Code', { Bodypart: this.bp }, 'Name')
})
return newArr.join(' | ')
var arr = bodyPart.split(separator);
var newArr = arr.map((i) => {
return this.$fd(
"Bodypart",
i.trim(),
"Code",
{ Bodypart: this.bp },
"Name"
);
});
return newArr.join(" | ");
},
//
copyCode() {
this.$copyText(`链接: ${this.shareLink} 提取码: ${this.extractionCode}`).then(
res => {
this.$message.success('复制成功')
}
).catch(() => { this.$alert('复制失败') })
this.$copyText(`链接: ${this.shareLink} 提取码: ${this.extractionCode}`)
.then((res) => {
this.$message.success("复制成功");
})
.catch(() => {
this.$alert("复制失败");
});
},
onCopyError() {
this.$alert('复制失败')
this.$alert("复制失败");
},
//
handleSearch() {
this.searchData.PageIndex = 1
this.getList()
this.searchData.PageIndex = 1;
this.getList();
},
//
handleReset() {
this.searchData = searchDataDefault()
this.getList()
this.searchData = searchDataDefault();
this.getList();
},
//
handleSortByColumn(column) {
if (column.order === 'ascending') {
this.searchData.Asc = true
if (column.order === "ascending") {
this.searchData.Asc = true;
} else {
this.searchData.Asc = false
}
this.searchData.SortField = column.prop
this.searchData.PageIndex = 1
this.getList()
}
}
this.searchData.Asc = false;
}
this.searchData.SortField = column.prop;
this.searchData.PageIndex = 1;
this.getList();
},
},
};
</script>

View File

@ -26,12 +26,15 @@
"
prop="CalledAE"
>
<el-input
v-model="searchData.Modalities"
size="small"
clearable
style="width: 150px"
/>
<el-select v-model="searchData.Modalities" clearable>
<el-option
v-for="item of DicomModalityList"
:key="item"
:label="item"
:value="item"
>
</el-option>
</el-select>
</el-form-item>
<!--检查日期-->
<el-form-item
@ -225,6 +228,7 @@
import {
getVisitPatientStudyFilterList,
submitVisitStudyBinding,
getDicomModalityList,
} from "@/api/trials";
import BaseContainer from "@/components/BaseContainer";
import Pagination from "@/components/Pagination";
@ -262,12 +266,28 @@ export default {
loading: false,
datetimerange: [],
tableSelectData: [],
DicomModalityList: [],
};
},
mounted() {
created() {
this.getList();
this.getDicomModalityList();
},
methods: {
//
async getDicomModalityList() {
try {
let params = {
TrialId: this.$route.query.trialId,
};
let res = await getDicomModalityList(params);
if (res.IsSuccess) {
this.DicomModalityList = res.Result;
}
} catch (err) {
console.log(err);
}
},
handleAddList() {
if (this.tableSelectData.length < 0)
return this.$message.warning(