Merge branch 'main' of https://gitea.frp.extimaging.com/XCKJ/hir_web into main
continuous-integration/drone/push Build is failing Details

main
caiyiling 2024-11-14 16:36:58 +08:00
commit b317344d73
8 changed files with 999 additions and 348 deletions

View File

@ -44,6 +44,7 @@
"jszip": "^3.7.1",
"moment": "^2.27.0",
"node-polyfill-webpack-plugin": "^2.0.1",
"streamsaver": "^2.0.6",
"node-sass": "^4.14.1",
"normalize.css": "7.0.0",
"nprogress": "0.2.0",

167
public/mitm.html Normal file
View File

@ -0,0 +1,167 @@
<!--
mitm.html is the lite "man in the middle"
This is only meant to signal the opener's messageChannel to
the service worker - when that is done this mitm can be closed
but it's better to keep it alive since this also stops the sw
from restarting
The service worker is capable of intercepting all request and fork their
own "fake" response - wish we are going to craft
when the worker then receives a stream then the worker will tell the opener
to open up a link that will start the download
-->
<script>
// This will prevent the sw from restarting
let keepAlive = () => {
keepAlive = () => {}
var ping = location.href.substr(0, location.href.lastIndexOf('/')) + '/ping'
var interval = setInterval(() => {
if (sw) {
sw.postMessage('ping')
} else {
fetch(ping).then(res => res.text(!res.ok && clearInterval(interval)))
}
}, 10000)
}
// message event is the first thing we need to setup a listner for
// don't want the opener to do a random timeout - instead they can listen for
// the ready event
// but since we need to wait for the Service Worker registration, we store the
// message for later
let messages = []
window.onmessage = evt => messages.push(evt)
let sw = null
let scope = ''
function registerWorker() {
return navigator.serviceWorker.getRegistration('./').then(swReg => {
return swReg || navigator.serviceWorker.register('sw.js', { scope: './' })
}).then(swReg => {
const swRegTmp = swReg.installing || swReg.waiting
scope = swReg.scope
return (sw = swReg.active) || new Promise(resolve => {
swRegTmp.addEventListener('statechange', fn = () => {
if (swRegTmp.state === 'activated') {
swRegTmp.removeEventListener('statechange', fn)
sw = swReg.active
resolve()
}
})
})
})
}
// Now that we have the Service Worker registered we can process messages
function onMessage (event) {
let { data, ports, origin } = event
// It's important to have a messageChannel, don't want to interfere
// with other simultaneous downloads
if (!ports || !ports.length) {
throw new TypeError("[StreamSaver] You didn't send a messageChannel")
}
if (typeof data !== 'object') {
throw new TypeError("[StreamSaver] You didn't send a object")
}
// the default public service worker for StreamSaver is shared among others.
// so all download links needs to be prefixed to avoid any other conflict
data.origin = origin
// if we ever (in some feature versoin of streamsaver) would like to
// redirect back to the page of who initiated a http request
data.referrer = data.referrer || document.referrer || origin
// pass along version for possible backwards compatibility in sw.js
data.streamSaverVersion = new URLSearchParams(location.search).get('version')
if (data.streamSaverVersion === '1.2.0') {
console.warn('[StreamSaver] please update streamsaver')
}
/** @since v2.0.0 */
if (!data.headers) {
console.warn("[StreamSaver] pass `data.headers` that you would like to pass along to the service worker\nit should be a 2D array or a key/val object that fetch's Headers api accepts")
} else {
// test if it's correct
// should thorw a typeError if not
new Headers(data.headers)
}
/** @since v2.0.0 */
if (typeof data.filename === 'string') {
console.warn("[StreamSaver] You shouldn't send `data.filename` anymore. It should be included in the Content-Disposition header option")
// Do what File constructor do with fileNames
data.filename = data.filename.replace(/\//g, ':')
}
/** @since v2.0.0 */
if (data.size) {
console.warn("[StreamSaver] You shouldn't send `data.size` anymore. It should be included in the content-length header option")
}
/** @since v2.0.0 */
if (data.readableStream) {
console.warn("[StreamSaver] You should send the readableStream in the messageChannel, not throught mitm")
}
/** @since v2.0.0 */
if (!data.pathname) {
console.warn("[StreamSaver] Please send `data.pathname` (eg: /pictures/summer.jpg)")
data.pathname = Math.random().toString().slice(-6) + '/' + data.filename
}
// remove all leading slashes
data.pathname = data.pathname.replace(/^\/+/g, '')
// remove protocol
let org = origin.replace(/(^\w+:|^)\/\//, '')
// set the absolute pathname to the download url.
data.url = new URL(`${scope + org}/${data.pathname}`).toString()
if (!data.url.startsWith(`${scope + org}/`)) {
throw new TypeError('[StreamSaver] bad `data.pathname`')
}
// This sends the message data as well as transferring
// messageChannel.port2 to the service worker. The service worker can
// then use the transferred port to reply via postMessage(), which
// will in turn trigger the onmessage handler on messageChannel.port1.
const transferable = data.readableStream
? [ ports[0], data.readableStream ]
: [ ports[0] ]
if (!(data.readableStream || data.transferringReadable)) {
keepAlive()
}
return sw.postMessage(data, transferable)
}
if (window.opener) {
// The opener can't listen to onload event, so we need to help em out!
// (telling them that we are ready to accept postMessage's)
window.opener.postMessage('StreamSaver::loadedPopup', '*')
}
if (navigator.serviceWorker) {
registerWorker().then(() => {
window.onmessage = onMessage
messages.forEach(window.onmessage)
})
}
// FF v102 just started to supports transferable streams, but still needs to ping sw.js
// even tough the service worker dose not have to do any kind of work and listen to any
// messages... #305
keepAlive()
</script>

130
public/sw.js Normal file
View File

@ -0,0 +1,130 @@
/* global self ReadableStream Response */
self.addEventListener('install', () => {
self.skipWaiting()
})
self.addEventListener('activate', event => {
event.waitUntil(self.clients.claim())
})
const map = new Map()
// This should be called once per download
// Each event has a dataChannel that the data will be piped through
self.onmessage = event => {
// We send a heartbeat every x second to keep the
// service worker alive if a transferable stream is not sent
if (event.data === 'ping') {
return
}
const data = event.data
const downloadUrl = data.url || self.registration.scope + Math.random() + '/' + (typeof data === 'string' ? data : data.filename)
const port = event.ports[0]
const metadata = new Array(3) // [stream, data, port]
metadata[1] = data
metadata[2] = port
// Note to self:
// old streamsaver v1.2.0 might still use `readableStream`...
// but v2.0.0 will always transfer the stream through MessageChannel #94
if (event.data.readableStream) {
metadata[0] = event.data.readableStream
} else if (event.data.transferringReadable) {
port.onmessage = evt => {
port.onmessage = null
metadata[0] = evt.data.readableStream
}
} else {
metadata[0] = createStream(port)
}
map.set(downloadUrl, metadata)
port.postMessage({ download: downloadUrl })
}
function createStream (port) {
// ReadableStream is only supported by chrome 52
return new ReadableStream({
start (controller) {
// When we receive data on the messageChannel, we write
port.onmessage = ({ data }) => {
if (data === 'end') {
return controller.close()
}
if (data === 'abort') {
controller.error('Aborted the download')
return
}
controller.enqueue(data)
}
},
cancel (reason) {
console.log('user aborted', reason)
port.postMessage({ abort: true })
}
})
}
self.onfetch = event => {
const url = event.request.url
// this only works for Firefox
if (url.endsWith('/ping')) {
return event.respondWith(new Response('pong'))
}
const hijacke = map.get(url)
if (!hijacke) return null
const [ stream, data, port ] = hijacke
map.delete(url)
// Not comfortable letting any user control all headers
// so we only copy over the length & disposition
const responseHeaders = new Headers({
'Content-Type': 'application/octet-stream; charset=utf-8',
// To be on the safe side, The link can be opened in a iframe.
// but octet-stream should stop it.
'Content-Security-Policy': "default-src 'none'",
'X-Content-Security-Policy': "default-src 'none'",
'X-WebKit-CSP': "default-src 'none'",
'X-XSS-Protection': '1; mode=block',
'Cross-Origin-Embedder-Policy': 'require-corp'
})
let headers = new Headers(data.headers || {})
if (headers.has('Content-Length')) {
responseHeaders.set('Content-Length', headers.get('Content-Length'))
}
if (headers.has('Content-Disposition')) {
responseHeaders.set('Content-Disposition', headers.get('Content-Disposition'))
}
// data, data.filename and size should not be used anymore
if (data.size) {
console.warn('Depricated')
responseHeaders.set('Content-Length', data.size)
}
let fileName = typeof data === 'string' ? data : data.filename
if (fileName) {
console.warn('Depricated')
// Make filename RFC5987 compatible
fileName = encodeURIComponent(fileName).replace(/['()]/g, escape).replace(/\*/g, '%2A')
responseHeaders.set('Content-Disposition', "attachment; filename*=UTF-8''" + fileName)
}
event.respondWith(new Response(stream, { headers: responseHeaders }))
port.postMessage({ debug: 'Download started' })
}

View File

@ -3610,4 +3610,21 @@ export function getAuthorizationCodeInfo(params) {
method: 'get',
params
})
}
// 获取下载信息
export function getDownloadSubjectVisitStudyInfo(params) {
return request({
url: `/Patient/getDownloadSubjectVisitStudyInfo`,
method: 'get',
params
})
}
// 下载成功回调
export function downloadImageSuccess(params) {
return request({
url: `/Patient/downloadImageSuccess`,
method: 'get',
params
})
}

106
src/utils/stream.js Normal file
View File

@ -0,0 +1,106 @@
import streamSaver from "streamsaver";
import "streamsaver/examples/zip-stream.js";
// import store from '@/store'
streamSaver.mitm = `${window.location.origin}/mitm.html?version=2.0.0`
// 下载文件并压缩
function zipFiles(zipName, files) {
return new Promise((resolve) => {
try {
console.log("同步下载打包开始时间:" + new Date());
// store.dispatch('trials/setUnLock', true)
files = formatFiles(files)
// 创建压缩文件输出流
const zipFileOutputStream = streamSaver.createWriteStream(zipName);
// 创建下载文件流
const fileIterator = files.values();
const readableZipStream = new ZIP({
async pull(ctrl) {
const fileInfo = fileIterator.next();
if (fileInfo.done) {//迭代终止
ctrl.close();
} else {
let { name, url } = fileInfo.value;
url = decodeUtf8(url);
return fetch(url).then(res => {
ctrl.enqueue({
name,
stream: () => res.body
});
})
}
}
});
if (window.WritableStream && readableZipStream.pipeTo) {
// 开始下载
readableZipStream
.pipeTo(zipFileOutputStream)
.then(() => {
console.log("同步下载打包结束时间:" + new Date());
// store.dispatch('trials/setUnLock', false)
resolve(true)
}).catch(err => {
console.log(err);
resolve(false)
});
} else {
resolve(false)
}
} catch (err) {
console.log(err);
resolve(false)
}
})
}
// 下载文件并修改名称
async function updateFile(file, name) {
return new Promise(async resolve => {
try {
// store.dispatch('trials/setUnLock', true)
const fileOutputStream = streamSaver.createWriteStream(name);
file = decodeUtf8(file);
let res = await fetch(file);
res.body.pipeTo(fileOutputStream).then(() => {
// store.dispatch('trials/setUnLock', true)
resolve(true)
}).catch(err => {
console.log(err)
resolve(false)
});
} catch (err) {
console.log(err)
resolve(false)
}
})
}
// 同名文件修改名称
function formatFiles(files) {
let fileObj = {};
files.forEach(file => {
let arr = Object.keys(fileObj);
if (!~arr.indexOf(file.name)) {
fileObj[file.name] = 1;
} else {
let name = file.name;
file.name = name.split(".")[0] + `(${fileObj[name]})` + name
.substring(name.lastIndexOf('.'))
.toLocaleLowerCase()
fileObj[name]++;
}
})
return files;
}
function decodeUtf8(bytes) {
let str = bytes.split('?');
let str2 = str[0].split('/');
let name = str2[str2.length - 1];
name = encodeURIComponent(name);
str.shift();
str2.pop();
return str2.join("/") + '/' + name;
}
export async function downLoadFile(file, name, type = 'file') {
if (type === 'zip') return await zipFiles(name, file);
return await updateFile(file, name)
}

View File

@ -83,7 +83,7 @@
<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
@ -91,7 +91,7 @@
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t("common:button:reset") }}
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
@ -164,7 +164,7 @@
sortable="custom"
>
<template slot-scope="scope">
<span>{{ $fd("sex", scope.row.SubjectSex) }}</span>
<span>{{ $fd('sex', scope.row.SubjectSex) }}</span>
</template>
</el-table-column>
<!-- 访视名称 -->
@ -213,12 +213,12 @@
? 'danger'
: ''
"
>{{ $fd("SubmitState", Number(scope.row.SubmitState)) }}</el-tag
>{{ $fd('SubmitState', Number(scope.row.SubmitState)) }}</el-tag
>
</template>
</el-table-column>
<!-- 打包状态 -->
<el-table-column
<!-- <el-table-column
prop="PackState"
:label="$t('trials:hirVisit:table:PackState')"
show-overflow-tooltip
@ -238,7 +238,7 @@
>{{ $fd("PackState", Number(scope.row.PackState)) }}</el-tag
>
</template>
</el-table-column>
</el-table-column> -->
<!-- 提交时间 -->
<el-table-column
prop="SubmitTime"
@ -296,10 +296,11 @@
<el-button
v-hasPermi="['trials:trials-panel:hirVisit:download']"
circle
:loading="downloading"
icon="el-icon-download"
:disabled="Number(scope.row.SubmitState) !== 2"
:title="$t('trials:reading:button:download')"
@click="downloadImage(scope.row)"
@click="getDownloadSubjectVisitStudyInfo(scope.row)"
/>
</template>
</el-table-column>
@ -330,14 +331,18 @@
</BaseContainer>
</template>
<script>
import BaseContainer from "@/components/BaseContainer";
import Pagination from "@/components/Pagination";
import editStudyList from "./components/edit-study-list.vue";
import visitInfo from "./components/visit-info.vue";
import { deleteSubjectVisit } from "@/api/trials";
import { getPatientSubejctVisitList } from "@/api/trials/visit.js";
import { submitVisitStudyBinding } from "@/api/inspection.js";
import { downloadImage } from "@/utils/uploadZip.js";
import BaseContainer from '@/components/BaseContainer'
import Pagination from '@/components/Pagination'
import editStudyList from './components/edit-study-list.vue'
import visitInfo from './components/visit-info.vue'
import { deleteSubjectVisit } from '@/api/trials'
import { getPatientSubejctVisitList } from '@/api/trials/visit.js'
import { submitVisitStudyBinding } from '@/api/inspection.js'
import { downLoadFile } from '@/utils/stream.js'
import {
getDownloadSubjectVisitStudyInfo,
downloadImageSuccess,
} from '@/api/trials.js'
const defaultSearchData = () => {
return {
subjectCode: null,
@ -346,7 +351,7 @@ const defaultSearchData = () => {
pageIndex: 1,
pageSize: 20,
asc: true,
sortField: "",
sortField: '',
SubmitState: null,
PatientName: null,
PatientIdStr: null,
@ -354,10 +359,10 @@ const defaultSearchData = () => {
BeginStudyTime: null,
EndStudyTime: null,
VisitName: null,
};
};
}
}
export default {
name: "hirVisit",
name: 'hirVisit',
components: {
BaseContainer,
Pagination,
@ -380,143 +385,213 @@ export default {
// 访
visitVisible: false,
rowData: {},
};
//
downloading: false,
downloadId: null,
}
},
created() {
if (zzSessionStorage.getItem("SubjectCode")) {
this.searchData.SubjectCode = zzSessionStorage.getItem("SubjectCode");
zzSessionStorage.removeItem("SubjectCode");
if (zzSessionStorage.getItem('SubjectCode')) {
this.searchData.SubjectCode = zzSessionStorage.getItem('SubjectCode')
zzSessionStorage.removeItem('SubjectCode')
}
this.getList();
this.getList()
},
methods: {
//
handleSearch() {
this.getList();
this.getList()
},
//
handleReset() {
this.searchData = defaultSearchData();
this.$refs.visitList.clearSort();
this.dateValue = [];
this.getList();
this.searchData = defaultSearchData()
this.$refs.visitList.clearSort()
this.dateValue = []
this.getList()
},
//
handleSortByColumn(sort) {
this.searchData.SortField = sort.prop;
if (sort.order === "ascending") this.searchData.Asc = true;
if (sort.order === "descending") this.searchData.Asc = false;
if (!sort.order) this.searchData.SortField = null;
this.getList();
this.searchData.SortField = sort.prop
if (sort.order === 'ascending') this.searchData.Asc = true
if (sort.order === 'descending') this.searchData.Asc = false
if (!sort.order) this.searchData.SortField = null
this.getList()
},
//
async getList() {
let data = {};
let data = {}
Object.keys(this.searchData).forEach((key) => {
data[key] = this.searchData[key];
});
data.TrialId = this.$route.query.trialId;
data[key] = this.searchData[key]
})
data.TrialId = this.$route.query.trialId
if (this.dateValue && this.dateValue[0] && this.dateValue[1]) {
data.BeginStudyTime = this.$moment(this.dateValue[0]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
data.EndStudyTime = this.$moment(this.dateValue[1]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
} else {
data.BeginStudyTime = null;
data.EndStudyTime = null;
data.BeginStudyTime = null
data.EndStudyTime = null
}
try {
this.loading = true;
let res = await getPatientSubejctVisitList(data);
this.loading = false;
this.loading = true
let res = await getPatientSubejctVisitList(data)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result.CurrentPageData;
this.total = res.Result.TotalCount;
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}
} catch (err) {
this.loading = false;
console.log(err);
this.loading = false
console.log(err)
}
},
// 访
handleOpenStudyDialog(row) {
this.visitVisible = true;
this.rowData = { ...row };
this.visitVisible = true
this.rowData = { ...row }
},
//
editStudy(item) {
this.editStudyData = item;
this.editStudyVisible = true;
this.editStudyData = item
this.editStudyVisible = true
},
//
async submit(item) {
let confirm = await this.$confirm(
this.$t("trials:adjustRecord:message:confirm"),
this.$t('trials:adjustRecord:message:confirm'),
{
type: "warning",
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: this.$t("common:button:confirm"),
cancelButtonText: this.$t("recompose:button:cancel"),
confirmButtonText: this.$t('common:button:confirm'),
cancelButtonText: this.$t('recompose:button:cancel'),
}
);
if (confirm !== "confirm") return;
)
if (confirm !== 'confirm') return
let data = {
TrialId: this.$route.query.trialId,
SubjectVisitIdList: [item.SubjectVisitId],
SubjectId: item.SubjectId,
};
}
try {
this.loading = true;
let res = await submitVisitStudyBinding(data);
this.loading = false;
this.loading = true
let res = await submitVisitStudyBinding(data)
this.loading = false
if (res.IsSuccess) {
this.$message.success(
this.$t("trials:crcUpload:message:submittedSuccessfully")
);
this.getList();
this.$t('trials:crcUpload:message:submittedSuccessfully')
)
this.getList()
}
} catch (err) {
this.loading = false;
console.log(err);
this.loading = false
console.log(err)
}
},
//
async remove(row) {
try {
let confirm = await this.$confirm(
this.$t("trials:crcUpload:message:deleteVisit"),
this.$t('trials:crcUpload:message:deleteVisit'),
{
type: "warning",
type: 'warning',
distinguishCancelAndClose: true,
}
);
if (confirm !== "confirm") return;
)
if (confirm !== 'confirm') return
let res = await deleteSubjectVisit(
this.$route.query.trialId,
row.SubjectVisitId
);
)
if (res.IsSuccess) {
this.getList();
this.getList()
this.$message.success(
this.$t("trials:crcUpload:message:deleteVisitSuccessfully")
);
this.$t('trials:crcUpload:message:deleteVisitSuccessfully')
)
}
} catch (err) {
console.log(err);
console.log(err)
}
},
//
async downloadImage(item) {
let res = await downloadImage(
this.$route.query.trialId,
item.SubjectVisitId
);
if (res) {
item.PackState = res;
//
async getDownloadSubjectVisitStudyInfo(row) {
if (this.downloading) return
try {
let data = {
SubjectVisitId: row.SubjectVisitId,
TrialId: this.$route.query.trialId,
}
this.downloading = true
let res = await getDownloadSubjectVisitStudyInfo(data)
this.downloading = false
if (res.IsSuccess) {
this.downloadId = res.OtherInfo
this.downloadImage(res.Result)
}
} catch (err) {
this.downloading = false
console.log(err)
}
},
//
async downloadImage(data) {
try {
let { files, name } = this.formatDownloadFile(data)
let res = await downLoadFile(files, name, 'zip')
if (res && this.downloadId) {
this.downloadImageSuccess()
}
} catch (err) {
console.log(err)
}
},
//
formatDownloadFile(data) {
let files = [],
name = `${data.SubjectCode}_${data.VisitName}_ImageStudy.zip`
if (Array.isArray(data.StudyList) && data.StudyList.length > 0) {
data.StudyList.forEach((study) => {
if (Array.isArray(study.SeriesList) && study.SeriesList.length > 0) {
study.SeriesList.forEach((series) => {
if (
Array.isArray(series.InstanceList) &&
series.InstanceList.length > 0
) {
series.InstanceList.forEach((instance) => {
let fileName = instance.Path.split('/').pop()
let obj = {
name: `${data.SubjectCode}_${data.VisitName}/${
study.StudyCode
}_${study.StudyTime.split(' ')[0]}_${
series.Modality
}/${fileName}`,
url: this.OSSclientConfig.basePath + instance.Path,
}
files.push(obj)
})
}
})
}
})
}
return { files, name }
},
//
async downloadImageSuccess() {
try {
let params = {
TrialImageDownloadId: this.downloadId,
}
await downloadImageSuccess(params)
} catch (err) {
console.log(err)
}
},
},
};
}
</script>

View File

@ -122,7 +122,7 @@
icon="el-icon-search"
@click="handleSearch"
>
{{ $t("common:button:search") }}
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button
@ -130,7 +130,7 @@
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t("common:button:reset") }}
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
@ -205,19 +205,19 @@
>
<template slot-scope="scope">
<el-tag v-if="scope.row.TaskState === 0" type="primary">{{
$fd("TaskState", scope.row.TaskState)
$fd('TaskState', scope.row.TaskState)
}}</el-tag>
<el-tag v-if="scope.row.TaskState === 1" type="info">{{
$fd("TaskState", scope.row.TaskState)
$fd('TaskState', scope.row.TaskState)
}}</el-tag>
<el-tag v-if="scope.row.TaskState === 3" type="danger">{{
$fd("TaskState", scope.row.TaskState)
$fd('TaskState', scope.row.TaskState)
}}</el-tag>
<el-tag v-if="scope.row.TaskState === 4" type="warning">{{
$fd("TaskState", scope.row.TaskState)
$fd('TaskState', scope.row.TaskState)
}}</el-tag>
<el-tag v-if="scope.row.TaskState === 5" type="danger">{{
$fd("TaskState", scope.row.TaskState)
$fd('TaskState', scope.row.TaskState)
}}</el-tag>
</template>
</el-table-column>
@ -253,7 +253,7 @@
show-overflow-tooltip
/>
<!-- 打包状态 -->
<el-table-column
<!-- <el-table-column
prop="PackState"
:label="$t('trials:hirVisit:table:PackState')"
show-overflow-tooltip
@ -269,11 +269,11 @@
: 'success'
"
>{{
$fd("PackState", Number(scope.row.PackState) || 0)
$fd('PackState', Number(scope.row.PackState) || 0)
}}</el-tag
>
</template>
</el-table-column>
</el-table-column> -->
<!-- 申请状态 -->
<!-- <el-table-column
v-if="!hasPermi(['role:air'])"
@ -348,8 +348,14 @@
circle
v-hasPermi="['trials:readTask:report']"
icon="el-icon-download"
:loading="downloading"
:title="$t('trials:reading:button:uploadImages')"
@click="handleCommand('downloadImage', scope.row)"
@click="
handleCommand(
'getDownloadSubjectVisitStudyInfo',
scope.row
)
"
/>
</template>
</el-table-column>
@ -385,7 +391,7 @@
>
<!-- 申请原因 -->
<el-divider content-position="left">{{
$t("trials:readTask:title:applyReason")
$t('trials:readTask:title:applyReason')
}}</el-divider>
<!-- 申请原因 -->
<el-form-item
@ -398,11 +404,11 @@
<el-radio-group v-model="ApplyforReasonForm.Type">
<!-- 阅片记录错误 -->
<el-radio :label="1">{{
$t("trials:readTask:option:errorRecords")
$t('trials:readTask:option:errorRecords')
}}</el-radio>
<!-- 其他 -->
<el-radio :label="2">{{
$t("trials:readTask:option:other")
$t('trials:readTask:option:other')
}}</el-radio>
</el-radio-group>
</el-form-item>
@ -442,7 +448,7 @@
</el-form>
<!-- 影响的任务列表 -->
<el-divider content-position="left">{{
$t("trials:readTask:title:influenceList")
$t('trials:readTask:title:influenceList')
}}</el-divider>
<div
style="
@ -513,19 +519,19 @@
>
<template slot-scope="scope">
<el-tag v-if="scope.row.TaskState === 0" type="primary">{{
$fd("TaskState", scope.row.TaskState)
$fd('TaskState', scope.row.TaskState)
}}</el-tag>
<el-tag v-if="scope.row.TaskState === 1" type="info">{{
$fd("TaskState", scope.row.TaskState)
$fd('TaskState', scope.row.TaskState)
}}</el-tag>
<el-tag v-if="scope.row.TaskState === 3" type="danger">{{
$fd("TaskState", scope.row.TaskState)
$fd('TaskState', scope.row.TaskState)
}}</el-tag>
<el-tag v-if="scope.row.TaskState === 4" type="warning">{{
$fd("TaskState", scope.row.TaskState)
$fd('TaskState', scope.row.TaskState)
}}</el-tag>
<el-tag v-if="scope.row.TaskState === 5" type="danger">{{
$fd("TaskState", scope.row.TaskState)
$fd('TaskState', scope.row.TaskState)
}}</el-tag>
</template>
</el-table-column>
@ -560,10 +566,10 @@
>
<template slot-scope="scope">
<el-tag v-if="scope.row.ReadingTaskState === 2" type="primary">{{
$fd("ReadingTaskState", scope.row.ReadingTaskState)
$fd('ReadingTaskState', scope.row.ReadingTaskState)
}}</el-tag>
<el-tag v-else type="danger">{{
$fd("ReadingTaskState", scope.row.ReadingTaskState)
$fd('ReadingTaskState', scope.row.ReadingTaskState)
}}</el-tag>
</template>
</el-table-column>
@ -576,13 +582,13 @@
>
<template slot-scope="scope">
<el-tag v-if="scope.row.OptType === 0" type="primary">{{
$fd("ReReadingOrBackOptType", scope.row.OptType)
$fd('ReReadingOrBackOptType', scope.row.OptType)
}}</el-tag>
<el-tag v-if="scope.row.OptType === 1" type="danger">{{
$fd("ReReadingOrBackOptType", scope.row.OptType)
$fd('ReReadingOrBackOptType', scope.row.OptType)
}}</el-tag>
<el-tag v-if="scope.row.OptType === 2" type="warning">{{
$fd("ReReadingOrBackOptType", scope.row.OptType)
$fd('ReReadingOrBackOptType', scope.row.OptType)
}}</el-tag>
</template>
</el-table-column>
@ -608,11 +614,11 @@
size="small"
type="primary"
@click="
ApplyforReasonVisible = false;
ApplyforReasonForm = { Type: null, RequestReReadingReason: null };
ApplyforReasonVisible = false
ApplyforReasonForm = { Type: null, RequestReReadingReason: null }
"
>
{{ $t("common:button:cancel") }}
{{ $t('common:button:cancel') }}
</el-button>
<!-- 保存 -->
<el-button
@ -621,7 +627,7 @@
type="primary"
@click="applyReReading"
>
{{ $t("common:button:save") }}
{{ $t('common:button:save') }}
</el-button>
</div>
</el-dialog>
@ -643,25 +649,29 @@
</BaseContainer>
</template>
<script>
import { getIRHaveReadTaskList, aIRReReading } from "@/api/trials";
import { getIRHaveReadTaskList, aIRReReading } from '@/api/trials'
import {
applyReReading,
getReReadingOrBackInfluenceTaskList,
getTrialCriterionList,
} from "@/api/trials/reading";
} from '@/api/trials/reading'
import BaseContainer from "@/components/BaseContainer";
import Pagination from "@/components/Pagination";
import ChatForm from "./components/ChatForm";
import { getToken } from "@/utils/auth";
import { showReadReport } from "@/api/export";
import { downloadImage } from "@/utils/uploadZip.js";
import BaseContainer from '@/components/BaseContainer'
import Pagination from '@/components/Pagination'
import ChatForm from './components/ChatForm'
import { getToken } from '@/utils/auth'
import { showReadReport } from '@/api/export'
import { downLoadFile } from '@/utils/stream.js'
import {
getDownloadSubjectVisitStudyInfo,
downloadImageSuccess,
} from '@/api/trials.js'
const searchDataDefault = () => {
return {
SubjectCode: "",
SubjectCode: '',
PatientIdStr: null,
PatientName: null,
SortField: "",
SortField: '',
PageIndex: 1,
PageSize: 20,
TaskState: null,
@ -670,10 +680,10 @@ const searchDataDefault = () => {
TaskName: null,
BeginSignDate: null,
EndSignDate: null,
};
};
}
}
export default {
name: "ReadTask",
name: 'ReadTask',
components: { BaseContainer, Pagination, ChatForm },
data() {
return {
@ -683,7 +693,7 @@ export default {
total: 0,
loading: false,
btnLoading: false,
trialId: "",
trialId: '',
ApplyforReasonVisible: false,
ApplyforReasonForm: {
Type: null,
@ -696,149 +706,218 @@ export default {
Type: [
{
required: true,
message: this.$t("common:ruleMessage:specify"),
trigger: "blur",
message: this.$t('common:ruleMessage:specify'),
trigger: 'blur',
},
],
IsCopyOrigenalForms: [
{
required: true,
message: this.$t("common:ruleMessage:specify"),
trigger: "blur",
message: this.$t('common:ruleMessage:specify'),
trigger: 'blur',
},
],
RequestReReadingReason: [
{
required: true,
message: this.$t("common:ruleMessage:specify"),
trigger: "blur",
message: this.$t('common:ruleMessage:specify'),
trigger: 'blur',
},
],
},
trialCriterionList: [],
TrialReadingCriterionId: "0",
TrialReadingCriterionId: '0',
openWindow: null,
auditRecordVisible: false,
reportFlag: {},
};
//
downloading: false,
downloadId: null,
}
},
watch: {
TrialReadingCriterionId(v) {
if (v) {
this.getList();
this.getList()
}
},
},
mounted() {
this.trialId = this.$route.query.trialId;
this.getTrialCriterionList();
this.trialId = this.$route.query.trialId
this.getTrialCriterionList()
},
beforeDestroy() {
if (this.openWindow) {
this.openWindow.close();
this.openWindow.close()
}
},
methods: {
//
handleCommand(command, item) {
this[command](item);
this[command](item)
},
//
async showReport(item) {
if (this.reportFlag[item.Id]) return;
if (this.reportFlag[item.Id]) return
let data = {
VisitTaskId: item.Id,
};
}
try {
if (!this.reportFlag.hasOwnProperty(item.Id)) {
this.$set(this.reportFlag, item.Id, true);
this.$set(this.reportFlag, item.Id, true)
}
if (!this.reportFlag[item.Id]) {
this.reportFlag[item.Id] = true;
this.reportFlag[item.Id] = true
}
let res = await showReadReport(data);
let res = await showReadReport(data)
if (res.IsSuccess) {
let a = document.createElement("a");
let href = this.OSSclientConfig.basePath + res.Result;
let fileName =
res.Result.split("/")[res.Result.split("/").length - 1];
a.download = fileName;
a.href = href;
a.click();
URL.revokeObjectURL(href);
let a = document.createElement('a')
let href = this.OSSclientConfig.basePath + res.Result
let fileName = res.Result.split('/')[res.Result.split('/').length - 1]
a.download = fileName
a.href = href
a.click()
URL.revokeObjectURL(href)
this.$nextTick(() => {
a = null;
href = null;
});
a = null
href = null
})
}
this.reportFlag[item.Id] = false;
this.reportFlag[item.Id] = false
} catch (err) {
this.reportFlag[item.Id] = false;
console.log(err);
this.reportFlag[item.Id] = false
console.log(err)
}
},
//
async downloadImage(item) {
let res = await downloadImage(
this.$route.query.trialId,
item.SourceSubjectVisitId
);
if (res) {
item.PackState = res;
//
async getDownloadSubjectVisitStudyInfo(row) {
if (this.downloading) return
try {
let data = {
SubjectVisitId: row.SourceSubjectVisitId,
TrialId: this.$route.query.trialId,
}
this.downloading = true
let res = await getDownloadSubjectVisitStudyInfo(data)
this.downloading = false
if (res.IsSuccess) {
this.downloadId = res.OtherInfo
this.downloadImage(res.Result)
}
} catch (err) {
this.downloading = false
console.log(err)
}
},
//
async downloadImage(data) {
try {
let { files, name } = this.formatDownloadFile(data)
let res = await downLoadFile(files, name, 'zip')
if (res && this.downloadId) {
this.downloadImageSuccess()
}
} catch (err) {
console.log(err)
}
},
//
formatDownloadFile(data) {
let files = [],
name = `${data.SubjectCode}_${data.VisitName}_ImageStudy.zip`
if (Array.isArray(data.StudyList) && data.StudyList.length > 0) {
data.StudyList.forEach((study) => {
if (Array.isArray(study.SeriesList) && study.SeriesList.length > 0) {
study.SeriesList.forEach((series) => {
if (
Array.isArray(series.InstanceList) &&
series.InstanceList.length > 0
) {
series.InstanceList.forEach((instance) => {
let fileName = instance.Path.split('/').pop()
let obj = {
name: `${data.SubjectCode}_${data.VisitName}/${
study.StudyCode
}_${study.StudyTime.split(' ')[0]}_${
series.Modality
}/${fileName}`,
url: this.OSSclientConfig.basePath + instance.Path,
}
files.push(obj)
})
}
})
}
})
}
return { files, name }
},
//
async downloadImageSuccess() {
try {
let params = {
TrialImageDownloadId: this.downloadId,
}
await downloadImageSuccess(params)
} catch (err) {
console.log(err)
}
},
getTrialCriterionList() {
getTrialCriterionList(this.trialId)
.then((res) => {
this.trialCriterionList = res.Result;
this.trialCriterionList = res.Result
this.TrialReadingCriterionId =
this.trialCriterionList[0].TrialReadingCriterionId;
this.trialCriterionList[0].TrialReadingCriterionId
})
.catch(() => {});
.catch(() => {})
},
//
reReadingHistory(row) {
this.$router.push({
path: `/trials/trials-panel/reading/rereadTask?trialId=${this.$route.query.trialId}&trialCode=${this.$route.query.trialCode}&researchProgramNo=${this.$route.query.researchProgramNo}&SiteId=${row.SiteId}&SubjectCode=${row.SubjectCode}&TaskName=${row.TaskName}`,
});
})
},
getList() {
this.loading = true;
this.searchData.TrialId = this.trialId;
this.searchData.TrialReadingCriterionId = this.TrialReadingCriterionId;
this.loading = true
this.searchData.TrialId = this.trialId
this.searchData.TrialReadingCriterionId = this.TrialReadingCriterionId
if (this.dateValue && this.dateValue[0] && this.dateValue[1]) {
this.searchData.BeginSignDate = this.$moment(this.dateValue[0]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
this.searchData.EndSignDate = this.$moment(this.dateValue[1]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
} else {
this.searchData.BeginSignDate = null;
this.searchData.EndSignDate = null;
this.searchData.BeginSignDate = null
this.searchData.EndSignDate = null
}
getIRHaveReadTaskList(this.searchData)
.then((res) => {
this.list = res.Result.CurrentPageData;
this.total = res.Result.TotalCount;
this.loading = false;
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
this.loading = false
})
.catch(() => {
this.loading = false;
});
this.loading = false
})
},
handleSearch() {
this.searchData.PageIndex = 1;
this.getList();
this.searchData.PageIndex = 1
this.getList()
},
handleReset() {
this.searchData = searchDataDefault();
this.dateValue = [];
this.getList();
this.searchData = searchDataDefault()
this.dateValue = []
this.getList()
},
handleReadImage(row) {
if (this.openWindow) {
this.openWindow.close();
this.openWindow.close()
}
// var token = getToken()
// var routeData = ''
@ -846,55 +925,55 @@ export default {
// path: `/readingPage?subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&trialId=${this.trialId}&visitTaskId=${row.Id}&TokenKey=${token}`
// })
window.localStorage.setItem(
"TrialReadingCriterionId",
'TrialReadingCriterionId',
this.TrialReadingCriterionId
);
var token = getToken();
var path = "";
)
var token = getToken()
var path = ''
if (row.ReadingTool === 0) {
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`;
path = `/readingDicoms?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
} else {
path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`;
path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`
}
var routeData = this.$router.resolve({ path });
this.openWindow = window.open(routeData.href, "_blank");
var routeData = this.$router.resolve({ path })
this.openWindow = window.open(routeData.href, '_blank')
},
async openApplyReReading(row) {
try {
let confirm = await this.$confirm(
this.$t("trials:readTask:message:msg2"),
this.$t('trials:readTask:message:msg2'),
{
type: "warning",
type: 'warning',
distinguishCancelAndClose: true,
}
);
if (!confirm) return;
)
if (!confirm) return
let params = {
TrialId: row.TrialId,
TrialReadingCriterionId: row.TrialReadingCriterionId,
VisitTaskId: row.Id,
};
this.loading = true;
let res = await aIRReReading(params);
this.loading = false;
}
this.loading = true
let res = await aIRReReading(params)
this.loading = false
if (res.IsSuccess) {
this.getList();
this.getList()
this.$message({
message: this.$t("trials:readTask:message:msg3"),
type: "success",
});
message: this.$t('trials:readTask:message:msg3'),
type: 'success',
})
}
} catch (err) {
console.log(err);
this.loading = false;
console.log(err)
this.loading = false
}
},
//
applyReReading() {
this.$refs.reasonForm.validate((valid) => {
if (!valid) return;
this.loading = true;
this.btnLoading = true;
if (!valid) return
this.loading = true
this.btnLoading = true
var params = {
TaskIdList: [this.rowData.Id],
TrialId: this.$route.query.trialId,
@ -904,66 +983,66 @@ export default {
RequestReReadingReason:
this.ApplyforReasonForm.Type === 2
? this.ApplyforReasonForm.RequestReReadingReason
: this.$t("trials:readTask:option:errorRecords"), // ''
};
: this.$t('trials:readTask:option:errorRecords'), // ''
}
applyReReading(params)
.then((res) => {
this.loading = false;
this.btnLoading = false;
this.$message.success(this.$t("trials:readTask:message:msg1")); // ''
this.getList();
this.ApplyforReasonVisible = false;
this.loading = false
this.btnLoading = false
this.$message.success(this.$t('trials:readTask:message:msg1')) // ''
this.getList()
this.ApplyforReasonVisible = false
})
.catch(() => {
this.loading = false;
this.btnLoading = false;
});
});
this.loading = false
this.btnLoading = false
})
})
},
//
handleReread() {
this.$confirm(this.$t("trials:readTask:message:msg2"), {
type: "warning",
this.$confirm(this.$t('trials:readTask:message:msg2'), {
type: 'warning',
distinguishCancelAndClose: true,
})
.then(() => {
this.loading = true;
this.loading = true
var params = {
trialId: this.trialId,
trialReadingCriterionId: this.TrialReadingCriterionId,
};
}
aIRReReading(params)
.then((res) => {
this.$message({
message: this.$t("trials:readTask:message:msg3"),
type: "success",
});
this.getList();
message: this.$t('trials:readTask:message:msg3'),
type: 'success',
})
this.getList()
})
.catch(() => {
this.loading = false;
});
console.log(params);
this.loading = false
})
console.log(params)
})
.catch(() => {
this.loading = false;
});
this.loading = false
})
},
handleAuditRecords(row) {
this.currentRow = { ...row };
this.auditRecordVisible = true;
this.currentRow = { ...row }
this.auditRecordVisible = true
},
//
handleSortChange(column) {
if (column.order === "ascending") {
this.searchData.Asc = true;
if (column.order === 'ascending') {
this.searchData.Asc = true
} else {
this.searchData.Asc = false;
this.searchData.Asc = false
}
this.searchData.SortField = column.prop;
this.searchData.PageIndex = 1;
this.getList();
this.searchData.SortField = column.prop
this.searchData.PageIndex = 1
this.getList()
},
},
};
}
</script>

View File

@ -104,7 +104,7 @@
<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
@ -112,7 +112,7 @@
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t("common:button:reset") }}
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
</el-form>
@ -192,7 +192,7 @@
scope.row.TaskState
]
"
>{{ $fd("TaskState", scope.row.TaskState) }}</el-tag
>{{ $fd('TaskState', scope.row.TaskState) }}</el-tag
>
</template>
</el-table-column>
@ -217,7 +217,7 @@
<template slot-scope="scope">
<el-tag
:type="scope.row.ReadingTaskState === 2 ? 'primary' : 'danger'"
>{{ $fd("ReadingTaskState", scope.row.ReadingTaskState) }}</el-tag
>{{ $fd('ReadingTaskState', scope.row.ReadingTaskState) }}</el-tag
>
</template>
</el-table-column>
@ -236,7 +236,7 @@
sortable="custom"
/>
<!-- 打包状态 -->
<el-table-column
<!-- <el-table-column
prop="PackState"
:label="$t('trials:hirVisit:table:PackState')"
show-overflow-tooltip
@ -251,10 +251,10 @@
? 'warning'
: 'success'
"
>{{ $fd("PackState", Number(scope.row.PackState)) }}</el-tag
>{{ $fd('PackState', Number(scope.row.PackState)) }}</el-tag
>
</template>
</el-table-column>
</el-table-column> -->
<!-- 建议完成时间 -->
<!-- <el-table-column
prop="StudyCode"
@ -289,8 +289,11 @@
<el-button
circle
icon="el-icon-download"
:loading="downloading"
:title="$t('trials:reading:button:uploadImages')"
@click="handleCommand('downloadImage', scope.row)"
@click="
handleCommand('getDownloadSubjectVisitStudyInfo', scope.row)
"
/>
</template>
</el-table-column>
@ -308,14 +311,18 @@
</BaseContainer>
</template>
<script>
import BaseContainer from "@/components/BaseContainer";
import Pagination from "@/components/Pagination";
import { getPatientVisitTaskList } from "@/api/readManagenent.js";
import { getToken } from "@/utils/auth";
import BaseContainer from '@/components/BaseContainer'
import Pagination from '@/components/Pagination'
import { getPatientVisitTaskList } from '@/api/readManagenent.js'
import { getToken } from '@/utils/auth'
// import { getSystemConfirmedCreiterionList } from "@/api/trials";
import { getTrialCriterionList } from "@/api/trials/reading";
import { showReadReport } from "@/api/export";
import { downloadImage } from "@/utils/uploadZip.js";
import { getTrialCriterionList } from '@/api/trials/reading'
import { showReadReport } from '@/api/export'
import { downLoadFile } from '@/utils/stream.js'
import {
getDownloadSubjectVisitStudyInfo,
downloadImageSuccess,
} from '@/api/trials.js'
const defaultSearchData = () => {
return {
SubjectCode: null,
@ -327,7 +334,7 @@ const defaultSearchData = () => {
PageIndex: 1,
PageSize: 20,
Asc: false,
SortField: "CreateTime",
SortField: 'CreateTime',
TrialReadingCriterionId: null,
TaskState: null,
SubjectShortName: null,
@ -337,10 +344,10 @@ const defaultSearchData = () => {
BeginTaskCreateTime: null,
EndTaskCreateTime: null,
SubjectShortName: null,
};
};
}
}
export default {
name: "readManagenent",
name: 'readManagenent',
components: { BaseContainer, Pagination },
data() {
return {
@ -355,146 +362,215 @@ export default {
total: 0,
//
reportFlag: {},
};
//
downloading: false,
downloadId: null,
}
},
created() {
this.getList();
this.getTrialConfirmedCreiterionList();
this.getList()
this.getTrialConfirmedCreiterionList()
},
methods: {
//
handleCommand(command, item) {
this[command](item);
this[command](item)
},
//
async showReport(item) {
if (this.reportFlag[item.Id]) return;
if (this.reportFlag[item.Id]) return
let data = {
VisitTaskId: item.Id,
};
}
try {
if (!this.reportFlag.hasOwnProperty(item.Id)) {
this.$set(this.reportFlag, item.Id, true);
this.$set(this.reportFlag, item.Id, true)
}
if (!this.reportFlag[item.Id]) {
this.reportFlag[item.Id] = true;
this.reportFlag[item.Id] = true
}
let res = await showReadReport(data);
let res = await showReadReport(data)
if (res.IsSuccess) {
let a = document.createElement("a");
let href = this.OSSclientConfig.basePath + res.Result;
let fileName =
res.Result.split("/")[res.Result.split("/").length - 1];
a.download = fileName;
a.href = href;
a.click();
URL.revokeObjectURL(href);
let a = document.createElement('a')
let href = this.OSSclientConfig.basePath + res.Result
let fileName = res.Result.split('/')[res.Result.split('/').length - 1]
a.download = fileName
a.href = href
a.click()
URL.revokeObjectURL(href)
this.$nextTick(() => {
a = null;
href = null;
});
a = null
href = null
})
}
this.reportFlag[item.Id] = false;
this.reportFlag[item.Id] = false
} catch (err) {
this.reportFlag[item.Id] = false;
console.log(err);
this.reportFlag[item.Id] = false
console.log(err)
}
},
//
async getTrialConfirmedCreiterionList() {
try {
let trialId = this.$route.query.trialId;
let res = await getTrialCriterionList(trialId);
let trialId = this.$route.query.trialId
let res = await getTrialCriterionList(trialId)
if (res.IsSuccess) {
this.CriterionTypeList = res.Result;
this.CriterionTypeList = res.Result
}
} catch (err) {
console.log(err);
console.log(err)
}
},
//
handleSearch() {
this.getList();
this.getList()
},
//
handleReset() {
this.reset();
this.getList();
this.reset()
this.getList()
},
//
reset() {
this.searchData = defaultSearchData();
this.dateValue = [];
this.dateValue2 = [];
this.$refs.redManagenentTable.clearSort();
this.searchData = defaultSearchData()
this.dateValue = []
this.dateValue2 = []
this.$refs.redManagenentTable.clearSort()
},
//
handleSortByColumn(sort) {
this.searchData.SortField = sort.prop;
if (sort.order === "ascending") this.searchData.Asc = true;
if (sort.order === "descending") this.searchData.Asc = false;
if (!sort.order) this.searchData.SortField = null;
this.getList();
this.searchData.SortField = sort.prop
if (sort.order === 'ascending') this.searchData.Asc = true
if (sort.order === 'descending') this.searchData.Asc = false
if (!sort.order) this.searchData.SortField = null
this.getList()
},
//
async getList() {
try {
let data = {};
let data = {}
Object.keys(this.searchData).forEach((key) => {
data[key] = this.searchData[key];
});
data.TrialId = this.$route.query.trialId;
data[key] = this.searchData[key]
})
data.TrialId = this.$route.query.trialId
if (this.dateValue && this.dateValue[0] && this.dateValue[1]) {
data.earliestStudyTime = this.$moment(this.dateValue[0]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
data.latestStudyTime = this.$moment(this.dateValue[1]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
} else {
data.EarliestStudyTime = null;
data.LatestStudyTime = null;
data.EarliestStudyTime = null
data.LatestStudyTime = null
}
if (this.dateValue2 && this.dateValue2[0] && this.dateValue2[1]) {
data.BeginTaskCreateTime = this.$moment(this.dateValue2[0]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
data.EndTaskCreateTime = this.$moment(this.dateValue2[1]).format(
"YYYY-MM-DD HH:mm:ss"
);
'YYYY-MM-DD HH:mm:ss'
)
} else {
data.BeginTaskCreateTime = null;
data.EndTaskCreateTime = null;
data.BeginTaskCreateTime = null
data.EndTaskCreateTime = null
}
this.loading = true;
let res = await getPatientVisitTaskList(data);
this.loading = false;
this.loading = true
let res = await getPatientVisitTaskList(data)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result.CurrentPageData;
this.total = res.Result.TotalCount;
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}
} catch (err) {
this.loading = false;
console.log(err);
this.loading = false
console.log(err)
}
},
//
async downloadImage(item) {
let res = await downloadImage(
this.$route.query.trialId,
item.SourceSubjectVisitId
);
if (res) {
item.PackState = res;
//
async getDownloadSubjectVisitStudyInfo(row) {
if (this.downloading) return
try {
let data = {
SubjectVisitId: row.SourceSubjectVisitId,
TrialId: this.$route.query.trialId,
}
this.downloading = true
let res = await getDownloadSubjectVisitStudyInfo(data)
this.downloading = false
if (res.IsSuccess) {
this.downloadId = res.OtherInfo
this.downloadImage(res.Result)
}
} catch (err) {
this.downloading = false
console.log(err)
}
},
//
async downloadImage(data) {
try {
let { files, name } = this.formatDownloadFile(data)
let res = await downLoadFile(files, name, 'zip')
if (res && this.downloadId) {
this.downloadImageSuccess()
}
} catch (err) {
console.log(err)
}
},
//
formatDownloadFile(data) {
let files = [],
name = `${data.SubjectCode}_${data.VisitName}_ImageStudy.zip`
if (Array.isArray(data.StudyList) && data.StudyList.length > 0) {
data.StudyList.forEach((study) => {
if (Array.isArray(study.SeriesList) && study.SeriesList.length > 0) {
study.SeriesList.forEach((series) => {
if (
Array.isArray(series.InstanceList) &&
series.InstanceList.length > 0
) {
series.InstanceList.forEach((instance) => {
let fileName = instance.Path.split('/').pop()
let obj = {
name: `${data.SubjectCode}_${data.VisitName}/${
study.StudyCode
}_${study.StudyTime.split(' ')[0]}_${
series.Modality
}/${fileName}`,
url: this.OSSclientConfig.basePath + instance.Path,
}
files.push(obj)
})
}
})
}
})
}
return { files, name }
},
//
async downloadImageSuccess() {
try {
let params = {
TrialImageDownloadId: this.downloadId,
}
await downloadImageSuccess(params)
} catch (err) {
console.log(err)
}
},
//
readResult(row) {
if (this.openWindow) {
this.openWindow.close();
this.openWindow.close()
}
var token = getToken();
var path;
var token = getToken()
var path
// if (row.ReadingTool === 0) {
path = `/readingDicoms?TrialReadingCriterionId=${
row.TrialReadingCriterionId
@ -504,15 +580,15 @@ export default {
row.Id
}&isReadingTaskViewInOrder=${true}&criterionType=${
row.CriterionType
}&readingTool=${row.ReadingTool}&TokenKey=${token}`;
}&readingTool=${row.ReadingTool}&TokenKey=${token}`
// } else {
// path = `/noneDicomReading?TrialReadingCriterionId=${row.TrialReadingCriterionId}&trialId=${this.trialId}&subjectCode=${row.SubjectCode}&subjectId=${row.SubjectId}&visitTaskId=${row.Id}&isReadingTaskViewInOrder=${row.IsReadingTaskViewInOrder}&criterionType=${row.CriterionType}&readingTool=${row.ReadingTool}&TokenKey=${token}`;
// }
// const routeData = this.$router.resolve({
// path: `/readingPage?subjectId=${row.SubjectId}&trialId=${row.TrialId}&visitTaskId=${row.Id}&TokenKey=${token}`
// })
this.openWindow = window.open(path, "_blank");
this.openWindow = window.open(path, '_blank')
},
},
};
}
</script>