Compare commits
276 Commits
2303c04857
...
v1.7.0
| Author | SHA1 | Date | |
|---|---|---|---|
| f58eb07323 | |||
| 83a14956e3 | |||
| ef2e7d4cf8 | |||
| 9e7ec09719 | |||
| 19f9c8012c | |||
| 506307690d | |||
| b945db8a47 | |||
| 7bb0213a8c | |||
| a75367480d | |||
| 64fd549d12 | |||
| f0ec643205 | |||
| 34c05a9728 | |||
| 49241bacfa | |||
| 3bb0250699 | |||
| 47dd21ea7e | |||
| 64d268b6e8 | |||
| 463ecee3d8 | |||
| 9936d8c942 | |||
| 1e132e0046 | |||
| 95097caac2 | |||
| dcde93b4f8 | |||
| e690aadd8a | |||
| 7874f69bfe | |||
| bdb45c7b4e | |||
| 0a4683386c | |||
| c73297003f | |||
| 4faff7e85c | |||
| 595e10a77a | |||
| 360826ef28 | |||
| cd7d261adf | |||
| 3ed09d16f6 | |||
| 2a016cf5f6 | |||
| 2d996941a2 | |||
| 2ac92aa8b3 | |||
| e8a21fa5a3 | |||
| 771554c9b2 | |||
| 3b7271d3a8 | |||
| d2ab510a3c | |||
| 7e8af2b4e5 | |||
| f9f3c55ea1 | |||
| 988317d0cd | |||
| a7c7c3dfc5 | |||
| 17d6e233c8 | |||
| c9a754a85f | |||
| a1addde722 | |||
| 001faf1f79 | |||
| 8d26368bcb | |||
| 3c8ea04457 | |||
| 112c78a832 | |||
| 590949e207 | |||
| 8a47f23fe7 | |||
| 2093308763 | |||
| 8fae8528c6 | |||
| 3d5229d3c0 | |||
| 386db94fdb | |||
| f80bd64ede | |||
| 339be24cc3 | |||
| d30953bb98 | |||
| dc60a1ca4a | |||
| 2d673a414b | |||
| 06c56889d0 | |||
| 68179f4214 | |||
| 2b5ee56e6b | |||
| 3d2f6d0c7e | |||
| 9752fd6946 | |||
| 0dcee2c84b | |||
| 43f49a36c0 | |||
| 16d5299ce0 | |||
| 16485f0c56 | |||
| 692fd7bc97 | |||
| f17f1d6a6b | |||
| b74337f2f0 | |||
| 37e65339f3 | |||
| b4d4fffd71 | |||
| f175838052 | |||
| 80aa18eff2 | |||
| 966e90498d | |||
| ca1b95201c | |||
| f2e6ecce8e | |||
| 3b06046c69 | |||
| d67bc1e02d | |||
| 3c35d2656d | |||
| d6048e4cdd | |||
| d80fdb36e1 | |||
| 40642a4fe6 | |||
| e550e5e31c | |||
| 5bf4c3cf5d | |||
| d86eee6825 | |||
| 76a70e819d | |||
| a512ed551b | |||
| c5383dd11d | |||
| 23378a663b | |||
| 693e240578 | |||
| 0144ae91e8 | |||
| 449e999d43 | |||
| c77ca02cbc | |||
| 8300cbaccf | |||
| 14b0a45817 | |||
| b3ba7e7e40 | |||
| c348260b45 | |||
| 4fbd4e28fe | |||
| d7b11c02e5 | |||
| d0281abfee | |||
| 2c268cbd4f | |||
| 857abb2c0d | |||
| 371a3acff2 | |||
| 3dddbafd04 | |||
| 86dde0a9e8 | |||
| aee2a78205 | |||
| 4733c0fd8f | |||
| 54b3e0399c | |||
| 8f6434f123 | |||
| c25183073a | |||
| 904a764ea5 | |||
| 248f40b5be | |||
| c50c6c7bc7 | |||
| 1ef8eed500 | |||
| 9310337f16 | |||
| 37529cef33 | |||
| 42ed756c4e | |||
| 97d786684b | |||
| 17f0a5d977 | |||
| 75a063acd9 | |||
| 5df08f52fc | |||
| 3a5de3fadf | |||
| be32fd8e15 | |||
| 8047ba7f5f | |||
| fbbd4ff805 | |||
| 25d8ee6bc5 | |||
| 0f29a2971c | |||
| 2b71341d4c | |||
| fa395f54b2 | |||
| 70d9623c63 | |||
| 82447c58de | |||
| 672cb9b2a2 | |||
| b06dcdc98f | |||
| b1096a8aa9 | |||
| 66a1654bfe | |||
| 986bce36e6 | |||
| e845fdaad4 | |||
| b762d3d0dd | |||
| dfb9392cda | |||
| 86c05070b3 | |||
| b8478e6451 | |||
| 4552caf82f | |||
| 9e83d51037 | |||
| dd0cd1ec64 | |||
| db5e5da06a | |||
| e6bd4576e6 | |||
| 8abcfcbe1a | |||
| 9653e4478b | |||
| 9402501c0b | |||
| d5c0e15f46 | |||
| 860d932a5d | |||
| 0e485a8984 | |||
| 95998f0dea | |||
| 8c7c82cf5e | |||
| bf701bf3d8 | |||
| 2ce7454b47 | |||
| ce079f923a | |||
| 60d3b25041 | |||
| 3d171caf1b | |||
| 472599c663 | |||
| 3a659cd9bc | |||
| ed7d2502d1 | |||
| 689c149a3a | |||
| 5b3ae0c076 | |||
| 4eba3b2cb3 | |||
| e2ebedb9e9 | |||
| 77c3f0244e | |||
| 3fc7d70b3f | |||
| c2aa83f4b8 | |||
| 7c77a42e90 | |||
| 08b8f8d107 | |||
| 1fca941f64 | |||
| d06afd42af | |||
| cbee69b4c0 | |||
| 39c4a13f5e | |||
| 7fed65dbe3 | |||
| 15cad74264 | |||
| b1c8f02271 | |||
| b95cc82997 | |||
| 59c342ccd1 | |||
| eba09135eb | |||
| 4f4934523f | |||
| 99bb929123 | |||
| 1538690604 | |||
| bfb1c03c63 | |||
| e05986ac9f | |||
| 4988155499 | |||
| e024c6c0b1 | |||
| aa526aad8c | |||
| 84bc101065 | |||
| adf6bdc44a | |||
| ec7851eb9d | |||
| 8831847850 | |||
| fa137ac535 | |||
| 1209a3962b | |||
| ccf3b823d8 | |||
| e043e85630 | |||
| 342c9325bf | |||
| 249448b15e | |||
| 4569f16050 | |||
| 07b2341f93 | |||
| e47c75937c | |||
| f39050e220 | |||
| f31e23d314 | |||
| 8b12d6a576 | |||
| 605bf04e43 | |||
| f380028c22 | |||
| 9a040024d9 | |||
| 04f68d8733 | |||
| b62a36b63a | |||
| 3dfe5b57a1 | |||
| 6a3068f942 | |||
| f58fa6011b | |||
| d42252ea78 | |||
| 6bf4a1b70d | |||
| 5bed446055 | |||
| 5d8c389090 | |||
| 5bfc4a9a82 | |||
| cb00ec7ac2 | |||
| dc5c1720c7 | |||
| 73a4135fd6 | |||
| f2af36b89a | |||
| 4f0f124378 | |||
| c618738725 | |||
| 1274af3e48 | |||
| b7a19c2581 | |||
| 842e959e2d | |||
| 0590742dac | |||
| f6b90c4c05 | |||
| e52378d5d4 | |||
| f52b2f151b | |||
| 9bb856b50a | |||
| 780c49959e | |||
| a470d961df | |||
| 84b1a2a4fa | |||
| e2026177a1 | |||
| c114903dba | |||
| 915c7c88fb | |||
| 64bd3033b5 | |||
| c1fbbc524f | |||
| 6f86700dbc | |||
| 85ed9fd9b7 | |||
| 002cd19053 | |||
| e24b1cc722 | |||
| 205b420074 | |||
| d42e446953 | |||
| 3be34d89ca | |||
| 67b04c2a51 | |||
| 65acb7ea05 | |||
| d25fd68db7 | |||
| 433064c353 | |||
| 0e766300f0 | |||
| 581980f111 | |||
| 7aaede5503 | |||
| ff7305c3a0 | |||
| 6f03bbe14c | |||
| 6b645d3161 | |||
| 4db4aed4dd | |||
| b368df6bfb | |||
| 7aa21c5ca1 | |||
| 45c4bc3b3a | |||
| 5de6a69bc8 | |||
| 324bc1a536 | |||
| 2628d2ec5f | |||
| 9d8bd9c910 | |||
| 615c91b197 | |||
| a7c0ae6d7a | |||
| 400b13e7a6 | |||
| a14f144066 | |||
| 655753d1c6 | |||
| 64e936ad6d | |||
| 6712cad721 | |||
| fed2c1a842 |
@@ -33,6 +33,7 @@
|
||||
"cornerstone-math": "^0.1.10",
|
||||
"cornerstone-tools": "^6.0.10",
|
||||
"cornerstone-wado-image-loader": "^4.13.2",
|
||||
"crypto-js": "^4.2.0",
|
||||
"dcmjs": "^0.29.8",
|
||||
"dicom-parser": "^1.8.9",
|
||||
"dicomedit": "^0.1.0",
|
||||
@@ -43,6 +44,7 @@
|
||||
"hammerjs": "^2.0.8",
|
||||
"html2canvas": "^1.4.1",
|
||||
"js-md5": "^0.7.3",
|
||||
"jsencrypt": "^3.3.2",
|
||||
"jszip": "^3.7.1",
|
||||
"moment": "^2.27.0",
|
||||
"node-polyfill-webpack-plugin": "^2.0.1",
|
||||
|
||||
@@ -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
@@ -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' })
|
||||
}
|
||||
+59
-3
@@ -8,11 +8,11 @@ export function requestPackageAndAnonymizImage(params) {
|
||||
})
|
||||
}
|
||||
// 获取影像上传列表
|
||||
export function getSubjectImageUploadList(params) {
|
||||
export function getSubjectImageUploadList(data) {
|
||||
return request({
|
||||
url: '/DownloadAndUpload/getSubjectImageUploadList',
|
||||
method: 'get',
|
||||
params
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 预上传
|
||||
@@ -47,4 +47,60 @@ export function getCRCUploadedStudyInfo(data) {
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 获取ir阅片和任务列表
|
||||
export function getSubjectImageDownloadSelectList(data) {
|
||||
return request({
|
||||
url: '/DownloadAndUpload/getSubjectImageDownloadSelectList',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 获取ir阅片和任务下载文件信息
|
||||
export function getIRReadingDownloadStudyInfo(data) {
|
||||
return request({
|
||||
url: '/DownloadAndUpload/getIRReadingDownloadStudyInfo',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 获取ir阅片和任务非dicom上传列表
|
||||
export function getIRUploadTaskNoneDicomStudyList(data) {
|
||||
return request({
|
||||
url: '/DownloadAndUpload/getIRUploadTaskNoneDicomStudyList',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 校验上传影像
|
||||
export function verifyIRStudyAllowUpload(data) {
|
||||
return request({
|
||||
url: '/DownloadAndUpload/verifyIRStudyAllowUpload',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 影像下载成功确认
|
||||
export function downloadImageSuccess(params) {
|
||||
return request({
|
||||
url: '/DownloadAndUpload/downloadImageSuccess',
|
||||
method: 'post',
|
||||
params
|
||||
})
|
||||
}
|
||||
// 影像下载记录列表
|
||||
export function getTrialDownloadList(data) {
|
||||
return request({
|
||||
url: '/DownloadAndUpload/getTrialDownloadList',
|
||||
method: 'post',
|
||||
data
|
||||
})
|
||||
}
|
||||
// 修改后处理检查类型
|
||||
export function updateTaskStudyModality(params) {
|
||||
return request({
|
||||
url: '/DownloadAndUpload/updateTaskStudyModality',
|
||||
method: 'put',
|
||||
params
|
||||
})
|
||||
}
|
||||
+60
-3
@@ -1,5 +1,5 @@
|
||||
import request from '@/utils/request'
|
||||
|
||||
import requestDownload from '@/utils/request-download'
|
||||
export function addBaseLineLesion(param) {
|
||||
return request({
|
||||
url: '/report/addBaseLineLesion',
|
||||
@@ -133,9 +133,11 @@ export function AddAdjudicationReport(param) {
|
||||
})
|
||||
}
|
||||
|
||||
export function getVisitStudyList(trialId, subjectVisitId, isReading) {
|
||||
export function getVisitStudyList(trialId, subjectVisitId, isReading, visitTaskId) {
|
||||
let url = `/SubjectVisit/getVisitStudyList/${trialId}/${subjectVisitId}/${isReading}`
|
||||
url = visitTaskId ? `${url}?visitTaskId=${visitTaskId}` : url
|
||||
return request({
|
||||
url: `/SubjectVisit/getVisitStudyList/${trialId}/${subjectVisitId}/${isReading}`,
|
||||
url: url,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
@@ -194,3 +196,58 @@ export function resetReadingTask(param) {
|
||||
data: param
|
||||
})
|
||||
}
|
||||
export function getTaskUploadedDicomStudyList(param) {
|
||||
return request({
|
||||
url: `/DownloadAndUpload/getTaskUploadedDicomStudyList`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
export function getIVUSTemplate(param) {
|
||||
return requestDownload({
|
||||
url: '/IVUSCalculate/getIVUSTemplate',
|
||||
method: 'post',
|
||||
responseType: 'blob',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
export function uploadIVUSTemplate(param) {
|
||||
return request({
|
||||
url: `/IVUSCalculate/uploadIVUSTemplate`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
|
||||
export function getOCTFCTTemplate(param) {
|
||||
return requestDownload({
|
||||
url: '/OCTCalculate/getOCTFCTTemplate',
|
||||
method: 'post',
|
||||
responseType: 'blob',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
|
||||
export function uploadOCTFCTTemplate(param) {
|
||||
return request({
|
||||
url: `/OCTCalculate/uploadOCTFCTTemplate`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
|
||||
export function getOCTLipidAngleTemplate(param) {
|
||||
return requestDownload({
|
||||
url: '/OCTCalculate/getOCTLipidAngleTemplate',
|
||||
method: 'post',
|
||||
responseType: 'blob',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
export function uploadOCTLipidAngleTemplate(param) {
|
||||
return request({
|
||||
url: `/OCTCalculate/uploadOCTLipidAngleTemplate`,
|
||||
method: 'post',
|
||||
data: param
|
||||
})
|
||||
}
|
||||
|
||||
+2
-2
@@ -1364,9 +1364,9 @@ export function getForwardList(param) {
|
||||
})
|
||||
}
|
||||
|
||||
export function getNoneDicomStudyList(subjectVisitId, sudyId = '', isFilterZip = false) {
|
||||
export function getNoneDicomStudyList(subjectVisitId, sudyId = '', isFilterZip = false, visitTaskId = '') {
|
||||
return request({
|
||||
url: `/NoneDicomStudy/getNoneDicomStudyList?subjectVisitId=${subjectVisitId}&nonedicomStudyId=${sudyId}&isFilterZip=${isFilterZip}`,
|
||||
url: `/NoneDicomStudy/getNoneDicomStudyList?subjectVisitId=${subjectVisitId}&nonedicomStudyId=${sudyId}&isFilterZip=${isFilterZip}&visitTaskId=${visitTaskId}`,
|
||||
method: 'get'
|
||||
})
|
||||
}
|
||||
|
||||
+9
-1
@@ -4,7 +4,8 @@ export function login(data) {
|
||||
return request({
|
||||
url: '/user/login',
|
||||
method: 'post',
|
||||
data
|
||||
data,
|
||||
ENCRYPT: true
|
||||
})
|
||||
}
|
||||
export function loginOut(params) {
|
||||
@@ -185,3 +186,10 @@ export function sendMFAEmail(params) {
|
||||
params
|
||||
})
|
||||
}
|
||||
// 获取公钥
|
||||
export function getPublicKey() {
|
||||
return request({
|
||||
url: `/user/getPublicKey`,
|
||||
method: 'get',
|
||||
})
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 61 KiB |
@@ -90,7 +90,7 @@
|
||||
custom-class="base-dialog-wrapper"
|
||||
append-to-body
|
||||
>
|
||||
<DicomTags :image-data="imageData" @close="dcmTag.visible = false" />
|
||||
<DicomTags :image-id="stack.imageIds[stack.currentImageIdIndex]" @close="dcmTag.visible = false" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
@@ -176,8 +176,7 @@ export default {
|
||||
markers: { top: '', right: '', bottom: '', left: '' },
|
||||
orientationMarkers: [],
|
||||
originalMarkers: [],
|
||||
dcmTag: { visible: false, title: 'DICOM Tags' },
|
||||
imageData: null
|
||||
dcmTag: { visible: false, title: this.$t('trials:dicom-tag:title') }
|
||||
}
|
||||
},
|
||||
|
||||
@@ -681,7 +680,7 @@ export default {
|
||||
resetWwwc() {
|
||||
this.toolState.viewportInvert = false
|
||||
var viewport = cornerstone.getViewport(this.canvas)
|
||||
viewport.invert = false
|
||||
// viewport.invert = false
|
||||
var image = cornerstone.getImage(this.canvas)
|
||||
viewport.voi.windowWidth = image.windowWidth
|
||||
viewport.voi.windowCenter = image.windowCenter
|
||||
@@ -761,11 +760,7 @@ export default {
|
||||
cornerstoneTools.SaveAs(this.canvas, `${uid}.png`)
|
||||
},
|
||||
showTags() {
|
||||
var image = cornerstone.getImage(this.canvas)
|
||||
// var dataSet = dicomParser.parseDicom(image.data.byteArray)
|
||||
// console.log('showTags', dataSet)
|
||||
this.dcmTag.visible = true
|
||||
this.imageData = image.data
|
||||
},
|
||||
fitToWindow() {
|
||||
if (this.stack.seriesNumber) {
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<el-input
|
||||
v-model="search"
|
||||
size="mini"
|
||||
placeholder="输入关键字搜索"
|
||||
:placeholder="$t('trials:dicom-tag:keywords')"
|
||||
style="width:200px"
|
||||
/>
|
||||
|
||||
@@ -54,15 +54,14 @@
|
||||
</template>
|
||||
<script>
|
||||
import TAG_DICT from './dataDictionary'
|
||||
import * as cornerstone from 'cornerstone-core'
|
||||
import dicomParser from 'dicom-parser'
|
||||
export default {
|
||||
name: 'DicomTags',
|
||||
props: {
|
||||
imageData: {
|
||||
type: Object,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
imageId: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
@@ -72,8 +71,9 @@ export default {
|
||||
search: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
var dataSet = dicomParser.parseDicom(this.imageData.byteArray)
|
||||
async mounted() {
|
||||
const image = await cornerstone.loadAndCacheImage(this.imageId)
|
||||
var dataSet = dicomParser.parseDicom(image.data.byteArray)
|
||||
var output = []
|
||||
this.dumpDataSet(dataSet, output)
|
||||
this.list = output
|
||||
@@ -84,7 +84,25 @@ export default {
|
||||
if (!this.search) {
|
||||
return list
|
||||
} else {
|
||||
return list.filter(data => data.tagCode.toLowerCase().includes(this.search.toLowerCase()) || data.tagName.toLowerCase().includes(this.search.toLowerCase()) || (data.value && data.value.toLowerCase().includes(this.search.toLowerCase())))
|
||||
const search = isNaN(parseFloat(this.search)) ? this.search.toLowerCase() : String(this.search)
|
||||
const arr = list.filter(data => {
|
||||
if (data.tagCode && data.tagCode.toLowerCase().includes(search)) {
|
||||
return data
|
||||
} else if (data.tagName && data.tagName.toLowerCase().includes(search)) {
|
||||
return data
|
||||
} else if (data.value) {
|
||||
let v = ''
|
||||
if (!isNaN(parseFloat(data.value))) {
|
||||
v = String(data.value)
|
||||
} else {
|
||||
v = data.value.toLowerCase()
|
||||
}
|
||||
if (v.includes(search)) {
|
||||
return data
|
||||
}
|
||||
}
|
||||
})
|
||||
return arr
|
||||
}
|
||||
},
|
||||
dumpDataSet(dataSet, output) {
|
||||
@@ -94,14 +112,17 @@ export default {
|
||||
const element = dataSet.elements[propertyName]
|
||||
const tag = this.getTag(element.tag)
|
||||
elementObject.id = `${this.idx++}${new Date().getTime()}`
|
||||
elementObject.tagCode = element.tag
|
||||
elementObject.tagName = tag.name
|
||||
if (!tag) {
|
||||
const group = element.tag.substring(1, 5)
|
||||
const el = element.tag.substring(5, 9)
|
||||
elementObject.tagCode = ('(' + group + ',' + el + ')').toUpperCase()
|
||||
} else {
|
||||
elementObject.tagCode = tag ? tag.tag : ''
|
||||
elementObject.tagName = tag ? tag.name : ''
|
||||
}
|
||||
|
||||
elementObject.tagLength = element.length
|
||||
elementObject.value = ''
|
||||
|
||||
if (element.vr) {
|
||||
elementObject.vr = element.vr
|
||||
}
|
||||
elementObject.child = []
|
||||
|
||||
if (element.items) {
|
||||
@@ -116,7 +137,12 @@ export default {
|
||||
var vr
|
||||
if (element.vr !== undefined) {
|
||||
vr = element.vr
|
||||
} else {
|
||||
if (tag !== undefined) {
|
||||
vr = tag.vr
|
||||
}
|
||||
}
|
||||
elementObject.vr = vr
|
||||
if (element.length < 128) {
|
||||
// const str = dataSet.string(propertyName)
|
||||
// if (elementObject.tagCode === 'x00280010') {
|
||||
@@ -224,7 +250,7 @@ export default {
|
||||
exception: err,
|
||||
output: output
|
||||
}
|
||||
throw ex
|
||||
console.log(ex)
|
||||
}
|
||||
},
|
||||
getTag(tag) {
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/>
|
||||
<!-- <embed v-else-if="fileType.indexOf('pdf') !== -1" :src="filePath+'#toolbar=0'" style="width: 100%; height: 100%"> -->
|
||||
<!-- <iframe v-else-if="fileType.indexOf('pdf') !== -1" :src="filePath+'#toolbar=0'" width="100%" height="100%" frameborder="0" /> -->
|
||||
<iframe v-else-if="fileType.indexOf('pdf') !== -1" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${filePath}?userName=${currentUser}`" width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
|
||||
<iframe v-else-if="fileType.indexOf('pdf') !== -1" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${filePath}?userName=${currentUser}&COMPANY=${COMPANY}`" width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
|
||||
<!-- <pdf-->
|
||||
<!-- v-else-if="fileType.indexOf('pdf') !== -1"-->
|
||||
<!-- :src="`/static/pdfjs/web/viewer.html?file=${filePath}`">-->
|
||||
@@ -40,7 +40,8 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentUser: zzSessionStorage.getItem('userName')
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
COMPANY:process.env.VUE_APP_COMPANY_NAME
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
@@ -0,0 +1,511 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible.sync="visible"
|
||||
:fullscreen="true"
|
||||
:close-on-click-modal="false"
|
||||
:before-close="beforeClose"
|
||||
:append-to-body="true"
|
||||
v-loading="btnLoading"
|
||||
class="downloadDicomAndNonedicom"
|
||||
>
|
||||
<span slot="title">{{ title }}</span>
|
||||
<div class="top">
|
||||
<span>{{ $t('download:top:title') }}</span>
|
||||
<div class="btnBox">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-if="hasDicom"
|
||||
@click.stop="getIRReadingDownloadStudyInfo('dicom')"
|
||||
>
|
||||
{{ $t('download:button:downloadDicom') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-if="hasNonedicom"
|
||||
@click.stop="getIRReadingDownloadStudyInfo('noneDicom')"
|
||||
>
|
||||
{{ $t('download:button:downloadNonedicom') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
v-if="hasDicom || hasNonedicom"
|
||||
@click.stop="getIRReadingDownloadStudyInfo('all')"
|
||||
>
|
||||
{{ $t('download:button:downloadAll') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tip">
|
||||
<i class="el-icon-warning-outline"></i>
|
||||
<div v-html="$t('download:tip:message')"></div>
|
||||
</div>
|
||||
<!--上传列表@selection-change="handleSelectionChange"-->
|
||||
<el-table
|
||||
ref="dicomFilesTable"
|
||||
v-adaptive="{ bottomOffset: 85 }"
|
||||
height="100"
|
||||
:data="list"
|
||||
:loading="loading"
|
||||
class="dicomFiles-table"
|
||||
@sort-change="handleSortByColumn"
|
||||
:default-sort="{ prop: 'TaskBlindName', order: 'descending' }"
|
||||
>
|
||||
<!-- <el-table-column
|
||||
type="selection"
|
||||
width="55"
|
||||
:selectable="handleSelectable"
|
||||
/> -->
|
||||
<el-table-column type="index" width="40" />
|
||||
<!--受试者-->
|
||||
<el-table-column
|
||||
:label="$t('download:table:subjectCode')"
|
||||
min-width="130"
|
||||
prop="SubjectCode"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<!--任务名称-->
|
||||
<el-table-column
|
||||
:label="$t('download:table:taskName')"
|
||||
min-width="130"
|
||||
show-overflow-tooltip
|
||||
prop="TaskBlindName"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!--检查类型-->
|
||||
<el-table-column
|
||||
:label="$t('download:table:studyType')"
|
||||
min-width="130"
|
||||
show-overflow-tooltip
|
||||
prop="IsDicom"
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{ $fd('IsDicom', scope.row.IsDicom) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('download:table:orginalStudyListNum')"
|
||||
min-width="150"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
v-if="
|
||||
(scope.row.IsDicom &&
|
||||
scope.row.DicomStudyList &&
|
||||
scope.row.DicomStudyList.length >= 1) ||
|
||||
(!scope.row.IsDicom &&
|
||||
scope.row.NoneDicomStudyList &&
|
||||
scope.row.NoneDicomStudyList.length >= 1)
|
||||
"
|
||||
type="text"
|
||||
@click="handleOpenDialog(scope.row)"
|
||||
>
|
||||
<span>{{
|
||||
scope.row.IsDicom
|
||||
? scope.row.DicomStudyList.length
|
||||
: scope.row.NoneDicomStudyList.length
|
||||
}}</span>
|
||||
</el-button>
|
||||
<span v-else>0</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
fixed="right"
|
||||
width="150"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<!--预览--->
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-view"
|
||||
:title="$t('download:button:preview')"
|
||||
@click.stop="preview(scope.row)"
|
||||
/>
|
||||
<!--下载--->
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-download"
|
||||
:title="$t('download:button:download')"
|
||||
@click.stop="getIRReadingDownloadStudyInfo('one', scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<study-view
|
||||
v-if="model_cfg.visible"
|
||||
:model_cfg="model_cfg"
|
||||
:modelList="modelList"
|
||||
:bodyPart="bodyPart"
|
||||
:IsDicom="IsDicom"
|
||||
:visitTaskId="modelTaskId"
|
||||
/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
getSubjectImageDownloadSelectList,
|
||||
getIRReadingDownloadStudyInfo,
|
||||
downloadImageSuccess,
|
||||
} from '@/api/load.js'
|
||||
import studyView from '@/components/uploadDicomAndNonedicom/study-view.vue'
|
||||
import store from '@/store'
|
||||
import { downLoadFile } from '@/utils/stream.js'
|
||||
import { getToken } from '@/utils/auth'
|
||||
let defaultSearchData = () => {
|
||||
return {
|
||||
SubjectId: null,
|
||||
TrialReadingCriterionId: null,
|
||||
SubjectCode: null,
|
||||
Asc: false,
|
||||
SortField: 'TaskBlindName',
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'downloadDicomAndNonedicom',
|
||||
components: {
|
||||
'study-view': studyView,
|
||||
},
|
||||
props: {
|
||||
visible: {
|
||||
required: true,
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
SubjectId: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
TaskId: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
SubjectCode: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
Criterion: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title: null,
|
||||
loading: false,
|
||||
list: [],
|
||||
searchData: defaultSearchData(),
|
||||
btnLoading: false,
|
||||
hasDicom: false,
|
||||
hasNonedicom: false,
|
||||
// 检查数弹框
|
||||
model_cfg: {
|
||||
visible: false,
|
||||
showClose: true,
|
||||
width: '1000px',
|
||||
title: '',
|
||||
appendToBody: true,
|
||||
},
|
||||
modelList: [],
|
||||
IsDicom: true,
|
||||
open: null,
|
||||
downloadId: null,
|
||||
IsReadingTaskViewInOrder: 0, // 阅片规则
|
||||
bodyPart: [],
|
||||
modelTaskId: null,
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
this.getList()
|
||||
this.bodyPart = await this.$getBodyPart(this.$route.query.trialId)
|
||||
this.title = `Download Images:${this.SubjectCode}(${this.Criterion.TrialReadingCriterionName})`
|
||||
},
|
||||
beforeDestroy() {
|
||||
store.dispatch('trials/setUnLock', false)
|
||||
},
|
||||
methods: {
|
||||
beforeClose() {
|
||||
this.$emit('update:visible', false)
|
||||
},
|
||||
// 获取列表
|
||||
async getList() {
|
||||
try {
|
||||
this.searchData.SubjectId = this.SubjectId
|
||||
this.searchData.TrialReadingCriterionId =
|
||||
this.Criterion.TrialReadingCriterionId
|
||||
this.searchData.SubjectCode = this.SubjectCode
|
||||
if (this.TaskId) {
|
||||
this.searchData.VisitTaskId = this.TaskId
|
||||
}
|
||||
this.loading = true
|
||||
let res = await getSubjectImageDownloadSelectList(this.searchData)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.list = res.Result
|
||||
this.hasDicom = this.list.some((item) => item.IsDicom)
|
||||
this.hasNonedicom = this.list.some((item) => !item.IsDicom)
|
||||
}
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 获取下载文件信息
|
||||
async getIRReadingDownloadStudyInfo(type, row) {
|
||||
try {
|
||||
let data = {
|
||||
SubjectId: this.SubjectId || this.list[0].SubjectId,
|
||||
TrialReadingCriterionId: this.Criterion.TrialReadingCriterionId,
|
||||
SubjectCode: this.SubjectCode || this.list[0].SubjectCode,
|
||||
SubjectVisitTaskList: [],
|
||||
DicomStudyIdList: [],
|
||||
NoneDicomStudyIdList: [],
|
||||
}
|
||||
if (type === 'dicom' || type === 'all') {
|
||||
this.list.forEach((item) => {
|
||||
if (
|
||||
item.IsDicom &&
|
||||
item.DicomStudyList &&
|
||||
item.DicomStudyList.length > 0
|
||||
) {
|
||||
data.SubjectVisitTaskList.push({
|
||||
SubjectvisitId: item.SourceSubjectVisitId,
|
||||
TaskId: item.VisitTaskId,
|
||||
})
|
||||
let arr = item.DicomStudyList.map((d) => d.Id)
|
||||
data.DicomStudyIdList = [...data.DicomStudyIdList, ...arr]
|
||||
}
|
||||
})
|
||||
}
|
||||
if (type === 'noneDicom' || type === 'all') {
|
||||
this.list.forEach((item) => {
|
||||
if (
|
||||
!item.IsDicom &&
|
||||
item.NoneDicomStudyList &&
|
||||
item.NoneDicomStudyList.length > 0
|
||||
) {
|
||||
data.SubjectVisitTaskList.push({
|
||||
SubjectvisitId: item.SourceSubjectVisitId,
|
||||
TaskId: item.VisitTaskId,
|
||||
})
|
||||
let arr = item.NoneDicomStudyList.map((d) => d.Id)
|
||||
data.NoneDicomStudyIdList = [...data.NoneDicomStudyIdList, ...arr]
|
||||
}
|
||||
})
|
||||
}
|
||||
if (type === 'one') {
|
||||
if (
|
||||
row.IsDicom &&
|
||||
row.DicomStudyList &&
|
||||
row.DicomStudyList.length > 0
|
||||
) {
|
||||
data.SubjectVisitTaskList.push({
|
||||
SubjectvisitId: row.SourceSubjectVisitId,
|
||||
TaskId: row.VisitTaskId,
|
||||
})
|
||||
let arr = row.DicomStudyList.map((d) => d.Id)
|
||||
data.DicomStudyIdList = [...data.DicomStudyIdList, ...arr]
|
||||
}
|
||||
if (
|
||||
!row.IsDicom &&
|
||||
row.NoneDicomStudyList &&
|
||||
row.NoneDicomStudyList.length > 0
|
||||
) {
|
||||
data.SubjectVisitTaskList.push({
|
||||
SubjectvisitId: row.SourceSubjectVisitId,
|
||||
TaskId: row.VisitTaskId,
|
||||
})
|
||||
let arr = row.NoneDicomStudyList.map((d) => d.Id)
|
||||
data.NoneDicomStudyIdList = [...data.NoneDicomStudyIdList, ...arr]
|
||||
}
|
||||
}
|
||||
this.btnLoading = true
|
||||
let res = await getIRReadingDownloadStudyInfo(data)
|
||||
this.btnLoading = false
|
||||
if (res.IsSuccess) {
|
||||
this.downloadId = res.OtherInfo.PreDownloadId
|
||||
this.IsReadingTaskViewInOrder = res.OtherInfo.IsReadingTaskViewInOrder
|
||||
this.downloadImage(res.Result)
|
||||
}
|
||||
} catch (err) {
|
||||
this.btnLoading = false
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 打包下载
|
||||
async downloadImage(data) {
|
||||
try {
|
||||
let { files, name, fileType } = this.formatDownloadFile(data)
|
||||
let res = await downLoadFile(files, name, 'zip')
|
||||
if (res && this.downloadId) {
|
||||
this.downloadImageSuccess()
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 格式化下载文件路径
|
||||
formatDownloadFile(list) {
|
||||
let files = [],
|
||||
name = `${list[0].SubjectCode}_${new Date().getTime()}.zip`
|
||||
if (this.IsReadingTaskViewInOrder === 1) {
|
||||
name = `${list[0].SubjectCode}_${list[0].TaskBlindName}.zip`
|
||||
}
|
||||
if (this.IsReadingTaskViewInOrder === 0) {
|
||||
name = `${list[0].TaskBlindName}.zip`
|
||||
}
|
||||
list.forEach((data) => {
|
||||
if (data.StudyList && data.StudyList.length > 0) {
|
||||
let StudyList = data.StudyList
|
||||
StudyList.forEach((study) => {
|
||||
if (study.SeriesList.length > 0) {
|
||||
study.SeriesList.forEach((series) => {
|
||||
if (series.InstancePathList.length > 0) {
|
||||
series.InstancePathList.forEach((instance) => {
|
||||
let fileName = instance.Path.split('/').pop()
|
||||
let obj = {
|
||||
name: `${data.SubjectCode}/${
|
||||
data.TaskBlindName
|
||||
}/${this.$fd('IsDicom', true)}/${
|
||||
study.StudyCode
|
||||
}/${fileName}`,
|
||||
url: this.OSSclientConfig.basePath + instance.Path,
|
||||
}
|
||||
if (this.IsReadingTaskViewInOrder === 0) {
|
||||
obj = {
|
||||
name: `${data.TaskBlindName}/${this.$fd(
|
||||
'IsDicom',
|
||||
true
|
||||
)}/${fileName}`,
|
||||
url: this.OSSclientConfig.basePath + instance.Path,
|
||||
}
|
||||
}
|
||||
files.push(obj)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
if (data.NoneDicomStudyList && data.NoneDicomStudyList.length > 0) {
|
||||
let NoneDicomStudyList = data.NoneDicomStudyList
|
||||
// 多文件
|
||||
NoneDicomStudyList.forEach((study) => {
|
||||
if (study.FileList.length > 0) {
|
||||
study.FileList.forEach((item) => {
|
||||
let obj = {
|
||||
name: `${data.SubjectCode}/${data.TaskBlindName}/${this.$fd(
|
||||
'IsDicom',
|
||||
false
|
||||
)}/${study.StudyCode}/${item.FileName}`,
|
||||
url: this.OSSclientConfig.basePath + item.Path,
|
||||
}
|
||||
if (this.IsReadingTaskViewInOrder === 0) {
|
||||
obj = {
|
||||
name: `${data.TaskBlindName}/${this.$fd(
|
||||
'IsDicom',
|
||||
false
|
||||
)}/${item.FileName}`,
|
||||
url: this.OSSclientConfig.basePath + item.Path,
|
||||
}
|
||||
}
|
||||
files.push(obj)
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
return { files, name }
|
||||
},
|
||||
// 影像下载成功确认
|
||||
async downloadImageSuccess() {
|
||||
try {
|
||||
let params = {
|
||||
TrialImageDownloadId: this.downloadId,
|
||||
}
|
||||
await downloadImageSuccess(params)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
handleOpenDialog(item) {
|
||||
this.model_cfg.title = `${item.SubjectCode || ''} > ${item.TaskBlindName}`
|
||||
if (item.IsDicom) {
|
||||
this.modelList = item.DicomStudyList
|
||||
} else {
|
||||
this.modelList = item.NoneDicomStudyList
|
||||
this.modelList.forEach((data) => {
|
||||
data.SourceSubjectVisitId = item.SourceSubjectVisitId
|
||||
})
|
||||
}
|
||||
this.modelTaskId = item.VisitTaskId
|
||||
this.IsDicom = item.IsDicom
|
||||
this.model_cfg.visible = true
|
||||
},
|
||||
// 排序
|
||||
handleSortByColumn(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
preview(row) {
|
||||
if (!row.IsDicom) {
|
||||
this.handlePreviewNoneDicomFiles(row)
|
||||
} else {
|
||||
this.handleViewReadingImages(row)
|
||||
}
|
||||
},
|
||||
// 预览单个检查下非Dicom文件
|
||||
handlePreviewNoneDicomFiles(row) {
|
||||
if (this.open) {
|
||||
this.open.close()
|
||||
}
|
||||
let trialId = this.$route.query.trialId
|
||||
var token = getToken()
|
||||
const routeData = this.$router.resolve({
|
||||
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SourceSubjectVisitId}&TokenKey=${token}`,
|
||||
})
|
||||
this.open = window.open(routeData.href, '_blank')
|
||||
},
|
||||
// 预览阅片影像
|
||||
handleViewReadingImages(row) {
|
||||
if (this.open) {
|
||||
this.open.close()
|
||||
}
|
||||
var token = getToken()
|
||||
let trialId = this.$route.query.trialId
|
||||
const routeData = this.$router.resolve({
|
||||
path: `/showvisitdicoms?page=download&trialId=${trialId}&visitTaskId=${row.VisitTaskId}&subjectVisitId=${row.SourceSubjectVisitId}&isReading=1&TokenKey=${token}`,
|
||||
})
|
||||
this.open = window.open(routeData.href, '_blank')
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.top {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
margin: 10px 0;
|
||||
}
|
||||
.tip {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-top: 5px;
|
||||
i {
|
||||
margin: 3px 5px 0 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -52,7 +52,7 @@
|
||||
class="el-icon-warning-outline"
|
||||
style="color: #f56c6c; font-size: 24px"
|
||||
></i>
|
||||
<span>{{ $t("feedBack:imgfail:tip") }}</span>
|
||||
<span>{{ $t('feedBack:imgfail:tip') }}</span>
|
||||
</p>
|
||||
<!-- 问题反馈 -->
|
||||
<el-form-item
|
||||
@@ -140,7 +140,7 @@
|
||||
<div slot="footer" v-if="type !== 'detail' || isImgfail">
|
||||
<!-- 取消 -->
|
||||
<el-button size="small" @click.stop="cancel">
|
||||
{{ $t("feedBack:button:cancel") }}
|
||||
{{ $t('feedBack:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button
|
||||
@@ -149,21 +149,21 @@
|
||||
@click.stop="save"
|
||||
:loading="loading"
|
||||
>
|
||||
{{ $t("feedBack:button:save") }}
|
||||
{{ $t('feedBack:button:save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import uploadImage from "./uploadImage.vue";
|
||||
import uploadImage from './uploadImage.vue'
|
||||
import {
|
||||
addOrUpdateUserFeedBack,
|
||||
getUserFeedBackInfo,
|
||||
batchUpdateFeedBackState,
|
||||
} from "@/api/trials.js";
|
||||
} from '@/api/trials.js'
|
||||
export default {
|
||||
name: "FB",
|
||||
name: 'FB',
|
||||
components: { uploadImage },
|
||||
data() {
|
||||
return {
|
||||
@@ -195,131 +195,131 @@ export default {
|
||||
QuestionType: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("common:ruleMessage:specify"),
|
||||
trigger: "blur",
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
QuestionDescription: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("common:ruleMessage:specify"),
|
||||
trigger: "blur",
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (value.length < 5) {
|
||||
callback(
|
||||
new Error(this.$t("feedBack:ruleMessage:lengthLimitMin5"))
|
||||
);
|
||||
new Error(this.$t('feedBack:ruleMessage:lengthLimitMin5'))
|
||||
)
|
||||
}
|
||||
callback();
|
||||
callback()
|
||||
},
|
||||
trigger: "blur",
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
},
|
||||
isUpload: false,
|
||||
};
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
level() {
|
||||
if (this.hasPermi(["role:dev", "role:admin"])) {
|
||||
return 9;
|
||||
if (this.hasPermi(['role:dev', 'role:admin'])) {
|
||||
return 9
|
||||
}
|
||||
if (this.hasPermi(["role:pm"])) {
|
||||
return 8;
|
||||
if (this.hasPermi(['role:pm', 'role:apm'])) {
|
||||
return 8
|
||||
}
|
||||
if (this.hasPermi(["role:ir", "role:crc"])) {
|
||||
return 7;
|
||||
if (this.hasPermi(['role:ir', 'role:crc'])) {
|
||||
return 7
|
||||
}
|
||||
return 0;
|
||||
return 0
|
||||
},
|
||||
QuestionTypeOptions() {
|
||||
if (this.level > 7) {
|
||||
return [
|
||||
...this.$d.FeedBackTypeToCRC.filter((item) => item.value > 0),
|
||||
...this.$d.FeedBackTypeToIR,
|
||||
];
|
||||
]
|
||||
}
|
||||
if (this.hasPermi(["role:ir"])) {
|
||||
return this.$d.FeedBackTypeToIR;
|
||||
if (this.hasPermi(['role:ir'])) {
|
||||
return this.$d.FeedBackTypeToIR
|
||||
}
|
||||
if (this.hasPermi(["role:crc"])) {
|
||||
return this.$d.FeedBackTypeToCRC;
|
||||
if (this.hasPermi(['role:crc'])) {
|
||||
return this.$d.FeedBackTypeToCRC
|
||||
}
|
||||
return [];
|
||||
return []
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
open(data) {
|
||||
let { type, trialId, Id, visitTaskId, SubjectVisitId } = data;
|
||||
this.type = type;
|
||||
this.trialId = trialId;
|
||||
this.Id = Id;
|
||||
this.visitTaskId = visitTaskId;
|
||||
this.SubjectVisitId = SubjectVisitId;
|
||||
let { type, trialId, Id, visitTaskId, SubjectVisitId } = data
|
||||
this.type = type
|
||||
this.trialId = trialId
|
||||
this.Id = Id
|
||||
this.visitTaskId = visitTaskId
|
||||
this.SubjectVisitId = SubjectVisitId
|
||||
if (visitTaskId) {
|
||||
this.isImgfail = true;
|
||||
this.isImgfail = true
|
||||
}
|
||||
this.setTypeOption();
|
||||
this.setTypeOption()
|
||||
if (!Id) {
|
||||
this.title = this.setTitle();
|
||||
this.title = this.setTitle()
|
||||
}
|
||||
if (Id || visitTaskId) {
|
||||
this.getInfo(Id, visitTaskId);
|
||||
this.getInfo(Id, visitTaskId)
|
||||
}
|
||||
this.visible = true;
|
||||
this.visible = true
|
||||
},
|
||||
cancel() {
|
||||
this.visible = false;
|
||||
this.$emit("closed");
|
||||
this.visible = false
|
||||
this.$emit('closed')
|
||||
},
|
||||
async save() {
|
||||
try {
|
||||
let validate = await this.$refs.feedBackForm.validate();
|
||||
if (!validate) return;
|
||||
let validate = await this.$refs.feedBackForm.validate()
|
||||
if (!validate) return
|
||||
if (this.trialId) {
|
||||
this.form.TrialId = this.trialId;
|
||||
this.form.TrialId = this.trialId
|
||||
}
|
||||
if (this.visitTaskId) {
|
||||
this.form.VisitTaskId = this.visitTaskId;
|
||||
this.form.VisitTaskId = this.visitTaskId
|
||||
}
|
||||
if (this.SubjectVisitId) {
|
||||
this.form.SubjectVisitId = this.SubjectVisitId;
|
||||
this.form.SubjectVisitId = this.SubjectVisitId
|
||||
}
|
||||
if (this.Id) {
|
||||
this.form.Id = this.Id;
|
||||
this.form.Id = this.Id
|
||||
}
|
||||
this.loading = true;
|
||||
let res = await addOrUpdateUserFeedBack(this.form);
|
||||
this.loading = false;
|
||||
this.loading = true
|
||||
let res = await addOrUpdateUserFeedBack(this.form)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.$emit("success");
|
||||
this.$message.success(this.$t("feedBack:save:success"));
|
||||
this.cancel();
|
||||
this.$emit('success')
|
||||
this.$message.success(this.$t('feedBack:save:success'))
|
||||
this.cancel()
|
||||
}
|
||||
} catch (err) {
|
||||
this.loading = false;
|
||||
console.log(err);
|
||||
this.loading = false
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 修改状态
|
||||
async changeState() {
|
||||
if (this.isImgfail) return;
|
||||
if (this.isImgfail) return
|
||||
try {
|
||||
let data = {
|
||||
IdList: [this.Id],
|
||||
State: this.form.State,
|
||||
};
|
||||
let res = await batchUpdateFeedBackState(data);
|
||||
}
|
||||
let res = await batchUpdateFeedBackState(data)
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t("feedBack:changeState:success"));
|
||||
this.$emit("success");
|
||||
this.$message.success(this.$t('feedBack:changeState:success'))
|
||||
this.$emit('success')
|
||||
// this.cancel();
|
||||
this.getInfo(this.Id, this.visitTaskId);
|
||||
this.getInfo(this.Id, this.visitTaskId)
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 获取反馈详情
|
||||
@@ -328,56 +328,56 @@ export default {
|
||||
let data = {
|
||||
Id,
|
||||
visitTaskId,
|
||||
};
|
||||
let res = await getUserFeedBackInfo(data);
|
||||
}
|
||||
let res = await getUserFeedBackInfo(data)
|
||||
if (res.IsSuccess && res.Result) {
|
||||
this.form = res.Result;
|
||||
this.Id = res.Result.Id;
|
||||
this.form = res.Result
|
||||
this.form.ScreenshotList = this.form.ScreenshotList || []
|
||||
this.Id = res.Result.Id
|
||||
if (res.Result.State > 0) {
|
||||
this.isStateChange = false;
|
||||
this.isStateChange = false
|
||||
}
|
||||
if (res.Result.VisitTaskId) {
|
||||
this.visitTaskId = res.Result.VisitTaskId;
|
||||
this.visitTaskId = res.Result.VisitTaskId
|
||||
}
|
||||
if (res.Result.SubjectVisitId) {
|
||||
this.SubjectVisitId = res.Result.SubjectVisitId;
|
||||
this.SubjectVisitId = res.Result.SubjectVisitId
|
||||
}
|
||||
let code = this.$fd("UserType", res.Result.UserTypeEnum);
|
||||
this.title = this.setTitle(code, res.Result.FeedBackFullName);
|
||||
let code = this.$fd('UserType', res.Result.UserTypeEnum)
|
||||
this.title = this.setTitle(code, res.Result.FeedBackFullName)
|
||||
if (visitTaskId) {
|
||||
code = `${res.Result.SubjectCode}-${res.Result.SubjectVisitName}`;
|
||||
this.title = this.setTitle(code, res.Result.FeedBackFullName);
|
||||
code = `${res.Result.SubjectCode}-${res.Result.SubjectVisitName}`
|
||||
this.title = this.setTitle(code, res.Result.FeedBackFullName)
|
||||
}
|
||||
this.$refs.uploadImage.initFileList(res.Result.ScreenshotList);
|
||||
this.$refs.uploadImage.initFileList(res.Result.ScreenshotList)
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
setTypeOption() {
|
||||
if (!this.trialId) return (this.options = []);
|
||||
if (this.hasPermi(["role:ir"]))
|
||||
return (this.option = this.$d.FeedBackTypeToIR);
|
||||
if (this.hasPermi(["role:crc"]))
|
||||
return (this.option = this.$d.FeedBackTypeToCRC);
|
||||
if (!this.trialId) return (this.options = [])
|
||||
if (this.hasPermi(['role:ir']))
|
||||
return (this.option = this.$d.FeedBackTypeToIR)
|
||||
if (this.hasPermi(['role:crc']))
|
||||
return (this.option = this.$d.FeedBackTypeToCRC)
|
||||
},
|
||||
setTitle(code, name) {
|
||||
console.log(code, name);
|
||||
if (this.hasPermi(["role:pm"]) && this.visitTaskId) {
|
||||
return `${this.$t("feedBack:form:title:pm2")}(${code}/${name})`;
|
||||
if (this.hasPermi(['role:pm']) && this.visitTaskId) {
|
||||
return `${this.$t('feedBack:form:title:pm2')}(${code}/${name})`
|
||||
}
|
||||
if (this.hasPermi(["role:pm", "role:dev", "role:admin"])) {
|
||||
return `${this.$t("feedBack:form:title:pm")}(${code},${name})`;
|
||||
if (this.hasPermi(['role:pm', 'role:dev', 'role:admin'])) {
|
||||
return `${this.$t('feedBack:form:title:pm')}(${code},${name})`
|
||||
}
|
||||
if (this.hasPermi(["role:ir", "role:crc"]) && this.type === "detail") {
|
||||
return `${this.$t("feedBack:form:detail:title")}`;
|
||||
if (this.hasPermi(['role:ir', 'role:crc']) && this.type === 'detail') {
|
||||
return `${this.$t('feedBack:form:detail:title')}`
|
||||
}
|
||||
if (this.hasPermi(["role:ir", "role:crc"])) {
|
||||
return `${this.$t("feedBack:form:title")}`;
|
||||
if (this.hasPermi(['role:ir', 'role:crc'])) {
|
||||
return `${this.$t('feedBack:form:title')}`
|
||||
}
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.tip {
|
||||
|
||||
@@ -58,14 +58,14 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
const type = "Statement of Work";
|
||||
const type = 'Statement of Work'
|
||||
export default {
|
||||
name: "UploadImage",
|
||||
name: 'UploadImage',
|
||||
props: {
|
||||
path: {
|
||||
required: true,
|
||||
default: () => {
|
||||
return [];
|
||||
return []
|
||||
},
|
||||
},
|
||||
disabled: {
|
||||
@@ -78,14 +78,14 @@ export default {
|
||||
},
|
||||
trialId: {
|
||||
type: String,
|
||||
default: "",
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fileList: [],
|
||||
btnDisabled: false,
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
remove(file, fileList) {
|
||||
@@ -93,115 +93,113 @@ export default {
|
||||
},
|
||||
fileToBlob(file) {
|
||||
// 创建 FileReader 对象
|
||||
const reader = new FileReader();
|
||||
const reader = new FileReader()
|
||||
return new Promise((resolve) => {
|
||||
// FileReader 添加 load 事件
|
||||
reader.addEventListener("load", (e) => {
|
||||
let blob;
|
||||
if (typeof e.target.result === "object") {
|
||||
blob = new Blob([e.target.result]);
|
||||
reader.addEventListener('load', (e) => {
|
||||
let blob
|
||||
if (typeof e.target.result === 'object') {
|
||||
blob = new Blob([e.target.result])
|
||||
} else {
|
||||
blob = e.target.result;
|
||||
blob = e.target.result
|
||||
}
|
||||
resolve(blob);
|
||||
});
|
||||
resolve(blob)
|
||||
})
|
||||
// FileReader 以 ArrayBuffer 格式 读取 File 对象中数据
|
||||
reader.readAsArrayBuffer(file);
|
||||
});
|
||||
reader.readAsArrayBuffer(file)
|
||||
})
|
||||
},
|
||||
// 上传oss
|
||||
async uploadToOSS(name, file) {
|
||||
try {
|
||||
let defaultPath = "/System/FeedBack/";
|
||||
let defaultPath = '/System/FeedBack/'
|
||||
if (this.trialId) {
|
||||
defaultPath = `/${this.trialId}/FeedBack/`;
|
||||
defaultPath = `/${this.trialId}/FeedBack/`
|
||||
}
|
||||
let res = await this.OSSclient.put(`${defaultPath}${name}`, file);
|
||||
return res;
|
||||
let res = await this.OSSclient.put(`${defaultPath}${name}`, file)
|
||||
return res
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
return false;
|
||||
console.log(err)
|
||||
return false
|
||||
}
|
||||
},
|
||||
initFileList(list) {
|
||||
if (list && list.length > 0) {
|
||||
this.fileList = [];
|
||||
this.fileList = []
|
||||
list.forEach((item, index) => {
|
||||
let name = item.split("/");
|
||||
let name = item.split('/')
|
||||
this.fileList.push({
|
||||
name: name[name.length - 1],
|
||||
path: item,
|
||||
fullPath: this.OSSclientConfig.basePath + item,
|
||||
url: this.OSSclientConfig.basePath + item,
|
||||
uid: `${name[name.length - 1]}${index}`,
|
||||
});
|
||||
});
|
||||
console.log(this.fileList);
|
||||
})
|
||||
})
|
||||
}
|
||||
},
|
||||
async uploadFile(param) {
|
||||
var fileName = param.file.name;
|
||||
this.$emit("update:isUpload", true);
|
||||
this.btnDisabled = true;
|
||||
var fileName = param.file.name
|
||||
this.$emit('update:isUpload', true)
|
||||
this.btnDisabled = true
|
||||
this.fileList.push({
|
||||
url: param.file.url,
|
||||
path: fileName,
|
||||
uid: param.file.uid,
|
||||
});
|
||||
let file = await this.fileToBlob(param.file);
|
||||
let res = await this.uploadToOSS(fileName, file);
|
||||
this.btnDisabled = false;
|
||||
let index = this.fileList.findIndex(
|
||||
(item) => item.uid === param.file.uid
|
||||
);
|
||||
})
|
||||
let file = await this.fileToBlob(param.file)
|
||||
let res = await this.uploadToOSS(fileName, file)
|
||||
this.btnDisabled = false
|
||||
let index = this.fileList.findIndex((item) => item.uid === param.file.uid)
|
||||
if (!res) {
|
||||
if (index >= 0) {
|
||||
this.fileList.splice(index, 1);
|
||||
this.fileList.splice(index, 1)
|
||||
}
|
||||
return this.$emit("update:isUpload", false);
|
||||
return this.$emit('update:isUpload', false)
|
||||
}
|
||||
this.fileList[index].url = this.OSSclientConfig.basePath + res.name;
|
||||
this.fileList[index].path = res.name;
|
||||
this.$emit("update:path", [...this.path, res.name]);
|
||||
this.$emit("update:isUpload", false);
|
||||
return false;
|
||||
let name = this.$getObjectName(res.url)
|
||||
this.fileList[index].url = this.OSSclientConfig.basePath + name
|
||||
this.fileList[index].path = name
|
||||
this.$emit('update:path', [...this.path, res.name])
|
||||
this.$emit('update:isUpload', false)
|
||||
return false
|
||||
},
|
||||
beforeUpload(file, fileList) {
|
||||
const isValidFile = this.fileValid(file.name, ["png", "jpg", "jpeg"]);
|
||||
const isValidFile = this.fileValid(file.name, ['png', 'jpg', 'jpeg'])
|
||||
if (isValidFile) {
|
||||
// this.fileList = [];
|
||||
} else {
|
||||
this.$alert(this.$t("feedBack:uploadImg:format"));
|
||||
return false;
|
||||
this.$alert(this.$t('feedBack:uploadImg:format'))
|
||||
return false
|
||||
}
|
||||
},
|
||||
handlePreview(file) {
|
||||
file.fullPath ? window.open(file.fullPath, "_blank") : "";
|
||||
file.fullPath ? window.open(file.fullPath, '_blank') : ''
|
||||
},
|
||||
handleExceed(files, fileList) {
|
||||
this.$message.warning(`Upload is currently limited to 1 file`);
|
||||
this.$message.warning(`Upload is currently limited to 1 file`)
|
||||
},
|
||||
fileValid(fileName, typeArr) {
|
||||
var extendName = fileName
|
||||
.substring(fileName.lastIndexOf(".") + 1)
|
||||
.toLocaleLowerCase();
|
||||
.substring(fileName.lastIndexOf('.') + 1)
|
||||
.toLocaleLowerCase()
|
||||
if (typeArr.indexOf(extendName) > -1) {
|
||||
return true;
|
||||
return true
|
||||
} else {
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
},
|
||||
handlePictureCardPreview(file) {
|
||||
this.$refs[file.url].$viewer.show();
|
||||
this.$refs[file.url].$viewer.show()
|
||||
},
|
||||
handleRemove(file) {
|
||||
let index = this.fileList.findIndex((item) => item.uid === file.uid);
|
||||
this.fileList.splice(index, 1);
|
||||
let arr = this.fileList.map((item) => item.path);
|
||||
this.$emit("update:path", arr);
|
||||
let index = this.fileList.findIndex((item) => item.uid === file.uid)
|
||||
this.fileList.splice(index, 1)
|
||||
let arr = this.fileList.map((item) => item.path)
|
||||
this.$emit('update:path', arr)
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.upload-container .el-upload--text {
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<el-dialog
|
||||
:visible.sync="visible"
|
||||
:fullscreen="true"
|
||||
:close-on-click-modal="false"
|
||||
:before-close="beforeClose"
|
||||
:append-to-body="true"
|
||||
class="uploadDicomAndNonedicom"
|
||||
>
|
||||
<span slot="title">{{ title }}</span>
|
||||
<el-tabs type="border-card" v-model="activeName">
|
||||
<el-tab-pane
|
||||
:label="$t('uploadDicomAndNonedicom:label:dicom')"
|
||||
name="dicom"
|
||||
>
|
||||
<dicomFile
|
||||
v-if="activeName === 'dicom'"
|
||||
:SubjectId="SubjectId"
|
||||
:SubjectCode="SubjectCode"
|
||||
:Criterion="Criterion"
|
||||
:TaskId="VisitTaskId"
|
||||
:isUpload.sync="isUpload"
|
||||
:isReadingTaskViewInOrder="isReadingTaskViewInOrder"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane
|
||||
:label="$t('uploadDicomAndNonedicom:label:nonedicom')"
|
||||
name="nonedicom"
|
||||
>
|
||||
<nonedicomFile
|
||||
v-if="activeName === 'nonedicom'"
|
||||
:SubjectId="SubjectId"
|
||||
:SubjectCode="SubjectCode"
|
||||
:Criterion="Criterion"
|
||||
:VisitTaskId="VisitTaskId"
|
||||
:isUpload.sync="isUpload"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
</el-dialog>
|
||||
</template>
|
||||
<script>
|
||||
import dicomFile from './dicomFile.vue'
|
||||
import nonedicomFile from './nonedicomFile.vue'
|
||||
import store from '@/store'
|
||||
export default {
|
||||
name: 'uploadDicomAndNonedicom',
|
||||
components: { dicomFile, nonedicomFile },
|
||||
props: {
|
||||
visible: {
|
||||
required: true,
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
SubjectId: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
SubjectCode: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
Criterion: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
VisitTaskId: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
isReadingTaskViewInOrder: {
|
||||
type: Number,
|
||||
default: 0,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
title: '',
|
||||
activeName: 'dicom',
|
||||
isUpload: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.title = `Upload Images:${this.SubjectCode}(${this.Criterion.TrialReadingCriterionName})`
|
||||
store.dispatch('trials/setUnLock', true)
|
||||
},
|
||||
methods: {
|
||||
beforeClose() {
|
||||
if (
|
||||
this.$route.path !== '/trials/trials-panel/reading/readingTask' &&
|
||||
this.isUpload
|
||||
) {
|
||||
return window.location.reload()
|
||||
}
|
||||
this.$emit('update:visible', false)
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
::v-deep.el-tabs--left .el-tabs__header.is-left {
|
||||
margin-right: 0;
|
||||
}
|
||||
.uploadDicomAndNonedicom {
|
||||
::v-deep.el-tabs--border-card > .el-tabs__header .el-tabs__item {
|
||||
color: #909399;
|
||||
}
|
||||
::v-deep.el-tabs--border-card > .el-tabs__header .el-tabs__item.is-active {
|
||||
color: #428bca;
|
||||
background-color: #fff;
|
||||
border-right-color: #dcdfe6;
|
||||
border-left-color: #dcdfe6;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,919 @@
|
||||
<template>
|
||||
<div class="nonedicomFile">
|
||||
<div class="top">
|
||||
<span>{{ $t('upload:nonedicom:title') }}</span>
|
||||
<div class="tip">
|
||||
<i class="el-icon-warning-outline"></i>
|
||||
<div v-html="$t('upload:nonedicom:tip:message')"></div>
|
||||
</div>
|
||||
</div>
|
||||
<!--检查列表-->
|
||||
<el-table
|
||||
:data="list"
|
||||
style="width: 100%"
|
||||
v-adaptive="{ bottomOffset: 60 }"
|
||||
:loading="loading"
|
||||
@sort-change="handleSortByColumn"
|
||||
:default-sort="{ prop: 'TaskBlindName', order: 'descending' }"
|
||||
>
|
||||
<!--受试者-->
|
||||
<el-table-column
|
||||
prop="SubjectCode"
|
||||
:label="$t('upload:nonedicom:table:subject')"
|
||||
/>
|
||||
<!--任务名称-->
|
||||
<el-table-column
|
||||
prop="TaskBlindName"
|
||||
:label="$t('upload:nonedicom:table:taskName')"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!--检查类型-->
|
||||
<el-table-column
|
||||
prop="Modality"
|
||||
:label="$t('upload:nonedicom:table:molityType')"
|
||||
sortable="custom"
|
||||
>
|
||||
</el-table-column>
|
||||
<!--检查部位-->
|
||||
<el-table-column
|
||||
prop="BodyPart"
|
||||
:label="$t('upload:nonedicom:table:bodyPart')"
|
||||
sortable="custom"
|
||||
/>
|
||||
<!--原文件数-->
|
||||
<el-table-column
|
||||
prop="FileCount"
|
||||
:label="$t('upload:nonedicom:table:fileCount')"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-popover
|
||||
v-if="scope.row.FileCount"
|
||||
trigger="click"
|
||||
placement="bottom"
|
||||
>
|
||||
<el-table :data="scope.row.FileList" height="300" size="small">
|
||||
<!-- 文件名称 -->
|
||||
<el-table-column
|
||||
prop="FileName"
|
||||
:label="$t('trials:audit:table:nonDicomsFileName')"
|
||||
width="200"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="FileSize"
|
||||
:label="$t('trials:audit:table:nonDicomsFileSize')"
|
||||
width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{
|
||||
scope.row.FileSize && scope.row.FileSize > 0
|
||||
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB`
|
||||
: ''
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common:action:action')" width="120">
|
||||
<template slot-scope="files">
|
||||
<!-- 预览 -->
|
||||
<viewer
|
||||
:ref="files.row.Path"
|
||||
style="margin: 0 10px"
|
||||
:images="[`${OSSclientConfig.basePath}${files.row.Path}`]"
|
||||
>
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-view"
|
||||
:title="$t('upload:nonedicom:button:preview')"
|
||||
:disabled="
|
||||
files.row.FileType &&
|
||||
files.row.FileType.indexOf('zip') >= 0
|
||||
"
|
||||
@click.native.prevent="previewFile(files.row)"
|
||||
/>
|
||||
<img
|
||||
v-show="false"
|
||||
crossorigin="anonymous"
|
||||
:src="`${OSSclientConfig.basePath}${files.row.Path}`"
|
||||
alt="Image"
|
||||
/>
|
||||
</viewer>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-button type="text">
|
||||
{{ scope.row.FileCount }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-popover>
|
||||
<span v-else>{{ scope.row.FileCount }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--后处理文件数-->
|
||||
<el-table-column
|
||||
prop="UploadedFileCount"
|
||||
:label="$t('upload:nonedicom:table:uploadFileCount')"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-popover
|
||||
v-if="scope.row.UploadedFileCount"
|
||||
trigger="click"
|
||||
placement="bottom"
|
||||
>
|
||||
<el-table
|
||||
:data="scope.row.UploadedFileList"
|
||||
height="300"
|
||||
size="small"
|
||||
>
|
||||
<!-- 文件名称 -->
|
||||
<el-table-column
|
||||
prop="FileName"
|
||||
:label="$t('trials:audit:table:nonDicomsFileName')"
|
||||
width="200"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="FileSize"
|
||||
:label="$t('trials:audit:table:nonDicomsFileSize')"
|
||||
width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{
|
||||
scope.row.FileSize && scope.row.FileSize > 0
|
||||
? `${(scope.row.FileSize / 1024 / 1024).toFixed(2)}MB`
|
||||
: ''
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common:action:action')" width="120">
|
||||
<template slot-scope="files">
|
||||
<!-- 预览 -->
|
||||
<viewer
|
||||
:ref="files.row.Path"
|
||||
style="margin: 0 10px"
|
||||
:images="[`${OSSclientConfig.basePath}${files.row.Path}`]"
|
||||
>
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-view"
|
||||
:title="$t('upload:nonedicom:button:preview')"
|
||||
:disabled="
|
||||
files.row.FileType &&
|
||||
files.row.FileType.indexOf('zip') >= 0
|
||||
"
|
||||
@click.native.prevent="previewFile(files.row)"
|
||||
/>
|
||||
<img
|
||||
v-show="false"
|
||||
crossorigin="anonymous"
|
||||
:src="`${OSSclientConfig.basePath}${files.row.Path}`"
|
||||
alt="Image"
|
||||
/>
|
||||
</viewer>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div slot="reference" class="name-wrapper">
|
||||
<el-button type="text">
|
||||
{{ scope.row.UploadedFileCount }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-popover>
|
||||
<span v-else>{{ scope.row.UploadedFileCount }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
fixed="right"
|
||||
width="180"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<!--预览--->
|
||||
<el-button
|
||||
circle
|
||||
:disabled="scope.row.UploadedFileCount <= 0"
|
||||
icon="el-icon-view"
|
||||
:title="$t('upload:nonedicom:button:preview')"
|
||||
@click.stop="handlePreviewNoneDicomFiles(scope.row)"
|
||||
/>
|
||||
<!--上传--->
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-upload2"
|
||||
:title="$t('upload:nonedicom:button:upload')"
|
||||
@click.native.prevent="handleUpload(scope.row)"
|
||||
/>
|
||||
<!--删除--->
|
||||
<el-button
|
||||
:disabled="
|
||||
scope.row.UploadedFileCount <= 0 ||
|
||||
scope.row.ReadingTaskState === 2
|
||||
"
|
||||
circle
|
||||
icon="el-icon-delete"
|
||||
:title="$t('upload:nonedicom:button:delete')"
|
||||
@click.stop="remove(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<!-- 预览单个图像 -->
|
||||
<el-dialog
|
||||
v-if="imgObj.visible"
|
||||
:visible.sync="imgObj.visible"
|
||||
:title="$t('upload:nonedicom:dialogTitle:preview')"
|
||||
append-to-body
|
||||
width="565px"
|
||||
>
|
||||
<div
|
||||
v-loading="imgObj.loading"
|
||||
class="base-modal-body"
|
||||
style="border: 2px solid #ccc; padding: 10px"
|
||||
>
|
||||
<el-image
|
||||
:src="`${OSSclientConfig.basePath}${imgObj.url}`"
|
||||
crossorigin="anonymous"
|
||||
fit="fit"
|
||||
style="height: 500px; width: 500px"
|
||||
@error="imgObj.loading = false"
|
||||
@load="imgObj.loading = false"
|
||||
/>
|
||||
</div>
|
||||
</el-dialog>
|
||||
<!-- 上传非dicom文件 -->
|
||||
<el-dialog
|
||||
v-if="uploadVisible"
|
||||
:visible.sync="uploadVisible"
|
||||
:close-on-click-modal="false"
|
||||
:title="$t('trials:uploadNonDicoms:dialogTitle:upload')"
|
||||
width="800px"
|
||||
append-to-body
|
||||
custom-class="base-dialog-wrapper"
|
||||
@close="resetFileDiaolg"
|
||||
>
|
||||
<!-- 多文件上传 -->
|
||||
<form id="inputForm" ref="uploadForm">
|
||||
<el-divider content-position="left">{{
|
||||
$t('trials:uploadNonDicoms:label:fileType')
|
||||
}}</el-divider>
|
||||
<div class="form-group">
|
||||
<div class="upload" style="margin-right: 10px">
|
||||
<input
|
||||
multiple="multiple"
|
||||
webkitdirectory=""
|
||||
directory
|
||||
accept="*/*"
|
||||
type="file"
|
||||
name="uploadFolder"
|
||||
class="select-file"
|
||||
title=""
|
||||
@change="beginScanFiles($event)"
|
||||
v-if="!btnLoading"
|
||||
/>
|
||||
<div class="btn-select">
|
||||
{{ $t('trials:uploadNonDicoms:button:selectFolder') }}
|
||||
</div>
|
||||
</div>
|
||||
<div class="upload">
|
||||
<input
|
||||
class="select-file"
|
||||
multiple=""
|
||||
:accept="faccept.join(',')"
|
||||
type="file"
|
||||
name="uploadFile"
|
||||
title=""
|
||||
@change="beginScanFiles($event)"
|
||||
v-if="!btnLoading"
|
||||
/>
|
||||
<div class="btn-select">
|
||||
{{ $t('trials:uploadNonDicoms:button:select') }}
|
||||
</div>
|
||||
</div>
|
||||
<!-- <span style="margin-left: 10px">{{
|
||||
$store.state.trials.uploadTip
|
||||
}}</span> -->
|
||||
</div>
|
||||
</form>
|
||||
<!-- 文件列表 -->
|
||||
<el-table
|
||||
ref="filesTable"
|
||||
:data="fileList"
|
||||
class="dicomFiles-table"
|
||||
height="300"
|
||||
@selection-change="handleSelectionChange"
|
||||
>
|
||||
<el-table-column
|
||||
type="selection"
|
||||
width="55"
|
||||
:selectable="(row, index) => row.status !== 2 && !btnLoading"
|
||||
/>
|
||||
<el-table-column type="index" width="50" />
|
||||
<!-- 文件名称 -->
|
||||
<el-table-column
|
||||
prop="name"
|
||||
:label="$t('trials:uploadNonDicoms:table:fileName')"
|
||||
min-width="100"
|
||||
/>
|
||||
<!-- 文件大小 -->
|
||||
<el-table-column
|
||||
prop="size"
|
||||
:label="$t('trials:uploadNonDicoms:table:fileSize')"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{
|
||||
scope.row.size && scope.row.size > 0
|
||||
? `${(scope.row.size / 1024 / 1024).toFixed(2)}MB`
|
||||
: ''
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 文件类型 -->
|
||||
<el-table-column
|
||||
prop="type"
|
||||
:label="$t('trials:uploadNonDicoms:table:fileType')"
|
||||
/>
|
||||
<!-- 上传状态 -->
|
||||
<el-table-column
|
||||
prop="status"
|
||||
:label="$t('trials:uploadNonDicoms:table:uploadStatus')"
|
||||
min-width="100"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag
|
||||
:type="['warning', 'info', 'success', 'danger'][scope.row.status]"
|
||||
v-if="scope.row.status || scope.row.status === 0"
|
||||
>{{ $fd('NoneDicomUploadStatus', scope.row.status) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
:label="$t('trials:uploadNonDicoms:table:failedFileCount')"
|
||||
min-width="150"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-progress
|
||||
color="#409eff"
|
||||
:percentage="
|
||||
((scope.row.uploadFileSize * 100) / scope.row.size).toFixed(2) *
|
||||
1
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column :label="$t('common:action:action')">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
size="mini"
|
||||
icon="el-icon-delete"
|
||||
circle
|
||||
:disabled="btnLoading"
|
||||
:title="$t('trials:crcUpload:action:delete')"
|
||||
@click="handleRemoveFile(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
<div style="text-align: right; padding: 10px 0px">
|
||||
<span style="margin-right: 10px">{{
|
||||
$store.state.trials.uploadTip
|
||||
}}</span>
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:disabled="selectArr.length == 0"
|
||||
:loading="btnLoading"
|
||||
@click="beginUpload"
|
||||
>
|
||||
{{ $t('trials:uploadNonDicoms:action:upload') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
getIRUploadTaskNoneDicomStudyList,
|
||||
deleteTaskStudy,
|
||||
} from '@/api/load.js'
|
||||
import { preArchiveStudy, uploadNoneDicomFile } from '@/api/trials'
|
||||
import store from '@/store'
|
||||
import { getToken } from '@/utils/auth'
|
||||
let defaultSearchData = () => {
|
||||
return {
|
||||
SubjectId: null,
|
||||
TrialReadingCriterionId: null,
|
||||
SubjectCode: null,
|
||||
Asc: false,
|
||||
SortField: 'TaskBlindName',
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'nonedicomFile',
|
||||
props: {
|
||||
SubjectId: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
SubjectCode: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
Criterion: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
VisitTaskId: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
isUpload: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
loading: false,
|
||||
list: [],
|
||||
searchData: defaultSearchData(),
|
||||
imgObj: { url: '', visible: false, loading: false },
|
||||
uploadVisible: false,
|
||||
fileList: [],
|
||||
selectArr: [],
|
||||
successFileList: [],
|
||||
isFail: false,
|
||||
faccept: ['.jpg', '.jpeg', '.png', '.bmp', '.zip'],
|
||||
fCount: 0,
|
||||
btnLoading: false,
|
||||
currentRow: {},
|
||||
studyMonitorId: null,
|
||||
open: null,
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
isFail() {
|
||||
if (this.isFail) {
|
||||
this.$confirm(
|
||||
this.$t('trials:visit:crcUpload:nomDicomFiles:failUpload'),
|
||||
{
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: this.$t('common:button:confirm'),
|
||||
cancelButtonText: this.$t('common:button:cancel'),
|
||||
}
|
||||
)
|
||||
.then(() => {
|
||||
this.beginUpload()
|
||||
})
|
||||
.catch((err) => {
|
||||
this.btnLoading = false
|
||||
console.log(err)
|
||||
})
|
||||
}
|
||||
},
|
||||
btnLoading() {
|
||||
store.dispatch('trials/setUnLock', this.btnLoading)
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getList()
|
||||
},
|
||||
beforeDestroy() {
|
||||
store.dispatch('trials/setUnLock', false)
|
||||
},
|
||||
methods: {
|
||||
async getList() {
|
||||
try {
|
||||
this.searchData.SubjectId = this.SubjectId
|
||||
this.searchData.TrialReadingCriterionId =
|
||||
this.Criterion.TrialReadingCriterionId
|
||||
this.searchData.SubjectCode = this.SubjectCode
|
||||
if (this.VisitTaskId) {
|
||||
this.searchData.VisitTaskId = this.VisitTaskId
|
||||
}
|
||||
this.loading = true
|
||||
let res = await getIRUploadTaskNoneDicomStudyList(this.searchData)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.list = res.Result
|
||||
}
|
||||
} catch (err) {
|
||||
this.loading = false
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 扫描待上传文件
|
||||
beginScanFiles(e) {
|
||||
var files = [...e.target.files]
|
||||
var sameFiles = []
|
||||
files.forEach((file) => {
|
||||
var extendName = file.name
|
||||
.substring(file.name.lastIndexOf('.'))
|
||||
.toLocaleLowerCase()
|
||||
if (
|
||||
this.faccept.indexOf(extendName) !== -1 &&
|
||||
this.fileList.findIndex((v) => v.name === file.name) > -1
|
||||
) {
|
||||
sameFiles.push(file.name)
|
||||
}
|
||||
})
|
||||
var scope = this
|
||||
if (sameFiles.length > 0) {
|
||||
const h = this.$createElement
|
||||
var msg = this.$t(
|
||||
'trials:uploadNonDicoms:message:exsitSameFile'
|
||||
).replace('xxx', sameFiles.join(', '))
|
||||
this.$msgbox({
|
||||
message: h('div', { style: 'maxHeight:300px;overflow: auto;' }, [
|
||||
h('p', null, msg),
|
||||
h(
|
||||
'p',
|
||||
null,
|
||||
this.$t('trials:uploadNonDicoms:message:isContinueUpload')
|
||||
),
|
||||
]),
|
||||
type: 'warning',
|
||||
showCancelButton: true,
|
||||
})
|
||||
.then(() => {
|
||||
scope.pendingUploadQuene(files)
|
||||
})
|
||||
.catch(() => {
|
||||
scope.resetUploadForm()
|
||||
})
|
||||
} else {
|
||||
scope.pendingUploadQuene(files)
|
||||
}
|
||||
},
|
||||
pendingUploadQuene(files) {
|
||||
for (var i = 0; i < files.length; ++i) {
|
||||
const fileName = files[i].name
|
||||
var extendName = fileName
|
||||
.substring(fileName.lastIndexOf('.'))
|
||||
.toLocaleLowerCase()
|
||||
if (this.faccept.indexOf(extendName) !== -1) {
|
||||
files[i].id = `${files[i].lastModified}${files[i].name}`
|
||||
let obj = {
|
||||
name: files[i].name,
|
||||
size: files[i].size,
|
||||
type: extendName.split('.')[1],
|
||||
status: 0,
|
||||
file: files[i],
|
||||
id: `${files[i].lastModified}${files[i].name}`,
|
||||
fileType: files[i].type,
|
||||
uploadFileSize: 0,
|
||||
}
|
||||
this.fileList.push(obj)
|
||||
this.$refs.filesTable.toggleRowSelection(obj, true)
|
||||
}
|
||||
}
|
||||
this.resetUploadForm()
|
||||
},
|
||||
handleRemoveFile(row) {
|
||||
this.$confirm(this.$t('trials:uploadNonDicoms:message:delete'), {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true,
|
||||
})
|
||||
.then(() => {
|
||||
this.fileList.splice(
|
||||
this.fileList.findIndex((item) => item.id === row.id),
|
||||
1
|
||||
)
|
||||
let flag = this.successFileList.some((item) => item.id === row.id)
|
||||
if (flag) {
|
||||
this.successFileList.splice(
|
||||
this.successFileList.findIndex((item) => item.id === row.id),
|
||||
1
|
||||
)
|
||||
}
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
resetUploadForm() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.uploadForm.reset()
|
||||
})
|
||||
},
|
||||
// 打开上传文件弹窗
|
||||
handleUpload(row) {
|
||||
this.fileList = []
|
||||
this.uploadVisible = true
|
||||
this.fCount = 0
|
||||
this.currentRow = { ...row }
|
||||
},
|
||||
resetFileDiaolg() {
|
||||
this.btnLoading = false
|
||||
this.uploadVisible = false
|
||||
this.selectArr = []
|
||||
this.successFileList = []
|
||||
this.OSSclient.close()
|
||||
},
|
||||
// 预览文件
|
||||
previewFile(row) {
|
||||
// window.open(row.FullFilePath, '_blank')
|
||||
// this.imgObj.url = row.FullFilePath || row.Path
|
||||
// this.imgObj.loading = true
|
||||
// this.imgObj.visible = true
|
||||
this.$refs[row.Path].$viewer.show()
|
||||
},
|
||||
// 预览单个检查下非Dicom文件
|
||||
handlePreviewNoneDicomFiles(row) {
|
||||
if (this.open) {
|
||||
this.open.close()
|
||||
}
|
||||
let trialId = this.$route.query.trialId
|
||||
var token = getToken()
|
||||
const routeData = this.$router.resolve({
|
||||
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SourceSubjectVisitId}&studyId=${row.Id}&visitTaskId=${row.VisitTaskId}&TokenKey=${token}`,
|
||||
})
|
||||
this.open = window.open(routeData.href, '_blank')
|
||||
},
|
||||
// 删除
|
||||
async remove(item) {
|
||||
try {
|
||||
let confirm = await this.$confirm(
|
||||
this.$t('upload:nonedicom:confirm:delMessage'),
|
||||
{
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: this.$t('common:button:confirm'),
|
||||
cancelButtonText: this.$t('common:button:cancel'),
|
||||
}
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
let params = {
|
||||
VisitTaskId: item.VisitTaskId,
|
||||
IsDicom: false,
|
||||
NoneDicomStudyId: item.Id,
|
||||
}
|
||||
let res = await deleteTaskStudy(params)
|
||||
if (res.IsSuccess) {
|
||||
this.getList()
|
||||
this.$emit('update:isUpload', true)
|
||||
this.$message.success(
|
||||
this.$t('trials:uploadImage:message:delSuccess')
|
||||
)
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 排序
|
||||
handleSortByColumn(column) {
|
||||
if (column.order === 'ascending') {
|
||||
this.searchData.Asc = true
|
||||
} else {
|
||||
this.searchData.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
// 获取待上传文件信息
|
||||
handleSelectionChange(selection) {
|
||||
this.selectArr = selection
|
||||
},
|
||||
// 开始上传文件
|
||||
async beginUpload() {
|
||||
this.btnLoading = true
|
||||
this.isFail = false
|
||||
const fileMaxSize = 1024 * 1024 * 1024 * 2 // 1G
|
||||
var currentFilesSize = 0
|
||||
this.selectArr.forEach((item) => {
|
||||
currentFilesSize += item.size
|
||||
})
|
||||
if (currentFilesSize / fileMaxSize > 1) {
|
||||
// 'Upload file size cannot exceed 1G'
|
||||
this.$alert(this.$t('trials:uploadNonDicoms:message:uploadSize'))
|
||||
this.btnLoading = false
|
||||
} else {
|
||||
this.selectArr.forEach((item) => (item.status = 0))
|
||||
let num = this.selectArr.length > 6 ? 6 : this.selectArr.length
|
||||
let funArr = []
|
||||
let res = await preArchiveStudy({
|
||||
subjectVisitId: this.currentRow.SourceSubjectVisitId,
|
||||
isDicom: false,
|
||||
FileCount: this.selectArr.length,
|
||||
})
|
||||
if (res.IsSuccess) {
|
||||
this.studyMonitorId = res.Result
|
||||
for (let i = 0; i < num; i++) {
|
||||
funArr.push(this.handleUploadTask(this.selectArr, i))
|
||||
}
|
||||
if (funArr.length > 0) {
|
||||
let res = await Promise.all(funArr)
|
||||
}
|
||||
} else {
|
||||
this.isFail = true
|
||||
}
|
||||
}
|
||||
},
|
||||
// 并发上传
|
||||
async handleUploadTask(arr, index) {
|
||||
if (!this.uploadVisible) return
|
||||
let file = this.fileList.filter((item) => item.id === arr[index].id)[0]
|
||||
file.status = 1
|
||||
let path = `/${this.$route.query.trialId}/TaskImage/${
|
||||
this.currentRow.SubjectId
|
||||
}/${this.currentRow.VisitTaskId}/${this.$guid()}${file.name
|
||||
.substring(file.name.lastIndexOf('.'))
|
||||
.toLocaleLowerCase()}`
|
||||
file.curPath = path
|
||||
const fileData = await this.fileToBlob(file.file)
|
||||
let res = await this.fileToOss(path, fileData, file)
|
||||
if (res) {
|
||||
file.status = 2
|
||||
this.successFileList.push({
|
||||
fileName: file.name,
|
||||
filePath: this.$getObjectName(res.url),
|
||||
fileFize: file.size,
|
||||
fileType: file.fileType,
|
||||
})
|
||||
let flag = arr.every((item) => item.status === 2)
|
||||
if (flag) {
|
||||
let RecordPath = await this.uploadRecord(arr)
|
||||
return this.submitFile(this.successFileList, RecordPath)
|
||||
}
|
||||
} else {
|
||||
file.status = 3
|
||||
}
|
||||
let flag = arr.every((item) => item.status > 1)
|
||||
if (flag) {
|
||||
let failFileList = arr.filter((item) => item.status === 3)
|
||||
if (failFileList && failFileList.length > 0) {
|
||||
let RecordPath = await this.uploadRecord(arr)
|
||||
this.$refs.filesTable.clearSelection()
|
||||
failFileList.forEach((row) => {
|
||||
row.uploadFileSize = 0
|
||||
this.$refs.filesTable.toggleRowSelection(row)
|
||||
})
|
||||
this.isFail = true
|
||||
this.submitFile(this.successFileList, RecordPath, true)
|
||||
return false
|
||||
}
|
||||
}
|
||||
let ind = arr.findIndex((item) => item.status === 0)
|
||||
if (ind >= 0) {
|
||||
return this.handleUploadTask(arr, ind)
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
},
|
||||
// file上传到oss
|
||||
async fileToOss(path, file, item) {
|
||||
try {
|
||||
let res = await this.OSSclient.multipartUpload(
|
||||
{
|
||||
path,
|
||||
file,
|
||||
speed: true,
|
||||
},
|
||||
(percentage, checkpoint, lastPer) => {
|
||||
item.uploadFileSize += checkpoint.size * (percentage - lastPer)
|
||||
if (item.uploadFileSize > file.fileSize) {
|
||||
item.uploadFileSize = file.fileSize
|
||||
}
|
||||
}
|
||||
)
|
||||
if (res) {
|
||||
return res
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
return false
|
||||
}
|
||||
},
|
||||
// 非Dicom文件上传归档
|
||||
submitFile(uploadedFileList, RecordPath, isReLoad = false) {
|
||||
if (!this.uploadVisible) return
|
||||
this.btnLoading = true
|
||||
var params = {
|
||||
trialId: this.$route.query.trialId,
|
||||
subjectVisitId: this.currentRow.SourceSubjectVisitId,
|
||||
noneDicomStudyId: this.currentRow.Id,
|
||||
studyMonitorId: this.studyMonitorId,
|
||||
VisitTaskId: this.currentRow.VisitTaskId,
|
||||
uploadedFileList: uploadedFileList,
|
||||
}
|
||||
if (RecordPath) {
|
||||
params.RecordPath = RecordPath.path
|
||||
params.FailedFileCount = RecordPath.Record.Failed.length
|
||||
}
|
||||
uploadNoneDicomFile(params)
|
||||
.then((res) => {
|
||||
if (!isReLoad) {
|
||||
this.resetFileDiaolg()
|
||||
}
|
||||
this.getList()
|
||||
this.$emit('update:isUpload', true)
|
||||
// 刷新父组件列表
|
||||
this.$emit('getList')
|
||||
this.$message.success(
|
||||
this.$t('trials:uploadNonDicoms:message:uploadedSuccessfully')
|
||||
)
|
||||
})
|
||||
.catch(() => {
|
||||
this.btnLoading = false
|
||||
})
|
||||
},
|
||||
// 上传提交记录
|
||||
uploadRecord(arr) {
|
||||
return new Promise(async (resolve) => {
|
||||
try {
|
||||
let Record = {
|
||||
Failed: [],
|
||||
Existed: [],
|
||||
Uploaded: [],
|
||||
FileCount: arr.length,
|
||||
}
|
||||
arr.forEach((item) => {
|
||||
let file = this.fileList.find((data) => data.id === item.id)
|
||||
if (file.status === 2) {
|
||||
Record.Uploaded.push(file.curPath)
|
||||
}
|
||||
if (file.status === 3) {
|
||||
Record.Failed.push(file.curPath)
|
||||
}
|
||||
})
|
||||
let text = JSON.stringify(Record)
|
||||
let logJsonBlob = this.generateTxtFile(text)
|
||||
let logJsonObjectName = `/${this.$route.query.trialId}/TaskImage/${this.currentRow.SubjectId}/${this.currentRow.VisitTaskId}/${this.studyMonitorId}.txt`
|
||||
let logRes
|
||||
try {
|
||||
logRes = await this.OSSclient.put(logJsonObjectName, logJsonBlob)
|
||||
if (logRes && logRes.url) {
|
||||
resolve({ path: this.$getObjectName(logRes.url), Record })
|
||||
} else {
|
||||
resolve(false)
|
||||
}
|
||||
} catch (e) {
|
||||
resolve(false)
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
resolve(false)
|
||||
}
|
||||
})
|
||||
},
|
||||
generateTxtFile(text) {
|
||||
let blob = new Blob(['\ufeff', text], { type: 'text/plain' })
|
||||
return blob
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.top {
|
||||
margin: 10px 0;
|
||||
}
|
||||
.upload {
|
||||
display: inline-block;
|
||||
height: 30px;
|
||||
width: 90px;
|
||||
padding: 2px 10px;
|
||||
line-height: 23px;
|
||||
position: relative;
|
||||
text-decoration: none;
|
||||
border-radius: 3px;
|
||||
overflow: hidden;
|
||||
text-align: center;
|
||||
background: #428bca;
|
||||
border-color: #428bca;
|
||||
color: #fff;
|
||||
.select-file {
|
||||
height: 30px;
|
||||
width: 90px;
|
||||
position: absolute;
|
||||
overflow: hidden;
|
||||
left: 0;
|
||||
top: 0;
|
||||
opacity: 0;
|
||||
font-size: 0;
|
||||
}
|
||||
.btn-select {
|
||||
//给显示在页面上的按钮写样式
|
||||
width: 90px;
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
text-align: center;
|
||||
cursor: pointer;
|
||||
border-radius: 24px;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
pointer-events: none; //pointer-events:none用来控制该标签的点击穿透事件
|
||||
}
|
||||
}
|
||||
.tip {
|
||||
display: flex;
|
||||
align-items: flex-start;
|
||||
margin-top: 5px;
|
||||
i {
|
||||
margin: 3px 5px 0 0;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,291 @@
|
||||
<template>
|
||||
<div v-if="model_cfg.visible">
|
||||
<base-model :config="model_cfg">
|
||||
<div slot="dialog-body">
|
||||
<el-table :data="modelList" style="width: 100%" height="300">
|
||||
<!--检查编号-->
|
||||
<el-table-column
|
||||
prop="StudyCode"
|
||||
:label="$t('trials:uploadImage:table:StudyCode')"
|
||||
/>
|
||||
<!--检查类型-->
|
||||
<el-table-column
|
||||
prop="ModalityForEdit"
|
||||
:label="$t('trials:uploadImage:table:ModalityForEdit')"
|
||||
v-if="IsDicom"
|
||||
/>
|
||||
<!--检查模态-->
|
||||
<el-table-column
|
||||
prop="Modalities"
|
||||
:label="$t('trials:uploadImage:table:Modalities')"
|
||||
v-if="IsDicom"
|
||||
/>
|
||||
<!--检查部位-->
|
||||
<el-table-column
|
||||
prop="BodyPartForEdit"
|
||||
:label="$t('trials:uploadImage:table:BodyPartForEdit')"
|
||||
v-if="IsDicom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{
|
||||
$fd(
|
||||
'Bodypart',
|
||||
scope.row.BodyPartForEdit,
|
||||
'Code',
|
||||
{ Bodypart: bodyPart },
|
||||
'Name'
|
||||
)
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--序列数量-->
|
||||
<el-table-column
|
||||
prop="SeriesCount"
|
||||
:label="$t('trials:uploadImage:table:SeriesCount')"
|
||||
v-if="IsDicom"
|
||||
/>
|
||||
<!--图像数量-->
|
||||
<el-table-column
|
||||
prop="InstanceCount"
|
||||
:label="$t('trials:uploadImage:table:InstanceCount')"
|
||||
v-if="IsDicom"
|
||||
/>
|
||||
<!--检查时间-->
|
||||
<el-table-column
|
||||
prop="StudyTime"
|
||||
:label="$t('trials:uploadImage:table:StudyTime')"
|
||||
v-if="IsDicom"
|
||||
min-width="130"
|
||||
/>
|
||||
<!--检查模态-->
|
||||
<el-table-column
|
||||
prop="Modality"
|
||||
:label="$t('trials:uploadImage:table:Modalities')"
|
||||
v-if="!IsDicom"
|
||||
/>
|
||||
<!--检查部位-->
|
||||
<el-table-column
|
||||
prop="BodyPart"
|
||||
:label="$t('trials:uploadImage:table:BodyPartForEdit')"
|
||||
v-if="!IsDicom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{
|
||||
$fd(
|
||||
'Bodypart',
|
||||
scope.row.BodyPart,
|
||||
'Code',
|
||||
{ Bodypart: bodyPart },
|
||||
'Name'
|
||||
)
|
||||
}}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!--文件数量-->
|
||||
<el-table-column
|
||||
prop="FileCount"
|
||||
:label="$t('trials:uploadImage:table:FileCount')"
|
||||
v-if="!IsDicom"
|
||||
/>
|
||||
<!--检查时间-->
|
||||
<el-table-column
|
||||
prop="ImageDate"
|
||||
:label="$t('trials:uploadImage:table:StudyTime')"
|
||||
v-if="!IsDicom"
|
||||
min-width="130"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('common:action:action')"
|
||||
fixed="right"
|
||||
width="80"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<!--预览--->
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-view"
|
||||
:title="$t('trials:uploadImage:button:preview')"
|
||||
v-if="!isUpload"
|
||||
@click.stop="preview(scope.row)"
|
||||
/>
|
||||
<!--编辑--->
|
||||
<el-button
|
||||
circle
|
||||
icon="el-icon-edit-outline"
|
||||
:title="$t('trials:uploadImage:button:edit')"
|
||||
v-else
|
||||
@click.stop="openEdit(scope.row)"
|
||||
/>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
</div>
|
||||
</base-model>
|
||||
<!--新增检查部位-->
|
||||
<base-model v-if="editModality_model.visible" :config="editModality_model">
|
||||
<template slot="dialog-body">
|
||||
<el-form
|
||||
ref="editModalityform"
|
||||
:inline="true"
|
||||
:model="form"
|
||||
class="demo-form-inline"
|
||||
:rules="rules"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$t('trials:uploadImage:form:ModalityForEdit')"
|
||||
prop="Modality"
|
||||
label-width="150px"
|
||||
>
|
||||
<el-select v-model="form.Modality" placeholder="">
|
||||
<el-option
|
||||
v-for="item in TrialModality"
|
||||
:key="item"
|
||||
:label="item"
|
||||
:value="item"
|
||||
>
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="dialog-footer">
|
||||
<el-button
|
||||
type="primary"
|
||||
@click="updateTaskStudyModality"
|
||||
:loading="loading"
|
||||
>
|
||||
{{ $t('common:button:confirm') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
@click="editModality_model.visible = false"
|
||||
:loading="loading"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</base-model>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import baseModel from '@/components/BaseModel'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import { updateTaskStudyModality } from '@/api/load.js'
|
||||
export default {
|
||||
name: 'studyView',
|
||||
props: {
|
||||
model_cfg: {
|
||||
type: Object,
|
||||
default: () => {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
bodyPart: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
},
|
||||
},
|
||||
modelList: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
},
|
||||
},
|
||||
TrialModality: {
|
||||
type: Array,
|
||||
default: () => {
|
||||
return []
|
||||
},
|
||||
},
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
},
|
||||
IsDicom: {
|
||||
required: true,
|
||||
type: Boolean,
|
||||
default: true,
|
||||
},
|
||||
isUpload: {
|
||||
required: true,
|
||||
type: Boolean,
|
||||
default: false,
|
||||
},
|
||||
},
|
||||
components: {
|
||||
'base-model': baseModel,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
form: {
|
||||
Modality: null,
|
||||
TaskStudyId: null,
|
||||
},
|
||||
editModality_model: {
|
||||
visible: false,
|
||||
title: this.$t('trials:uploadImage:button:edit'),
|
||||
width: '500px',
|
||||
appendToBody: true,
|
||||
},
|
||||
rules: {
|
||||
Modality: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('trials:uploadImage:format:notModality'),
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
},
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
// 预览
|
||||
preview(row) {
|
||||
let routeData = null
|
||||
if (this.IsDicom) {
|
||||
var token = getToken()
|
||||
routeData = this.$router.resolve({
|
||||
path: `/showdicom?studyId=${row.Id}&TokenKey=${token}&type=Study&visitTaskId=${this.visitTaskId}`,
|
||||
})
|
||||
} else {
|
||||
let trialId = this.$route.query.trialId
|
||||
var token = getToken()
|
||||
routeData = this.$router.resolve({
|
||||
path: `/showNoneDicoms?trialId=${trialId}&subjectVisitId=${row.SourceSubjectVisitId}&studyId=${row.Id}&TokenKey=${token}`,
|
||||
})
|
||||
}
|
||||
window.open(routeData.href, '_blank')
|
||||
},
|
||||
// 打开编辑
|
||||
openEdit(row) {
|
||||
this.form.TaskStudyId = row.Id
|
||||
this.form.Modality = row.ModalityForEdit
|
||||
this.editModality_model.visible = true
|
||||
},
|
||||
// 修改检查类型
|
||||
async updateTaskStudyModality() {
|
||||
try {
|
||||
let validate = await this.$refs.editModalityform.validate()
|
||||
if (!validate) return false
|
||||
this.loading = true
|
||||
let res = await updateTaskStudyModality(this.form)
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.modelList.some((item) => {
|
||||
if (this.form.TaskStudyId === item.Id) {
|
||||
item.ModalityForEdit = this.form.Modality
|
||||
}
|
||||
return this.form.TaskStudyId === item.Id
|
||||
})
|
||||
this.editModality_model.visible = false
|
||||
this.$emit('getList')
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
</style>
|
||||
@@ -102,7 +102,6 @@
|
||||
import uploadList from "./components/upload-list.vue";
|
||||
import studyView from "./components/study-view.vue";
|
||||
import { getSubjectImageUploadList, deleteTaskStudy } from "@/api/load.js";
|
||||
import { downloadImage } from "@/utils/uploadZip.js";
|
||||
import store from "@/store";
|
||||
export default {
|
||||
name: "uploadImage",
|
||||
@@ -591,7 +590,7 @@ export default {
|
||||
files.push(obj);
|
||||
}
|
||||
store.dispatch("trials/setUnLock", true);
|
||||
let res = await downloadImage(zipName, files);
|
||||
// let res = await downloadImage(zipName, files);
|
||||
store.dispatch("trials/setUnLock", false);
|
||||
},
|
||||
},
|
||||
|
||||
+49
-6
@@ -145,6 +145,12 @@ Vue.config.productionTip = false
|
||||
Vue.prototype.$upload = () => {
|
||||
_vm.$forceUpdate()
|
||||
}
|
||||
Vue.prototype.$guid = () => {
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
||||
var r = Math.random() * 16 | 0, v = c == 'x' ? r : (r & 0x3 | 0x8);
|
||||
return v.toString(16);
|
||||
});
|
||||
}
|
||||
Vue.prototype.fileToBlob = (file) => {
|
||||
// 创建 FileReader 对象
|
||||
const reader = new FileReader()
|
||||
@@ -249,6 +255,19 @@ async function VueInit() {
|
||||
} catch (e) {
|
||||
}
|
||||
}
|
||||
Vue.prototype.$company = (isShort = true) => {
|
||||
let companyName = null
|
||||
if (localStorage.getItem('CompanyInfo')) {
|
||||
let CompanyInfo = JSON.parse(localStorage.getItem('CompanyInfo'))
|
||||
let isZh = zzSessionStorage.getItem('lang') === 'zh' || _vm.$i18n.locale == 'zh'
|
||||
if (isZh) {
|
||||
companyName = isShort ? CompanyInfo.CompanyShortNameCN : CompanyInfo.CompanyNameCN
|
||||
} else {
|
||||
companyName = isShort ? CompanyInfo.CompanyShortName : CompanyInfo.CompanyName
|
||||
}
|
||||
}
|
||||
return companyName;
|
||||
}
|
||||
Vue.prototype.$updateDictionary = function () {
|
||||
Vue.prototype.$d = function (code) {
|
||||
var dictInfo = res.Result
|
||||
@@ -293,7 +312,8 @@ async function VueInit() {
|
||||
data: {
|
||||
unlock: {
|
||||
my_username: null,
|
||||
my_password: null
|
||||
my_password: null,
|
||||
view: false
|
||||
}
|
||||
},
|
||||
render: h => h(App)
|
||||
@@ -365,7 +385,7 @@ async function VueInit() {
|
||||
// process.env.VUE_APP_LOGOUT_FOR_TIME
|
||||
// eval(process.env.VUE_APP_LOCK_FOR_PERMISSION)
|
||||
// process.env.VUE_APP_LOCK_FOR_TIME
|
||||
window.VUE_APP_COMPANY_NAME = process.env.VUE_APP_COMPANY_NAME;
|
||||
// window.VUE_APP_COMPANY_NAME = process.env.VUE_APP_COMPANY_NAME;
|
||||
waitOperate(eval(process.env.VUE_APP_LOGOUT_FOR_PERMISSION) ? () => {
|
||||
var lang = zzSessionStorage.getItem('lang') ? zzSessionStorage.getItem('lang') : 'zh'
|
||||
if (_vm.$store.state.trials.unlock || _vm.$route.path === '/ReviewersResearchForm' || _vm.$route.path === '/ReviewersResearch' || _vm.$route.path === '/login' || _vm.$route.path === '/researchForm' || _vm.$route.path === '/researchDetail_m' || _vm.$route.path === '/researchLogin_m' || _vm.$route.path === '/researchLogin' || _vm.$route.path === '/email-recompose' || _vm.$route.path === '/recompose' || _vm.$route.path === '/resetpassword' || _vm.$route.path === '/error') {
|
||||
@@ -437,7 +457,8 @@ async function VueInit() {
|
||||
_vm.$message.success(_vm.$t("env:lock:msgBox:lockSuccess"))
|
||||
_vm.unlock = {
|
||||
my_username: null,
|
||||
my_password: null
|
||||
my_password: null,
|
||||
view: false
|
||||
}
|
||||
isOpen = false
|
||||
count = 0;
|
||||
@@ -501,16 +522,21 @@ async function VueInit() {
|
||||
]),
|
||||
h('el-form-item', {
|
||||
props: { label: _vm.$t("env:lock:msgBox:form:Password") },
|
||||
attrs: {
|
||||
style: "position: relative;"
|
||||
}
|
||||
}, [
|
||||
h('input', {
|
||||
props: {
|
||||
value: _vm.unlock.my_password
|
||||
},
|
||||
ref: "unlock_my_password_input",
|
||||
attrs: {
|
||||
id: 'my_password',
|
||||
class: 'el-input__inner',
|
||||
type: 'password',
|
||||
autocomplete: 'new-password'
|
||||
type: _vm.unlock.view ? 'text' : 'password',
|
||||
autocomplete: 'new-password',
|
||||
style: "padding-right:25px"
|
||||
},
|
||||
on: {
|
||||
change: (event) => {
|
||||
@@ -520,7 +546,24 @@ async function VueInit() {
|
||||
_vm.unlock.my_password = event.target.value
|
||||
}
|
||||
}
|
||||
})
|
||||
}),
|
||||
h('i', {
|
||||
attrs: {
|
||||
id: 'my_password_view',
|
||||
class: "el-icon-view",
|
||||
style: "cursor: pointer;position: absolute;top:35%;right:10px"
|
||||
},
|
||||
on: {
|
||||
click: (event) => {
|
||||
_vm.unlock.view = !_vm.unlock.view
|
||||
if (_vm.unlock.view) {
|
||||
_vm.$refs['unlock_my_password_input'].type = "text"
|
||||
} else {
|
||||
_vm.$refs['unlock_my_password_input'].type = "password"
|
||||
}
|
||||
},
|
||||
}
|
||||
}),
|
||||
])
|
||||
])
|
||||
])
|
||||
|
||||
+6
-5
@@ -6,11 +6,12 @@ import 'nprogress/nprogress.css'
|
||||
import { getToken } from '@/utils/auth'
|
||||
import Vue from 'vue'
|
||||
import { OSSclient } from './utils/oss'
|
||||
import WHITELIST from "./utils/whiteList"
|
||||
// import getPageTitle from '@/utils/get-page-title'
|
||||
|
||||
NProgress.configure({ showSpinner: false })
|
||||
|
||||
const whiteList = ['/ReviewersResearch', '/login', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms']
|
||||
const whiteList = WHITELIST
|
||||
store.state.trials.whiteList = whiteList;
|
||||
router.beforeEach(async (to, from, next) => {
|
||||
NProgress.start()
|
||||
@@ -25,15 +26,15 @@ router.beforeEach(async (to, from, next) => {
|
||||
if (to.path === '/login' || to.path === '/recompose' || to.path === '/email-recompose' || to.path === '/error' || to.path === '/ReviewersResearchForm' || to.path === '/ReviewersResearch') {
|
||||
if (to.path === '/ReviewersResearch') {
|
||||
await this.$store.dispatch('user/logout')
|
||||
OSSclient()
|
||||
await OSSclient()
|
||||
}
|
||||
if (to.path === '/ReviewersResearchForm') {
|
||||
OSSclient()
|
||||
await OSSclient()
|
||||
}
|
||||
next()
|
||||
NProgress.done()
|
||||
} else {
|
||||
OSSclient()
|
||||
await OSSclient()
|
||||
const hasGetUserInfo = store.getters.userId
|
||||
if (hasGetUserInfo) {
|
||||
next()
|
||||
@@ -66,7 +67,7 @@ router.beforeEach(async (to, from, next) => {
|
||||
} else {
|
||||
// 在免登录whiteList中,直接进入
|
||||
if (to.path === '/readingDicoms' || to.path === '/noneDicomReading') {
|
||||
OSSclient()
|
||||
await OSSclient()
|
||||
}
|
||||
next()
|
||||
}
|
||||
|
||||
@@ -35,26 +35,50 @@ const getDefaultState = () => {
|
||||
}
|
||||
}
|
||||
function getQuestions(questions) {
|
||||
const criterionType = parseInt(localStorage.getItem('CriterionType'))
|
||||
questions.forEach(item => {
|
||||
if (item.Type === 'table' && item.TableQuestions && item.TableQuestions.Answers.length > 0) {
|
||||
if ((item.Type === 'table' || item.Type === 'basicTable') && item.TableQuestions && item.TableQuestions.Answers.length > 0) {
|
||||
item.TableQuestions.Answers.forEach(answerObj => {
|
||||
answerObj.lesionPart = getQuestionAnswer(item.TableQuestions.Questions, 8, answerObj)
|
||||
answerObj.loctation = getQuestionAnswer(item.TableQuestions.Questions, 6, answerObj)
|
||||
answerObj.lesionLength = getQuestionAnswer(item.TableQuestions.Questions, 0, answerObj)
|
||||
answerObj.lesionShort = getQuestionAnswer(item.TableQuestions.Questions, 1, answerObj)
|
||||
answerObj.isDicomReading = answerObj.IsDicomReading === 'True'
|
||||
var isLymphLesion = getQuestionAnswer(item.TableQuestions.Questions, 2, answerObj)
|
||||
isLymphLesion = isLymphLesion ? parseInt(isLymphLesion) : null
|
||||
answerObj.isLymphLesion = isLymphLesion
|
||||
answerObj.lesionState = getQuestionAnswer(item.TableQuestions.Questions, 7, answerObj)
|
||||
var lesionNum = getQuestionAnswer(item.TableQuestions.Questions, 11, answerObj)
|
||||
answerObj.lesionNum = lesionNum
|
||||
|
||||
if (answerObj.RowId) {
|
||||
var idx = item.TableQuestions.Questions.findIndex(i => i.QuestionMark === 11)
|
||||
if (idx > -1) {
|
||||
if (criterionType === 10) {
|
||||
// pcwg
|
||||
var lesionNum = getQuestionAnswer(item.TableQuestions.Questions, 11, answerObj)
|
||||
answerObj.lesionNum = lesionNum
|
||||
answerObj.saveTypeEnum = isNaN(parseInt(answerObj.lesionNum)) ? 1 : 2
|
||||
} else if (criterionType === 19) {
|
||||
// ivus
|
||||
answerObj.area1 = getQuestionAnswer(item.TableQuestions.Questions, 1001, answerObj)
|
||||
answerObj.area2 = getQuestionAnswer(item.TableQuestions.Questions, 1002, answerObj)
|
||||
const v = getQuestionAnswer(item.TableQuestions.Questions, 1003, answerObj)
|
||||
answerObj.diff = v
|
||||
answerObj.saveTypeEnum = isNaN(parseFloat(v)) ? 1 : 2
|
||||
} else if (criterionType === 20) {
|
||||
// oct
|
||||
if (item.LesionType === 101) {
|
||||
answerObj.l1 = getQuestionAnswer(item.TableQuestions.Questions, 1011, answerObj)
|
||||
answerObj.l2 = getQuestionAnswer(item.TableQuestions.Questions, 1012, answerObj)
|
||||
answerObj.l3 = getQuestionAnswer(item.TableQuestions.Questions, 1013, answerObj)
|
||||
const min = getQuestionAnswer(item.TableQuestions.Questions, 1014, answerObj)
|
||||
answerObj.min = min
|
||||
const mean = getQuestionAnswer(item.TableQuestions.Questions, 1015, answerObj)
|
||||
answerObj.mean = mean
|
||||
answerObj.saveTypeEnum = (isNaN(parseFloat(min)) || isNaN(parseFloat(mean))) ? 1 : 2
|
||||
} else if (item.LesionType === 103) {
|
||||
const angle = getQuestionAnswer(item.TableQuestions.Questions, 1016, answerObj)
|
||||
answerObj.angle = angle
|
||||
answerObj.saveTypeEnum = isNaN(parseFloat(angle)) ? 1 : 2
|
||||
}
|
||||
} else {
|
||||
answerObj.lesionPart = getQuestionAnswer(item.TableQuestions.Questions, 8, answerObj)
|
||||
answerObj.loctation = getQuestionAnswer(item.TableQuestions.Questions, 6, answerObj)
|
||||
answerObj.lesionLength = getQuestionAnswer(item.TableQuestions.Questions, 0, answerObj)
|
||||
answerObj.lesionShort = getQuestionAnswer(item.TableQuestions.Questions, 1, answerObj)
|
||||
let isLymphLesion = getQuestionAnswer(item.TableQuestions.Questions, 2, answerObj)
|
||||
isLymphLesion = isLymphLesion ? parseInt(isLymphLesion) : null
|
||||
answerObj.isLymphLesion = isLymphLesion
|
||||
answerObj.lesionState = getQuestionAnswer(item.TableQuestions.Questions, 7, answerObj)
|
||||
answerObj.saveTypeEnum = isNaN(parseInt(answerObj.lesionState)) ? 1 : 2
|
||||
}
|
||||
} else {
|
||||
@@ -70,7 +94,7 @@ function getQuestions(questions) {
|
||||
}
|
||||
function findQuestionAndRemoveLesion(questions, obj) {
|
||||
for (var i = 0; i < questions.length; i++) {
|
||||
if (questions[i].Type === 'table' && questions[i].TableQuestions && (questions[i].LesionType === obj.lesionType) && questions[i].TableQuestions.Answers.length > 0) {
|
||||
if ((questions[i].Type === 'table' || questions[i].Type === 'basicTable') && questions[i].TableQuestions && (questions[i].LesionType === obj.lesionType) && questions[i].TableQuestions.Answers.length > 0) {
|
||||
var idx = questions[i].TableQuestions.Answers.findIndex(i => String(i.RowIndex) === String(obj.rowIndex))
|
||||
if (idx > -1) {
|
||||
questions[i].TableQuestions.Answers.splice(idx, 1)
|
||||
@@ -86,7 +110,7 @@ function findQuestionAndRemoveLesion(questions, obj) {
|
||||
function findQuestionAndUpdateLesion(questions, obj) {
|
||||
for (var i = 0; i < questions.length; i++) {
|
||||
var item = questions[i]
|
||||
if (item.Type === 'table' && item.Id === obj.questionId) {
|
||||
if ((item.Type === 'table' || item.Type === 'basicTable') && item.Id === obj.questionId) {
|
||||
var idx = item.TableQuestions.Answers.findIndex(i => i.RowIndex === obj.rowIndex)
|
||||
item.TableQuestions.Answers[idx].isLymphLesion = obj.isLymphLesion
|
||||
item.TableQuestions.Answers[idx].loctation = obj.lesionOrgan
|
||||
@@ -115,10 +139,10 @@ function findQuestionAndUpdateLesion(questions, obj) {
|
||||
}
|
||||
function findQuestionAndAddLesion(questions, obj) {
|
||||
for (var i = 0; i < questions.length; i++) {
|
||||
if (questions[i].Type === 'table' && questions[i].TableQuestions && (questions[i].LesionType === obj.lesionType)) {
|
||||
if ((questions[i].Type === 'table' || questions[i].Type === 'basicTable') && questions[i].TableQuestions && (questions[i].LesionType === obj.lesionType)) {
|
||||
var sourceObj = {}
|
||||
questions[i].TableQuestions.Questions.forEach(item => {
|
||||
sourceObj[item.Id] = ''
|
||||
sourceObj[item.Id] = null
|
||||
})
|
||||
var targetObj = Object.assign(sourceObj, obj.lesionObj)
|
||||
targetObj.IsCurrentTaskAdd = 'True'
|
||||
@@ -811,9 +835,16 @@ const actions = {
|
||||
// }
|
||||
series.InstanceInfoList.forEach(instance => {
|
||||
if (instance.NumberOfFrames && instance.NumberOfFrames > 1) {
|
||||
for (let i = 0; i < instance.NumberOfFrames; i++) {
|
||||
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?frame=${i}&instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${index}`
|
||||
imageIds.push(imageId)
|
||||
if (study.IsCriticalSequence && instance.KeyFramesList.length > 0) {
|
||||
instance.KeyFramesList.map(i => {
|
||||
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?frame=${i}&instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${index}`
|
||||
imageIds.push(imageId)
|
||||
})
|
||||
} else {
|
||||
for (let i = 0; i < instance.NumberOfFrames; i++) {
|
||||
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?frame=${i}&instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${index}`
|
||||
imageIds.push(imageId)
|
||||
}
|
||||
}
|
||||
instance.ImageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?frame=${0}&instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${index}`
|
||||
} else {
|
||||
@@ -1053,7 +1084,10 @@ const actions = {
|
||||
return new Promise(resolve => {
|
||||
var isReadingTaskViewInOrder = localStorage.getItem('isReadingTaskViewInOrder')
|
||||
if (parseInt(isReadingTaskViewInOrder) === 2) {
|
||||
if (!state.lastCanvasTaskId) state.lastCanvasTaskId = taskId
|
||||
if (!state.lastCanvasTaskId) {
|
||||
console.log('setLastCanvasTaskId')
|
||||
state.lastCanvasTaskId = taskId
|
||||
}
|
||||
} else {
|
||||
state.lastCanvasTaskId = taskId
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ const getDefaultState = () => {
|
||||
studyListQuery: null,
|
||||
unlock: false,
|
||||
config: {},
|
||||
uploadTip: '0.00kb/s',
|
||||
uploadTip: '0.00KB/s',
|
||||
timer: null,
|
||||
whiteList: [],
|
||||
checkTaskId: null
|
||||
|
||||
@@ -97,6 +97,7 @@ const actions = {
|
||||
zzSessionStorage.setItem('my_username', username.trim())
|
||||
zzSessionStorage.setItem('my_password', md5(password))
|
||||
zzSessionStorage.setItem('my_EMail', response.Result.BasicInfo.EMail)
|
||||
localStorage.setItem('CompanyInfo', JSON.stringify(response.Result.CompanyInfo))
|
||||
const data = response.Result
|
||||
if (data.BasicInfo.IsFirstAdd || data.BasicInfo.LoginState === 1) {
|
||||
try {
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
// crypto.js
|
||||
import CryptoJS from 'crypto-js';
|
||||
import { JSEncrypt } from "jsencrypt";
|
||||
import { getPublicKey } from "@/api/user.js"
|
||||
export const Crypto = {
|
||||
AES: {
|
||||
encrypt: function (plaintext, secretKey) {
|
||||
return CryptoJS.AES.encrypt(plaintext, CryptoJS.enc.Utf8.parse(secretKey), {
|
||||
mode: CryptoJS.mode.ECB,
|
||||
padding: CryptoJS.pad.Pkcs7,
|
||||
iv: ''
|
||||
}).ciphertext.toString(CryptoJS.enc.Base64);
|
||||
},
|
||||
decrypt: function (ciphertext, secretKey) {
|
||||
const bytes = CryptoJS.AES.decrypt(ciphertext, secretKey);
|
||||
return bytes.toString(CryptoJS.enc.Utf8);
|
||||
}
|
||||
}
|
||||
};
|
||||
export const Encrypt = {
|
||||
encrypt: async function (plaintext) {
|
||||
let PublicKey = null;
|
||||
if (sessionStorage.getItem('PublicKey')) {
|
||||
PublicKey = atob(sessionStorage.getItem('PublicKey'));
|
||||
} else {
|
||||
try {
|
||||
let res = await getPublicKey();
|
||||
if (res.IsSuccess) {
|
||||
PublicKey = atob(res.Result)
|
||||
sessionStorage.setItem('PublicKey', res.Result)
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
let encryptor = new JSEncrypt()
|
||||
encryptor.setPublicKey(PublicKey)
|
||||
return encryptor.encrypt(plaintext)
|
||||
|
||||
},
|
||||
|
||||
};
|
||||
@@ -0,0 +1,30 @@
|
||||
import { Encrypt, Crypto } from "./crypto";
|
||||
export const encryptConfig = async (config) => {
|
||||
let secretKey = randomRange(32, 32);
|
||||
let encryptSecretKey = await Encrypt.encrypt(secretKey); // 密钥进行非对称加密
|
||||
if (encryptSecretKey) {
|
||||
config.headers['X-Encrypted-Key'] = encryptSecretKey;
|
||||
}
|
||||
if (config.data && Object.prototype.toString.call(config.data) === '[object Object]') {
|
||||
Object.keys(config.data).forEach(async key => {
|
||||
config.data[key] = Crypto.AES.encrypt(config.data[key], secretKey)
|
||||
console.log(config.data[key], 'KEY')
|
||||
// config.data[key] = await Encrypt.encrypt(config.data[key])
|
||||
})
|
||||
}
|
||||
return config;
|
||||
}
|
||||
const randomRange = (min, max, charStr) => {
|
||||
var returnStr = "",
|
||||
range;
|
||||
if (typeof max == 'string') {
|
||||
charStr = max;
|
||||
}
|
||||
range = ((max && typeof max == 'number') ? Math.round(Math.random() * (max - min)) + min : min);
|
||||
charStr = charStr || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
|
||||
for (var i = 0; i < range; i++) {
|
||||
var index = Math.round(Math.random() * (charStr.length - 1));
|
||||
returnStr += charStr.substring(index, index + 1);
|
||||
}
|
||||
return returnStr;
|
||||
}
|
||||
@@ -14,7 +14,7 @@ export function AWSclose() {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
timer = null;
|
||||
store.state.trials.uploadTip = '0kb/s'
|
||||
store.state.trials.uploadTip = '0KB/s'
|
||||
}
|
||||
bytesReceivedPerSecond = {};
|
||||
}
|
||||
@@ -28,7 +28,7 @@ export async function exist(s3, bucket, fileInformation, progressFn, changeStatu
|
||||
// 设置每一片的大小,shardSize 指定上传的每个分片的大小,范围为100 KB~5 GB。
|
||||
// 分片标准为5MB,文件总大小大于5GB分片为20MB
|
||||
let shardSize = 5 * 1024 * 1024;
|
||||
if (uploadFileSize < partSize) {
|
||||
if (uploadFileSize < shardSize) {
|
||||
shardSize = uploadFileSize;
|
||||
}
|
||||
if (uploadFileSize > 5 * 1024 * 1024 * 1024) {
|
||||
@@ -45,8 +45,8 @@ export async function exist(s3, bucket, fileInformation, progressFn, changeStatu
|
||||
//判断sharding里面是否有东西,有东西证明已经上传过分片了,不需要再进行检测
|
||||
if (fileInformation.sharding.length === 0) {
|
||||
let existBucket = await existInBucket({ s3, bucket, fileInformation: fileInformation });
|
||||
console.log("existBucket", existBucket)
|
||||
if (existBucket === 'true') {
|
||||
progressFn(1, fileInformation.file, 0);
|
||||
changeStatus(fileInformation.path, 'success');//直接告诉前端,状态
|
||||
return;
|
||||
} else if (existBucket === 'same key') {
|
||||
@@ -126,13 +126,13 @@ async function uploadFile({ s3, fileInformation, uploadId, bucket, changeStatus,
|
||||
let timeList = Object.keys(bytesReceivedPerSecond).sort((a, b) => a - b);
|
||||
let bytesTime = timeList.find(item => time - item < 1000);
|
||||
if (bytesTime) {
|
||||
bytesReceivedPerSecond[bytesTime] += fileInformation.file.size * percentage;
|
||||
bytesReceivedPerSecond[bytesTime] += fileInformation.file.size * (percentage - lastPercentage);
|
||||
} else {
|
||||
console.log("未查询到时间")
|
||||
if (timeList.length > 0) {
|
||||
bytesReceivedPerSecond[timeList[timeList.length - 1]] += fileInformation.file.size * percentage;
|
||||
bytesReceivedPerSecond[timeList[timeList.length - 1]] += fileInformation.file.size * (percentage - lastPercentage);
|
||||
} else {
|
||||
bytesReceivedPerSecond[time] = fileInformation.file.size * percentage;
|
||||
bytesReceivedPerSecond[time] = fileInformation.file.size * (percentage - lastPercentage);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,6 @@ async function existInBucket({ s3, bucket, fileInformation }) {
|
||||
}
|
||||
}
|
||||
let bucketFileBufferArray = new Uint8Array(bucketFileUniArray);
|
||||
console.log("bucketFileBufferArray.buffer", bucketFileBufferArray.buffer)
|
||||
// 将传入文件的fileReader 转成 arrayBuffer
|
||||
let fileArrayBuff = null;
|
||||
fileArrayBuff = await new Promise((resolve) => {
|
||||
@@ -287,7 +286,6 @@ async function existUpload({ s3, bucket, fileInformation }) {
|
||||
|
||||
//计算arrayBuffer的md5值
|
||||
async function getMD5({ arrayBuffer }) {
|
||||
console.log("arrayBuffer", arrayBuffer)
|
||||
return await new Promise((resolve) => {
|
||||
const spark = new SparkMD5.ArrayBuffer();
|
||||
spark.append(arrayBuffer);
|
||||
@@ -442,10 +440,10 @@ function setTimer() {
|
||||
let timeList = Object.keys(bytesReceivedPerSecond).sort((a, b) => a - b);
|
||||
if (timeList.length > 0) {
|
||||
let totalBytes = timeList.reduce((sum, bytes) => sum + bytesReceivedPerSecond[bytes], 0) / (5 * 1024);
|
||||
let unit = 'kb/s';
|
||||
let unit = 'KB/s';
|
||||
if (totalBytes > 1024) {
|
||||
totalBytes = totalBytes / 1024;
|
||||
unit = "mb/s";
|
||||
unit = "MB/s";
|
||||
}
|
||||
store.state.trials.uploadTip = totalBytes.toFixed(2) + unit;
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ export function OSSclose() {
|
||||
if (timer) {
|
||||
clearInterval(timer);
|
||||
timer = null;
|
||||
store.state.trials.uploadTip = '0kb/s'
|
||||
store.state.trials.uploadTip = '0KB/s'
|
||||
}
|
||||
bytesReceivedPerSecond = {};
|
||||
savaData = {};
|
||||
@@ -57,13 +57,13 @@ async function multipartUpload(OSSclient, partSize, saveFileId, uploadFile, data
|
||||
let timeList = Object.keys(bytesReceivedPerSecond).sort((a, b) => a - b);
|
||||
let bytesTime = timeList.find(item => time - item < 1000);
|
||||
if (bytesTime) {
|
||||
bytesReceivedPerSecond[bytesTime] += data.file.size * percentage;
|
||||
bytesReceivedPerSecond[bytesTime] += data.file.size * (percentage - checkData[saveFileId]);
|
||||
} else {
|
||||
console.log("未查询到时间")
|
||||
// console.log("未查询到时间")
|
||||
if (timeList.length > 0) {
|
||||
bytesReceivedPerSecond[timeList[timeList.length - 1]] += data.file.size * percentage;
|
||||
bytesReceivedPerSecond[timeList[timeList.length - 1]] += data.file.size * (percentage - checkData[saveFileId]);
|
||||
} else {
|
||||
bytesReceivedPerSecond[time] = data.file.size * percentage;
|
||||
bytesReceivedPerSecond[time] = data.file.size * (percentage - checkData[saveFileId]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,10 +92,15 @@ async function multipartUpload(OSSclient, partSize, saveFileId, uploadFile, data
|
||||
// 重新去掉某个缓存进行设置
|
||||
delete savaData[saveFileId];
|
||||
saveFinishedData(savaData);
|
||||
} else if (res.res.status === 404) {
|
||||
delete savaData[saveFileId];
|
||||
saveFinishedData(savaData);
|
||||
}
|
||||
return res;
|
||||
} catch (e) {
|
||||
console.log(e);
|
||||
delete savaData[saveFileId];
|
||||
saveFinishedData(savaData);
|
||||
// 捕获超时异常。
|
||||
if (e.code === "ConnectionTimeoutError") {
|
||||
console.log("TimeoutError");
|
||||
@@ -136,13 +141,14 @@ function initPage() {
|
||||
function setTimer() {
|
||||
if (timer) return false;
|
||||
timer = setInterval(() => {
|
||||
// console.log(Object.assign({}, bytesReceivedPerSecond))
|
||||
let timeList = Object.keys(bytesReceivedPerSecond).sort((a, b) => a - b);
|
||||
if (timeList.length > 0) {
|
||||
let totalBytes = timeList.reduce((sum, bytes) => sum + bytesReceivedPerSecond[bytes], 0) / (5 * 1024);
|
||||
let unit = 'kb/s';
|
||||
let unit = 'KB/s';
|
||||
if (totalBytes > 1024) {
|
||||
totalBytes = totalBytes / 1024;
|
||||
unit = "mb/s";
|
||||
unit = "MB/s";
|
||||
}
|
||||
store.state.trials.uploadTip = totalBytes.toFixed(2) + unit;
|
||||
}
|
||||
|
||||
+118
-89
@@ -15,7 +15,15 @@ Vue.prototype.OSSclientConfig = {
|
||||
|
||||
|
||||
async function ossGenerateSTS() {
|
||||
let res = await GetObjectStoreToken()
|
||||
let res = null;
|
||||
if (localStorage.getItem('stsToken')) {
|
||||
res = JSON.parse(localStorage.getItem('stsToken'))
|
||||
} else {
|
||||
res = await GetObjectStoreToken()
|
||||
localStorage.setItem('stsToken', JSON.stringify(res))
|
||||
}
|
||||
|
||||
// res.Result.ObjectStoreUse = 'AWS';
|
||||
Vue.prototype.OSSclientConfig = { ...res.Result[res.Result.ObjectStoreUse] }
|
||||
Vue.prototype.OSSclientConfig.ObjectStoreUse = res.Result.ObjectStoreUse;
|
||||
Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint
|
||||
@@ -26,19 +34,10 @@ async function ossGenerateSTS() {
|
||||
Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000
|
||||
let OSSclient = new OSS(Vue.prototype.OSSclientConfig)
|
||||
Vue.prototype.OSSclient = {
|
||||
put: function (objectName, object) {
|
||||
put: async function (objectName, object) {
|
||||
OSSclient = await RefreshClient(OSSclient)
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
let config = await getSTSToken(Vue.prototype.OSSclientConfig.Expiration);
|
||||
if (config) {
|
||||
Vue.prototype.OSSclientConfig = { ...config.Result[res.Result.ObjectStoreUse] }
|
||||
Vue.prototype.OSSclientConfig.ObjectStoreUse = config.Result.ObjectStoreUse;
|
||||
Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint;
|
||||
Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName
|
||||
Vue.prototype.OSSclientConfig.stsToken = Vue.prototype.OSSclientConfig.securityToken
|
||||
Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000
|
||||
OSSclient = new OSS(Vue.prototype.OSSclientConfig);
|
||||
}
|
||||
let _vm = router.default.app
|
||||
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
|
||||
var objectItem = objectName.split('/')
|
||||
@@ -60,14 +59,15 @@ async function ossGenerateSTS() {
|
||||
}
|
||||
})
|
||||
},
|
||||
multipartUpload: (data, progress) => {
|
||||
multipartUpload: async (data, progress) => {
|
||||
OSSclient = await RefreshClient(OSSclient)
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const { file, path } = data;
|
||||
if (!file || !path) return reject('file and path be required');
|
||||
let config = await getSTSToken(Vue.prototype.OSSclientConfig.Expiration);
|
||||
let config = await getSTSToken(Vue.prototype.OSSclientConfig.expiration);
|
||||
if (config) {
|
||||
Vue.prototype.OSSclientConfig = { ...config.Result[res.Result.ObjectStoreUse] }
|
||||
Vue.prototype.OSSclientConfig = { ...config.Result[config.Result.ObjectStoreUse] }
|
||||
Vue.prototype.OSSclientConfig.ObjectStoreUse = config.Result.ObjectStoreUse;
|
||||
Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint;
|
||||
Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName
|
||||
@@ -85,7 +85,7 @@ async function ossGenerateSTS() {
|
||||
if (res) {
|
||||
resolve({
|
||||
name: data.path,
|
||||
url: Vue.prototype.OSSclientConfig.viewEndpoint + res.name
|
||||
url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(res.name)
|
||||
})
|
||||
} else {
|
||||
reject()
|
||||
@@ -142,78 +142,32 @@ async function ossGenerateSTS() {
|
||||
}
|
||||
break
|
||||
case 'AWS':
|
||||
let aws = new Minio.Client(Vue.prototype.OSSclientConfig);
|
||||
Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName
|
||||
let aws = new S3Client({
|
||||
endpoint: Vue.prototype.OSSclientConfig.viewEndpoint,
|
||||
region: Vue.prototype.OSSclientConfig.region,
|
||||
s3ForcePathStyle: true,
|
||||
signatureVersion: 'v4',
|
||||
forcePathStyle: true,
|
||||
// SessionToken: '',
|
||||
credentials: {
|
||||
accessKeyId: Vue.prototype.OSSclientConfig.accessKeyId,
|
||||
secretAccessKey: Vue.prototype.OSSclientConfig.secretAccessKey,
|
||||
sessionToken: Vue.prototype.OSSclientConfig.sessionToken
|
||||
}
|
||||
});
|
||||
Vue.prototype.OSSclient = {
|
||||
put: function (objectName, object) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
var name = objectName.split('/')[objectName.split('/').length - 1]
|
||||
let _vm = router.default.app
|
||||
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
|
||||
var objectItem = objectName.split('/')
|
||||
objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
|
||||
objectName = objectItem.join('/')
|
||||
}
|
||||
const reader = new FileReader();
|
||||
reader.onload = (ex) => {
|
||||
const bufferStream = new stream.PassThrough()
|
||||
bufferStream.end(Buffer.from(ex.target.result))
|
||||
aws.putObject(Vue.prototype.OSSclientConfig.bucketName, objectName, bufferStream, function (err, etag) {
|
||||
if (err) {
|
||||
console.log(err)
|
||||
reject()
|
||||
} else {
|
||||
console.log(objectName);
|
||||
resolve({
|
||||
name: objectName,
|
||||
url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(objectName)
|
||||
})
|
||||
}
|
||||
})
|
||||
};
|
||||
reader.readAsArrayBuffer(object);
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
})
|
||||
put: async function (objectName, object) {
|
||||
let data = {
|
||||
file: object,
|
||||
path: objectName
|
||||
}
|
||||
aws = await RefreshClient(aws);
|
||||
return uploadAWS(aws, data, () => { });
|
||||
},
|
||||
multipartUpload: (data, progress) => {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const { file, path } = data;
|
||||
if (!file || !path) return reject('file and path be required');
|
||||
let config = await getSTSToken(Vue.prototype.OSSclientConfig.Expiration);
|
||||
if (config) {
|
||||
Vue.prototype.OSSclientConfig = { ...config.Result[res.Result.ObjectStoreUse] }
|
||||
Vue.prototype.OSSclientConfig.ObjectStoreUse = config.Result.ObjectStoreUse;
|
||||
Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint;
|
||||
Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName
|
||||
Vue.prototype.OSSclientConfig.stsToken = Vue.prototype.OSSclientConfig.securityToken
|
||||
Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000
|
||||
OSSclient = new S3Client(Vue.prototype.OSSclientConfig);
|
||||
}
|
||||
let _vm = router.default.app
|
||||
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
|
||||
var objectItem = data.path.split('/')
|
||||
objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
|
||||
data.path = objectItem.join('/')
|
||||
}
|
||||
await exist(OSSclient, Vue.prototype.OSSclientConfig.bucket, data, progress, (res) => {
|
||||
if (res) {
|
||||
resolve({
|
||||
name: data.path,
|
||||
url: Vue.prototype.OSSclientConfig.viewEndpoint + res.name
|
||||
})
|
||||
} else {
|
||||
reject()
|
||||
}
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
multipartUpload: async (data, progress) => {
|
||||
aws = await RefreshClient(aws);
|
||||
return uploadAWS(aws, data, progress);
|
||||
},
|
||||
close: () => {
|
||||
AWSclose();
|
||||
@@ -222,6 +176,80 @@ async function ossGenerateSTS() {
|
||||
}
|
||||
return
|
||||
}
|
||||
// AWS上传函数
|
||||
function uploadAWS(aws, data, progress) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
try {
|
||||
const { file, path } = data;
|
||||
if (!file || !path) return reject('file and path be required');
|
||||
let _vm = router.default.app
|
||||
if (_vm._route.path !== '/trials/trials-panel/visit/crc-upload') {
|
||||
var objectItem = data.path.split('/')
|
||||
objectItem[objectItem.length - 1] = new Date().getTime() + '_' + objectItem[objectItem.length - 1]
|
||||
data.path = objectItem.join('/')
|
||||
}
|
||||
let bucketName = data.path.split("/")[1] || Vue.prototype.OSSclientConfig.bucket
|
||||
let curPath = data.path;
|
||||
data.path = data.path.replace(`/${bucketName}/`, '');
|
||||
await exist(aws, bucketName, data, progress, (path, status) => {
|
||||
if (status === 'success') {
|
||||
resolve({
|
||||
name: decodeUtf8(curPath),
|
||||
url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(curPath)
|
||||
})
|
||||
} else {
|
||||
reject()
|
||||
}
|
||||
});
|
||||
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
reject(err)
|
||||
}
|
||||
})
|
||||
}
|
||||
// client过期刷新
|
||||
async function RefreshClient(client) {
|
||||
let config = await getSTSToken(Vue.prototype.OSSclientConfig.expiration);
|
||||
if (config) {
|
||||
// config.Result.ObjectStoreUse = 'AWS'
|
||||
switch (config.Result.ObjectStoreUse) {
|
||||
case 'AliyunOSS': {
|
||||
Vue.prototype.OSSclientConfig = { ...config.Result[config.Result.ObjectStoreUse] }
|
||||
Vue.prototype.OSSclientConfig.ObjectStoreUse = config.Result.ObjectStoreUse;
|
||||
Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint;
|
||||
Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName
|
||||
Vue.prototype.OSSclientConfig.stsToken = Vue.prototype.OSSclientConfig.securityToken
|
||||
Vue.prototype.OSSclientConfig.timeout = 10 * 60 * 1000
|
||||
return new OSS(Vue.prototype.OSSclientConfig);
|
||||
}
|
||||
case "MinIO": {
|
||||
return client;
|
||||
}
|
||||
case "AWS": {
|
||||
Vue.prototype.OSSclientConfig = { ...config.Result[config.Result.ObjectStoreUse] }
|
||||
Vue.prototype.OSSclientConfig.ObjectStoreUse = config.Result.ObjectStoreUse;
|
||||
Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint;
|
||||
Vue.prototype.OSSclientConfig.bucket = Vue.prototype.OSSclientConfig.bucketName
|
||||
return new S3Client({
|
||||
endpoint: Vue.prototype.OSSclientConfig.viewEndpoint,
|
||||
region: Vue.prototype.OSSclientConfig.region,
|
||||
s3ForcePathStyle: true,
|
||||
signatureVersion: 'v4',
|
||||
forcePathStyle: true,
|
||||
credentials: {
|
||||
accessKeyId: Vue.prototype.OSSclientConfig.accessKeyId,
|
||||
secretAccessKey: Vue.prototype.OSSclientConfig.secretAccessKey,
|
||||
sessionToken: Vue.prototype.OSSclientConfig.sessionToken
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
return client;
|
||||
}
|
||||
}
|
||||
function decodeUtf8(bytes) {
|
||||
let str = bytes.split('?');
|
||||
let str2 = str[0].split('/');
|
||||
@@ -237,7 +265,7 @@ let loading = false;
|
||||
function getSTSToken(credentials) {
|
||||
return new Promise(async (resolve, reject) => {
|
||||
let isExpired = isCredentialsExpired(credentials);
|
||||
if (!isExpired) {
|
||||
if (isExpired) {
|
||||
if (loading) {
|
||||
queue.push({ resolve, reject })
|
||||
}
|
||||
@@ -245,6 +273,7 @@ function getSTSToken(credentials) {
|
||||
loading = true;
|
||||
let res = await GetObjectStoreToken();
|
||||
loading = false;
|
||||
localStorage.setItem('stsToken', JSON.stringify(res))
|
||||
resolve(res)
|
||||
let p = queue.shift();
|
||||
while (p) {
|
||||
@@ -254,7 +283,7 @@ function getSTSToken(credentials) {
|
||||
}
|
||||
|
||||
} else {
|
||||
console.log("凭证未过期");
|
||||
// console.log("凭证未过期");
|
||||
resolve(false)
|
||||
}
|
||||
|
||||
@@ -267,7 +296,7 @@ function isCredentialsExpired(credentials) {
|
||||
if (!credentials) {
|
||||
return true;
|
||||
}
|
||||
const expireDate = new Date(credentials.Expiration);
|
||||
const expireDate = new Date(credentials);
|
||||
const now = new Date();
|
||||
// 如果有效期不足五分钟,视为过期。
|
||||
return expireDate.getTime() - now.getTime() <= 300000;
|
||||
|
||||
@@ -113,10 +113,14 @@ export const parseDicom = (file, name = false) => {
|
||||
}
|
||||
})
|
||||
uintKey.forEach(key => {
|
||||
res[key] = data.uint16(dicom[key])
|
||||
if (res.hasOwnProperty(key)) {
|
||||
res[key] = data.uint16(dicom[key])
|
||||
}
|
||||
})
|
||||
intStringKey.forEach(key => {
|
||||
res[key] = data.intString(dicom[key])
|
||||
if (res.hasOwnProperty(key)) {
|
||||
res[key] = data.intString(dicom[key])
|
||||
}
|
||||
})
|
||||
defaultKey.forEach(key => {
|
||||
if (!res[key] && res.hasOwnProperty(key)) {
|
||||
|
||||
+15
-5
@@ -2,9 +2,9 @@ import axios from 'axios'
|
||||
import { Message, MessageBox, Alert } from 'element-ui'
|
||||
import store from '@/store'
|
||||
import router from '@/router'
|
||||
import Vue from 'vue'
|
||||
import WHITELIST from "./whiteList"
|
||||
import moment from 'moment-timezone';
|
||||
console.log(moment.tz.guess())
|
||||
import { encryptConfig } from "@/utils/encrypt"
|
||||
axios.defaults.withCredentials = false
|
||||
const service = axios.create({
|
||||
baseURL: '/api',
|
||||
@@ -16,18 +16,28 @@ var path
|
||||
// var lang = store.state.lang.language
|
||||
|
||||
service.interceptors.request.use(
|
||||
config => {
|
||||
async config => {
|
||||
path = router && router.app && router.app._route && router.app._route.path
|
||||
config.headers['Content-Type'] = 'application/json;charset=UTF-8'
|
||||
var language = zzSessionStorage.getItem('lang')
|
||||
config.headers['Accept-Language'] = language === 'en' ? 'en-US,en;q=0.5' : 'zh-CN,zh;q=0.9'
|
||||
config.headers['TimeZoneId'] = moment.tz.guess()
|
||||
if (store.getters.token) {
|
||||
if (config.ENCRYPT) {
|
||||
try {
|
||||
config = await encryptConfig(config)
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
}
|
||||
if (store.getters.token && !config.clearToken) {
|
||||
config.headers.Authorization = `Bearer ${store.getters.token}`
|
||||
}
|
||||
try {
|
||||
if (eval(process.env.VUE_APP_LOGIN_FOR_PERMISSION)) {
|
||||
if (!path || path === '/ReviewersResearchForm' || path === '/ReviewersResearch' || path === '/login' || path === '/researchForm' || path === '/researchDetail_m' || path === '/researchLogin_m' || path === '/researchLogin' || path === '/email-recompose' || path === '/recompose' || path === '/resetpassword' || path === '/error') {
|
||||
// if (!path || path === '/ReviewersResearchForm' || path === '/ReviewersResearch' || path === '/login' || path === '/researchForm' || path === '/researchDetail_m' || path === '/researchLogin_m' || path === '/researchLogin' || path === '/email-recompose' || path === '/recompose' || path === '/resetpassword' || path === '/error') {
|
||||
// return config
|
||||
// }
|
||||
if (!path || WHITELIST.some(item => item === path)) {
|
||||
return config
|
||||
}
|
||||
if (store.state.user.userId !== zzSessionStorage.getItem('userId')) {
|
||||
|
||||
+93
-35
@@ -1,48 +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) {
|
||||
console.log("同步下载打包开始时间:" + new Date());
|
||||
// 创建压缩文件输出流
|
||||
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 {
|
||||
const { name, url } = fileInfo.value;
|
||||
return fetch(url).then(res => {
|
||||
ctrl.enqueue({
|
||||
name,
|
||||
stream: () => res.body
|
||||
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)
|
||||
}
|
||||
});
|
||||
if (window.WritableStream && readableZipStream.pipeTo) {
|
||||
// 开始下载
|
||||
readableZipStream
|
||||
.pipeTo(zipFileOutputStream)
|
||||
.then(() => console.log("同步下载打包结束时间:" + new Date()));
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
// 下载文件并修改名称
|
||||
async function updateFile(file, name) {
|
||||
try {
|
||||
const fileOutputStream = streamSaver.createWriteStream(name);
|
||||
let res = await fetch(file);
|
||||
res.body.pipeTo(fileOutputStream);
|
||||
} catch (err) {
|
||||
console.log(err)
|
||||
}
|
||||
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)
|
||||
}
|
||||
})
|
||||
}
|
||||
export function downLoadFile(file, name, type = 'file') {
|
||||
if (type === 'zip') return zipFiles(name, file);
|
||||
return updateFile(file, name)
|
||||
// 同名文件修改名称
|
||||
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)
|
||||
|
||||
}
|
||||
@@ -1,168 +0,0 @@
|
||||
import Vue from 'vue';
|
||||
import store from "@/store";
|
||||
import {
|
||||
requestPackageAndAnonymizImage,
|
||||
} from "@/api/load.js";
|
||||
import streamSaver from "streamsaver";
|
||||
import "streamsaver/examples/zip-stream.js"
|
||||
let flag = {};
|
||||
export const resetFlag = () => {
|
||||
flag = {};
|
||||
store.state.trials.uploadTip = null;
|
||||
if (store.state.trials.timer) {
|
||||
clearInterval(store.state.trials.timer);
|
||||
store.state.trials.timer = null;
|
||||
}
|
||||
store.dispatch("trials/setUnLock", false);
|
||||
}
|
||||
export const downloadImage = async (id, id2, IsDicom = true) => {
|
||||
// if (flag[`${id2}_${IsDicom}`]) return Vue.prototype.$message.warning(Vue.prototype.$t('trials:upload:tip:uploading'));
|
||||
if (flag[`${id2}_${IsDicom}`]) return false;
|
||||
flag[`${id2}_${IsDicom}`] = true
|
||||
try {
|
||||
let params = {
|
||||
TrialId: id,
|
||||
SubjectVisitId: id2,
|
||||
IsDicom: IsDicom
|
||||
}
|
||||
store.dispatch("trials/setUnLock", true);
|
||||
let res = await requestPackageAndAnonymizImage(params);
|
||||
if (res.IsSuccess) {
|
||||
if (!res.Result) {
|
||||
flag[`${id2}_${IsDicom}`] = false;
|
||||
// Vue.prototype.$message.warning(Vue.prototype.$t("trials:upload:message:not"))
|
||||
let message = Vue.prototype.$t('trials:upload:tip:uploading').replace("xxx", res.OtherInfo.FileName);
|
||||
store.state.trials.uploadTip = message;
|
||||
if (!store.state.trials.timer) {
|
||||
store.state.trials.timer = setInterval(() => {
|
||||
downloadImage(id, id2, IsDicom);
|
||||
}, 2000);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (store.state.trials.timer) {
|
||||
clearInterval(store.state.trials.timer);
|
||||
store.state.trials.timer = null;
|
||||
}
|
||||
let fileName = res.Result.split("/").pop();
|
||||
let href = Vue.prototype.OSSclientConfig.basePath + res.Result;
|
||||
if (fileName !== res.OtherInfo.FileName) {
|
||||
let message = Vue.prototype.$t('trials:upload:tip:uploading').replace("xxx", res.OtherInfo.FileName);
|
||||
store.state.trials.uploadTip = message;
|
||||
// Vue.prototype.$message.success(Vue.prototype.$t("trials:upload:message:startUpload"));
|
||||
return download(href, res.OtherInfo.FileName, { id2, IsDicom });
|
||||
|
||||
}
|
||||
let a = document.createElement("a");
|
||||
a.download = res.OtherInfo.FileName;
|
||||
a.href = href;
|
||||
a.click();
|
||||
URL.revokeObjectURL(href);
|
||||
let timer = setTimeout(() => {
|
||||
a = null;
|
||||
href = null;
|
||||
timer = null;
|
||||
}, 500)
|
||||
store.state.trials.uploadTip = null;
|
||||
return true;
|
||||
} else {
|
||||
flag[`${id2}_${IsDicom}`] = false;
|
||||
return false;
|
||||
}
|
||||
} catch (err) {
|
||||
flag[`${id2}_${IsDicom}`] = false;
|
||||
console.log(err);
|
||||
}
|
||||
};
|
||||
export const fileDownload = (content, filename) => {
|
||||
const eleLink = document.createElement("a");
|
||||
eleLink.download = filename;
|
||||
eleLink.style.display = "none";
|
||||
const blob = new Blob([content]);
|
||||
eleLink.href = URL.createObjectURL(blob);
|
||||
document.body.appendChild(eleLink);
|
||||
eleLink.click();
|
||||
document.body.removeChild(eleLink);
|
||||
};
|
||||
let download = async (downloadUrl, downloadFileName, res) => {
|
||||
const blob = await getBlob(downloadUrl);
|
||||
flag[`${res.id2}_${res.IsDicom}`] = false;
|
||||
store.state.trials.uploadTip = null;
|
||||
store.dispatch("trials/setUnLock", false);
|
||||
saveAsB(blob, downloadFileName);
|
||||
return true;
|
||||
}
|
||||
|
||||
let getBlob = (url) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const xhr = new XMLHttpRequest();
|
||||
|
||||
xhr.open('GET', url, true);
|
||||
xhr.responseType = 'blob';
|
||||
xhr.onload = () => {
|
||||
if (xhr.status === 200) {
|
||||
resolve(xhr.response);
|
||||
} else {
|
||||
reject(new Error(`Request failed with status ${xhr.status}`));
|
||||
}
|
||||
};
|
||||
xhr.onerror = () => {
|
||||
reject(new Error('Request failed'));
|
||||
};
|
||||
|
||||
xhr.send();
|
||||
});
|
||||
}
|
||||
|
||||
let saveAsB = (blob, filename) => {
|
||||
const link = document.createElement('a');
|
||||
const body = document.body;
|
||||
|
||||
link.href = window.URL.createObjectURL(blob);
|
||||
link.download = filename;
|
||||
|
||||
// hide the link
|
||||
link.style.display = 'none';
|
||||
body.appendChild(link);
|
||||
|
||||
link.click();
|
||||
body.removeChild(link);
|
||||
|
||||
window.URL.revokeObjectURL(link.href);
|
||||
}
|
||||
|
||||
// 前端流式打包下载
|
||||
const handleBatchDown = async (item, zip) => {
|
||||
return new Promise((resolve) => {
|
||||
console.log("同步下载打包开始时间:" + new Date());
|
||||
// 创建压缩文件输出流
|
||||
const zipFileOutputStream = streamSaver.createWriteStream(zipName);
|
||||
// 创建下载文件流
|
||||
const fileIterator = files.values();
|
||||
const readableZipStream = new window.ZIP({
|
||||
async pull(ctrl) {
|
||||
const fileInfo = fileIterator.next();
|
||||
if (fileInfo.done) {//迭代终止
|
||||
ctrl.close();
|
||||
} else {
|
||||
const { name, url } = fileInfo.value;
|
||||
return fetch(url).then(res => {
|
||||
ctrl.enqueue({
|
||||
name,
|
||||
stream: () => res.body
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
if (window.WritableStream && readableZipStream.pipeTo) {
|
||||
// 开始下载
|
||||
readableZipStream
|
||||
.pipeTo(zipFileOutputStream)
|
||||
.then(() => { console.log("同步下载打包结束时间:" + new Date()); resolve(true) })
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
})
|
||||
|
||||
};
|
||||
@@ -0,0 +1,2 @@
|
||||
const WHITELIST = ['/', 'researchDetail_m', '/researchForm', '/ReviewersResearch', '/login', '/error', '/resetpassword', '/recompose', '/email-recompose', '/trialStats', '/showdicom', '/imagesShare', '/audit', '/preview', '/researchLogin', '/researchLogin_m', '/blindResumeInfo', '/trialsResume', '/joinVerify', '/showNoneDicoms', '/noneDicomReading', '/clinicalData', '/readingDicoms', '/readingPage', '/visitDicomReview', '/visitNondicomReview', '/globalReview', '/adReview', '/oncologyReview', '/nonedicoms']
|
||||
export default WHITELIST
|
||||
@@ -251,7 +251,7 @@ export default {
|
||||
},
|
||||
async loadPatientStudy() {
|
||||
try {
|
||||
let data = await getPatientSeriesList(this.studyId);
|
||||
const data = await getPatientSeriesList(this.studyId)
|
||||
if (data.IsSuccess) {
|
||||
const { Result } = data
|
||||
var seriesList = []
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<div class="sidePanelThumbs">
|
||||
<el-tabs v-model="activeName" type="border-card" @tab-click="handleTabClick">
|
||||
<el-tab-pane :label="$t('trials:dicom-show:currentVisit')" name="current-study">
|
||||
<div class="text-desc" style="background:rgb(55 55 55);">
|
||||
<div v-if="visitInfo" class="text-desc" style="background:rgb(55 55 55);">
|
||||
{{ visitInfo }}
|
||||
</div>
|
||||
<div class="viewerSidethumbs ps" style="position: relative;">
|
||||
@@ -143,7 +143,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
<el-tab-pane :label="$t('trials:dicom-show:relatedVisit')" name="relation-study" class="pane-relation-wrapper">
|
||||
<el-tab-pane :label="$t('trials:dicom-show:relatedVisit')" name="relation-study" class="pane-relation-wrapper" v-if="!visitTaskId">
|
||||
<div class="viewerSidethumbinner">
|
||||
<el-collapse v-model="relationActiveName" @change="handelRelationActiveChange">
|
||||
<el-collapse-item v-for="(study,studyIndex) in relationStudyList" :key="`${study.StudyId}`" :name="`${study.StudyId}`">
|
||||
@@ -261,6 +261,7 @@ import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
|
||||
import dicomViewer from '@/components/Dicom/DicomViewer'
|
||||
import { getVisitStudyList, getAllRelationStudyList, getSeriesList } from '@/api/reading'
|
||||
import { setSeriesStatus } from '@/api/trials'
|
||||
import { getTaskUploadedDicomStudyList } from '@/api/reading'
|
||||
import requestPoolManager from '@/utils/request-pool'
|
||||
import store from '@/store'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
@@ -301,7 +302,9 @@ export default {
|
||||
relationActiveName: [],
|
||||
showSeriesList: [],
|
||||
currentLoadIns: [],
|
||||
isFromCRCUpload: false
|
||||
isFromCRCUpload: false,
|
||||
visitTaskId: null,
|
||||
page: ''
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -318,6 +321,8 @@ export default {
|
||||
this.isReading = this.$router.currentRoute.query.isReading ? this.$router.currentRoute.query.isReading * 1 : 0
|
||||
this.showDelete = parseInt(this.$router.currentRoute.query.showDelete)
|
||||
this.isFromCRCUpload = !!this.$router.currentRoute.query.isFromCRCUpload
|
||||
this.visitTaskId = this.$router.currentRoute.query.visitTaskId
|
||||
this.page = this.$route.query.page
|
||||
// cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
|
||||
this.getStudiesInfo()
|
||||
cornerstone.events.addEventListener('cornerstoneimageloadprogress', this.cornerstoneimageloadprogress)
|
||||
@@ -338,7 +343,14 @@ export default {
|
||||
async getStudiesInfo() {
|
||||
this.studyList = []
|
||||
try {
|
||||
const res = await getVisitStudyList(this.trialId, this.subjectVisitId, this.isReading)
|
||||
let res = null
|
||||
if (this.page === 'upload') {
|
||||
res = await getTaskUploadedDicomStudyList({ visitTaskId: this.visitTaskId })
|
||||
} else if (this.page === 'download'){
|
||||
res = await getVisitStudyList(this.trialId, this.subjectVisitId, this.isReading, this.visitTaskId)
|
||||
} else {
|
||||
res = await getVisitStudyList(this.trialId, this.subjectVisitId, this.isReading)
|
||||
}
|
||||
if (res.IsSuccess) {
|
||||
res.Result.forEach((study, studyIndex) => {
|
||||
const data = {}
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
ref="sysTemplateFrom"
|
||||
v-loading="loading"
|
||||
:model="form"
|
||||
label-width="90px"
|
||||
label-width="140px"
|
||||
size="small"
|
||||
:rules="rules"
|
||||
class="upload-temporary-file"
|
||||
@@ -15,7 +15,7 @@
|
||||
<el-form-item label="业务场景: " prop="BusinessScenarioEnum">
|
||||
<el-select
|
||||
v-model="form.BusinessScenarioEnum"
|
||||
style="width:100%;"
|
||||
style="width: 100%"
|
||||
size="small"
|
||||
filterable
|
||||
>
|
||||
@@ -44,12 +44,14 @@
|
||||
:on-exceed="handleExceed"
|
||||
:disabled="!form.FileTypeEnum || !form.BusinessScenarioEnum"
|
||||
>
|
||||
<el-button size="small" type="primary" :disabled="!form.FileTypeEnum || !form.BusinessScenarioEnum" :loading="btnLoading">Select</el-button>
|
||||
<span
|
||||
slot="tip"
|
||||
style="margin-left:10px;"
|
||||
class="el-upload__tip"
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:disabled="!form.FileTypeEnum || !form.BusinessScenarioEnum"
|
||||
:loading="btnLoading"
|
||||
>Select</el-button
|
||||
>
|
||||
<span slot="tip" style="margin-left: 10px" class="el-upload__tip">
|
||||
(must be in xlsx/xls/doc/docx format)
|
||||
</span>
|
||||
</el-upload>
|
||||
@@ -58,37 +60,61 @@
|
||||
<el-form-item label="文件名" prop="Name">
|
||||
<el-input v-model="form.Name" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('dictionary:attachment:export:form:nameCN')"
|
||||
prop="NameCN"
|
||||
>
|
||||
<el-input v-model="form.NameCN" />
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.Id !== ''" label="是否废除: ">
|
||||
<el-radio-group v-model="form.IsDeleted">
|
||||
<el-radio v-for="item of $d.YesOrNo" :label="item.value">{{item.label}}</el-radio>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:label="item.value"
|
||||
:key="item.id"
|
||||
>{{ item.label }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="描述">
|
||||
<el-input
|
||||
v-model="form.Description"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:autosize="{ minRows: 2, maxRows: 4 }"
|
||||
placeholder="请输入内容"
|
||||
/>
|
||||
</el-form-item>
|
||||
</div>
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item style="text-align:right;">
|
||||
<el-button size="small" type="primary" :disabled="!form.FileTypeEnum || !form.BusinessScenarioEnum" :loading="saveBtnLoading" @click="handleSave">Save</el-button>
|
||||
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
|
||||
<el-form-item style="text-align: right">
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:disabled="!form.FileTypeEnum || !form.BusinessScenarioEnum"
|
||||
:loading="saveBtnLoading"
|
||||
@click="handleSave"
|
||||
>Save</el-button
|
||||
>
|
||||
</el-form-item>
|
||||
</div>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { addOrUpdateCommonDocument, uploadCommonDoc, Upload } from '@/api/dictionary'
|
||||
import {
|
||||
addOrUpdateCommonDocument,
|
||||
uploadCommonDoc,
|
||||
Upload,
|
||||
} from '@/api/dictionary'
|
||||
import { getBasicDataSelects } from '@/api/dictionary/dictionary'
|
||||
export default {
|
||||
name: 'TemplateForm',
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default() { return {} }
|
||||
}
|
||||
default() {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
data() {
|
||||
@@ -99,20 +125,30 @@ export default {
|
||||
FileTypeEnum: null,
|
||||
BusinessScenarioEnum: null,
|
||||
Name: '',
|
||||
NameCN: '',
|
||||
Path: '',
|
||||
Description: '',
|
||||
IsDeleted: false
|
||||
IsDeleted: false,
|
||||
},
|
||||
rules: {
|
||||
Code: [{ required: true, message: 'Please specify', trigger: ['blur'] }],
|
||||
Name: [{ required: true, message: 'Please specify', trigger: ['blur'] }],
|
||||
BusinessScenarioEnum: [{ required: true, message: 'Please select', trigger: ['blur'] }]
|
||||
Code: [
|
||||
{ required: true, message: 'Please specify', trigger: ['blur'] },
|
||||
],
|
||||
Name: [
|
||||
{ required: true, message: 'Please specify', trigger: ['blur'] },
|
||||
],
|
||||
NameCN: [
|
||||
{ required: true, message: 'Please specify', trigger: ['blur'] },
|
||||
],
|
||||
BusinessScenarioEnum: [
|
||||
{ required: true, message: 'Please select', trigger: ['blur'] },
|
||||
],
|
||||
},
|
||||
fileList: [],
|
||||
btnLoading: false,
|
||||
saveBtnLoading: false,
|
||||
loading: false,
|
||||
dictionaryList: {}
|
||||
dictionaryList: {},
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -128,8 +164,8 @@ export default {
|
||||
name: this.data.Name,
|
||||
path: this.data.Path,
|
||||
url: this.data.Path,
|
||||
type: this.data.Type
|
||||
}
|
||||
type: this.data.Type,
|
||||
},
|
||||
]
|
||||
}
|
||||
for (const k in this.form) {
|
||||
@@ -142,12 +178,14 @@ export default {
|
||||
// 获取文件类型下拉框
|
||||
getDicData() {
|
||||
this.loading = true
|
||||
getBasicDataSelects(['Common_File_ModuleType', 'Common_File_Type']).then(res => {
|
||||
this.dictionaryList = { ...res.Result }
|
||||
this.loading = false
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
getBasicDataSelects(['Common_File_ModuleType', 'Common_File_Type'])
|
||||
.then((res) => {
|
||||
this.dictionaryList = { ...res.Result }
|
||||
this.loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
beforeUpload(file) {
|
||||
// 检测文件类型是否符合要求
|
||||
@@ -165,35 +203,43 @@ export default {
|
||||
const formData = new FormData()
|
||||
formData.append('file', param.file)
|
||||
this.form.FileName = param.file.name
|
||||
Upload(formData, 1).then(res => {
|
||||
this.fileList.push({ name: param.file.name, path: res.Result.FilePath, fullPath: res.Result.FullFilePath, url: res.Result.FilePath })
|
||||
Upload(formData, 1).then((res) => {
|
||||
this.fileList.push({
|
||||
name: param.file.name,
|
||||
path: res.Result.FilePath,
|
||||
fullPath: res.Result.FullFilePath,
|
||||
url: res.Result.FilePath,
|
||||
})
|
||||
this.form.Path = res.Result.FilePath
|
||||
this.form.Name = param.file.name
|
||||
this.form.NameCN = param.file.name
|
||||
this.loading = false
|
||||
this.btnLoading = false
|
||||
})
|
||||
},
|
||||
handleSave() {
|
||||
this.$refs.sysTemplateFrom.validate(valid => {
|
||||
this.$refs.sysTemplateFrom.validate((valid) => {
|
||||
if (!valid) return
|
||||
if (!this.form.Name) {
|
||||
this.$alert('Please select file.')
|
||||
return
|
||||
}
|
||||
this.saveBtnLoading = true
|
||||
addOrUpdateCommonDocument(this.form).then(res => {
|
||||
this.saveBtnLoading = false
|
||||
this.$emit('closeDialog')
|
||||
this.$emit('getList')
|
||||
this.$message.success('Uploaded successfully')
|
||||
}).catch(() => {
|
||||
this.saveBtnLoading = false
|
||||
})
|
||||
addOrUpdateCommonDocument(this.form)
|
||||
.then((res) => {
|
||||
this.saveBtnLoading = false
|
||||
this.$emit('closeDialog')
|
||||
this.$emit('getList')
|
||||
this.$message.success('Uploaded successfully')
|
||||
})
|
||||
.catch(() => {
|
||||
this.saveBtnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleRemoveFile() {
|
||||
this.fileList = []
|
||||
this.form.Path = ''
|
||||
this.form.NameCN = ''
|
||||
this.form.Name = ''
|
||||
},
|
||||
handlePreview(file) {
|
||||
@@ -206,19 +252,21 @@ export default {
|
||||
},
|
||||
checkFileSuffix(fileName) {
|
||||
var typeArr = ['xls', 'xlsx', 'doc', 'docx']
|
||||
var extendName = fileName.substring(fileName.lastIndexOf('.') + 1).toLocaleLowerCase()
|
||||
var extendName = fileName
|
||||
.substring(fileName.lastIndexOf('.') + 1)
|
||||
.toLocaleLowerCase()
|
||||
if (typeArr.indexOf(extendName) !== -1) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.upload-temporary-file{
|
||||
.upload-temporary-file {
|
||||
.upload-container .el-upload--text {
|
||||
border: none;
|
||||
width: 80px;
|
||||
@@ -231,8 +279,8 @@ export default {
|
||||
color: #428bca;
|
||||
font-size: 13px;
|
||||
}
|
||||
.account_item_clear{
|
||||
.el-tag__close{
|
||||
.account_item_clear {
|
||||
.el-tag__close {
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<el-form-item label="业务场景">
|
||||
<el-select
|
||||
v-model="searchData.BusinessScenarioEnum"
|
||||
style="width:150px;"
|
||||
style="width: 150px"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.Common_File_BusinessScenario"
|
||||
@@ -13,15 +13,10 @@
|
||||
:label="item.label"
|
||||
:value="item.value"
|
||||
/>
|
||||
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="文件名称">
|
||||
<el-input
|
||||
v-model="searchData.Name"
|
||||
style="width:130px;"
|
||||
clearable
|
||||
/>
|
||||
<el-input v-model="searchData.Name" style="width: 130px" clearable />
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item>
|
||||
@@ -30,24 +25,28 @@
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<!-- 重置 -->
|
||||
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-refresh-left"
|
||||
@click="handleReset"
|
||||
>
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
style="float: right"
|
||||
size="small"
|
||||
@click="handleAdd"
|
||||
>
|
||||
{{ $t('common:button:new') }}
|
||||
</el-button>
|
||||
</el-form>
|
||||
<el-button
|
||||
type="primary"
|
||||
icon="el-icon-plus"
|
||||
style="margin-left:auto;"
|
||||
size="small"
|
||||
@click="handleAdd"
|
||||
>
|
||||
{{ $t('common:button:new') }}
|
||||
</el-button>
|
||||
</template>
|
||||
<template slot="main-container">
|
||||
<el-table
|
||||
v-adaptive="{bottomOffset:60}"
|
||||
v-adaptive="{ bottomOffset: 60 }"
|
||||
v-loading="loading"
|
||||
:data="list"
|
||||
stripe
|
||||
@@ -69,9 +68,13 @@
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ $fd('Common_File_BusinessScenario',scope.row.BusinessScenarioEnum) }}
|
||||
{{
|
||||
$fd(
|
||||
'Common_File_BusinessScenario',
|
||||
scope.row.BusinessScenarioEnum
|
||||
)
|
||||
}}
|
||||
</template>
|
||||
|
||||
</el-table-column>
|
||||
|
||||
<el-table-column
|
||||
@@ -80,6 +83,12 @@
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="NameCN"
|
||||
:label="$t('dictionary:attachment:upload:table:nameCN')"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
prop="Description"
|
||||
label="描述"
|
||||
@@ -92,8 +101,12 @@
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.IsDeleted" type="danger">{{ $fd('YesOrNo', scope.row.IsDeleted) }}</el-tag>
|
||||
<el-tag v-else type="primary">{{ $fd('YesOrNo', scope.row.IsDeleted) }}</el-tag>
|
||||
<el-tag v-if="scope.row.IsDeleted" type="danger">{{
|
||||
$fd('YesOrNo', scope.row.IsDeleted)
|
||||
}}</el-tag>
|
||||
<el-tag v-else type="primary">{{
|
||||
$fd('YesOrNo', scope.row.IsDeleted)
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@@ -105,29 +118,26 @@
|
||||
|
||||
<el-table-column label="Action">
|
||||
<template slot-scope="scope">
|
||||
<el-button
|
||||
type="text"
|
||||
@click="handleDownload(scope.row)"
|
||||
>
|
||||
<el-button type="text" @click="handleDownload(scope.row)">
|
||||
下载
|
||||
</el-button>
|
||||
<el-button
|
||||
type="text"
|
||||
@click="handleEdit(scope.row)"
|
||||
>
|
||||
<el-button type="text" @click="handleEdit(scope.row)">
|
||||
编辑
|
||||
</el-button>
|
||||
<el-button
|
||||
type="text"
|
||||
@click="handleDelete(scope.row)"
|
||||
>
|
||||
<el-button type="text" @click="handleDelete(scope.row)">
|
||||
删除
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</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"
|
||||
/>
|
||||
|
||||
<!-- 新增/编辑 -->
|
||||
<el-dialog
|
||||
@@ -138,13 +148,21 @@
|
||||
width="600px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<TemplateForm :data="currentRow" @closeDialog="closeDialog" @getList="getList" />
|
||||
<TemplateForm
|
||||
:data="currentRow"
|
||||
@closeDialog="closeDialog"
|
||||
@getList="getList"
|
||||
/>
|
||||
</el-dialog>
|
||||
</template>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import { getCommonDocumentList, DownloadCommonDoc, deleteCommonDocument } from '@/api/dictionary'
|
||||
import {
|
||||
getCommonDocumentList,
|
||||
DownloadCommonDoc,
|
||||
deleteCommonDocument,
|
||||
} from '@/api/dictionary'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import TemplateForm from './TemplateForm'
|
||||
@@ -155,7 +173,7 @@ const searchDataDefault = () => {
|
||||
BusinessScenarioEnum: null,
|
||||
Name: '',
|
||||
PageIndex: 1,
|
||||
PageSize: 20
|
||||
PageSize: 20,
|
||||
}
|
||||
}
|
||||
export default {
|
||||
@@ -168,7 +186,7 @@ export default {
|
||||
total: 0,
|
||||
currentRow: {},
|
||||
editDialog: { title: '', visible: false },
|
||||
loading: false
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -185,13 +203,15 @@ export default {
|
||||
},
|
||||
getList() {
|
||||
this.loading = true
|
||||
getCommonDocumentList(this.searchData).then(res => {
|
||||
this.loading = false
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
getCommonDocumentList(this.searchData)
|
||||
.then((res) => {
|
||||
this.loading = false
|
||||
this.list = res.Result.CurrentPageData
|
||||
this.total = res.Result.TotalCount
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 新增
|
||||
handleAdd() {
|
||||
@@ -202,9 +222,13 @@ export default {
|
||||
// 下载
|
||||
handleDownload(row) {
|
||||
this.loading = true
|
||||
DownloadCommonDoc(row.Code).then(data => {
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
DownloadCommonDoc(row.Code)
|
||||
.then((data) => {
|
||||
this.loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
// 编辑
|
||||
handleEdit(row) {
|
||||
@@ -233,7 +257,12 @@ export default {
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .search {
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -142,11 +142,16 @@
|
||||
<el-input v-model="form.Identification" placeholder="请输入标识" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-show="form.ConfigType === 'C' && title !== '复制'" :span="24">
|
||||
<el-col v-show="form.ConfigType === 'C' && title !== '复制'" :span="12">
|
||||
<el-form-item label="字段key">
|
||||
<el-input v-model="form.Code" placeholder="请输入字段key" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-show="form.ConfigType === 'C' && title !== '复制'" :span="12">
|
||||
<el-form-item label="字段key英文">
|
||||
<el-input v-model="form.CodeEn" placeholder="请输入字段key英文" />
|
||||
</el-form-item>
|
||||
</el-col>
|
||||
<el-col v-show="form.ConfigType === 'C' && title !== '复制'" :span="12">
|
||||
<el-form-item label="字段英文">
|
||||
<el-input v-model="form.Value" placeholder="请输入字段英文" />
|
||||
@@ -686,6 +691,7 @@
|
||||
height="100"
|
||||
>
|
||||
<el-table-column prop="Code" label="字段名" min-width="120px" :show-overflow-tooltip="true" />
|
||||
<el-table-column prop="CodeEn" label="字段名英文" min-width="120px" :show-overflow-tooltip="true" />
|
||||
<el-table-column prop="Value" label="字段英文" min-width="120px" :show-overflow-tooltip="true" />
|
||||
<el-table-column prop="ValueCN" label="字段中文" min-width="120px" :show-overflow-tooltip="true" />
|
||||
<el-table-column
|
||||
@@ -1143,6 +1149,7 @@ export default {
|
||||
IsShowParent: 0,
|
||||
Sort: 0,
|
||||
Code: null,
|
||||
CodeEn: null,
|
||||
Value: null,
|
||||
ValueCN: null,
|
||||
EnumType: '',
|
||||
|
||||
@@ -213,7 +213,6 @@ export default {
|
||||
}).then(res => {
|
||||
this.loading = false
|
||||
this.list = res.Result
|
||||
console.log(this.$d.GlobalAssessType)
|
||||
})
|
||||
},
|
||||
handleAdd() {
|
||||
@@ -265,7 +264,7 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="scss" scoped>
|
||||
/deep/ .el-form-item__content{
|
||||
width: calc(100% - 110px);
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@
|
||||
<template slot-scope="scope">
|
||||
<div>
|
||||
<el-radio-group v-model="scope.row.CrterionDictionaryGroup" @change="(v) => {crterionDictionaryGroupChange(v, scope.row)}" size="mini">
|
||||
<el-radio-button v-for="item of $d.CrterionDictionaryGroup" :label="item.value">{{item.label}}</el-radio-button>
|
||||
<el-radio-button v-for="item of $d.CrterionDictionaryGroup" :label="item.value" :key="item.id">{{item.label}}</el-radio-button>
|
||||
</el-radio-group>
|
||||
</div>
|
||||
</template>
|
||||
@@ -158,7 +158,6 @@ export default {
|
||||
},
|
||||
mounted() {
|
||||
this.getList()
|
||||
console.log(this.$d[this.parentCode])
|
||||
},
|
||||
methods: {
|
||||
crterionDictionaryGroupChange(v, row) {
|
||||
@@ -231,7 +230,7 @@ export default {
|
||||
}
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
<style lang="scss" scoped>
|
||||
/deep/ .el-form-item__content{
|
||||
width: calc(100% - 110px);
|
||||
}
|
||||
|
||||
@@ -10,7 +10,15 @@
|
||||
>
|
||||
<div class="base-dialog-body">
|
||||
<el-form-item label="类型" prop="Type">
|
||||
<el-select v-model="form.Type" clearable @change="((val)=>{typeChange(val, form)})">
|
||||
<el-select
|
||||
v-model="form.Type"
|
||||
clearable
|
||||
@change="
|
||||
(val) => {
|
||||
typeChange(val, form)
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of $d.Criterion_Question_Type"
|
||||
:key="item.value"
|
||||
@@ -31,10 +39,7 @@
|
||||
v-if="form.Type === 'group'"
|
||||
prop="GroupClassify"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.GroupClassify"
|
||||
clearable
|
||||
>
|
||||
<el-select v-model="form.GroupClassify" clearable>
|
||||
<el-option
|
||||
v-for="item of groupClassifyList"
|
||||
:key="item.Id"
|
||||
@@ -70,13 +75,9 @@
|
||||
v-if="form.Type === 'number' || form.Type === 'calculation'"
|
||||
label="数值类型"
|
||||
prop="ValueType"
|
||||
:rules="[
|
||||
{ required: true, message: '请选择'}
|
||||
]"
|
||||
:rules="[{ required: true, message: '请选择' }]"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.ValueType"
|
||||
>
|
||||
<el-radio-group v-model="form.ValueType">
|
||||
<el-radio
|
||||
v-for="item of $d.ValueType"
|
||||
:key="item.id"
|
||||
@@ -92,9 +93,7 @@
|
||||
v-if="form.Type === 'number' || form.Type === 'calculation'"
|
||||
label="单位"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.Unit"
|
||||
>
|
||||
<el-radio-group v-model="form.Unit">
|
||||
<el-radio
|
||||
v-for="item of $d.ValueUnit"
|
||||
:key="item.id"
|
||||
@@ -109,15 +108,26 @@
|
||||
label="表格类型标识"
|
||||
prop="LesionType"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.LesionType"
|
||||
clearable
|
||||
>
|
||||
<el-select v-model="form.LesionType" clearable>
|
||||
<el-option
|
||||
v-for="item of lesionTypes"
|
||||
:key="item.Code"
|
||||
:value="parseInt(item.Code)"
|
||||
:label="$fd('LesionType',parseInt(item.Code))"
|
||||
:label="$fd('LesionType', parseInt(item.Code))"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.Type === 'basicTable'"
|
||||
label="表格类型标识"
|
||||
prop="LesionType"
|
||||
>
|
||||
<el-select v-model="form.LesionType" clearable>
|
||||
<el-option
|
||||
v-for="item of lesionTypeList"
|
||||
:key="item.Id"
|
||||
:value="parseInt(item.Code)"
|
||||
:label="item.ValueCN"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
@@ -133,25 +143,27 @@
|
||||
</el-form-item> -->
|
||||
<!-- 选项类型 -->
|
||||
<el-form-item
|
||||
v-if="form.Type === 'select' || form.Type === 'radio' || form.Type === 'calculation'"
|
||||
v-if="
|
||||
form.Type === 'select' ||
|
||||
form.Type === 'radio' ||
|
||||
form.Type === 'calculation'
|
||||
"
|
||||
label="选项类型"
|
||||
prop="QuestionGenre"
|
||||
:rules="[
|
||||
{ required: form.Type !== 'calculation', message: '请选择'}
|
||||
]"
|
||||
:rules="[{ required: form.Type !== 'calculation', message: '请选择' }]"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.QuestionGenre"
|
||||
@change="((val)=>{questionGenreChange(val, form)})"
|
||||
@change="
|
||||
(val) => {
|
||||
questionGenreChange(val, form)
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-radio
|
||||
:label="-1"
|
||||
>
|
||||
无
|
||||
</el-radio>
|
||||
<el-radio :label="-1"> 无 </el-radio>
|
||||
<el-radio
|
||||
v-for="item of $d.TableQuestionType"
|
||||
v-show="item.value===0 || item.value===3"
|
||||
v-show="item.value === 0 || item.value === 3"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>
|
||||
@@ -183,13 +195,8 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
label="转化显示类型"
|
||||
prop="ConvertShowType"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.ConvertShowType"
|
||||
>
|
||||
<el-form-item label="转化显示类型" prop="ConvertShowType">
|
||||
<el-radio-group v-model="form.ConvertShowType">
|
||||
<el-radio
|
||||
v-for="item of $d.ConvertShowType"
|
||||
:key="item.id"
|
||||
@@ -200,11 +207,19 @@
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.QuestionGenre === 3 "
|
||||
v-if="form.QuestionGenre === 3"
|
||||
label="关联字典"
|
||||
prop="DictionaryCode"
|
||||
>
|
||||
<el-select v-model="form.DictionaryCode" clearable @change="() => {form.DefaultValue = null}">
|
||||
<el-select
|
||||
v-model="form.DictionaryCode"
|
||||
clearable
|
||||
@change="
|
||||
() => {
|
||||
form.DefaultValue = null
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of dicList"
|
||||
:key="item.Id"
|
||||
@@ -213,10 +228,7 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.QuestionGenre === 3 "
|
||||
label="默认值"
|
||||
>
|
||||
<el-form-item v-if="form.QuestionGenre === 3" label="默认值">
|
||||
<el-select v-model="form.DefaultValue" clearable>
|
||||
<el-option
|
||||
v-for="item of form.DictionaryCode ? $d[form.DictionaryCode] : []"
|
||||
@@ -226,10 +238,7 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="form.QuestionGenre === 0 "
|
||||
label="默认值"
|
||||
>
|
||||
<el-form-item v-if="form.QuestionGenre === 0" label="默认值">
|
||||
<el-select v-model="form.DefaultValue" clearable>
|
||||
<el-option
|
||||
v-for="item of form.TypeValue ? form.TypeValue.split('|') : []"
|
||||
@@ -240,10 +249,18 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
|
||||
<el-form-item v-if="form.Type !== 'group'" label="是否显示" prop="ShowQuestion">
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group'"
|
||||
label="是否显示"
|
||||
prop="ShowQuestion"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.ShowQuestion"
|
||||
@change="((val)=>{isShowQuestionChange(val, form)})"
|
||||
@change="
|
||||
(val) => {
|
||||
isShowQuestionChange(val, form)
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.ShowQuestion"
|
||||
@@ -257,14 +274,18 @@
|
||||
|
||||
<!-- 显示时依赖父问题 -->
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group' && form.ShowQuestion===1"
|
||||
v-if="form.Type !== 'group' && form.ShowQuestion === 1"
|
||||
label="显示依赖父问题"
|
||||
prop="ParentId"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.ParentId"
|
||||
clearable
|
||||
@change="((val)=>{parentQuestionChange(val, form)})"
|
||||
@change="
|
||||
(val) => {
|
||||
parentQuestionChange(val, form)
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of parentOptions"
|
||||
@@ -275,15 +296,19 @@
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<!-- 显示时依赖父问题触发值 -->
|
||||
<el-form-item v-if="form.ParentId && form.ShowQuestion===1" label="显示触发值" prop="ParentTriggerValueList">
|
||||
<!-- <el-select v-model="form.ParentTriggerValue" clearable>-->
|
||||
<!-- <el-option-->
|
||||
<!-- v-for="item of parentTriggerValOptions"-->
|
||||
<!-- :key="item.id"-->
|
||||
<!-- :label="item.label"-->
|
||||
<!-- :value="item.value.toString()"-->
|
||||
<!-- />-->
|
||||
<!-- </el-select>-->
|
||||
<el-form-item
|
||||
v-if="form.ParentId && form.ShowQuestion === 1"
|
||||
label="显示触发值"
|
||||
prop="ParentTriggerValueList"
|
||||
>
|
||||
<!-- <el-select v-model="form.ParentTriggerValue" clearable>-->
|
||||
<!-- <el-option-->
|
||||
<!-- v-for="item of parentTriggerValOptions"-->
|
||||
<!-- :key="item.id"-->
|
||||
<!-- :label="item.label"-->
|
||||
<!-- :value="item.value.toString()"-->
|
||||
<!-- />-->
|
||||
<!-- </el-select>-->
|
||||
<el-select v-model="form.ParentTriggerValueList" clearable multiple>
|
||||
<el-option
|
||||
v-for="item of parentTriggerValOptions"
|
||||
@@ -293,16 +318,44 @@
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.Type === 'select' || form.Type === 'radio' || form.Type === 'calculation'" label="是否裁判问题">
|
||||
<el-radio-group v-model="form.IsJudgeQuestion" @change="((val)=>{isJudgeQuestionChange(val, form)})">
|
||||
<el-radio v-for="item of $d.YesOrNo" :key="`YesOrNo${item.value}`" :label="item.value">{{ item.label }}</el-radio>
|
||||
<el-form-item
|
||||
v-if="
|
||||
form.Type === 'select' ||
|
||||
form.Type === 'radio' ||
|
||||
form.Type === 'calculation' ||
|
||||
form.Type === 'number'
|
||||
"
|
||||
label="是否裁判问题"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsJudgeQuestion"
|
||||
@change="
|
||||
(val) => {
|
||||
isJudgeQuestionChange(val, form)
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="`YesOrNo${item.value}`"
|
||||
:label="item.value"
|
||||
>{{ item.label }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.Type !== 'group' && form.Type !== 'table'" label="是否必填" prop="IsRequired">
|
||||
<el-form-item
|
||||
v-if="form.Type !== 'group' && form.Type !== 'table'"
|
||||
label="是否必填"
|
||||
prop="IsRequired"
|
||||
>
|
||||
<el-radio-group
|
||||
v-model="form.IsRequired"
|
||||
:disabled="form.IsJudgeQuestion===true || form.ShowQuestion===2"
|
||||
@change="((val)=>{isRequiredChange(val, form)})"
|
||||
:disabled="form.IsJudgeQuestion === true || form.ShowQuestion === 2"
|
||||
@change="
|
||||
(val) => {
|
||||
isRequiredChange(val, form)
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-radio
|
||||
v-for="item of $d.QuestionRequired"
|
||||
@@ -323,7 +376,11 @@
|
||||
<el-select
|
||||
v-model="form.RelevanceId"
|
||||
clearable
|
||||
@change="((val)=>{relevanceQuestionChange(val, form)})"
|
||||
@change="
|
||||
(val) => {
|
||||
relevanceQuestionChange(val, form)
|
||||
}
|
||||
"
|
||||
>
|
||||
<el-option
|
||||
v-for="item of parentOptions"
|
||||
@@ -339,14 +396,14 @@
|
||||
label="必填触发值"
|
||||
prop="RelevanceValueList"
|
||||
>
|
||||
<!-- <el-select v-model="form.RelevanceValue" clearable>-->
|
||||
<!-- <el-option-->
|
||||
<!-- v-for="item of reParentTriggerValOptions"-->
|
||||
<!-- :key="item.id"-->
|
||||
<!-- :label="item.label"-->
|
||||
<!-- :value="item.value.toString()"-->
|
||||
<!-- />-->
|
||||
<!-- </el-select>-->
|
||||
<!-- <el-select v-model="form.RelevanceValue" clearable>-->
|
||||
<!-- <el-option-->
|
||||
<!-- v-for="item of reParentTriggerValOptions"-->
|
||||
<!-- :key="item.id"-->
|
||||
<!-- :label="item.label"-->
|
||||
<!-- :value="item.value.toString()"-->
|
||||
<!-- />-->
|
||||
<!-- </el-select>-->
|
||||
<el-select v-model="form.RelevanceValueList" clearable multiple>
|
||||
<el-option
|
||||
v-for="item of reParentTriggerValOptions"
|
||||
@@ -385,7 +442,11 @@
|
||||
</el-form-item> -->
|
||||
|
||||
<el-form-item v-if="form.Type !== 'group'" label="问题分组">
|
||||
<el-select v-model="form.GroupId" clearable :disabled="isParentExistGroup">
|
||||
<el-select
|
||||
v-model="form.GroupId"
|
||||
clearable
|
||||
:disabled="isParentExistGroup"
|
||||
>
|
||||
<el-option
|
||||
v-for="group of groupOptions"
|
||||
:key="group.GroupId"
|
||||
@@ -396,12 +457,22 @@
|
||||
</el-form-item>
|
||||
<el-form-item label="限制编辑">
|
||||
<el-radio-group v-model="form.LimitEdit">
|
||||
<el-radio v-for="item of $d.LimitEdit" :key="`LimitEdit${item.value}`" :label="item.value">{{ item.label }}</el-radio>
|
||||
<el-radio
|
||||
v-for="item of $d.LimitEdit"
|
||||
:key="`LimitEdit${item.value}`"
|
||||
:label="item.value"
|
||||
>{{ item.label }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="全局阅片是否显示">
|
||||
<el-radio-group v-model="form.GlobalReadingShowType">
|
||||
<el-radio v-for="item of $d.GlobalReadingShowType" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
|
||||
<el-radio
|
||||
v-for="item of $d.GlobalReadingShowType"
|
||||
:key="item.id"
|
||||
:label="item.value"
|
||||
>{{ item.label }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
@@ -409,10 +480,7 @@
|
||||
v-if="form.Type !== 'group'"
|
||||
prop="QuestionType"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.QuestionType"
|
||||
clearable
|
||||
>
|
||||
<el-select v-model="form.QuestionType" clearable>
|
||||
<el-option
|
||||
v-for="item of CriterionDictionaryList.QuestionType"
|
||||
:key="item.Id"
|
||||
@@ -428,9 +496,18 @@
|
||||
</el-radio-group>
|
||||
</el-form-item> -->
|
||||
<el-form-item v-if="form.Type === 'upload'" label="最大上传个数">
|
||||
<el-input-number v-model="form.ImageCount" controls-position="right" :min="1" :max="10" />
|
||||
<el-input-number
|
||||
v-model="form.ImageCount"
|
||||
controls-position="right"
|
||||
:min="1"
|
||||
:max="10"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item v-if="form.Type === 'select' || form.Type === 'radio'" label="高亮标记值" prop="HighlightAnswerList">
|
||||
<el-form-item
|
||||
v-if="form.Type === 'select' || form.Type === 'radio'"
|
||||
label="高亮标记值"
|
||||
prop="HighlightAnswerList"
|
||||
>
|
||||
<el-select v-model="form.HighlightAnswerList" clearable multiple>
|
||||
<template v-if="form.TypeValue">
|
||||
<el-option
|
||||
@@ -471,20 +548,23 @@
|
||||
|
||||
<el-form-item label="是否在阅片页面显示">
|
||||
<el-radio-group v-model="form.IsShowInDicom">
|
||||
<el-radio v-for="item of $d.YesOrNo" :key="`YesOrNo${item.value}`" :label="item.value">{{ item.label }}</el-radio>
|
||||
<el-radio
|
||||
v-for="item of $d.YesOrNo"
|
||||
:key="`YesOrNo${item.value}`"
|
||||
:label="item.value"
|
||||
>{{ item.label }}</el-radio
|
||||
>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('trials:readingUnit:qsList:title:Remark')"
|
||||
prop="Remark"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.Remark"
|
||||
/>
|
||||
<el-input v-model="form.Remark" />
|
||||
</el-form-item>
|
||||
</div>
|
||||
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
|
||||
<el-form-item>
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
@@ -496,7 +576,12 @@
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button size="small" type="primary" :loading="btnLoading" @click="save">
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:loading="btnLoading"
|
||||
@click="save"
|
||||
>
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
@@ -504,20 +589,31 @@
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { getBasicConfigSelect, addOrUpdateReadingQuestionSystem, getSystemCriterionOtherQuestion, getSystemGroupNameList, getCriterionDictionary, getCriterionDictionaryList } from '@/api/dictionary'
|
||||
import {
|
||||
getBasicConfigSelect,
|
||||
addOrUpdateReadingQuestionSystem,
|
||||
getSystemCriterionOtherQuestion,
|
||||
getSystemGroupNameList,
|
||||
getCriterionDictionary,
|
||||
getCriterionDictionaryList,
|
||||
} from '@/api/dictionary'
|
||||
import { getCriterionLesionType } from '@/api/trials'
|
||||
export default {
|
||||
name: 'AddOrUpdateClinicalData',
|
||||
props: {
|
||||
data: {
|
||||
type: Object,
|
||||
default() { return {} }
|
||||
default() {
|
||||
return {}
|
||||
},
|
||||
},
|
||||
type: {
|
||||
type: String,
|
||||
default() { return '' }
|
||||
}
|
||||
},
|
||||
default() {
|
||||
return ''
|
||||
},
|
||||
},
|
||||
},
|
||||
data() {
|
||||
var validateTypeVal = (rule, value, callback) => {
|
||||
if (value === '') {
|
||||
@@ -553,7 +649,7 @@ export default {
|
||||
IsJudgeQuestion: false,
|
||||
GroupName: '',
|
||||
GroupEnName: '',
|
||||
GroupClassify:null,
|
||||
GroupClassify: null,
|
||||
Remark: '',
|
||||
ImageCount: 1,
|
||||
RelevanceId: '',
|
||||
@@ -570,32 +666,38 @@ export default {
|
||||
GroupId: null,
|
||||
ConvertShowType: 0,
|
||||
QuestionClassify: null,
|
||||
HighlightAnswerList: []
|
||||
HighlightAnswerList: [],
|
||||
},
|
||||
rules: {
|
||||
Type: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
Type: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
LesionType: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
QuestionName: [
|
||||
{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 300, message: '最大长度为 300' },
|
||||
],
|
||||
LesionType: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
],
|
||||
QuestionName: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 300, message: '最大长度为 300' }],
|
||||
QuestionGenre: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
TypeValue: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
TypeValue: [
|
||||
{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ validator: validateTypeVal, trigger: 'blur' },
|
||||
{ max: 500, message: '最大长度为 500' }],
|
||||
DictionaryCode: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
{ max: 500, message: '最大长度为 500' },
|
||||
],
|
||||
DictionaryCode: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' },
|
||||
],
|
||||
ShowQuestion: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
IsRequired: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
ParentId: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
ParentTriggerValueList: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' }
|
||||
{ required: true, message: '请选择', trigger: 'blur' },
|
||||
],
|
||||
RelevanceId: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
RelevanceValueList: [{ required: true, message: '请选择', trigger: 'blur' }],
|
||||
GroupName: [{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 50, message: '最大长度为 50' }]
|
||||
RelevanceValueList: [
|
||||
{ required: true, message: '请选择', trigger: 'blur' },
|
||||
],
|
||||
GroupName: [
|
||||
{ required: true, message: '请注明', trigger: 'blur' },
|
||||
{ max: 50, message: '最大长度为 50' },
|
||||
],
|
||||
},
|
||||
loading: false,
|
||||
btnLoading: false,
|
||||
@@ -606,8 +708,9 @@ export default {
|
||||
lesionTypes: [],
|
||||
dicList: [],
|
||||
CriterionDictionaryList: [],
|
||||
groupClassifyList:[],
|
||||
highlightAnswers: []
|
||||
groupClassifyList: [],
|
||||
highlightAnswers: [],
|
||||
lesionTypeList: []
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -622,14 +725,14 @@ export default {
|
||||
}
|
||||
let res = await getCriterionDictionary({
|
||||
ReadingCriterionId: this.data.ReadingQuestionCriterionSystemId,
|
||||
DictionaryCode: this.form.DictionaryCode
|
||||
DictionaryCode: this.form.DictionaryCode,
|
||||
})
|
||||
this.highlightAnswers = res.Result[this.form.DictionaryCode]
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.initForm()
|
||||
@@ -638,22 +741,31 @@ export default {
|
||||
getCriterionDictionary() {
|
||||
getCriterionDictionary({
|
||||
ReadingCriterionId: this.data.ReadingQuestionCriterionSystemId,
|
||||
DictionaryCode: 'QuestionType'
|
||||
}).then(res => {
|
||||
DictionaryCode: 'QuestionType',
|
||||
}).then((res) => {
|
||||
this.CriterionDictionaryList = res.Result
|
||||
})
|
||||
},
|
||||
getGroupClassifyDictionary() {
|
||||
getCriterionDictionary({
|
||||
ReadingCriterionId: this.data.ReadingQuestionCriterionSystemId,
|
||||
DictionaryCode: 'GroupClassify'
|
||||
}).then(res => {
|
||||
DictionaryCode: 'GroupClassify',
|
||||
}).then((res) => {
|
||||
this.groupClassifyList = res.Result.GroupClassify
|
||||
})
|
||||
},
|
||||
getLesionTypeDictionary() {
|
||||
getCriterionDictionary({
|
||||
ReadingCriterionId: this.data.ReadingQuestionCriterionSystemId,
|
||||
DictionaryCode: 'LesionType',
|
||||
}).then((res) => {
|
||||
this.lesionTypeList = res.Result.LesionType
|
||||
})
|
||||
},
|
||||
async initForm() {
|
||||
await this.getGroupOptions()
|
||||
await this.getParentQuestions()
|
||||
await this.getLesionTypeDictionary()
|
||||
await this.getLesionType()
|
||||
if (Object.keys(this.data).length > 0) {
|
||||
for (const k in this.form) {
|
||||
@@ -661,37 +773,47 @@ export default {
|
||||
this.form[k] = this.data[k]
|
||||
}
|
||||
}
|
||||
if (this.form.ParentId !== '' && this.form.ParentId !== null && this.form.GroupName !== '') {
|
||||
if (
|
||||
this.form.ParentId !== '' &&
|
||||
this.form.ParentId !== null &&
|
||||
this.form.GroupName !== ''
|
||||
) {
|
||||
this.isParentExistGroup = true
|
||||
}
|
||||
if (this.form.ParentId) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
var index = this.parentOptions.findIndex((item) => {
|
||||
return item.QuestionId === this.form.ParentId
|
||||
})
|
||||
if (index !== -1) {
|
||||
if (this.parentOptions[index].QuestionGenre === 3) {
|
||||
this.parentTriggerValOptions = this.$d[this.parentOptions[index].DictionaryCode]
|
||||
this.parentTriggerValOptions =
|
||||
this.$d[this.parentOptions[index].DictionaryCode]
|
||||
} else {
|
||||
const options = []
|
||||
this.parentOptions[index].TypeValue.split('|').forEach((item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
})
|
||||
this.parentOptions[index].TypeValue.split('|').forEach(
|
||||
(item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
}
|
||||
)
|
||||
this.parentTriggerValOptions = options
|
||||
}
|
||||
}
|
||||
}
|
||||
if (this.form.RelevanceId) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
var index = this.parentOptions.findIndex((item) => {
|
||||
return item.QuestionId === this.form.RelevanceId
|
||||
})
|
||||
if (index !== -1) {
|
||||
if (this.parentOptions[index].QuestionGenre === 3) {
|
||||
this.reParentTriggerValOptions = this.$d[this.parentOptions[index].DictionaryCode]
|
||||
this.reParentTriggerValOptions =
|
||||
this.$d[this.parentOptions[index].DictionaryCode]
|
||||
} else {
|
||||
const options = []
|
||||
this.parentOptions[index].TypeValue.split('|').forEach((item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
})
|
||||
this.parentOptions[index].TypeValue.split('|').forEach(
|
||||
(item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
}
|
||||
)
|
||||
this.reParentTriggerValOptions = options
|
||||
}
|
||||
}
|
||||
@@ -701,18 +823,19 @@ export default {
|
||||
this.getGroupClassifyDictionary()
|
||||
},
|
||||
save() {
|
||||
this.$refs.clinicalDataForm.validate(valid => {
|
||||
this.$refs.clinicalDataForm.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.btnLoading = true
|
||||
if (this.form.Type !== 'upload') {
|
||||
this.form.ImageCount = 0
|
||||
}
|
||||
addOrUpdateReadingQuestionSystem(this.form).then(res => {
|
||||
this.btnLoading = false
|
||||
this.$emit('getList')
|
||||
this.$emit('close')
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
})
|
||||
addOrUpdateReadingQuestionSystem(this.form)
|
||||
.then((res) => {
|
||||
this.btnLoading = false
|
||||
this.$emit('getList')
|
||||
this.$emit('close')
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
})
|
||||
.catch(() => {
|
||||
this.btnLoading = false
|
||||
})
|
||||
@@ -722,33 +845,38 @@ export default {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
criterionId: this.data.ReadingQuestionCriterionSystemId
|
||||
criterionId: this.data.ReadingQuestionCriterionSystemId,
|
||||
}
|
||||
getSystemGroupNameList(param).then(res => {
|
||||
this.groupOptions = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
getSystemGroupNameList(param)
|
||||
.then((res) => {
|
||||
this.groupOptions = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
getParentQuestions() {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
readingQuestionCriterionSystemId: this.data.ReadingQuestionCriterionSystemId,
|
||||
id: this.data.Id
|
||||
readingQuestionCriterionSystemId:
|
||||
this.data.ReadingQuestionCriterionSystemId,
|
||||
id: this.data.Id,
|
||||
}
|
||||
getSystemCriterionOtherQuestion(param).then(res => {
|
||||
this.parentOptions = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
getSystemCriterionOtherQuestion(param)
|
||||
.then((res) => {
|
||||
this.parentOptions = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
questionGenreChange(val, form) {
|
||||
@@ -819,17 +947,20 @@ export default {
|
||||
parentQuestionChange(val, form) {
|
||||
this.isParentExistGroup = false
|
||||
if (val) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
var index = this.parentOptions.findIndex((item) => {
|
||||
return item.QuestionId === val
|
||||
})
|
||||
if (index !== -1) {
|
||||
if (this.parentOptions[index].QuestionGenre === 3) {
|
||||
this.parentTriggerValOptions = this.$d[this.parentOptions[index].DictionaryCode]
|
||||
this.parentTriggerValOptions =
|
||||
this.$d[this.parentOptions[index].DictionaryCode]
|
||||
} else {
|
||||
var options = []
|
||||
this.parentOptions[index].TypeValue.split('|').forEach((item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
})
|
||||
this.parentOptions[index].TypeValue.split('|').forEach(
|
||||
(item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
}
|
||||
)
|
||||
this.parentTriggerValOptions = options
|
||||
}
|
||||
if (this.parentOptions[index].GroupName) {
|
||||
@@ -845,17 +976,20 @@ export default {
|
||||
},
|
||||
relevanceQuestionChange(val, form) {
|
||||
if (val) {
|
||||
var index = this.parentOptions.findIndex(item => {
|
||||
var index = this.parentOptions.findIndex((item) => {
|
||||
return item.QuestionId === val
|
||||
})
|
||||
if (index !== -1) {
|
||||
if (this.parentOptions[index].QuestionGenre === 3) {
|
||||
this.reParentTriggerValOptions = this.$d[this.parentOptions[index].DictionaryCode]
|
||||
this.reParentTriggerValOptions =
|
||||
this.$d[this.parentOptions[index].DictionaryCode]
|
||||
} else {
|
||||
var options = []
|
||||
this.parentOptions[index].TypeValue.split('|').forEach((item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
})
|
||||
this.parentOptions[index].TypeValue.split('|').forEach(
|
||||
(item, index) => {
|
||||
options.push({ id: index, label: item, value: item })
|
||||
}
|
||||
)
|
||||
this.reParentTriggerValOptions = options
|
||||
}
|
||||
}
|
||||
@@ -871,23 +1005,24 @@ export default {
|
||||
return new Promise((resolve, reject) => {
|
||||
this.loading = true
|
||||
var param = {
|
||||
SystemCriterionId: this.data.ReadingQuestionCriterionSystemId
|
||||
SystemCriterionId: this.data.ReadingQuestionCriterionSystemId,
|
||||
}
|
||||
getCriterionLesionType(param).then(res => {
|
||||
this.lesionTypes = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
}).catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
getCriterionLesionType(param)
|
||||
.then((res) => {
|
||||
this.lesionTypes = res.Result
|
||||
this.loading = false
|
||||
resolve()
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
reject()
|
||||
})
|
||||
})
|
||||
},
|
||||
close() {
|
||||
this.$emit('close')
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -170,7 +170,7 @@
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
:disabled="scope.row.Type !== 'table'"
|
||||
:disabled="!(scope.row.Type === 'table' || scope.row.Type === 'basicTable')"
|
||||
@click="handleConfig(scope.row)"
|
||||
>
|
||||
表格问题
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
>{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="序号">
|
||||
<el-form-item label="序号" prop="ShowOrder">
|
||||
<el-input v-model="form.ShowOrder" type="number" />
|
||||
</el-form-item>
|
||||
<!-- 描述 -->
|
||||
@@ -135,7 +135,8 @@ export default {
|
||||
Part: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] }],
|
||||
TULOC: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] }],
|
||||
Remark: [{ max: 500, message: `${this.$t('common:ruleMessage:maxLength')} 500`, trigger: ['blur', 'change'] }],
|
||||
IsLymphNodes: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] }]
|
||||
IsLymphNodes: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] }],
|
||||
ShowOrder: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] }]
|
||||
},
|
||||
lesionTypes: [],
|
||||
loading: false,
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<el-form :inline="true" size="mini">
|
||||
<el-form-item label="器官类型">
|
||||
<el-select v-model="searchData.OrganType" clearable style="width:130px;">
|
||||
<el-option v-for="item of CriterionDictionaryOrganTypeList.OrganType" :key="item.Id" :value="parseInt(item.Code)" :label="item.ValueCN" />
|
||||
<el-option v-for="item of CriterionDictionaryOrganTypeList && CriterionDictionaryOrganTypeList.OrganType" :key="item.Id" :value="parseInt(item.Code)" :label="item.ValueCN" />
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="部位">
|
||||
|
||||
@@ -355,11 +355,11 @@
|
||||
<el-radio v-for="item of $d.LimitEdit" :key="item.value" :label="item.value">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
<el-form-item label="全局阅片是否显示">
|
||||
<!-- <el-form-item label="全局阅片是否显示">
|
||||
<el-radio-group v-model="form.GlobalReadingShowType">
|
||||
<el-radio v-for="item of $d.GlobalReadingShowType" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
|
||||
</el-radio-group>
|
||||
</el-form-item>
|
||||
</el-radio-group>
|
||||
</el-form-item> -->
|
||||
</div>
|
||||
<div class="base-dialog-footer" style="text-align:right;margin-top:10px;">
|
||||
<el-form-item>
|
||||
@@ -445,7 +445,7 @@ export default {
|
||||
DependParentId: '',
|
||||
QuestionMark: null,
|
||||
LimitEdit: 0,
|
||||
GlobalReadingShowType: null,
|
||||
// GlobalReadingShowType: null,
|
||||
QuestionClassify: null,
|
||||
HighlightAnswerList: []
|
||||
|
||||
|
||||
@@ -1,11 +1,29 @@
|
||||
<template>
|
||||
<div style="display: flex;justify-content: center">
|
||||
<div style="width: 600px;text-align: center;border: 1px solid #e6e6e6;margin-top:40px;padding:10px;">
|
||||
<div class="trial-myinfo-head" style="font-size: 30px;line-height: 120px;">
|
||||
<div style="display: flex; justify-content: center">
|
||||
<div
|
||||
style="
|
||||
width: 600px;
|
||||
text-align: center;
|
||||
border: 1px solid #e6e6e6;
|
||||
margin-top: 40px;
|
||||
padding: 10px;
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="trial-myinfo-head"
|
||||
style="font-size: 30px; line-height: 120px"
|
||||
>
|
||||
<!-- 首次登录修改密码 -->
|
||||
{{ $t('recompose:title:init') }}
|
||||
</div>
|
||||
<el-form ref="passwordForm" v-loading="loading" label-position="right" :model="password" :rules="passwordFormRules" label-width="200px">
|
||||
<el-form
|
||||
ref="passwordForm"
|
||||
v-loading="loading"
|
||||
label-position="right"
|
||||
:model="password"
|
||||
:rules="passwordFormRules"
|
||||
:label-width="$i18n.locale == 'zh' ? '100px' : '200px'"
|
||||
>
|
||||
<!-- 邮箱 -->
|
||||
<el-form-item :label="$t('recompose:form:email')" prop="Email">
|
||||
<el-input v-model="password.Email" disabled />
|
||||
@@ -19,70 +37,135 @@
|
||||
<el-input v-model="password.NewUserName" />
|
||||
</el-form-item>
|
||||
<!-- 新密码 -->
|
||||
<el-form-item :label="$t('recompose:form:newPassword')" prop="NewPassWord">
|
||||
<el-input v-model="password.NewPassWord" type="password" show-password auto-complete="new-password" />
|
||||
<el-form-item
|
||||
:label="$t('recompose:form:newPassword')"
|
||||
prop="NewPassWord"
|
||||
>
|
||||
<el-input
|
||||
v-model="password.NewPassWord"
|
||||
type="password"
|
||||
show-password
|
||||
auto-complete="new-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 确认密码 -->
|
||||
<el-form-item :label="$t('recompose:form:confirmPassword')" prop="ConfirmPassWord">
|
||||
<el-input v-model="password.ConfirmPassWord" type="password" show-password auto-complete="new-password" />
|
||||
<el-form-item
|
||||
:label="$t('recompose:form:confirmPassword')"
|
||||
prop="ConfirmPassWord"
|
||||
>
|
||||
<el-input
|
||||
v-model="password.ConfirmPassWord"
|
||||
type="password"
|
||||
show-password
|
||||
auto-complete="new-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item style="text-align:right">
|
||||
<el-form-item style="text-align: right">
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
size="small"
|
||||
@click="cancel"
|
||||
>
|
||||
<el-button size="small" @click="cancel">
|
||||
{{ $t('recompose:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="save"
|
||||
>
|
||||
<el-button type="primary" size="small" @click="save">
|
||||
{{ $t('recompose:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { initSetUserNameAndPwd } from '@/api/admin.js'
|
||||
import md5 from 'js-md5'
|
||||
import {mapGetters, mapMutations} from "vuex";
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
password: {
|
||||
NewUserName: null,
|
||||
UserId: null
|
||||
UserId: null,
|
||||
},
|
||||
passwordFormRules: {
|
||||
NewUserName: [{ required: true, validator: (rule, value, callback) => {!value ? callback(new Error(this.$t('trials:researchForm:formRule:specify'))) : callback()}, trigger: 'blur' }],
|
||||
NewUserName: [
|
||||
{
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
var lang = zzSessionStorage.getItem('lang')
|
||||
? zzSessionStorage.getItem('lang')
|
||||
: 'zh'
|
||||
/* eslint-disable */
|
||||
var reg1 = /^[a-zA-Z0-9_]{4,16}$/ //密码必须是8位以上、必须含有字母、数字、特殊符号
|
||||
console.log(!reg1.test(value))
|
||||
if (!reg1.test(value)) {
|
||||
callback(
|
||||
lang === 'zh'
|
||||
? new Error(
|
||||
'1)新建账号,用户名字符长度最小为4个字符,最大为16个字符,只可使用字母、数字、下划线;'
|
||||
)
|
||||
: new Error(
|
||||
'For a new account, the username must have:1) At least 4 characters;2) At most 16 characters;3)Only letters, numbers, and underscores are allowed.'
|
||||
)
|
||||
)
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
NewPassWord: [
|
||||
{ required: true, validator: (rule, value, callback) => {!value ? callback(new Error(this.$t('trials:researchForm:formRule:specify'))) : callback()}, trigger: 'blur' },
|
||||
{
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
!value
|
||||
? callback(
|
||||
new Error(this.$t('trials:researchForm:formRule:specify'))
|
||||
)
|
||||
: callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
validator: this.$validatePassword
|
||||
validator: this.$validatePassword,
|
||||
},
|
||||
],
|
||||
ConfirmPassWord: [
|
||||
{ required: true, validator: (rule, value, callback) => {!value ? callback(new Error(this.$t('trials:researchForm:formRule:specify'))) : callback()}, trigger: 'blur' }
|
||||
]
|
||||
{
|
||||
required: true,
|
||||
validator: (rule, value, callback) => {
|
||||
!value
|
||||
? callback(
|
||||
new Error(this.$t('trials:researchForm:formRule:specify'))
|
||||
)
|
||||
: callback()
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
validator: (rule, value, callback) => {
|
||||
value !== this.password.NewPassWord
|
||||
? callback(
|
||||
new Error(
|
||||
this.$t(
|
||||
'trials:researchForm:formRule:NewPassWordAndConfirmPassWord'
|
||||
)
|
||||
)
|
||||
)
|
||||
: callback()
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
userId: null,
|
||||
loading: false
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters([
|
||||
'asyncRoutes',
|
||||
'routes',
|
||||
'language'
|
||||
])
|
||||
...mapGetters(['asyncRoutes', 'routes', 'language']),
|
||||
},
|
||||
mounted() {
|
||||
this.password.UserId = this.$route.query.UserId
|
||||
@@ -112,7 +195,7 @@ export default {
|
||||
this.$updateDictionary()
|
||||
},
|
||||
save() {
|
||||
this.$refs.passwordForm.validate(valid => {
|
||||
this.$refs.passwordForm.validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.password.NewPassWord !== this.password.ConfirmPassWord) {
|
||||
// 两次密码输入不一致
|
||||
@@ -123,26 +206,32 @@ export default {
|
||||
NewUserName: this.password.NewUserName,
|
||||
UserId: this.password.UserId,
|
||||
NewPwd: md5(this.password.NewPassWord),
|
||||
access_token: this.password.access_token
|
||||
access_token: this.password.access_token,
|
||||
}
|
||||
this.loading = true
|
||||
initSetUserNameAndPwd(param).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
// 修改成功,请重新登录账号
|
||||
this.$message.success(this.$t('recompose:message:updatedSuccessfully'))
|
||||
setTimeout(() => {
|
||||
this.logout()
|
||||
}, 500)
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
initSetUserNameAndPwd(param)
|
||||
.then((res) => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
// 修改成功,请重新登录账号
|
||||
this.$message.success(
|
||||
this.$t('recompose:message:updatedSuccessfully')
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.logout()
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
cancel() {
|
||||
this.$refs['passwordForm'].resetFields()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
@@ -165,13 +254,16 @@ export default {
|
||||
<style scoped>
|
||||
input:-webkit-autofill {
|
||||
-webkit-text-fill-color: #ededed !important;
|
||||
box-shadow: 0 0 0px 1000px transparent inset !important;
|
||||
background-color:transparent;
|
||||
box-shadow: 0 0 0px 1000px transparent inset !important;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
transition: background-color 50000s ease-in-out 0s;
|
||||
}
|
||||
input {
|
||||
background-color:transparent;
|
||||
background-color: transparent;
|
||||
caret-color: #fff;
|
||||
}
|
||||
.el-form-item {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -114,7 +114,7 @@
|
||||
size="mini"
|
||||
@click="getList"
|
||||
>
|
||||
{{ $t("common:button:search") }}
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<!-- 重置 -->
|
||||
<el-button
|
||||
@@ -122,7 +122,7 @@
|
||||
icon="el-icon-refresh-left"
|
||||
@click="handleReset"
|
||||
>
|
||||
{{ $t("common:button:reset") }}
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
<!-- <el-button
|
||||
type="primary"
|
||||
@@ -141,7 +141,7 @@
|
||||
v-if="level > 7"
|
||||
:disabled="tableSelectData.length <= 0"
|
||||
>
|
||||
{{ $t("feedBack:button:resolve") }}
|
||||
{{ $t('feedBack:button:resolve') }}
|
||||
</el-button>
|
||||
</el-form>
|
||||
<el-table
|
||||
@@ -257,7 +257,7 @@
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag :type="['danger', 'success'][scope.row.State]">{{
|
||||
$fd("FeedBackStatus", scope.row.State)
|
||||
$fd('FeedBackStatus', scope.row.State)
|
||||
}}</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -278,7 +278,7 @@
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button size="mini" type="text" @click="getDetail(scope.row)">
|
||||
{{ $t("common:button:view") }}
|
||||
{{ $t('common:button:view') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -295,8 +295,8 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import Pagination from "@/components/Pagination";
|
||||
import { batchUpdateFeedBackState, getUserFeedBackList } from "@/api/trials.js";
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { batchUpdateFeedBackState, getUserFeedBackList } from '@/api/trials.js'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
TrialKeyInfo: null,
|
||||
@@ -312,23 +312,23 @@ const searchDataDefault = () => {
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
Asc: false,
|
||||
SortField: "CreateTime",
|
||||
};
|
||||
};
|
||||
SortField: 'CreateTime',
|
||||
}
|
||||
}
|
||||
export default {
|
||||
components: { Pagination },
|
||||
props: {
|
||||
trialId: {
|
||||
type: String,
|
||||
default: "",
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
dicts: [
|
||||
"NoticeApplicableTrial",
|
||||
"NoteLevel",
|
||||
"NoteType",
|
||||
"NoticeState",
|
||||
"NoticeMode",
|
||||
'NoticeApplicableTrial',
|
||||
'NoteLevel',
|
||||
'NoteType',
|
||||
'NoticeState',
|
||||
'NoticeMode',
|
||||
],
|
||||
data() {
|
||||
return {
|
||||
@@ -340,100 +340,100 @@ export default {
|
||||
searchData: searchDataDefault(),
|
||||
tableSelectData: [],
|
||||
UserTypeOptins: [
|
||||
{ label: "CRC", value: 2 },
|
||||
{ label: "IR", value: 13 },
|
||||
{ label: 'CRC', value: 2 },
|
||||
{ label: 'IR', value: 13 },
|
||||
],
|
||||
};
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
level() {
|
||||
if (this.hasPermi(["role:dev", "role:admin"])) {
|
||||
return 9;
|
||||
if (this.hasPermi(['role:dev', 'role:admin'])) {
|
||||
return 9
|
||||
}
|
||||
if (this.hasPermi(["role:pm"])) {
|
||||
return 8;
|
||||
if (this.hasPermi(['role:pm', 'role:apm'])) {
|
||||
return 8
|
||||
}
|
||||
if (this.hasPermi(["role:ir", "role:crc"])) {
|
||||
return 7;
|
||||
if (this.hasPermi(['role:ir', 'role:crc'])) {
|
||||
return 7
|
||||
}
|
||||
return 0;
|
||||
return 0
|
||||
},
|
||||
QuestionTypeOptions() {
|
||||
if (this.level > 7) {
|
||||
return [
|
||||
...this.$d.FeedBackTypeToCRC.filter((item) => item.value > 0),
|
||||
...this.$d.FeedBackTypeToIR,
|
||||
];
|
||||
]
|
||||
}
|
||||
if (this.hasPermi(["role:ir"])) {
|
||||
return this.$d.FeedBackTypeToIR;
|
||||
if (this.hasPermi(['role:ir'])) {
|
||||
return this.$d.FeedBackTypeToIR
|
||||
}
|
||||
if (this.hasPermi(["role:crc"])) {
|
||||
return this.$d.FeedBackTypeToCRC;
|
||||
if (this.hasPermi(['role:crc'])) {
|
||||
return this.$d.FeedBackTypeToCRC
|
||||
}
|
||||
return [];
|
||||
return []
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.getList();
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
// 通过提交状态决定该行的 CheckBox 是否可以勾选
|
||||
handleSelectTable(row) {
|
||||
return row.State < 1;
|
||||
return row.State < 1
|
||||
},
|
||||
async getList() {
|
||||
try {
|
||||
if (this.trialId) {
|
||||
this.searchData.TrialId = this.trialId;
|
||||
this.searchData.TrialId = this.trialId
|
||||
}
|
||||
this.loading = true;
|
||||
let res = await getUserFeedBackList(this.searchData);
|
||||
this.loading = false;
|
||||
this.loading = true
|
||||
let res = await getUserFeedBackList(this.searchData)
|
||||
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)
|
||||
}
|
||||
},
|
||||
handleDatetimeChange(val) {
|
||||
if (val) {
|
||||
this.searchData.BeginCreatime = val[0];
|
||||
this.searchData.EndCreatime = val[1];
|
||||
this.searchData.BeginCreatime = val[0]
|
||||
this.searchData.EndCreatime = val[1]
|
||||
} else {
|
||||
this.searchData.BeginCreatime = "";
|
||||
this.searchData.EndCreatime = "";
|
||||
this.searchData.BeginCreatime = ''
|
||||
this.searchData.EndCreatime = ''
|
||||
}
|
||||
},
|
||||
// 重置列表查询
|
||||
handleReset() {
|
||||
this.datetimerange = null;
|
||||
this.handleDatetimeChange();
|
||||
this.searchData = searchDataDefault();
|
||||
this.getList();
|
||||
this.datetimerange = null
|
||||
this.handleDatetimeChange()
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
// 设为解决
|
||||
async resolve() {
|
||||
try {
|
||||
let confirm = await this.$confirm(this.$t("feedBack:resolve:tip"), {
|
||||
type: "warning",
|
||||
let confirm = await this.$confirm(this.$t('feedBack:resolve:tip'), {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true,
|
||||
});
|
||||
if (!confirm) return;
|
||||
})
|
||||
if (!confirm) return
|
||||
let data = {
|
||||
IdList: this.tableSelectData.map((item) => item.Id),
|
||||
state: 1,
|
||||
};
|
||||
let res = await batchUpdateFeedBackState(data);
|
||||
}
|
||||
let res = await batchUpdateFeedBackState(data)
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t("feedBack:resolve:success"));
|
||||
this.getList();
|
||||
this.$message.success(this.$t('feedBack:resolve:success'))
|
||||
this.getList()
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
// 导出
|
||||
@@ -441,32 +441,32 @@ export default {
|
||||
// 表格选择
|
||||
handleSelectChange(selection) {
|
||||
// console.log(selection, "handleSelectChange");
|
||||
this.tableSelectData = selection;
|
||||
this.tableSelectData = selection
|
||||
},
|
||||
// 排序
|
||||
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.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop;
|
||||
this.searchData.PageIndex = 1;
|
||||
this.getList();
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
// 获取详情
|
||||
getDetail(row) {
|
||||
this.$FB({
|
||||
type: "detail",
|
||||
type: 'detail',
|
||||
Id: row.Id,
|
||||
callBack: () => {
|
||||
this.getList();
|
||||
this.$emit("success");
|
||||
this.getList()
|
||||
this.$emit('success')
|
||||
},
|
||||
});
|
||||
})
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.role {
|
||||
|
||||
@@ -61,16 +61,16 @@
|
||||
:disabled="form.VerificationCode === '' || form.EmailOrPhone === ''"
|
||||
@click="verifyCode"
|
||||
>
|
||||
{{ $t("passwordReset:button:verify") }}
|
||||
{{ $t('passwordReset:button:verify') }}
|
||||
</el-button>
|
||||
</div>
|
||||
<div class="box-wrapper" v-if="active === 1">
|
||||
<div class="box-wrapper" v-show="active === 1">
|
||||
<el-form
|
||||
ref="resetForm"
|
||||
ref="resetForm2"
|
||||
v-loading="formLoading"
|
||||
:model="form"
|
||||
label-width="100px"
|
||||
:rules="rules"
|
||||
:label-width="$i18n.locale === 'en' ? '180px' : '100px'"
|
||||
:rules="rules2"
|
||||
class="demo-ruleForm"
|
||||
size="small"
|
||||
>
|
||||
@@ -131,7 +131,7 @@
|
||||
<div style="width: 50%; margin: auto; display: flex">
|
||||
<!-- 取消 -->
|
||||
<el-button size="small" @click="onCancel" style="width: 46%">
|
||||
{{ $t("passwordReset:button:cancel") }}
|
||||
{{ $t('passwordReset:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 提交 -->
|
||||
<el-button
|
||||
@@ -140,17 +140,17 @@
|
||||
@click="onSubmit"
|
||||
style="width: 46%"
|
||||
>
|
||||
{{ $t("passwordReset:button:submit") }}
|
||||
{{ $t('passwordReset:button:submit') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="box-wrapper flexBox" v-if="active === 3">
|
||||
<svg-icon icon-class="resetSuccess" style="width: 300px; height: 300px" />
|
||||
<p style="width: 100%; text-align: center">
|
||||
{{ $t("resetPassword:successTip") }}
|
||||
{{ $t('resetPassword:successTip') }}
|
||||
</p>
|
||||
<el-button size="small" type="primary" @click="goBack">
|
||||
{{ $t("passwordReset:button:back") }}
|
||||
{{ $t('passwordReset:button:back') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -160,32 +160,30 @@ import {
|
||||
anonymousSendVerificationCode,
|
||||
verifyAnonymousVerifyCode,
|
||||
anonymousSetPassword,
|
||||
} from "@/api/user";
|
||||
import md5 from "js-md5";
|
||||
import Img from "@/assets/icons/svg/resetSuccess.svg";
|
||||
var timer = "";
|
||||
var countdown = 60;
|
||||
} from '@/api/user'
|
||||
import md5 from 'js-md5'
|
||||
import Img from '@/assets/icons/svg/resetSuccess.svg'
|
||||
var timer = ''
|
||||
var countdown = 60
|
||||
export default {
|
||||
data() {
|
||||
var validateEmail = (rule, value, callback) => {
|
||||
if (value === "") {
|
||||
if (value === '') {
|
||||
// 请输入邮箱
|
||||
callback(new Error(this.$t("passwordReset:formRule:email")));
|
||||
callback(new Error(this.$t('passwordReset:formRule:email')))
|
||||
} else {
|
||||
var reg =
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/;
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.form.EmailOrPhone && reg.test(this.form.EmailOrPhone)) {
|
||||
this.sendDisabled = false;
|
||||
callback();
|
||||
this.sendDisabled = false
|
||||
callback()
|
||||
} else {
|
||||
// 邮箱无效
|
||||
callback(
|
||||
new Error(this.$t("passwordReset:formRule:passwordinvalid"))
|
||||
);
|
||||
this.sendDisabled = true;
|
||||
callback(new Error(this.$t('passwordReset:formRule:passwordinvalid')))
|
||||
this.sendDisabled = true
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
// var validatePass = (rule, value, callback) => {
|
||||
// if (value === '') {
|
||||
// // 请输入密码
|
||||
@@ -198,181 +196,206 @@ export default {
|
||||
// }
|
||||
// }
|
||||
var validatePass2 = (rule, value, callback) => {
|
||||
if (value === "" || value === undefined) {
|
||||
if (value === '' || value === undefined) {
|
||||
// 请再次输入密码
|
||||
callback(new Error(this.$t("passwordReset:formRule:confirmPassword")));
|
||||
callback(new Error(this.$t('passwordReset:formRule:confirmPassword')))
|
||||
} else if (value !== undefined && value !== this.form.NewPwd) {
|
||||
// 两次密码不一致
|
||||
callback(new Error(this.$t("passwordReset:formRule:passwordsDiffer")));
|
||||
callback(new Error(this.$t('passwordReset:formRule:passwordsDiffer')))
|
||||
} else {
|
||||
callback();
|
||||
callback()
|
||||
}
|
||||
};
|
||||
}
|
||||
return {
|
||||
active: 0,
|
||||
Img,
|
||||
form: {
|
||||
EmailOrPhone: "",
|
||||
VerificationCode: "",
|
||||
NewPwd: "",
|
||||
UserId: "",
|
||||
UserType: "",
|
||||
EmailOrPhone: '',
|
||||
VerificationCode: '',
|
||||
NewPwd: '',
|
||||
CheckPass: '',
|
||||
UserId: '',
|
||||
UserType: '',
|
||||
},
|
||||
users: [],
|
||||
CheckPass: "",
|
||||
CheckPass: '',
|
||||
rules: {
|
||||
EmailOrPhone: [
|
||||
{
|
||||
required: true,
|
||||
validator: validateEmail,
|
||||
trigger: ["blur", "change"],
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
VerificationCode: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("common:ruleMessage:specify"),
|
||||
trigger: ["blur", "change"],
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
NewPwd: [
|
||||
{
|
||||
required: true,
|
||||
validator: this.$validatePassword,
|
||||
trigger: ["blur", "change"],
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
CheckPass: [
|
||||
{
|
||||
required: true,
|
||||
validator: validatePass2,
|
||||
trigger: ["blur", "change"],
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
UserId: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("common:ruleMessage:select"),
|
||||
trigger: ["blur", "change"],
|
||||
message: this.$t('common:ruleMessage:select'),
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
},
|
||||
rules2: {
|
||||
NewPwd: [
|
||||
{
|
||||
required: true,
|
||||
validator: this.$validatePassword,
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
CheckPass: [
|
||||
{
|
||||
required: true,
|
||||
validator: validatePass2,
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
UserId: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:select'),
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
},
|
||||
sendDisabled: true,
|
||||
sendTitle: this.$t("passwordReset:button:send"),
|
||||
sendTitle: this.$t('passwordReset:button:send'),
|
||||
formLoading: false,
|
||||
};
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
onSubmit() {
|
||||
this.$refs["resetForm"].validate((valid) => {
|
||||
this.$refs['resetForm2'].validate((valid) => {
|
||||
if (valid) {
|
||||
this.formLoading = true;
|
||||
this.formLoading = true
|
||||
anonymousSetPassword(this.form.UserId, md5(this.form.NewPwd))
|
||||
.then((res) => {
|
||||
if (res.IsSuccess) {
|
||||
// 修改成功
|
||||
this.$message.success(
|
||||
this.$t("passwordReset:message:updatedSuccessfully")
|
||||
);
|
||||
this.formLoading = false;
|
||||
this.active = 3;
|
||||
this.$t('passwordReset:message:updatedSuccessfully')
|
||||
)
|
||||
this.formLoading = false
|
||||
this.active = 3
|
||||
// this.goBack();
|
||||
} else {
|
||||
this.$alert(res.ErrorMessage);
|
||||
this.$alert(res.ErrorMessage)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.formLoading = false;
|
||||
});
|
||||
this.formLoading = false
|
||||
})
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
handleSendCode() {
|
||||
const that = this;
|
||||
this.sendDisabled = true;
|
||||
const that = this
|
||||
this.sendDisabled = true
|
||||
// var isReviewer = JSON.parse(zzSessionStorage.getItem('IsReviewer'))
|
||||
anonymousSendVerificationCode(this.form.EmailOrPhone)
|
||||
.then((res) => {
|
||||
if (res.IsSuccess) {
|
||||
let msg = this.$t('passwordReset:message:tip:sendCode').replace("xxx", this.form.EmailOrPhone)
|
||||
let msg = this.$t('passwordReset:message:tip:sendCode').replace(
|
||||
'xxx',
|
||||
this.form.EmailOrPhone
|
||||
)
|
||||
this.$message.success(msg)
|
||||
that.settime(that);
|
||||
that.settime(that)
|
||||
} else {
|
||||
that.$alert(res.ErrorMessage);
|
||||
that.$alert(res.ErrorMessage)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.sendDisabled = false;
|
||||
});
|
||||
this.sendDisabled = false
|
||||
})
|
||||
},
|
||||
verifyCode() {
|
||||
this.formLoading = true;
|
||||
this.formLoading = true
|
||||
verifyAnonymousVerifyCode(
|
||||
this.form.EmailOrPhone,
|
||||
this.form.VerificationCode
|
||||
)
|
||||
.then((res) => {
|
||||
this.formLoading = false;
|
||||
this.users = res.Result;
|
||||
this.formLoading = false
|
||||
this.users = res.Result
|
||||
if (this.users.length === 1) {
|
||||
this.form.UserId = this.users[0].UserId;
|
||||
this.form.UserType = this.users[0].UserType;
|
||||
this.form.UserId = this.users[0].UserId
|
||||
this.form.UserType = this.users[0].UserType
|
||||
}
|
||||
// 验证成功
|
||||
this.$message.success(
|
||||
this.$t("passwordReset:message:verifiedSuccessfully")
|
||||
);
|
||||
this.active = 1;
|
||||
this.$t('passwordReset:message:verifiedSuccessfully')
|
||||
)
|
||||
this.active = 1
|
||||
})
|
||||
.catch(() => {
|
||||
this.formLoading = false;
|
||||
});
|
||||
this.formLoading = false
|
||||
})
|
||||
},
|
||||
handleEmailChange() {
|
||||
var reg =
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/;
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.form.EmailOrPhone && reg.test(this.form.EmailOrPhone)) {
|
||||
this.sendDisabled = false;
|
||||
this.sendDisabled = false
|
||||
}
|
||||
},
|
||||
handleUserChange(val) {
|
||||
const seleted = this.users.findIndex((user) => user.UserId === val);
|
||||
const seleted = this.users.findIndex((user) => user.UserId === val)
|
||||
if (seleted > -1) {
|
||||
this.form.UserType = this.users[seleted].UserType;
|
||||
this.form.UserType = this.users[seleted].UserType
|
||||
}
|
||||
},
|
||||
settime(obj) {
|
||||
if (countdown === 0) {
|
||||
obj.sendDisabled = false;
|
||||
obj.sendTitle = this.$t("passwordReset:button:send");
|
||||
countdown = 60;
|
||||
clearTimeout(timer);
|
||||
return;
|
||||
obj.sendDisabled = false
|
||||
obj.sendTitle = this.$t('passwordReset:button:send')
|
||||
countdown = 60
|
||||
clearTimeout(timer)
|
||||
return
|
||||
} else {
|
||||
obj.sendDisabled = true;
|
||||
obj.sendTitle = `${this.$t(
|
||||
"passwordReset:button:wait"
|
||||
)}(${countdown}s)`;
|
||||
countdown--;
|
||||
obj.sendDisabled = true
|
||||
obj.sendTitle = `${this.$t('passwordReset:button:wait')}(${countdown}s)`
|
||||
countdown--
|
||||
// eslint-disable-next-line no-self-assign
|
||||
countdown = countdown;
|
||||
countdown = countdown
|
||||
timer = setTimeout(function () {
|
||||
obj.settime(obj);
|
||||
}, 1000);
|
||||
obj.settime(obj)
|
||||
}, 1000)
|
||||
}
|
||||
},
|
||||
onCancel() {
|
||||
this.$refs["resetForm"].resetFields();
|
||||
this.$refs['resetForm'].resetFields()
|
||||
Object.keys(this.form).forEach((key) => {
|
||||
this.form[key] = "";
|
||||
});
|
||||
this.active = 0;
|
||||
this.form[key] = ''
|
||||
})
|
||||
this.active = 0
|
||||
},
|
||||
goBack() {
|
||||
this.$router.push("/login");
|
||||
this.$router.push('/login')
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.reset-wrapper {
|
||||
|
||||
+92
-90
@@ -34,7 +34,7 @@
|
||||
style="width: 300px; height: 94px"
|
||||
/>
|
||||
</div>
|
||||
<div class="title" v-else>{{ $t("login:title:system") }}</div>
|
||||
<div class="title" v-else>{{ $t('login:title:system') }}</div>
|
||||
</div>
|
||||
<el-form
|
||||
ref="loginForm"
|
||||
@@ -112,7 +112,7 @@
|
||||
size="medium"
|
||||
@click.native.prevent="handleLogin"
|
||||
>
|
||||
{{ $t("login:button:login") }}
|
||||
{{ $t('login:button:login') }}
|
||||
</el-button>
|
||||
<div style="text-align: right">
|
||||
<TopLang
|
||||
@@ -128,7 +128,7 @@
|
||||
@click.native.prevent="handleResetPwd"
|
||||
style="color: rgb(0, 147, 221)"
|
||||
>
|
||||
{{ $t("login:button:forgetPassword") }}
|
||||
{{ $t('login:button:forgetPassword') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</el-form>
|
||||
@@ -181,10 +181,12 @@
|
||||
>
|
||||
<h1 style="text-align: center; margin-bottom: 20px">关于</h1>
|
||||
<p style="margin-bottom: 20px" v-if="NODE_ENV === 'usa'">
|
||||
{{ $t("login:title:system_title") }}
|
||||
{{ $t('login:title:system_title') }}
|
||||
</p>
|
||||
<p style="margin-bottom: 20px" v-else>{{ $t('login:title:system') }}</p>
|
||||
<p style="margin-bottom: 20px">
|
||||
V{{ $version.IsEnv_US ? $version.Version_US : $version.Version }}
|
||||
</p>
|
||||
<p style="margin-bottom: 20px" v-else>{{ $t("login:title:system") }}</p>
|
||||
<p style="margin-bottom: 20px">V{{ $version.Version }}</p>
|
||||
<p style="margin-bottom: 20px" v-if="language === 'zh'">
|
||||
Copyright © {{ new Date().getFullYear() }} 上海展影医疗科技有限公司
|
||||
版权所有
|
||||
@@ -208,14 +210,14 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import { mapGetters, mapMutations } from "vuex";
|
||||
import TopLang from "./topLang";
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
import TopLang from './topLang'
|
||||
// import NoticeMarquee from '../trials/trials-layout/components/noticeMarquee'
|
||||
import Vcode from "vue-puzzle-vcode";
|
||||
import browserTip from "@/views/dictionary/template/browser/tip.vue";
|
||||
import Img1 from "@/assets/pic-2.png";
|
||||
import Vcode from 'vue-puzzle-vcode'
|
||||
import browserTip from '@/views/dictionary/template/browser/tip.vue'
|
||||
import Img1 from '@/assets/pic-2.png'
|
||||
export default {
|
||||
name: "Login",
|
||||
name: 'Login',
|
||||
components: { TopLang, Vcode, browserTip },
|
||||
data() {
|
||||
return {
|
||||
@@ -223,18 +225,18 @@ export default {
|
||||
VUE_APP_OSS_CONFIG_REGION: process.env.VUE_APP_OSS_CONFIG_REGION,
|
||||
aboutVisible: false,
|
||||
loginForm: {
|
||||
username: "",
|
||||
password: "",
|
||||
username: '',
|
||||
password: '',
|
||||
UserId: null,
|
||||
},
|
||||
loginRules: {
|
||||
username: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("login:formRule:userName"),
|
||||
trigger: "blur",
|
||||
message: this.$t('login:formRule:userName'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{ max: 20, message: `${this.$t("common:ruleMessage:maxLength")} 20` },
|
||||
{ max: 20, message: `${this.$t('common:ruleMessage:maxLength')} 20` },
|
||||
],
|
||||
password: [
|
||||
// {
|
||||
@@ -244,29 +246,29 @@ export default {
|
||||
// },
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("login:formRule:password"),
|
||||
trigger: "blur",
|
||||
message: this.$t('login:formRule:password'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{ max: 20, message: `${this.$t("common:ruleMessage:maxLength")} 20` },
|
||||
{ max: 20, message: `${this.$t('common:ruleMessage:maxLength')} 20` },
|
||||
],
|
||||
},
|
||||
loading: false,
|
||||
passwordType: "password",
|
||||
passwordType: 'password',
|
||||
loginType: null,
|
||||
location: null,
|
||||
isShow: false,
|
||||
showCode: false,
|
||||
Img1,
|
||||
};
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["asyncRoutes", "routes", "language"]),
|
||||
...mapGetters(['asyncRoutes', 'routes', 'language']),
|
||||
},
|
||||
watch: {
|
||||
"$i18n.locale": {
|
||||
'$i18n.locale': {
|
||||
handler() {
|
||||
if (this.$refs.browserTip) {
|
||||
this.$refs.browserTip.open();
|
||||
this.$refs.browserTip.open()
|
||||
}
|
||||
},
|
||||
deep: true,
|
||||
@@ -274,88 +276,88 @@ export default {
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.loginType = this.$route.query.loginType;
|
||||
this.location = this.$route.query.location;
|
||||
zzSessionStorage.setItem("loginType", this.loginType);
|
||||
localStorage.setItem("location", this.location);
|
||||
if (process.env.VUE_APP_OSS_CONFIG_REGION === "oss-us-west-1") {
|
||||
this.$i18n.locale = "en";
|
||||
this.setLanguage("en");
|
||||
this.$updateDictionary();
|
||||
this.loginType = this.$route.query.loginType
|
||||
this.location = this.$route.query.location
|
||||
zzSessionStorage.setItem('loginType', this.loginType)
|
||||
localStorage.setItem('location', this.location)
|
||||
if (process.env.VUE_APP_OSS_CONFIG_REGION === 'oss-us-west-1') {
|
||||
this.$i18n.locale = 'en'
|
||||
this.setLanguage('en')
|
||||
this.$updateDictionary()
|
||||
} else {
|
||||
if (this.location === "USA" || this.NODE_ENV === "usa") {
|
||||
this.$i18n.locale = "en";
|
||||
this.setLanguage("en");
|
||||
this.$updateDictionary();
|
||||
if (this.location === 'USA' || this.NODE_ENV === 'usa') {
|
||||
this.$i18n.locale = 'en'
|
||||
this.setLanguage('en')
|
||||
this.$updateDictionary()
|
||||
} else {
|
||||
// this.$i18n.locale = 'zh'
|
||||
// this.setLanguage('zh')
|
||||
// this.$updateDictionary()
|
||||
}
|
||||
}
|
||||
this.$refs.browserTip.open();
|
||||
this.$refs.browserTip.open()
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({ setLanguage: "lang/setLanguage" }),
|
||||
...mapMutations({ setLanguage: 'lang/setLanguage' }),
|
||||
openAbout() {
|
||||
this.aboutVisible = true;
|
||||
this.aboutVisible = true
|
||||
},
|
||||
showPwd() {
|
||||
if (this.passwordType === "password") {
|
||||
this.passwordType = "";
|
||||
if (this.passwordType === 'password') {
|
||||
this.passwordType = ''
|
||||
} else {
|
||||
this.passwordType = "password";
|
||||
this.passwordType = 'password'
|
||||
}
|
||||
this.$nextTick(() => {
|
||||
this.$refs.password.focus();
|
||||
});
|
||||
this.$refs.password.focus()
|
||||
})
|
||||
},
|
||||
handleLogin() {
|
||||
this.loginType = this.$route.query.loginType;
|
||||
this.loginType = this.$route.query.loginType
|
||||
this.$refs.loginForm.validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.showCode) {
|
||||
this.isShow = true;
|
||||
this.isShow = true
|
||||
} else {
|
||||
this.onSuccess();
|
||||
this.onSuccess()
|
||||
}
|
||||
} else {
|
||||
// console.log('error submit!!')
|
||||
return false;
|
||||
return false
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
loginIn(Id) {
|
||||
this.loading = true;
|
||||
this.showCode = false;
|
||||
if (Id) this.loginForm.UserId = Id;
|
||||
this.loading = true
|
||||
this.showCode = false
|
||||
if (Id) this.loginForm.UserId = Id
|
||||
this.$store
|
||||
.dispatch("user/login", this.loginForm)
|
||||
.dispatch('user/login', this.loginForm)
|
||||
.then((res) => {
|
||||
if (res.BasicInfo.IsFirstAdd) {
|
||||
// 当前用户为首次登录,请先修改密码之后再次登录
|
||||
this.$message.success(this.$t("login:message:login1"));
|
||||
this.$message.success(this.$t('login:message:login1'))
|
||||
setTimeout(() => {
|
||||
this.$router.push({
|
||||
path: `/recompose?userName=${this.loginForm.username}`,
|
||||
});
|
||||
}, 500);
|
||||
return;
|
||||
})
|
||||
}, 500)
|
||||
return
|
||||
} else if (res.BasicInfo.LoginState === 1) {
|
||||
// 请先修改密码后再登录!
|
||||
this.$alert(
|
||||
this.$t("login:message:login3"),
|
||||
this.$t("common:title:warning"),
|
||||
this.$t('login:message:login3'),
|
||||
this.$t('common:title:warning'),
|
||||
{
|
||||
callback: (action) => {
|
||||
this.$router.push({
|
||||
path: `/recompose?userName=${this.loginForm.username}`,
|
||||
});
|
||||
return;
|
||||
})
|
||||
return
|
||||
},
|
||||
}
|
||||
);
|
||||
return;
|
||||
)
|
||||
return
|
||||
} else if (res.IsMFA) {
|
||||
this.$MFA({
|
||||
UserId: res.BasicInfo.Id,
|
||||
@@ -363,55 +365,55 @@ export default {
|
||||
username: this.loginForm.username,
|
||||
callBack: this.loginIn,
|
||||
cancelBack: () => {
|
||||
this.loading = false;
|
||||
this.loading = false
|
||||
},
|
||||
});
|
||||
return;
|
||||
})
|
||||
return
|
||||
} else if (res.BasicInfo.LoginState === 2) {
|
||||
// 本次登录的IP或设备与上次不一致,请确认'
|
||||
// this.$alert(this.$t('login:message:login4'), this.$t('common:title:warning'))
|
||||
this.$message.warning(this.$t("login:message:login4"));
|
||||
this.$message.warning(this.$t('login:message:login4'))
|
||||
}
|
||||
this.$store.dispatch("permission/generateRoutes").then((res) => {
|
||||
this.loading = false;
|
||||
this.$store.dispatch('permission/generateRoutes').then((res) => {
|
||||
this.loading = false
|
||||
if (res && res.length > 0) {
|
||||
this.$store.dispatch("global/getNoticeList");
|
||||
this.$router.addRoutes(res);
|
||||
if (this.loginType === "DevOps") {
|
||||
this.$router.replace({ path: res[0].path });
|
||||
return;
|
||||
this.$store.dispatch('global/getNoticeList')
|
||||
this.$router.addRoutes(res)
|
||||
if (this.loginType === 'DevOps') {
|
||||
this.$router.replace({ path: res[0].path })
|
||||
return
|
||||
}
|
||||
if (this.hasPermi(["role:radmin"])) {
|
||||
this.$router.replace({ path: res[0].path });
|
||||
return;
|
||||
if (this.hasPermi(['role:radmin'])) {
|
||||
this.$router.replace({ path: res[0].path })
|
||||
return
|
||||
}
|
||||
if (
|
||||
this.hasPermi(["role:air", "role:rpm", "role:rcrc", "role:rir"])
|
||||
this.hasPermi(['role:air', 'role:rpm', 'role:rcrc', 'role:rir'])
|
||||
) {
|
||||
this.$router.replace({ path: "/trials/trials-list" });
|
||||
this.$router.replace({ path: '/trials/trials-list' })
|
||||
} else {
|
||||
this.$router.replace({ path: "/trials" });
|
||||
this.$router.replace({ path: '/trials' })
|
||||
}
|
||||
} else {
|
||||
// 此账户暂未配置菜单权限,请联系管理员处理后再登录。
|
||||
this.$message.warning(this.$t("login:message:login2"));
|
||||
this.$message.warning(this.$t('login:message:login2'))
|
||||
}
|
||||
});
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
this.showCode = true;
|
||||
this.loading = false;
|
||||
});
|
||||
this.showCode = true
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
onSuccess() {
|
||||
this.isShow = false;
|
||||
this.loginIn();
|
||||
this.isShow = false
|
||||
this.loginIn()
|
||||
},
|
||||
handleResetPwd() {
|
||||
this.$router.push({ name: "Resetpassword" });
|
||||
this.$router.push({ name: 'Resetpassword' })
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
|
||||
@@ -2,52 +2,65 @@
|
||||
<div v-loading="loading" class="img-container">
|
||||
<el-card class="box-card left">
|
||||
<div class="title">
|
||||
{{$t('trials:none-dicom-show:fileList')}}
|
||||
{{ $t('trials:none-dicom-show:fileList') }}
|
||||
</div>
|
||||
<div class="left-content">
|
||||
<!-- 检查层级 -->
|
||||
<div v-for="(study,i) in studyList" :key="study.CodeView">
|
||||
<div v-for="(study, i) in studyList" :key="study.CodeView">
|
||||
<div class="study-desc">
|
||||
<span>{{ study.CodeView }}</span>
|
||||
<span style="margin:0 5px">{{ study.Modality }}</span>
|
||||
<span style="margin: 0 5px">{{ study.Modality }}</span>
|
||||
<span>{{ getBodyPart(study.BodyPart) }}</span>
|
||||
</div>
|
||||
<!-- 文件层级 -->
|
||||
<div v-if="study.NoneDicomStudyFileList.length === 0" class="empty-text">
|
||||
<slot name="empty">暂无数据</slot>
|
||||
<div
|
||||
v-if="study.NoneDicomStudyFileList.length === 0"
|
||||
class="empty-text"
|
||||
>
|
||||
<slot name="empty">{{ $t('trials:audit:message:noData') }}</slot>
|
||||
</div>
|
||||
<div v-else id="imgList" style="height:100%;overflow: hidden">
|
||||
<div v-else id="imgList" style="height: 100%; overflow: hidden">
|
||||
<div
|
||||
v-for="(item,j) in study.NoneDicomStudyFileList"
|
||||
v-for="(item, j) in study.NoneDicomStudyFileList"
|
||||
:id="`img${item.Id}`"
|
||||
:key="item.Id"
|
||||
:class="{
|
||||
'is-boxActive': item.Id === currentFileId
|
||||
'is-boxActive': item.Id === currentFileId,
|
||||
}"
|
||||
class="img-box"
|
||||
@click="selected(item,i,j,true)"
|
||||
@click="selected(item, i, j, true)"
|
||||
>
|
||||
{{ `${j+1}. ${item.FileName}` }}
|
||||
<div v-if="item.FileName.length < 15" class="img-text">
|
||||
{{ `${j + 1}. ${item.FileName}` }}
|
||||
</div>
|
||||
<el-tooltip v-else :content="item.FileName" placement="bottom">
|
||||
<div class="img-text">
|
||||
{{ `${j + 1}. ${item.FileName}` }}
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</el-card>
|
||||
<!-- 预览图像 -->
|
||||
<el-card class="box-card right">
|
||||
<div style="width:100%;height: 100%;">
|
||||
<Preview v-if="previewImage.imgList.length > 0" ref="previewImage" style="width:100%;" :preview-image="previewImage" :value="currentStudyFileIndex" @selectedImg="selectedImg" />
|
||||
<div style="width: 100%; height: 100%">
|
||||
<Preview
|
||||
v-if="previewImage.imgList.length > 0"
|
||||
ref="previewImage"
|
||||
style="width: 100%"
|
||||
:preview-image="previewImage"
|
||||
:value="currentStudyFileIndex"
|
||||
@selectedImg="selectedImg"
|
||||
/>
|
||||
</div>
|
||||
|
||||
</el-card>
|
||||
|
||||
<!-- <el-card class="box-card" style="width:300px;height:100%;padding: 10px;margin-left:10px;">
|
||||
<CheckForm />
|
||||
</el-card> -->
|
||||
</div>
|
||||
|
||||
</template>
|
||||
|
||||
<script>
|
||||
@@ -59,7 +72,7 @@ import Preview from './components/preview'
|
||||
export default {
|
||||
name: 'Notice',
|
||||
components: {
|
||||
Preview
|
||||
Preview,
|
||||
// CheckForm
|
||||
},
|
||||
data() {
|
||||
@@ -76,18 +89,18 @@ export default {
|
||||
popup: true, // 弹窗的显示隐藏
|
||||
studyCode: '',
|
||||
modality: '',
|
||||
bodyPart: ''
|
||||
bodyPart: '',
|
||||
},
|
||||
previewVisible: false,
|
||||
studyList: [],
|
||||
subjectVisitId: '',
|
||||
sudyId: '',
|
||||
loading: false,
|
||||
bp:[]
|
||||
bp: [],
|
||||
}
|
||||
},
|
||||
async created(){
|
||||
this.bp = await this.$getBodyPart(this.$route.query.trialId);
|
||||
async created() {
|
||||
this.bp = await this.$getBodyPart(this.$route.query.trialId)
|
||||
},
|
||||
async mounted() {
|
||||
if (this.$router.currentRoute.query.TokenKey) {
|
||||
@@ -112,31 +125,47 @@ export default {
|
||||
separator = ','
|
||||
}
|
||||
var arr = bodyPart.split(separator)
|
||||
var newArr = arr.map(i => {
|
||||
return this.$fd('Bodypart', i.trim(),'Code',{Bodypart:this.bp},'Name')
|
||||
var newArr = arr.map((i) => {
|
||||
return this.$fd(
|
||||
'Bodypart',
|
||||
i.trim(),
|
||||
'Code',
|
||||
{ Bodypart: this.bp },
|
||||
'Name'
|
||||
)
|
||||
})
|
||||
console.log(newArr,this.bp)
|
||||
console.log(newArr, this.bp)
|
||||
return newArr.join(' | ')
|
||||
},
|
||||
// 获取非Dicom检查信息
|
||||
getNoneDicomList() {
|
||||
this.loading = true
|
||||
getNoneDicomStudyList(this.subjectVisitId, this.studyId).then(res => {
|
||||
this.studyList = res.Result
|
||||
this.loading = false
|
||||
const studyIndex = this.studyList.findIndex(item => {
|
||||
return item.NoneDicomStudyFileList.length > 0
|
||||
getNoneDicomStudyList(
|
||||
this.subjectVisitId,
|
||||
this.studyId,
|
||||
false,
|
||||
this.$route.query.visitTaskId
|
||||
)
|
||||
.then((res) => {
|
||||
this.studyList = res.Result
|
||||
this.loading = false
|
||||
const studyIndex = this.studyList.findIndex((item) => {
|
||||
return item.NoneDicomStudyFileList.length > 0
|
||||
})
|
||||
if (studyIndex > -1) {
|
||||
var fileObj = this.studyList[studyIndex]['NoneDicomStudyFileList']
|
||||
this.selected(fileObj[0], studyIndex, 0, true)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
if (studyIndex > -1) {
|
||||
var fileObj = this.studyList[studyIndex]['NoneDicomStudyFileList']
|
||||
this.selected(fileObj[0], studyIndex, 0, true)
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
},
|
||||
selected(file, studyIndex, fileIndex, isChangeSub = false) {
|
||||
this.currentFileId = file.Id
|
||||
this.currentStudyIndex = studyIndex
|
||||
this.previewImage.imgList = this.studyList[studyIndex].NoneDicomStudyFileList
|
||||
this.previewImage.imgList =
|
||||
this.studyList[studyIndex].NoneDicomStudyFileList
|
||||
this.currentStudyFileIndex = fileIndex
|
||||
this.previewImage.index = fileIndex
|
||||
this.previewImage.studyCode = this.studyList[studyIndex].CodeView
|
||||
@@ -151,11 +180,17 @@ export default {
|
||||
selectedImg(fileIndex) {
|
||||
if (this.studyList.length > 0) {
|
||||
this.currentStudyFileIndex = fileIndex
|
||||
this.currentFileId = this.studyList[this.currentStudyIndex].NoneDicomStudyFileList[fileIndex].Id
|
||||
this.currentFileId =
|
||||
this.studyList[this.currentStudyIndex].NoneDicomStudyFileList[
|
||||
fileIndex
|
||||
].Id
|
||||
this.previewImage.index = fileIndex
|
||||
this.previewImage.studyCode = this.studyList[this.currentStudyIndex].CodeView
|
||||
this.previewImage.bodyPart = this.studyList[this.currentStudyIndex].BodyPart
|
||||
this.previewImage.modality = this.studyList[this.currentStudyIndex].Modality
|
||||
this.previewImage.studyCode =
|
||||
this.studyList[this.currentStudyIndex].CodeView
|
||||
this.previewImage.bodyPart =
|
||||
this.studyList[this.currentStudyIndex].BodyPart
|
||||
this.previewImage.modality =
|
||||
this.studyList[this.currentStudyIndex].Modality
|
||||
this.$nextTick(() => {
|
||||
const target = document.getElementById(`img${this.currentFileId}`)
|
||||
const parent = document.getElementsByClassName('left-content')[0]
|
||||
@@ -165,14 +200,13 @@ export default {
|
||||
},
|
||||
preview() {
|
||||
this.previewVisible = true
|
||||
}
|
||||
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.img-container{
|
||||
.img-container {
|
||||
position: relative;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@@ -186,27 +220,27 @@ export default {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
/deep/ .el-card__body{
|
||||
/deep/ .el-card__body {
|
||||
padding: 0px;
|
||||
}
|
||||
}
|
||||
.study-desc{
|
||||
.study-desc {
|
||||
padding: 15px 5px;
|
||||
line-height: 20px;
|
||||
background-color: #d5d5d5;
|
||||
font-weight: 500;
|
||||
}
|
||||
.left{
|
||||
width:220px;
|
||||
.left {
|
||||
width: 220px;
|
||||
height: 100%;
|
||||
|
||||
/deep/ .el-card__body{
|
||||
/deep/ .el-card__body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
.title{
|
||||
.title {
|
||||
height: 40px;
|
||||
line-height: 40px;
|
||||
border: 1ppx solid;
|
||||
@@ -215,7 +249,7 @@ export default {
|
||||
background-color: #4e4e4e;
|
||||
color: #ffffff;
|
||||
}
|
||||
.left-content{
|
||||
.left-content {
|
||||
flex: 1;
|
||||
overflow-y: auto;
|
||||
}
|
||||
@@ -231,21 +265,26 @@ export default {
|
||||
// overflow-y: auto;
|
||||
// padding: 0;
|
||||
// }
|
||||
.img-box{
|
||||
.img-box {
|
||||
// position: relative;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 2px solid #f3f3f3;
|
||||
width: 180px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
|
||||
cursor: pointer;
|
||||
// margin-bottom: 5px;
|
||||
padding-left: 5px;
|
||||
text-overflow:ellipsis;
|
||||
}
|
||||
.img-text {
|
||||
display: inline-block;
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; /* 用省略号表示溢出的文本 */
|
||||
white-space: nowrap;
|
||||
}
|
||||
.img-box:nth-last-child(1){
|
||||
.img-box:nth-last-child(1) {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.is-boxActive {
|
||||
@@ -256,14 +295,13 @@ export default {
|
||||
opacity: 0;
|
||||
}
|
||||
}
|
||||
.right{
|
||||
.right {
|
||||
flex: 1;
|
||||
height: 100%;
|
||||
margin-left: 10px;
|
||||
/deep/ .el-card__body{
|
||||
/deep/ .el-card__body {
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
+123
-64
@@ -1,76 +1,130 @@
|
||||
<template>
|
||||
<div style="display: flex;justify-content: center">
|
||||
<div style="width: 600px;text-align: center;border: 1px solid #e6e6e6;margin-top:40px;padding:10px;">
|
||||
<div class="trial-myinfo-head" style="font-size: 30px;line-height: 120px;">
|
||||
<div style="display: flex; justify-content: center">
|
||||
<div
|
||||
style="
|
||||
width: 600px;
|
||||
text-align: center;
|
||||
border: 1px solid #e6e6e6;
|
||||
margin-top: 40px;
|
||||
padding: 10px;
|
||||
"
|
||||
>
|
||||
<div
|
||||
class="trial-myinfo-head"
|
||||
style="font-size: 30px; line-height: 120px"
|
||||
>
|
||||
<!-- 首次登录修改密码 -->
|
||||
{{ $t('recompose:title:init') }}
|
||||
</div>
|
||||
<el-form ref="passwordForm" v-loading="loading" label-position="right" :model="password" :rules="passwordFormRules" label-width="120px">
|
||||
<el-form
|
||||
ref="passwordForm"
|
||||
v-loading="loading"
|
||||
label-position="right"
|
||||
:model="password"
|
||||
:rules="passwordFormRules"
|
||||
:label-width="$i18n.locale === 'en' ? '180px' : '120px'"
|
||||
>
|
||||
<!-- 用户名 -->
|
||||
<el-form-item :label="$t('recompose:form:userName')" prop="NewUserName">
|
||||
<el-input v-model="password.NewUserName" />
|
||||
</el-form-item>
|
||||
<!-- 旧密码 -->
|
||||
<el-form-item :label="$t('recompose:form:oldPassword')" prop="OldPassWord">
|
||||
<el-input v-model="password.OldPassWord" type="password" show-password auto-complete="new-password" />
|
||||
<el-form-item
|
||||
:label="$t('recompose:form:oldPassword')"
|
||||
prop="OldPassWord"
|
||||
>
|
||||
<el-input
|
||||
v-model="password.OldPassWord"
|
||||
type="password"
|
||||
show-password
|
||||
auto-complete="new-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 新密码 -->
|
||||
<el-form-item :label="$t('recompose:form:newPassword')" prop="NewPassWord">
|
||||
<el-input v-model="password.NewPassWord" type="password" show-password auto-complete="new-password" />
|
||||
<el-form-item
|
||||
:label="$t('recompose:form:newPassword')"
|
||||
prop="NewPassWord"
|
||||
>
|
||||
<el-input
|
||||
v-model="password.NewPassWord"
|
||||
type="password"
|
||||
show-password
|
||||
auto-complete="new-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
<!-- 确认密码 -->
|
||||
<el-form-item :label="$t('recompose:form:confirmPassword')" prop="ConfirmPassWord">
|
||||
<el-input v-model="password.ConfirmPassWord" type="password" show-password auto-complete="new-password" />
|
||||
<el-form-item
|
||||
:label="$t('recompose:form:confirmPassword')"
|
||||
prop="ConfirmPassWord"
|
||||
>
|
||||
<el-input
|
||||
v-model="password.ConfirmPassWord"
|
||||
type="password"
|
||||
show-password
|
||||
auto-complete="new-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item style="text-align:right">
|
||||
<el-form-item style="text-align: right">
|
||||
<!-- 取消 -->
|
||||
<el-button
|
||||
size="small"
|
||||
@click="cancel"
|
||||
>
|
||||
<el-button size="small" @click="cancel">
|
||||
{{ $t('recompose:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="save"
|
||||
>
|
||||
<el-button type="primary" size="small" @click="save">
|
||||
{{ $t('recompose:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { modifyPassword } from '@/api/admin.js'
|
||||
import md5 from 'js-md5'
|
||||
import {mapMutations} from "vuex";
|
||||
import { mapMutations } from 'vuex'
|
||||
export default {
|
||||
data() {
|
||||
return {
|
||||
password: {
|
||||
NewUserName: null
|
||||
NewUserName: null,
|
||||
},
|
||||
passwordFormRules: {
|
||||
NewUserName: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }],
|
||||
OldPassWord: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }],
|
||||
NewUserName: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
OldPassWord: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
NewPassWord: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' },
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
trigger: 'blur',
|
||||
validator: this.$validatePassword
|
||||
validator: this.$validatePassword,
|
||||
},
|
||||
],
|
||||
ConfirmPassWord: [
|
||||
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' },
|
||||
]
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
},
|
||||
userId: null,
|
||||
loading: false
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
@@ -78,7 +132,6 @@ export default {
|
||||
if (!this.password.NewUserName) {
|
||||
// 该页面只提供给首次进入系统的用户使用
|
||||
this.$alert(this.$t('recompose:message:warning'))
|
||||
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
@@ -96,7 +149,7 @@ export default {
|
||||
this.$updateDictionary()
|
||||
},
|
||||
save() {
|
||||
this.$refs.passwordForm.validate(valid => {
|
||||
this.$refs.passwordForm.validate((valid) => {
|
||||
if (valid) {
|
||||
if (this.password.NewPassWord !== this.password.ConfirmPassWord) {
|
||||
// 两次密码输入不一致
|
||||
@@ -106,58 +159,64 @@ export default {
|
||||
const param = {
|
||||
NewUserName: this.password.NewUserName,
|
||||
NewPassWord: md5(this.password.NewPassWord),
|
||||
OldPassWord: md5(this.password.OldPassWord)
|
||||
OldPassWord: md5(this.password.OldPassWord),
|
||||
}
|
||||
this.loading = true
|
||||
modifyPassword(param).then(res => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
// 修改成功,请重新登录账号
|
||||
this.$message.success(this.$t('recompose:message:updatedSuccessfully'))
|
||||
setTimeout(() => {
|
||||
this.logout()
|
||||
}, 500)
|
||||
}
|
||||
}).catch(() => { this.loading = false })
|
||||
modifyPassword(param)
|
||||
.then((res) => {
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
// 修改成功,请重新登录账号
|
||||
this.$message.success(
|
||||
this.$t('recompose:message:updatedSuccessfully')
|
||||
)
|
||||
setTimeout(() => {
|
||||
this.logout()
|
||||
}, 500)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
}
|
||||
})
|
||||
},
|
||||
cancel() {
|
||||
this.$refs['passwordForm'].resetFields()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
.reset-wrapper {
|
||||
padding: 20px;
|
||||
}
|
||||
.reset-wrapper .el-page-header {
|
||||
line-height: 50px;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.reset-wrapper .box-wrapper {
|
||||
width: 60%;
|
||||
margin: 20px auto;
|
||||
padding: 10px;
|
||||
color: #303133;
|
||||
}
|
||||
.reset-wrapper {
|
||||
padding: 20px;
|
||||
}
|
||||
.reset-wrapper .el-page-header {
|
||||
line-height: 50px;
|
||||
border: 1px solid #ebeef5;
|
||||
border-radius: 4px;
|
||||
background-color: #fff;
|
||||
}
|
||||
.reset-wrapper .box-wrapper {
|
||||
width: 60%;
|
||||
margin: 20px auto;
|
||||
padding: 10px;
|
||||
color: #303133;
|
||||
}
|
||||
</style>
|
||||
<style scoped>
|
||||
::v-deep .is-error{
|
||||
::v-deep .is-error {
|
||||
margin-bottom: 40px;
|
||||
}
|
||||
input:-webkit-autofill {
|
||||
-webkit-text-fill-color: #ededed !important;
|
||||
box-shadow: 0 0 0px 1000px transparent inset !important;
|
||||
background-color:transparent;
|
||||
box-shadow: 0 0 0px 1000px transparent inset !important;
|
||||
background-color: transparent;
|
||||
background-image: none;
|
||||
transition: background-color 50000s ease-in-out 0s;
|
||||
}
|
||||
input {
|
||||
background-color:transparent;
|
||||
background-color: transparent;
|
||||
caret-color: #fff;
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<div class="login_content">
|
||||
<el-form-item
|
||||
:label="$t('trials:researchForm:form:siteName')"
|
||||
prop="SiteId"
|
||||
prop="TrialSiteId"
|
||||
>
|
||||
<el-select
|
||||
v-model="form.TrialSiteId"
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
<el-input v-model="form.IndicationType" disabled />
|
||||
</el-form-item>
|
||||
<!-- 中心名称 -->
|
||||
<el-form-item :label="$t('trials:researchForm:form:siteName')" prop="SiteId">
|
||||
<el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId">
|
||||
<el-select v-model="form.TrialSiteId" filterable style="width:100%;" @change="handleSiteChange">
|
||||
<el-option
|
||||
v-for="(item,index) of siteOptions"
|
||||
|
||||
@@ -147,7 +147,7 @@
|
||||
>
|
||||
{{
|
||||
$fd(
|
||||
"InternationalizationType",
|
||||
'InternationalizationType',
|
||||
scope.row.InternationalizationType
|
||||
)
|
||||
}}
|
||||
@@ -158,7 +158,7 @@
|
||||
>
|
||||
{{
|
||||
$fd(
|
||||
"InternationalizationType",
|
||||
'InternationalizationType',
|
||||
scope.row.InternationalizationType
|
||||
)
|
||||
}}
|
||||
@@ -166,7 +166,7 @@
|
||||
<el-tag v-else>
|
||||
{{
|
||||
$fd(
|
||||
"InternationalizationType",
|
||||
'InternationalizationType',
|
||||
scope.row.InternationalizationType
|
||||
)
|
||||
}}
|
||||
@@ -176,7 +176,7 @@
|
||||
<el-table-column
|
||||
label="功能模块/服务名"
|
||||
prop="Module"
|
||||
min-width="120"
|
||||
min-width="140"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
@@ -210,13 +210,13 @@
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-tag v-if="scope.row.State === 0" type="danger">
|
||||
{{ $fd("InternationalizationKeyState", scope.row.State) }}
|
||||
{{ $fd('InternationalizationKeyState', scope.row.State) }}
|
||||
</el-tag>
|
||||
<el-tag v-else-if="scope.row.State === 1" type="primary">
|
||||
{{ $fd("InternationalizationKeyState", scope.row.State) }}
|
||||
{{ $fd('InternationalizationKeyState', scope.row.State) }}
|
||||
</el-tag>
|
||||
<el-tag v-else>
|
||||
{{ $fd("InternationalizationKeyState", scope.row.State) }}
|
||||
{{ $fd('InternationalizationKeyState', scope.row.State) }}
|
||||
</el-tag>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -241,7 +241,13 @@
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
|
||||
<el-table-column
|
||||
label="创建时间"
|
||||
prop="CreateTime"
|
||||
width="150"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
fixed="right"
|
||||
@@ -289,11 +295,11 @@ import {
|
||||
deleteInternationalization,
|
||||
getPublishVersionSelect,
|
||||
batchUpdateInternationalInfo,
|
||||
} from "@/api/admin";
|
||||
import Pagination from "@/components/Pagination";
|
||||
import I18nForm from "./components/I18nForm.vue";
|
||||
import BatchAddForm from "./components/BatchAddForm.vue";
|
||||
import moment from "moment";
|
||||
} from '@/api/admin'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import I18nForm from './components/I18nForm.vue'
|
||||
import BatchAddForm from './components/BatchAddForm.vue'
|
||||
import moment from 'moment'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
Description: null,
|
||||
@@ -304,13 +310,13 @@ const searchDataDefault = () => {
|
||||
Module: null,
|
||||
PublishLogId: null,
|
||||
Asc: true,
|
||||
SortField: "",
|
||||
SortField: '',
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: "I18n",
|
||||
name: 'I18n',
|
||||
components: { Pagination, I18nForm, BatchAddForm },
|
||||
data() {
|
||||
return {
|
||||
@@ -321,140 +327,140 @@ export default {
|
||||
loading: false,
|
||||
PublishVersionList: [],
|
||||
selectTableList: [],
|
||||
};
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
this.getPublishVersionSelect();
|
||||
this.getList()
|
||||
this.getPublishVersionSelect()
|
||||
},
|
||||
methods: {
|
||||
// 获取迭代
|
||||
async getPublishVersionSelect() {
|
||||
try {
|
||||
let res = await getPublishVersionSelect();
|
||||
let res = await getPublishVersionSelect()
|
||||
if (res.IsSuccess) {
|
||||
this.PublishVersionList = res.Result;
|
||||
this.PublishVersionList = res.Result
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
getList() {
|
||||
this.loading = true;
|
||||
this.loading = true
|
||||
getInternationalizationList(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
|
||||
})
|
||||
},
|
||||
// 批量更新
|
||||
handleBatchUpdate() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs["i18nForm"].openDialog(
|
||||
"批量更新",
|
||||
this.$refs['i18nForm'].openDialog(
|
||||
'批量更新',
|
||||
{},
|
||||
this.PublishVersionList,
|
||||
"batch"
|
||||
);
|
||||
});
|
||||
'batch'
|
||||
)
|
||||
})
|
||||
},
|
||||
async batch(row) {
|
||||
let { PublishLogId, State } = row;
|
||||
let { PublishLogId, State } = row
|
||||
let data = {
|
||||
PublishLogId,
|
||||
State,
|
||||
IdList: this.selectTableList.map((item) => item.Id),
|
||||
};
|
||||
}
|
||||
try {
|
||||
let res = await batchUpdateInternationalInfo(data);
|
||||
let res = await batchUpdateInternationalInfo(data)
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t("common:message:updatedSuccessfully"));
|
||||
this.getList();
|
||||
this.$message.success(this.$t('common:message:updatedSuccessfully'))
|
||||
this.getList()
|
||||
this.$nextTick(() => {
|
||||
this.$refs["i18nForm"].handleCancle();
|
||||
});
|
||||
this.$refs['i18nForm'].handleCancle()
|
||||
})
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
handleAdd() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs["i18nForm"].openDialog(
|
||||
"新增",
|
||||
this.$refs['i18nForm'].openDialog(
|
||||
'新增',
|
||||
{},
|
||||
this.PublishVersionList,
|
||||
"add"
|
||||
);
|
||||
});
|
||||
'add'
|
||||
)
|
||||
})
|
||||
},
|
||||
handleBatchAdd() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs["batcnAddForm"].openDialog(
|
||||
"批量新增",
|
||||
this.$refs['batcnAddForm'].openDialog(
|
||||
'批量新增',
|
||||
{},
|
||||
this.PublishVersionList
|
||||
);
|
||||
});
|
||||
)
|
||||
})
|
||||
},
|
||||
handleEdit(row) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs["i18nForm"].openDialog(
|
||||
"编辑",
|
||||
this.$refs['i18nForm'].openDialog(
|
||||
'编辑',
|
||||
row,
|
||||
this.PublishVersionList,
|
||||
"update"
|
||||
);
|
||||
});
|
||||
'update'
|
||||
)
|
||||
})
|
||||
},
|
||||
// 重置列表查询
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault();
|
||||
this.getList();
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
// 删除
|
||||
handleDelete(row) {
|
||||
this.$confirm("是否确认删除?", {
|
||||
type: "warning",
|
||||
this.$confirm('是否确认删除?', {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true,
|
||||
}).then(() => {
|
||||
this.loading = true;
|
||||
this.loading = true
|
||||
deleteInternationalization(row.Id)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.getList();
|
||||
this.getList()
|
||||
this.$message.success(
|
||||
this.$t("common:message:deletedSuccessfully")
|
||||
);
|
||||
this.$t('common:message:deletedSuccessfully')
|
||||
)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
});
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
// 排序
|
||||
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.Asc = false
|
||||
}
|
||||
this.searchData.SortField = column.prop;
|
||||
this.searchData.PageIndex = 1;
|
||||
this.getList();
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
},
|
||||
// 选择
|
||||
handleSelectionChange(val) {
|
||||
this.selectTableList = val;
|
||||
this.selectTableList = val
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.log {
|
||||
|
||||
@@ -9,10 +9,16 @@
|
||||
label-width="120px"
|
||||
size="small"
|
||||
>
|
||||
<el-form-item label="发布版本" prop="Version">
|
||||
<el-form-item :label="$t('system:log:form:version')" prop="Version">
|
||||
<el-input v-model="form.Version" />
|
||||
</el-form-item>
|
||||
<el-form-item label="更新功能" prop="UpdateContent">
|
||||
<el-form-item :label="$t('system:log:form:versionUS')" prop="Version">
|
||||
<el-input v-model="form.Version_US" />
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
:label="$t('system:log:form:updateContent')"
|
||||
prop="UpdateContent"
|
||||
>
|
||||
<el-input
|
||||
v-model="form.UpdateContent"
|
||||
type="textarea"
|
||||
@@ -20,8 +26,8 @@
|
||||
:autosize="{ minRows: 4, maxRows: 5 }"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="发布状态" prop="State">
|
||||
<el-select v-model="form.State" placeholder="请选择">
|
||||
<el-form-item :label="$t('system:log:form:State')" prop="State">
|
||||
<el-select v-model="form.State" placeholder="">
|
||||
<el-option
|
||||
v-for="item in $d.PublishStatus"
|
||||
:key="item.id"
|
||||
@@ -31,15 +37,18 @@
|
||||
</el-option>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item label="发布日期">
|
||||
<el-form-item :label="$t('system:log:form:PublishTime')">
|
||||
<el-date-picker
|
||||
v-model="form.PublishTime"
|
||||
type="date"
|
||||
value-format="yyyy-MM-dd HH:mm:ss"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="是否当前版本" prop="IsCurrentVersion">
|
||||
<el-select v-model="form.IsCurrentVersion" placeholder="请选择">
|
||||
<el-form-item
|
||||
:label="$t('system:log:form:IsCurrentVersion')"
|
||||
prop="IsCurrentVersion"
|
||||
>
|
||||
<el-select v-model="form.IsCurrentVersion" placeholder="">
|
||||
<el-option
|
||||
v-for="item in $d.YesOrNo"
|
||||
:key="item.id"
|
||||
@@ -52,30 +61,31 @@
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="dialog-footer">
|
||||
<el-button size="small" type="primary" @click="handleCancle"
|
||||
>取消</el-button
|
||||
>
|
||||
<el-button size="small" type="primary" @click="handleSave"
|
||||
>保存</el-button
|
||||
>
|
||||
<el-button size="small" type="primary" @click="handleCancle">
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<el-button size="small" type="primary" @click="handleSave">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</base-model>
|
||||
</template>
|
||||
<script>
|
||||
import { addOrUpdatePublishLog } from "@/api/admin";
|
||||
import BaseModel from "@/components/BaseModel";
|
||||
import { addOrUpdatePublishLog } from '@/api/admin'
|
||||
import BaseModel from '@/components/BaseModel'
|
||||
const formDataDefault = () => {
|
||||
return {
|
||||
Id: null,
|
||||
Version: null,
|
||||
Version_US: null,
|
||||
PublishTime: null,
|
||||
UpdateContent: null,
|
||||
State: null,
|
||||
IsCurrentVersion: null,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: "LogForm",
|
||||
name: 'LogForm',
|
||||
components: { BaseModel },
|
||||
data() {
|
||||
return {
|
||||
@@ -83,69 +93,87 @@ export default {
|
||||
form: formDataDefault(),
|
||||
rules: {
|
||||
Version: [
|
||||
{ required: true, message: "请注明", trigger: "blur" },
|
||||
{ max: 50, message: `${this.$t("common:ruleMessage:maxLength")} 50` },
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{ max: 50, message: `${this.$t('common:ruleMessage:maxLength')} 50` },
|
||||
],
|
||||
// PublishTime: [
|
||||
// { required: true, message: '请注明', trigger: 'blur' }
|
||||
// ],
|
||||
IsCurrentVersion: [
|
||||
{ required: true, message: "请选择", trigger: "blur" },
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:select'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
State: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:select'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
State: [{ required: true, message: "请选择", trigger: "blur" }],
|
||||
UpdateContent: [
|
||||
{ required: true, message: "请注明", trigger: "blur" },
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
max: 1000,
|
||||
message: `${this.$t("common:ruleMessage:maxLength")} 500`,
|
||||
message: `${this.$t('common:ruleMessage:maxLength')} 500`,
|
||||
},
|
||||
],
|
||||
},
|
||||
model_cfg: {
|
||||
visible: false,
|
||||
showClose: true,
|
||||
width: "500px",
|
||||
title: "",
|
||||
width: '500px',
|
||||
title: '',
|
||||
appendToBody: true,
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
mounted() {},
|
||||
methods: {
|
||||
openDialog(title, data) {
|
||||
this.model_cfg.visible = true;
|
||||
this.model_cfg.title = title;
|
||||
this.model_cfg.visible = true
|
||||
this.model_cfg.title = title
|
||||
if (Object.keys(data).length > 0) {
|
||||
for (const k in this.form) {
|
||||
if (data.hasOwnProperty(k)) {
|
||||
this.form[k] = data[k];
|
||||
this.form[k] = data[k]
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.form = formDataDefault();
|
||||
this.form = formDataDefault()
|
||||
}
|
||||
},
|
||||
handleSave() {
|
||||
this.$refs.LogForm.validate((valid) => {
|
||||
if (!valid) return;
|
||||
this.loading = true;
|
||||
if (!valid) return
|
||||
this.loading = true
|
||||
addOrUpdatePublishLog(this.form)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
this.$message.success(this.$t("common:message:savedSuccessfully"));
|
||||
this.model_cfg.visible = false;
|
||||
this.$emit("getList");
|
||||
this.loading = false
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.model_cfg.visible = false
|
||||
this.$emit('getList')
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
});
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleCancle() {
|
||||
this.model_cfg.visible = false;
|
||||
this.model_cfg.visible = false
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
::v-deep .el-select,
|
||||
|
||||
@@ -2,9 +2,12 @@
|
||||
<div class="log">
|
||||
<div ref="leftContainer" class="left">
|
||||
<el-form :inline="true">
|
||||
<el-form-item label="发布版本" prop="Version">
|
||||
<el-form-item :label="$t('system:log:table:version')" prop="Version">
|
||||
<el-input v-model="searchData.Version" size="small" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('system:log:table:versionUS')" prop="Version">
|
||||
<el-input v-model="searchData.Version_US" size="small" clearable />
|
||||
</el-form-item>
|
||||
<el-form-item label="更新功能" prop="UpdateContent">
|
||||
<el-input v-model="searchData.UpdateContent" size="small" clearable />
|
||||
</el-form-item>
|
||||
@@ -38,30 +41,37 @@
|
||||
>
|
||||
<el-table-column type="index" width="50" />
|
||||
<el-table-column
|
||||
label="发布版本"
|
||||
:label="$t('system:log:table:version')"
|
||||
prop="Version"
|
||||
min-width="90"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
label="更新功能"
|
||||
:label="$t('system:log:table:versionUS')"
|
||||
prop="Version_US"
|
||||
min-width="90"
|
||||
show-overflow-tooltip
|
||||
sortable="custom"
|
||||
/>
|
||||
<el-table-column
|
||||
:label="$t('system:log:table:UpdateContent')"
|
||||
prop="UpdateContent"
|
||||
min-width="150"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
<el-table-column
|
||||
label="发布状态"
|
||||
:label="$t('system:log:table:State')"
|
||||
prop="State"
|
||||
min-width="150"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{ $fd("PublishStatus", scope.row.State) }}</span>
|
||||
<span>{{ $fd('PublishStatus', scope.row.State) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="发布日期"
|
||||
:label="$t('system:log:table:PublishTime')"
|
||||
prop="PublishTime"
|
||||
min-width="90"
|
||||
show-overflow-tooltip
|
||||
@@ -70,23 +80,23 @@
|
||||
<template slot-scope="scope">
|
||||
{{
|
||||
scope.row.PublishTime
|
||||
? moment(scope.row.PublishTime).format("YYYY-MM-DD")
|
||||
: ""
|
||||
? moment(scope.row.PublishTime).format('YYYY-MM-DD')
|
||||
: ''
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="是否当前版本"
|
||||
:label="$t('system:log:table:IsCurrentVersion')"
|
||||
prop="IsCurrentVersion"
|
||||
min-width="150"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span>{{ $fd("YesOrNo", scope.row.IsCurrentVersion) }}</span>
|
||||
<span>{{ $fd('YesOrNo', scope.row.IsCurrentVersion) }}</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
label="操作"
|
||||
:label="$t('common:action:action')"
|
||||
fixed="right"
|
||||
prop=""
|
||||
min-width="200"
|
||||
@@ -99,7 +109,7 @@
|
||||
icon="el-icon-edit-outline"
|
||||
@click="handleEdit(scope.row)"
|
||||
>
|
||||
编辑
|
||||
{{ $t('common:button:edit') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
size="mini"
|
||||
@@ -107,7 +117,7 @@
|
||||
icon="el-icon-delete"
|
||||
@click="handleDelete(scope.row)"
|
||||
>
|
||||
删除
|
||||
{{ $t('common:button:delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
@@ -125,20 +135,21 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { getPublishLogList, deletePublishLog } from "@/api/admin";
|
||||
import Pagination from "@/components/Pagination";
|
||||
import LogForm from "./components/LogForm.vue";
|
||||
import moment from "moment";
|
||||
import { getPublishLogList, deletePublishLog } from '@/api/admin'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import LogForm from './components/LogForm.vue'
|
||||
import moment from 'moment'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
Version: null,
|
||||
Version_US: null,
|
||||
UpdateContent: null,
|
||||
Asc: false,
|
||||
SortField: "PublishTime",
|
||||
SortField: 'PublishTime',
|
||||
PageIndex: 1,
|
||||
PageSize: 20,
|
||||
};
|
||||
};
|
||||
}
|
||||
}
|
||||
export default {
|
||||
components: { Pagination, LogForm },
|
||||
data() {
|
||||
@@ -148,74 +159,74 @@ export default {
|
||||
list: [],
|
||||
total: 0,
|
||||
loading: false,
|
||||
};
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.getList();
|
||||
this.getList()
|
||||
},
|
||||
methods: {
|
||||
getList() {
|
||||
this.loading = true;
|
||||
this.loading = true
|
||||
getPublishLogList(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
|
||||
})
|
||||
},
|
||||
handleAdd() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs["LogForm"].openDialog("新增", {});
|
||||
});
|
||||
this.$refs['LogForm'].openDialog('新增', {})
|
||||
})
|
||||
},
|
||||
handleEdit(row) {
|
||||
this.$nextTick(() => {
|
||||
this.$refs["LogForm"].openDialog("编辑", row);
|
||||
});
|
||||
this.$refs['LogForm'].openDialog('编辑', row)
|
||||
})
|
||||
},
|
||||
// 重置列表查询
|
||||
handleReset() {
|
||||
this.searchData = searchDataDefault();
|
||||
this.getList();
|
||||
this.searchData = searchDataDefault()
|
||||
this.getList()
|
||||
},
|
||||
// 删除
|
||||
handleDelete(row) {
|
||||
this.$confirm("是否确认删除?", {
|
||||
type: "warning",
|
||||
this.$confirm('是否确认删除?', {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true,
|
||||
}).then(() => {
|
||||
this.loading = true;
|
||||
this.loading = true
|
||||
deletePublishLog(row.Id)
|
||||
.then((res) => {
|
||||
this.loading = false;
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
this.getList();
|
||||
this.getList()
|
||||
this.$message.success(
|
||||
this.$t("common:message:deletedSuccessfully")
|
||||
);
|
||||
this.$t('common:message:deletedSuccessfully')
|
||||
)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false;
|
||||
});
|
||||
});
|
||||
this.loading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
// 排序
|
||||
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.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>
|
||||
<style lang="scss">
|
||||
.log {
|
||||
|
||||
@@ -3,14 +3,19 @@
|
||||
<div class="trial-myinfo-right-box">
|
||||
<div class="trial-myinfo-head">
|
||||
<!-- 账号信息 -->
|
||||
{{ $t("trials:trials-myinfo:title:accountInfo") }}
|
||||
{{ $t('trials:trials-myinfo:title:accountInfo') }}
|
||||
</div>
|
||||
<el-form label-position="right" label-width="100px">
|
||||
<el-form
|
||||
label-position="right"
|
||||
label-width="100px"
|
||||
:rules="rule"
|
||||
:model="userForm"
|
||||
ref="userFormRef"
|
||||
>
|
||||
<!-- 用户名 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:trials-myinfo:form:userName')"
|
||||
style="margin-bottom: 5px"
|
||||
prop="UserName"
|
||||
>
|
||||
<span>{{ user.UserName }}</span>
|
||||
</el-form-item>
|
||||
@@ -27,18 +32,18 @@
|
||||
size="small"
|
||||
@click="setNewUserName"
|
||||
>
|
||||
{{ $t("trials:trials-myinfo:button:update") }}
|
||||
{{ $t('trials:trials-myinfo:button:update') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<!-- 电话 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:trials-myinfo:form:phone')"
|
||||
style="margin-bottom: 5px"
|
||||
prop="UserName"
|
||||
prop="Phone"
|
||||
>
|
||||
<span>{{ user.Phone }}</span>
|
||||
</el-form-item>
|
||||
<el-form-item label="" style="position: relative" prop="UserName">
|
||||
<el-form-item label="" style="position: relative" prop="Phone">
|
||||
<el-input
|
||||
v-model="userForm.Phone"
|
||||
:placeholder="$t('trials:trials-myinfo:form:phone')"
|
||||
@@ -51,14 +56,14 @@
|
||||
size="small"
|
||||
@click="setNewPhone"
|
||||
>
|
||||
{{ $t("trials:trials-myinfo:button:update") }}
|
||||
{{ $t('trials:trials-myinfo:button:update') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
<!-- 邮箱 -->
|
||||
<el-form-item
|
||||
:label="$t('trials:trials-myinfo:form:email')"
|
||||
style="margin-bottom: 5px"
|
||||
prop="UserName"
|
||||
prop="EMail"
|
||||
>
|
||||
<span>{{ user.EMail }}</span>
|
||||
</el-form-item>
|
||||
@@ -100,7 +105,7 @@
|
||||
size="small"
|
||||
@click="setNewEmail"
|
||||
>
|
||||
{{ $t("trials:trials-myinfo:button:update") }}
|
||||
{{ $t('trials:trials-myinfo:button:update') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -114,19 +119,19 @@ import {
|
||||
setNewEmail,
|
||||
setNewPhone,
|
||||
setNewUserName,
|
||||
} from "@/api/system/user.js";
|
||||
import { removeToken } from "@/utils/auth";
|
||||
import password from "./password.vue";
|
||||
var timer = "";
|
||||
var countdown = 60;
|
||||
} from '@/api/system/user.js'
|
||||
import { removeToken } from '@/utils/auth'
|
||||
import password from './password.vue'
|
||||
var timer = ''
|
||||
var countdown = 60
|
||||
export default {
|
||||
name: "account",
|
||||
name: 'account',
|
||||
components: { password },
|
||||
props: {
|
||||
user: {
|
||||
required: true,
|
||||
default: () => {
|
||||
return {};
|
||||
return {}
|
||||
},
|
||||
},
|
||||
IsCanConnectInternet: {
|
||||
@@ -138,108 +143,138 @@ export default {
|
||||
return {
|
||||
userForm: {},
|
||||
sendDisabled: true,
|
||||
sendTitle: this.$t("trials:trials-myinfo:button:getVCode"),
|
||||
};
|
||||
sendTitle: this.$t('trials:trials-myinfo:button:getVCode'),
|
||||
rule: {
|
||||
UserName: [
|
||||
{
|
||||
validator: (rule, value, callback) => {
|
||||
if (!value) return callback()
|
||||
var lang = zzSessionStorage.getItem('lang')
|
||||
? zzSessionStorage.getItem('lang')
|
||||
: 'zh'
|
||||
/* eslint-disable */
|
||||
var reg1 = /^[a-zA-Z0-9_]{4,16}$/ //密码必须是8位以上、必须含有字母、数字、特殊符号
|
||||
if (!reg1.test(value)) {
|
||||
callback(
|
||||
lang === 'zh'
|
||||
? new Error(
|
||||
'1)用户名字符长度最小为4个字符,最大为16个字符,只可使用字母、数字、下划线;'
|
||||
)
|
||||
: new Error(
|
||||
'the username must have:1) At least 4 characters;2) At most 16 characters;3)Only letters, numbers, and underscores are allowed.'
|
||||
)
|
||||
)
|
||||
} else {
|
||||
callback()
|
||||
}
|
||||
},
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
},
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
setNewEmail() {
|
||||
setNewEmail(this.userForm.EMail, this.userForm.VerificationCode).then(
|
||||
() => {
|
||||
this.userForm.EMail = "";
|
||||
this.userForm.VerificationCode = "";
|
||||
this.userForm.EMail = ''
|
||||
this.userForm.VerificationCode = ''
|
||||
this.$message.success(
|
||||
this.$t("trials:trials-myinfo:message:updateSuccessfully")
|
||||
);
|
||||
this.$emit("getUserInfo");
|
||||
this.$t('trials:trials-myinfo:message:updateSuccessfully')
|
||||
)
|
||||
this.$emit('getUserInfo')
|
||||
}
|
||||
);
|
||||
)
|
||||
},
|
||||
async setNewUserName() {
|
||||
try {
|
||||
let validate = await this.$refs.userFormRef.validate()
|
||||
if (!validate) return false
|
||||
let confirm = await this.$confirm(
|
||||
this.$t("trials:trials-myInfo:confirmMessage:updateUserName"),
|
||||
this.$t('trials:trials-myInfo:confirmMessage:updateUserName'),
|
||||
{
|
||||
type: "warning",
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: this.$t("common:button:confirm"),
|
||||
cancelButtonText: this.$t("common:button:cancel"),
|
||||
confirmButtonText: this.$t('common:button:confirm'),
|
||||
cancelButtonText: this.$t('common:button:cancel'),
|
||||
}
|
||||
);
|
||||
if (confirm !== "confirm") return;
|
||||
let res = await setNewUserName(this.userForm.UserName);
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
let res = await setNewUserName(this.userForm.UserName)
|
||||
if (res.IsSuccess) {
|
||||
this.userForm.UserName = "";
|
||||
this.userForm.UserName = ''
|
||||
this.$message.success(
|
||||
this.$t("trials:trials-myinfo:message:updateSuccessfully")
|
||||
);
|
||||
this.$emit("getUserInfo");
|
||||
removeToken();
|
||||
this.logout();
|
||||
this.$t('trials:trials-myinfo:message:updateSuccessfully')
|
||||
)
|
||||
this.$emit('getUserInfo')
|
||||
removeToken()
|
||||
this.logout()
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
setNewPhone() {
|
||||
setNewPhone(this.userForm.Phone).then(() => {
|
||||
this.userForm.Phone = "";
|
||||
this.userForm.Phone = ''
|
||||
this.$message.success(
|
||||
this.$t("trials:trials-myinfo:message:updateSuccessfully")
|
||||
);
|
||||
this.$emit("getUserInfo");
|
||||
});
|
||||
this.$t('trials:trials-myinfo:message:updateSuccessfully')
|
||||
)
|
||||
this.$emit('getUserInfo')
|
||||
})
|
||||
},
|
||||
handleEmailChange() {
|
||||
var reg =
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/;
|
||||
/^[A-Za-z0-9]+([_\.][A-Za-z0-9]+)*@([A-Za-z0-9\-]+\.)+[A-Za-z]{2,6}$/
|
||||
if (this.userForm.EMail && reg.test(this.userForm.EMail)) {
|
||||
this.sendDisabled = false;
|
||||
this.sendDisabled = false
|
||||
} else {
|
||||
this.sendDisabled = true;
|
||||
this.sendDisabled = true
|
||||
}
|
||||
},
|
||||
sendVerificationCode() {
|
||||
sendVerificationCode(this.userForm.EMail).then(() => {
|
||||
this.settime(this);
|
||||
this.settime(this)
|
||||
// 发送成功
|
||||
this.$message.success(
|
||||
this.$t("trials:trials-myinfo:message:sendSuccessfully")
|
||||
);
|
||||
});
|
||||
this.$t('trials:trials-myinfo:message:sendSuccessfully')
|
||||
)
|
||||
})
|
||||
},
|
||||
settime(obj) {
|
||||
if (countdown === 0) {
|
||||
obj.sendDisabled = false;
|
||||
obj.sendTitle = this.$t("trials:trials-myinfo:button:getVCode"); // '获取验证码'
|
||||
countdown = 60;
|
||||
clearTimeout(timer);
|
||||
return;
|
||||
obj.sendDisabled = false
|
||||
obj.sendTitle = this.$t('trials:trials-myinfo:button:getVCode') // '获取验证码'
|
||||
countdown = 60
|
||||
clearTimeout(timer)
|
||||
return
|
||||
} else {
|
||||
obj.sendDisabled = true;
|
||||
obj.sendDisabled = true
|
||||
obj.sendTitle = `${this.$t(
|
||||
"trials:trials-myinfo:button:wait"
|
||||
)}(${countdown}s)`;
|
||||
countdown--;
|
||||
'trials:trials-myinfo:button:wait'
|
||||
)}(${countdown}s)`
|
||||
countdown--
|
||||
// eslint-disable-next-line no-self-assign
|
||||
countdown = countdown;
|
||||
countdown = countdown
|
||||
timer = setTimeout(function () {
|
||||
obj.settime(obj);
|
||||
}, 1000);
|
||||
obj.settime(obj)
|
||||
}, 1000)
|
||||
}
|
||||
},
|
||||
async logout() {
|
||||
/* eslint-disable */
|
||||
var loginType = zzSessionStorage.getItem("loginType");
|
||||
await this.$store.dispatch("user/logout");
|
||||
var loginType = zzSessionStorage.getItem('loginType')
|
||||
await this.$store.dispatch('user/logout')
|
||||
if (loginType) {
|
||||
this.$router.push(`/login?loginType=${loginType}`);
|
||||
this.$router.push(`/login?loginType=${loginType}`)
|
||||
} else {
|
||||
this.$router.push(`/login`);
|
||||
this.$router.push(`/login`)
|
||||
}
|
||||
this.$i18n.locale = "zh";
|
||||
this.setLanguage("zh");
|
||||
this.$updateDictionary();
|
||||
this.$i18n.locale = 'zh'
|
||||
this.setLanguage('zh')
|
||||
this.$updateDictionary()
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
</script>
|
||||
@@ -2,7 +2,7 @@
|
||||
<div class="trial-myinfo-right-box">
|
||||
<div class="trial-myinfo-head">
|
||||
<!-- 修改密码 -->
|
||||
{{ $t("trials:trials-myinfo:title:updatePaasord") }}
|
||||
{{ $t('trials:trials-myinfo:title:updatePaasord') }}
|
||||
</div>
|
||||
<el-form
|
||||
ref="passwordForm"
|
||||
@@ -52,17 +52,17 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
<el-button type="primary" size="small" class="trial-info-btn" @click="save">
|
||||
{{ $t("trials:trials-myinfo:button:save") }}
|
||||
{{ $t('trials:trials-myinfo:button:save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import md5 from "js-md5";
|
||||
import { mapGetters, mapMutations } from "vuex";
|
||||
import { modifyPassword } from "@/api/admin.js";
|
||||
import { removeToken } from "@/utils/auth";
|
||||
import md5 from 'js-md5'
|
||||
import { mapGetters, mapMutations } from 'vuex'
|
||||
import { modifyPassword } from '@/api/admin.js'
|
||||
import { removeToken } from '@/utils/auth'
|
||||
export default {
|
||||
name: "password",
|
||||
name: 'password',
|
||||
data() {
|
||||
return {
|
||||
password: {},
|
||||
@@ -70,91 +70,96 @@ export default {
|
||||
OldPassWord: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("common:ruleMessage:specify"),
|
||||
trigger: "blur",
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
],
|
||||
NewPassWord: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("common:ruleMessage:specify"),
|
||||
trigger: "blur",
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
trigger: "blur",
|
||||
trigger: 'blur',
|
||||
validator: this.$validatePassword,
|
||||
},
|
||||
],
|
||||
ConfirmPassWord: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t("common:ruleMessage:specify"),
|
||||
trigger: "blur",
|
||||
message: this.$t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
{
|
||||
required: true,
|
||||
trigger: "blur",
|
||||
trigger: 'blur',
|
||||
validator: this.$validatePassword,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(["userId"]),
|
||||
...mapGetters(['userId']),
|
||||
},
|
||||
methods: {
|
||||
...mapMutations({ setLanguage: "lang/setLanguage" }),
|
||||
...mapMutations({ setLanguage: 'lang/setLanguage' }),
|
||||
async save() {
|
||||
try {
|
||||
let validate = await this.$refs.passwordForm.validate();
|
||||
if (!validate) return;
|
||||
let validate = await this.$refs.passwordForm.validate()
|
||||
if (!validate) return
|
||||
if (this.password.NewPassWord !== this.password.ConfirmPassWord) {
|
||||
this.$alert(this.$t("passwordReset:formRule:passwordsDiffer"));
|
||||
return;
|
||||
this.$alert(this.$t('passwordReset:formRule:passwordsDiffer'))
|
||||
return
|
||||
}
|
||||
let confirm = await this.$confirm(
|
||||
this.$t("trials:trials-myInfo:confirmMessage:updatePassWord"),
|
||||
this.$t('trials:trials-myInfo:confirmMessage:updatePassWord'),
|
||||
{
|
||||
type: "warning",
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true,
|
||||
confirmButtonText: this.$t("common:button:confirm"),
|
||||
cancelButtonText: this.$t("common:button:cancel"),
|
||||
confirmButtonText: this.$t('common:button:confirm'),
|
||||
cancelButtonText: this.$t('common:button:cancel'),
|
||||
}
|
||||
);
|
||||
if (confirm !== "confirm") return;
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
const param = {
|
||||
UserId: this.userId,
|
||||
NewPassWord: md5(this.password.NewPassWord),
|
||||
OldPassWord: md5(this.password.OldPassWord),
|
||||
};
|
||||
let res = await modifyPassword(param);
|
||||
}
|
||||
let res = await modifyPassword(param)
|
||||
if (res.IsSuccess) {
|
||||
// 修改成功,请重新登录账号
|
||||
this.$message.success(
|
||||
this.$t("trials:trials-myinfo:message:modifyPWSuccessfully")
|
||||
);
|
||||
removeToken();
|
||||
this.logout();
|
||||
this.$t('trials:trials-myinfo:message:modifyPWSuccessfully')
|
||||
)
|
||||
removeToken()
|
||||
this.logout()
|
||||
}
|
||||
} catch (err) {
|
||||
console.log(err);
|
||||
console.log(err)
|
||||
}
|
||||
},
|
||||
async logout() {
|
||||
/* eslint-disable */
|
||||
var loginType = zzSessionStorage.getItem("loginType");
|
||||
await this.$store.dispatch("user/logout");
|
||||
var loginType = zzSessionStorage.getItem('loginType')
|
||||
await this.$store.dispatch('user/logout')
|
||||
if (loginType) {
|
||||
this.$router.push(`/login?loginType=${loginType}`);
|
||||
this.$router.push(`/login?loginType=${loginType}`)
|
||||
} else {
|
||||
this.$router.push(`/login`);
|
||||
this.$router.push(`/login`)
|
||||
}
|
||||
this.$i18n.locale = "zh";
|
||||
this.setLanguage("zh");
|
||||
this.$updateDictionary();
|
||||
this.$i18n.locale = 'zh'
|
||||
this.setLanguage('zh')
|
||||
this.$updateDictionary()
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.el-form-item {
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
</style>
|
||||
@@ -5,7 +5,7 @@
|
||||
<el-form :inline="true">
|
||||
<!-- 文件类型 -->
|
||||
<el-form-item :label="$t('trials:signRecords:table:fileType')">
|
||||
<el-select v-model="searchData.FileTypeId" style="width: 150px">
|
||||
<el-select v-model="searchData.FileTypeId" clearable style="width: 150px">
|
||||
<el-option
|
||||
v-for="item of typeOptions"
|
||||
:key="item.FileTypeId"
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="sign-form-wrapper">
|
||||
<div class="sign-form-body">
|
||||
<h4 v-if="signText" style="color:red">*{{ signText }}</h4>
|
||||
<h4 v-if="signText" style="color: red">*{{ signText }}</h4>
|
||||
<el-form
|
||||
ref="signForm"
|
||||
:model="signForm"
|
||||
size="small"
|
||||
label-width="100px"
|
||||
>
|
||||
|
||||
<el-form-item
|
||||
:label="$t('common:form:sign:userName')"
|
||||
prop="UserName"
|
||||
:rules="[
|
||||
{ required: true, message: $t('common:ruleMessage:specify'), trigger: 'blur' }
|
||||
{
|
||||
required: true,
|
||||
message: $t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<el-input v-model="signForm.UserName" />
|
||||
@@ -22,18 +25,36 @@
|
||||
:label="$t('common:form:sign:password')"
|
||||
prop="Password"
|
||||
:rules="[
|
||||
{ required: true, message: $t('common:ruleMessage:specify'), trigger: 'blur' }
|
||||
{
|
||||
required: true,
|
||||
message: $t('common:ruleMessage:specify'),
|
||||
trigger: 'blur',
|
||||
},
|
||||
]"
|
||||
>
|
||||
<el-input v-model="signForm.Password" show-password auto-complete="new-password" />
|
||||
<el-input
|
||||
v-model="signForm.Password"
|
||||
show-password
|
||||
auto-complete="new-password"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</div>
|
||||
<div slot="footer" class="dialog-footer sign-form-footer">
|
||||
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleclose">
|
||||
<el-button
|
||||
:disabled="btnLoading"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleclose"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<el-button :loading="btnLoading" size="small" type="primary" @click="userConfirm">
|
||||
<el-button
|
||||
:loading="btnLoading"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="userConfirm"
|
||||
>
|
||||
{{ $t('common:button:sign') }}
|
||||
</el-button>
|
||||
</div>
|
||||
@@ -49,48 +70,54 @@ export default {
|
||||
props: {
|
||||
fileName: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
isSystemDoc: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
documentId: {
|
||||
type: String,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
trialId: {
|
||||
type: String,
|
||||
default: ''
|
||||
}
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
signForm: {
|
||||
UserName: '',
|
||||
Password: ''
|
||||
Password: '',
|
||||
},
|
||||
signText: '',
|
||||
btnLoading: false,
|
||||
loading: false
|
||||
loading: false,
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
this.loading = true
|
||||
getSystemBasicData(attachmentSignCode).then(res => {
|
||||
var text
|
||||
if (this.$i18n.locale === 'zh') {
|
||||
text = res.Result.ValueCN
|
||||
} else {
|
||||
text = res.Result.Value
|
||||
}
|
||||
this.signText = text.replace('xxx', this.fileName)
|
||||
this.loading = false
|
||||
}).catch(() => { this.loading = false })
|
||||
getSystemBasicData(attachmentSignCode)
|
||||
.then((res) => {
|
||||
var text
|
||||
if (this.$i18n.locale === 'zh') {
|
||||
text = res.Result.ValueCN
|
||||
} else {
|
||||
text = res.Result.Value
|
||||
}
|
||||
this.signText = text.replace('xxx', this.fileName)
|
||||
this.loading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.loading = false
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
userConfirm() {
|
||||
const currentUser = zzSessionStorage.getItem('userName').toLocaleLowerCase()
|
||||
const currentUser = zzSessionStorage
|
||||
.getItem('userName')
|
||||
.toLocaleLowerCase()
|
||||
this.$refs.signForm.validate((valid) => {
|
||||
console.log(valid)
|
||||
if (!valid) return
|
||||
@@ -102,44 +129,52 @@ export default {
|
||||
this.btnLoading = true
|
||||
var params = {
|
||||
data: {
|
||||
trialId: this.trialId,
|
||||
// trialId: this.trialId,
|
||||
documentId: this.documentId,
|
||||
isSystemDoc: this.isSystemDoc
|
||||
isSystemDoc: this.isSystemDoc,
|
||||
},
|
||||
signInfo: {
|
||||
UserName: this.signForm.UserName,
|
||||
PassWord: md5(this.signForm.Password),
|
||||
TrialId: this.trialId,
|
||||
// c: this.trialId,
|
||||
SignCode: '',
|
||||
SignText: this.signText,
|
||||
SignCodeId: '',
|
||||
SubjectVisitId: ''
|
||||
}
|
||||
SubjectVisitId: '',
|
||||
},
|
||||
}
|
||||
userConfirm(params).then(res => {
|
||||
if (res.IsSuccess) {
|
||||
// 签名成功!
|
||||
this.$message.success(this.$t('common:message:signSuccessfully'))
|
||||
this.$emit('closeDialog', true)
|
||||
}
|
||||
}).catch(() => { this.btnLoading = false })
|
||||
if (!this.isSystemDoc) {
|
||||
params.data.TrialId = this.trialId
|
||||
params.signInfo.TrialId = this.trialId
|
||||
}
|
||||
userConfirm(params)
|
||||
.then((res) => {
|
||||
if (res.IsSuccess) {
|
||||
// 签名成功!
|
||||
this.$message.success(this.$t('common:message:signSuccessfully'))
|
||||
this.$emit('closeDialog', true)
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
this.btnLoading = false
|
||||
})
|
||||
})
|
||||
},
|
||||
handleclose() {
|
||||
this.$emit('closeDialog', false)
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.sign-form-wrapper{
|
||||
.sign-form-body{
|
||||
padding:10px;
|
||||
.sign-form-wrapper {
|
||||
.sign-form-body {
|
||||
padding: 10px;
|
||||
border: 1px solid #e0e0e0;
|
||||
max-height:650px;
|
||||
max-height: 650px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.sign-form-footer{
|
||||
.sign-form-footer {
|
||||
margin-top: 10px;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
<el-form-item :label="$t('trials:self-attachment:table:fileType')">
|
||||
<el-select
|
||||
v-model="searchData.FileTypeId"
|
||||
clearable
|
||||
style="width:150px;"
|
||||
>
|
||||
<el-option
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<el-table
|
||||
ref="myTable"
|
||||
v-loading="listLoading"
|
||||
v-adaptive="{bottomOffset:55}"
|
||||
v-adaptive="{ bottomOffset: 55 }"
|
||||
:data="list"
|
||||
stripe
|
||||
height="100"
|
||||
@@ -32,7 +32,15 @@
|
||||
v-if="!hasPermi(['role:ea'])"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" @click="go(`/trialsResume?doctorId=${scope.row.DoctorId}&token=${token}`)">{{ scope.row.LastName }} / {{ scope.row.FirstName }}</el-button>
|
||||
<el-button
|
||||
type="text"
|
||||
@click="
|
||||
go(
|
||||
`/trialsResume?doctorId=${scope.row.DoctorId}&token=${token}`
|
||||
)
|
||||
"
|
||||
>{{ scope.row.LastName }} / {{ scope.row.FirstName }}</el-button
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- Name CN -->
|
||||
@@ -48,7 +56,7 @@
|
||||
<el-table-column
|
||||
prop="UserName"
|
||||
:label="$t('trials:enrolledReviews:table:userName')"
|
||||
:width="hasPermi(['role:ea'])?300:150"
|
||||
:width="hasPermi(['role:ea']) ? 300 : 150"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
/>
|
||||
@@ -56,12 +64,16 @@
|
||||
<el-table-column
|
||||
prop="EnrollTimeStr"
|
||||
:label="$t('trials:enrolledReviews:table:enrollmentTime')"
|
||||
:width="hasPermi(['role:ea'])?320:130"
|
||||
:width="hasPermi(['role:ea']) ? 320 : 130"
|
||||
sortable="custom"
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.EnrollTime?moment(scope.row.EnrollTime).format('YYYY-MM-DD'):'' }}
|
||||
{{
|
||||
scope.row.EnrollTime
|
||||
? moment(scope.row.EnrollTime).format('YYYY-MM-DD')
|
||||
: ''
|
||||
}}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@@ -78,8 +90,16 @@
|
||||
:inactive-value="false"
|
||||
:active-text="$fd('IsEnable', true)"
|
||||
:inactive-text="$fd('IsEnable', false)"
|
||||
@change="(v) => {return isEnableChange(scope.row, v)}"
|
||||
:disabled="!hasPermi(['trials:trials-panel:enrolled-reviewers:list:edit'])"
|
||||
@change="
|
||||
(v) => {
|
||||
return isEnableChange(scope.row, v)
|
||||
}
|
||||
"
|
||||
:disabled="
|
||||
!hasPermi([
|
||||
'trials:trials-panel:enrolled-reviewers:list:edit',
|
||||
])
|
||||
"
|
||||
/>
|
||||
<!-- <span :style="{color:scope.row.IsEnable?'#409eff':'#dcdfe6'}"> {{$fd('IsEnable', scope.row.IsEnable)}}</span> -->
|
||||
</div>
|
||||
@@ -98,16 +118,46 @@
|
||||
width="300"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-for="item of scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}) ? scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).ReadingCategorys : []" :key="item.TrialReadingCriterionId" style="margin:5px 5px 5px 0;">
|
||||
<el-tag v-if="item === 1" type="primary">{{ $fd('ReadingCategory', item) + ' & ' + $fd('ReadingCategory', 2) }}</el-tag>
|
||||
<!-- <el-tag v-if="item === 2" type="info">{{ $fd('ReadingCategory', item) }}</el-tag>-->
|
||||
<el-tag v-if="item === 4" type="danger">{{ $fd('ReadingCategory', item) }}</el-tag>
|
||||
<el-tag v-if="item === 5" type="warning">{{ $fd('ReadingCategory', item) }}</el-tag>
|
||||
</span>
|
||||
<el-button
|
||||
v-hasPermi="['trials:trials-panel:enrolled-reviewers:list:edit']"
|
||||
<span
|
||||
v-for="item of scope.row.CriterionCategoryList.find((v) => {
|
||||
return (
|
||||
v.TrialReadingCriterionId === ite.TrialReadingCriterionId
|
||||
)
|
||||
})
|
||||
? scope.row.CriterionCategoryList.find((v) => {
|
||||
return (
|
||||
v.TrialReadingCriterionId ===
|
||||
ite.TrialReadingCriterionId
|
||||
)
|
||||
}).ReadingCategorys
|
||||
: []"
|
||||
:key="item.TrialReadingCriterionId"
|
||||
style="margin: 5px 5px 5px 0"
|
||||
>
|
||||
<el-tag v-if="item === 1" type="primary">{{
|
||||
$fd('ReadingCategory', item) +
|
||||
' & ' +
|
||||
$fd('ReadingCategory', 2)
|
||||
}}</el-tag>
|
||||
<!-- <el-tag v-if="item === 2" type="info">{{ $fd('ReadingCategory', item) }}</el-tag>-->
|
||||
<el-tag v-if="item === 4" type="danger">{{
|
||||
$fd('ReadingCategory', item)
|
||||
}}</el-tag>
|
||||
<el-tag v-if="item === 5" type="warning">{{
|
||||
$fd('ReadingCategory', item)
|
||||
}}</el-tag>
|
||||
</span>
|
||||
<el-button
|
||||
v-hasPermi="[
|
||||
'trials:trials-panel:enrolled-reviewers:list:edit',
|
||||
]"
|
||||
type="text"
|
||||
@click="openSetEnrollReadingCategory(scope.row, ite.TrialReadingCriterionId)"
|
||||
@click="
|
||||
openSetEnrollReadingCategory(
|
||||
scope.row,
|
||||
ite.TrialReadingCriterionId
|
||||
)
|
||||
"
|
||||
>
|
||||
{{ $t('trials:enrolledReviews:button:config') }}
|
||||
</el-button>
|
||||
@@ -120,13 +170,27 @@
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-switch
|
||||
v-model="scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).IsJoinAnalysis"
|
||||
v-model="
|
||||
scope.row.CriterionCategoryList.find((v) => {
|
||||
return (
|
||||
v.TrialReadingCriterionId === ite.TrialReadingCriterionId
|
||||
)
|
||||
}).IsJoinAnalysis
|
||||
"
|
||||
:active-value="true"
|
||||
:inactive-value="false"
|
||||
:active-text="$fd('YesOrNo', true)"
|
||||
:inactive-text="$fd('YesOrNo', false)"
|
||||
@change="(v) => {return isConsistencyChange(scope.row, ite, v, true)}"
|
||||
:disabled="!hasPermi(['trials:trials-panel:enrolled-reviewers:list:edit'])"
|
||||
@change="
|
||||
(v) => {
|
||||
return isConsistencyChange(scope.row, ite, v, true)
|
||||
}
|
||||
"
|
||||
:disabled="
|
||||
!hasPermi([
|
||||
'trials:trials-panel:enrolled-reviewers:list:edit',
|
||||
])
|
||||
"
|
||||
/>
|
||||
<!-- <span v-if="scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).IsJoinAnalysis"> {{$fd('YesOrNo', scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).IsJoinAnalysis)}}</span>
|
||||
<span v-else> {{$fd('YesOrNo',false)}}</span> -->
|
||||
@@ -138,8 +202,20 @@
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).StatementCriterionFileList.length > 0">
|
||||
<el-button type="text" @click="preview(scope.row,ite.TrialReadingCriterionId)">View</el-button>
|
||||
<div
|
||||
v-if="
|
||||
scope.row.CriterionCategoryList.find((v) => {
|
||||
return (
|
||||
v.TrialReadingCriterionId === ite.TrialReadingCriterionId
|
||||
)
|
||||
}).StatementCriterionFileList.length > 0
|
||||
"
|
||||
>
|
||||
<el-button
|
||||
type="text"
|
||||
@click="preview(scope.row, ite.TrialReadingCriterionId)"
|
||||
>View</el-button
|
||||
>
|
||||
<!-- <el-button type="text" @click="windowOpen(scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).StatementCriterionFileList[0].FilePath)">View</el-button> -->
|
||||
</div>
|
||||
<div v-else>
|
||||
@@ -147,10 +223,19 @@
|
||||
<!-- 上传 -->
|
||||
<el-button
|
||||
v-if="ite.CriterionType === 0"
|
||||
v-hasPermi="['trials:trials-panel:enrolled-reviewers:list:edit']"
|
||||
v-hasPermi="[
|
||||
'trials:trials-panel:enrolled-reviewers:list:edit',
|
||||
]"
|
||||
type="text"
|
||||
style="margin-left: 10px"
|
||||
@click="addCol(0, scope.row, ite, $t('trials:enrolledReviews:message:SOW'))"
|
||||
@click="
|
||||
addCol(
|
||||
0,
|
||||
scope.row,
|
||||
ite,
|
||||
$t('trials:enrolledReviews:message:SOW')
|
||||
)
|
||||
"
|
||||
>
|
||||
{{ $t('trials:enrolledReviews:button:upload') }}
|
||||
</el-button>
|
||||
@@ -163,18 +248,40 @@
|
||||
show-overflow-tooltip
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div v-if="scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).AcknowledgementCriterionFileList.length > 0">
|
||||
<el-button type="text" @click="windowOpen(scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).AcknowledgementCriterionFileList[0].FilePath)">View</el-button>
|
||||
<div
|
||||
v-if="
|
||||
scope.row.CriterionCategoryList.find((v) => {
|
||||
return (
|
||||
v.TrialReadingCriterionId === ite.TrialReadingCriterionId
|
||||
)
|
||||
}).AcknowledgementCriterionFileList.length > 0
|
||||
"
|
||||
>
|
||||
<el-button
|
||||
type="text"
|
||||
@click="preview(scope.row, ite.TrialReadingCriterionId)"
|
||||
>
|
||||
View
|
||||
</el-button>
|
||||
</div>
|
||||
<div v-else>
|
||||
<span>{{ $t('trials:enrolledReviews:label:notUpload') }}</span>
|
||||
<!-- 上传 -->
|
||||
<el-button
|
||||
v-if="ite.CriterionType === 0"
|
||||
v-hasPermi="['trials:trials-panel:enrolled-reviewers:list:edit']"
|
||||
v-hasPermi="[
|
||||
'trials:trials-panel:enrolled-reviewers:list:edit',
|
||||
]"
|
||||
type="text"
|
||||
style="margin-left: 10px"
|
||||
@click="addCol(1, scope.row, ite, $t('trials:enrolledReviews:message:SOW'))"
|
||||
@click="
|
||||
addCol(
|
||||
1,
|
||||
scope.row,
|
||||
ite,
|
||||
$t('trials:enrolledReviews:message:SOW')
|
||||
)
|
||||
"
|
||||
>
|
||||
{{ $t('trials:enrolledReviews:button:upload') }}
|
||||
</el-button>
|
||||
@@ -188,30 +295,47 @@
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div>
|
||||
{{ scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).PendingCount }}
|
||||
{{
|
||||
scope.row.CriterionCategoryList.find((v) => {
|
||||
return (
|
||||
v.TrialReadingCriterionId === ite.TrialReadingCriterionId
|
||||
)
|
||||
}).PendingCount
|
||||
}}
|
||||
/
|
||||
{{ scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).ComplectedCount }}
|
||||
{{
|
||||
scope.row.CriterionCategoryList.find((v) => {
|
||||
return (
|
||||
v.TrialReadingCriterionId === ite.TrialReadingCriterionId
|
||||
)
|
||||
}).ComplectedCount
|
||||
}}
|
||||
/
|
||||
{{ scope.row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === ite.TrialReadingCriterionId}).TotalCount }}
|
||||
{{
|
||||
scope.row.CriterionCategoryList.find((v) => {
|
||||
return (
|
||||
v.TrialReadingCriterionId === ite.TrialReadingCriterionId
|
||||
)
|
||||
}).TotalCount
|
||||
}}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table-column>
|
||||
|
||||
</el-table>
|
||||
</template>
|
||||
|
||||
<!-- 上传SOW -->
|
||||
<!-- <base-model :config="sow_model">-->
|
||||
<!-- <template slot="dialog-body">-->
|
||||
<!-- <upload-acksow-->
|
||||
<!-- ref="uploadAckSow"-->
|
||||
<!-- :trial-id="listQuery.TrialId"-->
|
||||
<!-- :doctor-id="doctorId"-->
|
||||
<!-- @getFileList="getFileList"-->
|
||||
<!-- />-->
|
||||
<!-- </template>-->
|
||||
<!-- </base-model>-->
|
||||
<!-- <base-model :config="sow_model">-->
|
||||
<!-- <template slot="dialog-body">-->
|
||||
<!-- <upload-acksow-->
|
||||
<!-- ref="uploadAckSow"-->
|
||||
<!-- :trial-id="listQuery.TrialId"-->
|
||||
<!-- :doctor-id="doctorId"-->
|
||||
<!-- @getFileList="getFileList"-->
|
||||
<!-- />-->
|
||||
<!-- </template>-->
|
||||
<!-- </base-model>-->
|
||||
|
||||
<!-- 修改 Reading Type -->
|
||||
<base-model :config="readingType_model">
|
||||
@@ -258,25 +382,42 @@
|
||||
allow-create
|
||||
multiple
|
||||
default-first-option
|
||||
style="width: 50%;"
|
||||
style="width: 50%"
|
||||
>
|
||||
<template v-for="item of $d.ReadingCategory">
|
||||
<el-option v-if="item.value === 1" :key="item.id" :value="1" :label="$fd('ReadingCategory', 1) + ' & ' + $fd('ReadingCategory', 2)" />
|
||||
<el-option
|
||||
v-if="item.value === 1"
|
||||
:key="item.id"
|
||||
:value="1"
|
||||
:label="
|
||||
$fd('ReadingCategory', 1) + ' & ' + $fd('ReadingCategory', 2)
|
||||
"
|
||||
/>
|
||||
</template>
|
||||
<template v-for="item of $d.ReadingCategory">
|
||||
<el-option v-if="item.value === 4 && IsArbitrationReading" :key="item.id" :value="item.value" :label="$fd('ReadingCategory', 4)" />
|
||||
<el-option
|
||||
v-if="item.value === 4 && IsArbitrationReading"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="$fd('ReadingCategory', 4)"
|
||||
/>
|
||||
</template>
|
||||
<template v-for="item of $d.ReadingCategory">
|
||||
<el-option v-if="item.value === 5 && IsOncologyReading" :key="item.id" :value="item.value" :label="$fd('ReadingCategory', 5)" />
|
||||
<el-option
|
||||
v-if="item.value === 5 && IsOncologyReading"
|
||||
:key="item.id"
|
||||
:value="item.value"
|
||||
:label="$fd('ReadingCategory', 5)"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
</template>
|
||||
<template slot="dialog-footer">
|
||||
<div style="margin-top:30px;">
|
||||
<div style="margin-top: 30px">
|
||||
<el-button
|
||||
:disabled="readingCategory_model.btnLoading"
|
||||
type="primary"
|
||||
@click="readingCategory_model.visible = false"
|
||||
:disabled="readingCategory_model.btnLoading"
|
||||
type="primary"
|
||||
@click="readingCategory_model.visible = false"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
@@ -298,17 +439,23 @@
|
||||
:model="updateStatusForm"
|
||||
:rules="updateStatusFormrules"
|
||||
>
|
||||
<el-form-item :label="$t('trials:enrolledReviews:label:enrollmentStatus')" prop="Status">
|
||||
<el-select
|
||||
v-model="updateStatusForm.Status"
|
||||
style="width:60%;"
|
||||
>
|
||||
<el-form-item
|
||||
:label="$t('trials:enrolledReviews:label:enrollmentStatus')"
|
||||
prop="Status"
|
||||
>
|
||||
<el-select v-model="updateStatusForm.Status" style="width: 60%">
|
||||
<!-- 0:回退;1:出组; -->
|
||||
<el-option v-for="item of $d.OutOrInEnrollment" :key="`OutOrInEnrollment${item.value}`" :value="item.value" :label="item.label" :disabled="item.value === 0 && currentWorkload>0" />
|
||||
<el-option
|
||||
v-for="item of $d.OutOrInEnrollment"
|
||||
:key="`OutOrInEnrollment${item.value}`"
|
||||
:value="item.value"
|
||||
:label="item.label"
|
||||
:disabled="item.value === 0 && currentWorkload > 0"
|
||||
/>
|
||||
</el-select>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
v-if="updateStatusForm.Status== 1"
|
||||
v-if="updateStatusForm.Status == 1"
|
||||
:label="$t('trials:enrolledReviews:label:outOfEnrollmentTime')"
|
||||
prop="OutEnrollmentTime"
|
||||
>
|
||||
@@ -346,10 +493,16 @@
|
||||
label-width="120px"
|
||||
size="small"
|
||||
>
|
||||
<el-form-item :label="$t('trials:enrolledReviews:table:criterionName')" prop="CriterionType">
|
||||
<el-form-item
|
||||
:label="$t('trials:enrolledReviews:table:criterionName')"
|
||||
prop="CriterionType"
|
||||
>
|
||||
<el-input v-model="form.CriterionName" disabled />
|
||||
</el-form-item>
|
||||
<el-form-item :label="$t('trials:enrolledReviews:table:file')" prop="FilePath">
|
||||
<el-form-item
|
||||
:label="$t('trials:enrolledReviews:table:file')"
|
||||
prop="FilePath"
|
||||
>
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
action
|
||||
@@ -358,19 +511,35 @@
|
||||
:on-preview="handlePreview2"
|
||||
:on-remove="handleRemoveFile2"
|
||||
:show-file-list="true"
|
||||
accept=".pdf"
|
||||
:limit="1"
|
||||
:file-list="fileList"
|
||||
>
|
||||
<el-button size="small" type="primary" :disabled="fileList.length > 0">{{$t('common:button:upload')}}</el-button>
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:disabled="fileList.length > 0"
|
||||
>{{ $t('common:button:upload') }}</el-button
|
||||
>
|
||||
</el-upload>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<template slot="dialog-footer">
|
||||
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancle">
|
||||
<el-button
|
||||
:disabled="btnLoading"
|
||||
size="small"
|
||||
type="primary"
|
||||
@click="handleCancle"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">
|
||||
<el-button
|
||||
size="small"
|
||||
type="primary"
|
||||
:loading="btnLoading"
|
||||
@click="handleSave"
|
||||
>
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</template>
|
||||
@@ -384,7 +553,7 @@ import {
|
||||
updateReviewerReadingType,
|
||||
enrollBackOrOut,
|
||||
setEnrollReadingCategory,
|
||||
batchSetCriterionJoinJoinAnalysis
|
||||
batchSetCriterionJoinJoinAnalysis,
|
||||
} from '@/api/trials'
|
||||
import { addDoctorCriterionFile } from '@/api/reviewers'
|
||||
import { uploadFile } from '@/api/attachment'
|
||||
@@ -405,7 +574,7 @@ export default {
|
||||
PageIndex: 1,
|
||||
PageSize: 100,
|
||||
Asc: false,
|
||||
SortField: ''
|
||||
SortField: '',
|
||||
},
|
||||
doctorId: '',
|
||||
currentRow: {},
|
||||
@@ -415,41 +584,59 @@ export default {
|
||||
currentClickRowData: '',
|
||||
btnLoading: false,
|
||||
readingType: '',
|
||||
model_cfg: { visible: false, showClose: true, width: '600px', title: '', appendToBody: true },
|
||||
model_cfg: {
|
||||
visible: false,
|
||||
showClose: true,
|
||||
width: '600px',
|
||||
title: '',
|
||||
appendToBody: true,
|
||||
},
|
||||
sow_model: {
|
||||
visible: false,
|
||||
title: this.$t('trials:enrolledReviews:dialogTitle:signedAckOfSow'),
|
||||
showClose: true,
|
||||
width: '500px'
|
||||
width: '500px',
|
||||
},
|
||||
readingType_model: {
|
||||
visible: false,
|
||||
title: this.$t('trials:enrolledReviews:dialogTitle:changeReadingType'),
|
||||
showClose: true,
|
||||
width: '500px',
|
||||
btnLoading: false
|
||||
btnLoading: false,
|
||||
},
|
||||
readingCategory_model: {
|
||||
visible: false,
|
||||
title: this.$t('trials:enrolledReviews:dialogTitle:changeReadingType'),
|
||||
showClose: true,
|
||||
width: '600px',
|
||||
btnLoading: false
|
||||
btnLoading: false,
|
||||
},
|
||||
reviewerStatus_model: {
|
||||
visible: false,
|
||||
title: this.$t('trials:enrolledReviews:dialogTitle:changeStatus'),
|
||||
showClose: true,
|
||||
width: '500px',
|
||||
btnLoading: false
|
||||
btnLoading: false,
|
||||
},
|
||||
updateStatusForm: {
|
||||
Status: '',
|
||||
OutEnrollmentTime: ''
|
||||
OutEnrollmentTime: '',
|
||||
},
|
||||
updateStatusFormrules: {
|
||||
Status: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }],
|
||||
OutEnrollmentTime: [{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur', 'change'] }]
|
||||
Status: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:select'),
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
OutEnrollmentTime: [
|
||||
{
|
||||
required: true,
|
||||
message: this.$t('common:ruleMessage:select'),
|
||||
trigger: ['blur', 'change'],
|
||||
},
|
||||
],
|
||||
},
|
||||
token: store.getters.token,
|
||||
ReadingCategorys: [],
|
||||
@@ -460,15 +647,25 @@ export default {
|
||||
fileList: [],
|
||||
form: {},
|
||||
rowData: {},
|
||||
moment
|
||||
moment,
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
currentWorkload() {
|
||||
if (Object.keys(this.currentRow).length === 0) return 0
|
||||
var total = this.currentRow.Adjudication + this.currentRow.AdjudicationIn24H + this.currentRow.AdjudicationIn48H + this.currentRow.Timepoint + this.currentRow.TimepointIn24H + this.currentRow.TimepointIn48H + this.currentRow.TrainingTimes + this.currentRow.RefresherTraining + this.currentRow.Global + this.currentRow.Downtime
|
||||
var total =
|
||||
this.currentRow.Adjudication +
|
||||
this.currentRow.AdjudicationIn24H +
|
||||
this.currentRow.AdjudicationIn48H +
|
||||
this.currentRow.Timepoint +
|
||||
this.currentRow.TimepointIn24H +
|
||||
this.currentRow.TimepointIn48H +
|
||||
this.currentRow.TrainingTimes +
|
||||
this.currentRow.RefresherTraining +
|
||||
this.currentRow.Global +
|
||||
this.currentRow.Downtime
|
||||
return total
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.trialId = this.$route.query.trialCode
|
||||
@@ -477,14 +674,16 @@ export default {
|
||||
},
|
||||
methods: {
|
||||
// 预览
|
||||
preview(row,TrialReadingCriterionId){
|
||||
let file = row.CriterionCategoryList.find(v => {return v.TrialReadingCriterionId === TrialReadingCriterionId}).StatementCriterionFileList[0];
|
||||
let arr = file.FilePath.split(".");
|
||||
preview(row, TrialReadingCriterionId) {
|
||||
let file = row.CriterionCategoryList.find((v) => {
|
||||
return v.TrialReadingCriterionId === TrialReadingCriterionId
|
||||
}).StatementCriterionFileList[0]
|
||||
let arr = file.FilePath.split('.')
|
||||
|
||||
this.$preview({
|
||||
path:file.FilePath,
|
||||
type:arr[arr.length - 1],
|
||||
title:file.FileName
|
||||
path: file.FilePath,
|
||||
type: arr[arr.length - 1],
|
||||
title: file.FileName,
|
||||
})
|
||||
},
|
||||
isConsistencyChange(row, ite, value, showMessage) {
|
||||
@@ -492,39 +691,50 @@ export default {
|
||||
},
|
||||
batchSetCriterionJoinJoinAnalysis(row, ite, value, showMessage) {
|
||||
let params
|
||||
if (row.DoctorCriterionStatusList && row.DoctorCriterionStatusList.length > 0) {
|
||||
if (
|
||||
row.DoctorCriterionStatusList &&
|
||||
row.DoctorCriterionStatusList.length > 0
|
||||
) {
|
||||
if (ite) {
|
||||
let item = row.CriterionCategoryList.find(v => v.TrialReadingCriterionId === ite.TrialReadingCriterionId)
|
||||
let item = row.CriterionCategoryList.find(
|
||||
(v) => v.TrialReadingCriterionId === ite.TrialReadingCriterionId
|
||||
)
|
||||
if (item) {
|
||||
params = [{
|
||||
Id: item.Id,
|
||||
EnrollId: item.EnrollId,
|
||||
TrialReadingCriterionId: item.TrialReadingCriterionId,
|
||||
IsJoinAnalysis: value
|
||||
}]
|
||||
params = [
|
||||
{
|
||||
Id: item.Id,
|
||||
EnrollId: item.EnrollId,
|
||||
TrialReadingCriterionId: item.TrialReadingCriterionId,
|
||||
IsJoinAnalysis: value,
|
||||
},
|
||||
]
|
||||
}
|
||||
} else {
|
||||
params = row.DoctorCriterionStatusList.map(v => {
|
||||
params = row.DoctorCriterionStatusList.map((v) => {
|
||||
return {
|
||||
Id: v.Id,
|
||||
EnrollId: v.EnrollId,
|
||||
TrialReadingCriterionId: v.TrialReadingCriterionId,
|
||||
IsJoinAnalysis: v.IsJoinAnalysis
|
||||
IsJoinAnalysis: v.IsJoinAnalysis,
|
||||
}
|
||||
})
|
||||
}
|
||||
} else {
|
||||
params = row.CriterionCategoryList.map(v => {
|
||||
params = row.CriterionCategoryList.map((v) => {
|
||||
return {
|
||||
EnrollId: v.EnrollId,
|
||||
TrialReadingCriterionId: v.TrialReadingCriterionId,
|
||||
IsJoinAnalysis: value
|
||||
IsJoinAnalysis: value,
|
||||
}
|
||||
})
|
||||
}
|
||||
batchSetCriterionJoinJoinAnalysis(params).then(res => {
|
||||
batchSetCriterionJoinJoinAnalysis(params).then((res) => {
|
||||
if (showMessage) {
|
||||
this.$message.success(this.$t('trials:enrolledReviews:message:batchSetCriterionJoinJoinAnalysis1'))
|
||||
this.$message.success(
|
||||
this.$t(
|
||||
'trials:enrolledReviews:message:batchSetCriterionJoinJoinAnalysis1'
|
||||
)
|
||||
)
|
||||
}
|
||||
this.initPage()
|
||||
})
|
||||
@@ -532,17 +742,25 @@ export default {
|
||||
go(path) {
|
||||
window.open(path)
|
||||
},
|
||||
beforeUpload() {
|
||||
beforeUpload(file) {
|
||||
if (this.fileList.length > 0) {
|
||||
// 只允许上传1个文件
|
||||
this.$alert(this.$t('trials:enrolledReviews:message:uploadSowWaring1'))
|
||||
return
|
||||
return false
|
||||
}
|
||||
const fileName = file.name
|
||||
var extendName = fileName
|
||||
.substring(fileName.lastIndexOf('.'))
|
||||
.toLocaleLowerCase()
|
||||
if (extendName !== '.pdf') {
|
||||
this.$alert(this.$t('trials:enrolledReviews:message:uploadSowWaring2'))
|
||||
return false
|
||||
}
|
||||
},
|
||||
handleSave() {
|
||||
this.$refs['DictionaryTypeConfigForm'].validate(valid => {
|
||||
this.$refs['DictionaryTypeConfigForm'].validate((valid) => {
|
||||
if (!valid) return
|
||||
addDoctorCriterionFile(this.form).then(res => {
|
||||
addDoctorCriterionFile(this.form).then((res) => {
|
||||
// 保存成功
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.initPage()
|
||||
@@ -560,11 +778,19 @@ export default {
|
||||
this.btnLoading = true
|
||||
var fileName = param.file.name
|
||||
let file = await this.fileToBlob(param.file)
|
||||
let res = await this.OSSclient.put(`/SystemData/reviewer/${this.form.FileType === 0 ? '既往阅片情况声明' : '入项资格确认书'}/${this.rowData.DoctorId}/${fileName}`, file)
|
||||
let res = await this.OSSclient.put(
|
||||
`/SystemData/reviewer/${
|
||||
this.form.FileType === 0 ? '既往阅片情况声明' : '入项资格确认书'
|
||||
}/${this.rowData.DoctorId}/${fileName}`,
|
||||
file
|
||||
)
|
||||
this.form.FileName = param.file.name
|
||||
this.form.FilePath = this.$getObjectName(res.url)
|
||||
param.file.url = this.$getObjectName(res.url)
|
||||
this.$set(this.fileList, 0, { name: this.form.FileName, url: this.$getObjectName(res.url) })
|
||||
this.$set(this.fileList, 0, {
|
||||
name: this.form.FileName,
|
||||
url: this.$getObjectName(res.url),
|
||||
})
|
||||
this.btnLoading = false
|
||||
|
||||
// this.btnLoading = true
|
||||
@@ -587,7 +813,7 @@ export default {
|
||||
this.fileList = []
|
||||
},
|
||||
addCol(fileType, row, item) {
|
||||
this.rowData = {...row}
|
||||
this.rowData = { ...row }
|
||||
this.model_cfg.visible = true
|
||||
this.form = {
|
||||
Remark: null,
|
||||
@@ -599,10 +825,13 @@ export default {
|
||||
DoctorId: row.DoctorId,
|
||||
CriterionType: item.CriterionType,
|
||||
CriterionName: item.TrialReadingCriterionName,
|
||||
TrialReadingCriterionId: item.TrialReadingCriterionId
|
||||
TrialReadingCriterionId: item.TrialReadingCriterionId,
|
||||
}
|
||||
this.handleRemoveFile2()
|
||||
this.model_cfg.title = fileType === 0 ? this.$t('trials:enrolledReviews:message:SOW') : this.$t('trials:enrolledReviews:message:EQC')// '既往阅片情况说明' : '入项资格确认书'
|
||||
this.model_cfg.title =
|
||||
fileType === 0
|
||||
? this.$t('trials:enrolledReviews:message:SOW')
|
||||
: this.$t('trials:enrolledReviews:message:EQC') // '既往阅片情况说明' : '入项资格确认书'
|
||||
},
|
||||
windowOpen(url) {
|
||||
console.log(url)
|
||||
@@ -614,14 +843,16 @@ export default {
|
||||
updateTrialReviewerState({
|
||||
TrialId: this.listQuery.TrialId,
|
||||
IsEnable: v,
|
||||
EnrollId: row.EnrollId
|
||||
}).then(res => {
|
||||
// '保存成功'
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.listLoading = false
|
||||
}).catch(() => {
|
||||
this.listLoading = false
|
||||
EnrollId: row.EnrollId,
|
||||
})
|
||||
.then((res) => {
|
||||
// '保存成功'
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
this.listLoading = false
|
||||
})
|
||||
.catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
handleUpdateReadingCategory() {
|
||||
this.readingCategory_model.btnLoading = true
|
||||
@@ -630,19 +861,20 @@ export default {
|
||||
TrialId: this.$route.query.trialId,
|
||||
EnrollId: this.currentRow.EnrollId,
|
||||
ReadingCategorys: Object.assign([], this.ReadingCategorys),
|
||||
TrialReadingCriterionId: this.TrialReadingCriterionId
|
||||
TrialReadingCriterionId: this.TrialReadingCriterionId,
|
||||
}
|
||||
if (~this.ReadingCategorys.indexOf(1)) {
|
||||
params.ReadingCategorys.push(2)
|
||||
}
|
||||
setEnrollReadingCategory(params)
|
||||
.then(res => {
|
||||
.then((res) => {
|
||||
this.readingCategory_model.visible = false
|
||||
this.readingCategory_model.btnLoading = false
|
||||
this.readingCategory_model.showClose = true
|
||||
this.initPage()
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}).catch(_ => {
|
||||
})
|
||||
.catch((_) => {
|
||||
this.readingCategory_model.btnLoading = false
|
||||
this.readingCategory_model.showClose = true
|
||||
})
|
||||
@@ -653,16 +885,20 @@ export default {
|
||||
this.currentRow = row
|
||||
this.TrialReadingCriterionId = TrialReadingCriterionId
|
||||
this.readingCategory_model.visible = true
|
||||
var o = row.CriterionCategoryList.find(v => {
|
||||
var o = row.CriterionCategoryList.find((v) => {
|
||||
return v.TrialReadingCriterionId === TrialReadingCriterionId
|
||||
}) ? row.CriterionCategoryList.find(v => {
|
||||
return v.TrialReadingCriterionId === TrialReadingCriterionId
|
||||
}) : null
|
||||
var i = row.TrialReadingCriterionList.find(v => {
|
||||
})
|
||||
? row.CriterionCategoryList.find((v) => {
|
||||
return v.TrialReadingCriterionId === TrialReadingCriterionId
|
||||
})
|
||||
: null
|
||||
var i = row.TrialReadingCriterionList.find((v) => {
|
||||
return v.TrialReadingCriterionId === TrialReadingCriterionId
|
||||
}) ? row.TrialReadingCriterionList.find(v => {
|
||||
return v.TrialReadingCriterionId === TrialReadingCriterionId
|
||||
}) : null
|
||||
})
|
||||
? row.TrialReadingCriterionList.find((v) => {
|
||||
return v.TrialReadingCriterionId === TrialReadingCriterionId
|
||||
})
|
||||
: null
|
||||
if (i) {
|
||||
this.IsArbitrationReading = i.IsArbitrationReading
|
||||
this.IsOncologyReading = i.IsOncologyReading
|
||||
@@ -678,48 +914,56 @@ export default {
|
||||
// 获取入组医生列表数据
|
||||
initPage() {
|
||||
this.listLoading = true
|
||||
getTrialEnrollmentWorkloadStats(this.listQuery).then((res) => {
|
||||
this.listLoading = false
|
||||
let resArray = res.Result.CurrentPageData
|
||||
try {
|
||||
resArray.forEach(v => {
|
||||
if (v.DoctorCriterionStatusList && v.DoctorCriterionStatusList.length === 0) {
|
||||
this.isConsistencyChange(v, null,true, false)
|
||||
}
|
||||
v.CriterionCategoryList.forEach(v1 => {
|
||||
let o = v.DoctorCriterionStatusList.find(v2 => {
|
||||
return v2.TrialReadingCriterionId === v1.TrialReadingCriterionId
|
||||
})
|
||||
if (o) {
|
||||
this.$set(v1, 'Id', o.Id)
|
||||
this.$set(v1, 'IsJoinAnalysis', o.IsJoinAnalysis)
|
||||
getTrialEnrollmentWorkloadStats(this.listQuery)
|
||||
.then((res) => {
|
||||
this.listLoading = false
|
||||
let resArray = res.Result.CurrentPageData
|
||||
try {
|
||||
resArray.forEach((v) => {
|
||||
if (
|
||||
v.DoctorCriterionStatusList &&
|
||||
v.DoctorCriterionStatusList.length === 0
|
||||
) {
|
||||
this.isConsistencyChange(v, null, true, false)
|
||||
}
|
||||
v.CriterionCategoryList.forEach((v1) => {
|
||||
let o = v.DoctorCriterionStatusList.find((v2) => {
|
||||
return (
|
||||
v2.TrialReadingCriterionId === v1.TrialReadingCriterionId
|
||||
)
|
||||
})
|
||||
if (o) {
|
||||
this.$set(v1, 'Id', o.Id)
|
||||
this.$set(v1, 'IsJoinAnalysis', o.IsJoinAnalysis)
|
||||
}
|
||||
})
|
||||
v.DoctorCriterionStatusList.push({})
|
||||
})
|
||||
v.DoctorCriterionStatusList.push({})
|
||||
})
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
this.list = resArray
|
||||
if (this.list.length > 0) {
|
||||
this.TrialReadingCriterionList = this.list[0].TrialReadingCriterionList
|
||||
}
|
||||
this.total = res.Result.TotalCount
|
||||
this.$nextTick(() => {
|
||||
// myTable是表格的ref属性值
|
||||
if (this.$refs.myTable && this.$refs.myTable.doLayout) {
|
||||
this.$refs.myTable.doLayout()
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
this.list = resArray
|
||||
if (this.list.length > 0) {
|
||||
this.TrialReadingCriterionList =
|
||||
this.list[0].TrialReadingCriterionList
|
||||
}
|
||||
this.total = res.Result.TotalCount
|
||||
this.$nextTick(() => {
|
||||
// myTable是表格的ref属性值
|
||||
if (this.$refs.myTable && this.$refs.myTable.doLayout) {
|
||||
this.$refs.myTable.doLayout()
|
||||
}
|
||||
})
|
||||
})
|
||||
.catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
}).catch(() => {
|
||||
this.listLoading = false
|
||||
})
|
||||
},
|
||||
|
||||
// Enroll按钮回调
|
||||
handleEnroll() {
|
||||
this.$router.push({
|
||||
path: `/trials/trials-panel/enrolled-reviewers/enroll?trialId=${this.listQuery.TrialId}&trialCode=${this.trialId}`
|
||||
path: `/trials/trials-panel/enrolled-reviewers/enroll?trialId=${this.listQuery.TrialId}&trialCode=${this.trialId}`,
|
||||
})
|
||||
},
|
||||
|
||||
@@ -731,12 +975,16 @@ export default {
|
||||
|
||||
// 更新医生状态信息
|
||||
handleUpdateReviewerStatus() {
|
||||
this.$refs.updateStatusForm.validate(valid => {
|
||||
this.$refs.updateStatusForm.validate((valid) => {
|
||||
if (!valid) return
|
||||
this.reviewerStatus_model.btnLoading = true
|
||||
this.reviewerStatus_model.showClose = false
|
||||
enrollBackOrOut(this.listQuery.TrialId, this.currentRow.DoctorId, this.updateStatusForm.Status)
|
||||
.then(res => {
|
||||
enrollBackOrOut(
|
||||
this.listQuery.TrialId,
|
||||
this.currentRow.DoctorId,
|
||||
this.updateStatusForm.Status
|
||||
)
|
||||
.then((res) => {
|
||||
this.$nextTick(() => {
|
||||
this.$refs['updateStatusForm'].resetFields()
|
||||
})
|
||||
@@ -765,14 +1013,19 @@ export default {
|
||||
handleUpdateReadingType() {
|
||||
this.readingType_model.btnLoading = true
|
||||
this.readingType_model.showClose = false
|
||||
updateReviewerReadingType(this.listQuery.TrialId, this.currentRow.DoctorId, this.readingType)
|
||||
.then(res => {
|
||||
updateReviewerReadingType(
|
||||
this.listQuery.TrialId,
|
||||
this.currentRow.DoctorId,
|
||||
this.readingType
|
||||
)
|
||||
.then((res) => {
|
||||
this.readingType_model.visible = false
|
||||
this.readingType_model.btnLoading = false
|
||||
this.readingType_model.showClose = true
|
||||
this.initPage()
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}).catch(_ => {
|
||||
})
|
||||
.catch((_) => {
|
||||
this.readingType_model.btnLoading = false
|
||||
this.readingType_model.showClose = true
|
||||
})
|
||||
@@ -791,17 +1044,15 @@ export default {
|
||||
this.initPage()
|
||||
},
|
||||
|
||||
|
||||
|
||||
handleTipCloseOK() {
|
||||
zzSessionStorage.setItem(
|
||||
'ReviewerName',
|
||||
this.currentClickRowData.FirstName +
|
||||
' ' +
|
||||
this.currentClickRowData.LastName
|
||||
' ' +
|
||||
this.currentClickRowData.LastName
|
||||
)
|
||||
this.$router.push({
|
||||
path: `/trials/trials-panel/enrolled-reviewers/stats?doctorId=${this.currentClickRowData.DoctorId}&trialId=${this.listQuery.TrialId}&trialCode=${this.trialId}&doctorName=${this.currentClickRowData.LastName}/${this.currentClickRowData.FirstName}`
|
||||
path: `/trials/trials-panel/enrolled-reviewers/stats?doctorId=${this.currentClickRowData.DoctorId}&trialId=${this.listQuery.TrialId}&trialCode=${this.trialId}&doctorName=${this.currentClickRowData.LastName}/${this.currentClickRowData.FirstName}`,
|
||||
})
|
||||
},
|
||||
|
||||
@@ -827,18 +1078,18 @@ export default {
|
||||
}
|
||||
})
|
||||
return sums
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss">
|
||||
.enroll-list {
|
||||
height: 100%;
|
||||
.readingCategory_model{
|
||||
.base-modal-body{
|
||||
min-height: 150px;
|
||||
padding-bottom: 30px !important;
|
||||
}
|
||||
.enroll-list {
|
||||
height: 100%;
|
||||
.readingCategory_model {
|
||||
.base-modal-body {
|
||||
min-height: 150px;
|
||||
padding-bottom: 30px !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
||||
@@ -70,53 +70,21 @@
|
||||
width="150"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<div
|
||||
v-if="
|
||||
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i]
|
||||
.QuestionType === 1
|
||||
"
|
||||
>
|
||||
<span
|
||||
v-if="
|
||||
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i]
|
||||
.DictionaryCode
|
||||
"
|
||||
>{{
|
||||
$fd(
|
||||
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[
|
||||
i
|
||||
].DictionaryCode,
|
||||
parseInt(
|
||||
scope.row.VisitTaskInfoList[j.index]
|
||||
.JudgeQuestionList[i].Answer
|
||||
)
|
||||
)
|
||||
}}</span>
|
||||
<span v-else>{{
|
||||
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i]
|
||||
.Answer
|
||||
}}</span>
|
||||
<div v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].QuestionType === 1">
|
||||
<span v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].DictionaryCode">
|
||||
{{ $fd(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].DictionaryCode,parseInt(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer))
|
||||
}}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer }}
|
||||
</span>
|
||||
<span v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Unit && !isNaN(parseFloat(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer))">{{ $fd('ValueUnit', parseInt(scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Unit)) }}</span>
|
||||
</div>
|
||||
<div
|
||||
v-else-if="
|
||||
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i]
|
||||
.QuestionType === 2
|
||||
"
|
||||
>
|
||||
<div
|
||||
v-if="
|
||||
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i]
|
||||
.Answer
|
||||
"
|
||||
>
|
||||
<span>{{
|
||||
$fd(
|
||||
"YesOrNo",
|
||||
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[
|
||||
i
|
||||
].Answer
|
||||
)
|
||||
}}</span>
|
||||
<div v-else-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].QuestionType === 2">
|
||||
<div v-if="scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer">
|
||||
<span>
|
||||
{{ $fd("YesOrNo",scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer) }}
|
||||
</span>
|
||||
<!-- 查看详情 -->
|
||||
<el-button
|
||||
type="text"
|
||||
@@ -143,10 +111,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div v-else>
|
||||
{{
|
||||
scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i]
|
||||
.Answer
|
||||
}}
|
||||
{{ scope.row.VisitTaskInfoList[j.index].JudgeQuestionList[i].Answer }}
|
||||
</div>
|
||||
</template>
|
||||
</el-table-column>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
</div>
|
||||
<div class="right-wrapper">
|
||||
<div v-if="selected.type===1" class="right-content">
|
||||
<iframe :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${selected.filePath}?userName=${currentUser}`" width="100%" height="100%" frameborder="0" />
|
||||
<iframe :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${selected.filePath}?userName=${currentUser}&COMPANY=${COMPANY}`" width="100%" height="100%" frameborder="0" />
|
||||
</div>
|
||||
<div v-else-if="selected.type===2" class="right-content" style="padding: 10px">
|
||||
<clinicalDataQuestions
|
||||
@@ -216,7 +216,8 @@ export default {
|
||||
otherInfo: {},
|
||||
moment,
|
||||
loading: false,
|
||||
currentUser: zzSessionStorage.getItem('userName')
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
COMPANY:process.env.VUE_APP_COMPANY_NAME
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
@@ -1039,7 +1039,7 @@ export default {
|
||||
loadImageStack(dicomSeries) {
|
||||
return new Promise(resolve => {
|
||||
this.isCurrentTask = dicomSeries.isCurrentTask
|
||||
this.isBaseline = dicomSeries.isBaseline
|
||||
this.isBaseline = dicomSeries.isBaseLineTask
|
||||
this.readingTaskState = dicomSeries.readingTaskState
|
||||
if (this.isCurrentTask && this.readingTaskState < 2) {
|
||||
this.activeTool = 1
|
||||
@@ -1088,16 +1088,16 @@ export default {
|
||||
var frame = imageInfo.frame
|
||||
this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
|
||||
this.stack.instanceId = instanceId
|
||||
|
||||
const element = this.$refs.canvas
|
||||
cornerstone.enable(element)
|
||||
element.tabIndex = 0
|
||||
element.focus()
|
||||
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||
ToolStateManager.clearImageIdToolState(dicomSeries.imageIds)
|
||||
this.toggleClipPlay(false)
|
||||
this.toolState.viewportInvert = false
|
||||
this.toolState.dicomInfoVisible = false
|
||||
|
||||
const element = this.$refs.canvas
|
||||
cornerstone.enable(element)
|
||||
element.tabIndex = 0
|
||||
element.focus()
|
||||
var scope = this
|
||||
// var p = parseInt(new Date().getTime())
|
||||
// requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, p*100).then(image=>{
|
||||
@@ -1654,7 +1654,7 @@ export default {
|
||||
resetWwwc() {
|
||||
this.toolState.viewportInvert = false
|
||||
var viewport = cornerstone.getViewport(this.canvas)
|
||||
viewport.invert = false
|
||||
// viewport.invert = false
|
||||
var image = cornerstone.getImage(this.canvas)
|
||||
viewport.voi.windowWidth = image.windowWidth
|
||||
viewport.voi.windowCenter = image.windowCenter
|
||||
|
||||
@@ -352,7 +352,44 @@
|
||||
<div class="text">{{ $t('trials:reading:button:reset') }}</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
|
||||
<el-tooltip
|
||||
v-if="trialCriterion.ImageUploadEnum > 0 && currentReadingTaskState < 2"
|
||||
v-hasPermi="['role:ir']"
|
||||
class="item"
|
||||
effect="dark"
|
||||
:content="$t('trials:reading:button:upload')"
|
||||
placement="bottom"
|
||||
>
|
||||
<div class="tool-wrapper">
|
||||
<div class="icon" @click.prevent="openUploadImage('upload')">
|
||||
<i class="el-icon-upload2 svg-icon" />
|
||||
</div>
|
||||
<div class="text">{{ $t('trials:reading:button:upload') }}</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
v-if="trialCriterion.ImageDownloadEnum > 0"
|
||||
v-hasPermi="[
|
||||
'role:ir',
|
||||
'role:mim',
|
||||
'role:mc',
|
||||
'role:pm',
|
||||
'role:apm',
|
||||
'role:ea',
|
||||
'role:qa',
|
||||
]"
|
||||
class="item"
|
||||
effect="dark"
|
||||
:content="$t('trials:reading:button:download')"
|
||||
placement="bottom"
|
||||
>
|
||||
<div class="tool-wrapper">
|
||||
<div class="icon" @click.prevent="openUploadImage('download')">
|
||||
<i class="el-icon-download svg-icon" />
|
||||
</div>
|
||||
<div class="text">{{ $t('trials:reading:button:download') }}</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<div style="margin-left:auto;">
|
||||
<div style="padding:5px">
|
||||
<!-- 手册 -->
|
||||
@@ -397,49 +434,88 @@
|
||||
</div>
|
||||
</div>
|
||||
<div ref="form-container" class="form-container">
|
||||
<!-- 激活canvas测量数据 -->
|
||||
<div class="form-wrapper">
|
||||
<RecistBMQuestionList
|
||||
v-if="CriterionType === 17"
|
||||
ref="measurementList"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
/>
|
||||
<IRecistQuestionList
|
||||
v-else-if="CriterionType === 3"
|
||||
ref="measurementList"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
/>
|
||||
<PCWGQuestionList
|
||||
v-else-if="CriterionType === 10"
|
||||
ref="measurementList"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
/>
|
||||
<LuganoQuestionList
|
||||
v-else-if="CriterionType === 2"
|
||||
ref="measurementList"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
/>
|
||||
|
||||
<RecistBMQuestionList
|
||||
v-if="CriterionType === 17"
|
||||
ref="measurementList"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
/>
|
||||
<IRecistQuestionList
|
||||
v-else-if="CriterionType === 3"
|
||||
ref="measurementList"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
/>
|
||||
<PCWGQuestionList
|
||||
v-else-if="CriterionType === 10"
|
||||
ref="measurementList"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
/>
|
||||
<LuganoQuestionList
|
||||
v-else-if="CriterionType === 2"
|
||||
ref="measurementList"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
/>
|
||||
<RecistQuestionList
|
||||
v-else-if="CriterionType === 1"
|
||||
ref="measurementList"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
/>
|
||||
|
||||
<IVUSList
|
||||
v-else-if="CriterionType === 19"
|
||||
ref="measurementList"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
/>
|
||||
<OCTList
|
||||
v-else-if="CriterionType === 20"
|
||||
ref="measurementList"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
/>
|
||||
<h2 v-else style="color:#ddd">
|
||||
Developing...
|
||||
</h2>
|
||||
</div>
|
||||
<div v-if="iseCRFShowInDicomReading && currentReadingTaskState < 2" class="form-footer">
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="skipTask"
|
||||
>
|
||||
<!-- 跳过 -->
|
||||
{{ $t('trials:readingReport:button:skip') }}
|
||||
</el-button>
|
||||
<el-button
|
||||
type="primary"
|
||||
size="small"
|
||||
@click="submit"
|
||||
>
|
||||
<!-- 提交 -->
|
||||
{{ $t('common:button:submit') }}
|
||||
</el-button>
|
||||
</div>
|
||||
|
||||
<RecistQuestionList
|
||||
v-else-if="CriterionType !== 17"
|
||||
ref="measurementList"
|
||||
:question-form-change-state="questionFormChangeState"
|
||||
:question-form-change-num="questionFormChangeNum"
|
||||
:is-show="isShow"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -655,6 +731,37 @@
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
<upload-dicom-and-nonedicom
|
||||
v-if="uploadImageVisible"
|
||||
:subject-id="uploadSubjectId"
|
||||
:subject-code="uploadSubjectCode"
|
||||
:criterion="uploadTrialCriterion"
|
||||
:visible.sync="uploadImageVisible"
|
||||
:visit-task-id="taskId"
|
||||
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
|
||||
/>
|
||||
<download-dicom-and-nonedicom
|
||||
v-if="downloadImageVisible"
|
||||
:subject-id="uploadSubjectId"
|
||||
:subject-code="uploadSubjectCode"
|
||||
:criterion="uploadTrialCriterion"
|
||||
:task-id="taskId"
|
||||
:visible.sync="downloadImageVisible"
|
||||
/>
|
||||
<!-- 签名框 -->
|
||||
<el-dialog
|
||||
v-if="signVisible"
|
||||
:visible.sync="signVisible"
|
||||
:close-on-click-modal="false"
|
||||
width="600px"
|
||||
custom-class="base-dialog-wrapper"
|
||||
>
|
||||
<div slot="title">
|
||||
<span style="font-size:18px;">{{ $t('common:dialogTitle:sign') }}</span>
|
||||
<span style="font-size:12px;margin-left:5px;user-select: text !important;">{{ `(${$t('common:label:sign')}${ currentUser })` }}</span>
|
||||
</div>
|
||||
<SignForm ref="signForm" :sign-code-enum="signCode" @closeDialog="closeSignDialog" />
|
||||
</el-dialog>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
@@ -677,6 +784,8 @@ import RecistBMQuestionList from './RecistBM/QuestionList'
|
||||
import IRecistQuestionList from './IRecist/QuestionList'
|
||||
import PCWGQuestionList from './PCWG/QuestionList'
|
||||
import LuganoQuestionList from './Lugano/QuestionList'
|
||||
import IVUSList from './IVUS/QuestionList'
|
||||
import OCTList from './OCT/QuestionList'
|
||||
import CustomWwwcForm from './CustomWwwcForm'
|
||||
import Manuals from './Manuals'
|
||||
import Hotkeys from './Hotkeys'
|
||||
@@ -684,6 +793,14 @@ import WL from './WL'
|
||||
import Others from './Others'
|
||||
import DicomEvent from './DicomEvent'
|
||||
import html2canvas from 'html2canvas'
|
||||
import uploadDicomAndNonedicom from '@/components/uploadDicomAndNonedicom'
|
||||
import downloadDicomAndNonedicom from '@/components/downloadDicomAndNonedicom'
|
||||
import SignForm from '@/views/trials/components/newSignForm'
|
||||
import { getCriterionReadingInfo, verifyVisitTaskQuestions, submitDicomVisitTask } from '@/api/trials'
|
||||
import { setSkipReadingCache } from '@/api/reading'
|
||||
import { getAutoCutNextTask } from '@/api/user'
|
||||
import const_ from '@/const/sign-code'
|
||||
import { changeURLStatic } from '@/utils/history.js'
|
||||
export default {
|
||||
name: 'DicomViewer',
|
||||
components: {
|
||||
@@ -698,7 +815,13 @@ export default {
|
||||
PCWGQuestionList,
|
||||
RecistBMQuestionList,
|
||||
IRecistQuestionList,
|
||||
LuganoQuestionList },
|
||||
LuganoQuestionList,
|
||||
IVUSList,
|
||||
OCTList,
|
||||
'download-dicom-and-nonedicom': downloadDicomAndNonedicom,
|
||||
'upload-dicom-and-nonedicom': uploadDicomAndNonedicom,
|
||||
SignForm
|
||||
},
|
||||
props: {
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
@@ -724,6 +847,10 @@ export default {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
iseCRFShowInDicomReading: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
questionFormChangeState: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
@@ -839,7 +966,19 @@ export default {
|
||||
activeCanvasWC: null,
|
||||
activeTaskInfo: {},
|
||||
clipPlaying: false,
|
||||
fps: 15
|
||||
fps: 15,
|
||||
trialCriterion: {},
|
||||
// 上传
|
||||
downloadImageVisible: false,
|
||||
uploadImageVisible: false,
|
||||
uploadSubjectId: null,
|
||||
uploadSubjectCode: null,
|
||||
uploadTrialCriterion: {},
|
||||
uploadStatus: 'upload',
|
||||
taskId: '',
|
||||
signVisible: false,
|
||||
signCode: null,
|
||||
currentUser: zzSessionStorage.getItem('userName')
|
||||
}
|
||||
},
|
||||
|
||||
@@ -912,6 +1051,7 @@ export default {
|
||||
mounted() {
|
||||
this.getHotKeys()
|
||||
this.getWwcTpl()
|
||||
this.getTrialCriterion()
|
||||
// cornerstone.imageCache.setMaximumSizeBytes(0)
|
||||
|
||||
// const maximumSizeInBytes = 1024 * 1024 * 1024 // 1 GB
|
||||
@@ -923,6 +1063,10 @@ export default {
|
||||
this.measuredTools = [{ toolName: 'ArrowAnnotate', text: this.$t('trials:reading:button:arrowAnnotate'), icon: 'arrow', isDisabled: false, disabledReason: '' }, { toolName: 'RectangleRoi', text: this.$t('trials:reading:button:rectangle'), icon: 'rectangle', isDisabled: false, disabledReason: '' }]
|
||||
} else if (this.CriterionType === 17) {
|
||||
this.measuredTools = [{ toolName: 'Length', text: this.$t('trials:reading:button:length'), icon: 'length', isDisabled: false, disabledReason: '' }, { toolName: 'RectangleRoi', text: this.$t('trials:reading:button:rectangle'), icon: 'rectangle', isDisabled: false, disabledReason: '' }, { toolName: 'ArrowAnnotate', text: this.$t('trials:reading:button:arrowAnnotate'), icon: 'arrow', isDisabled: false, disabledReason: '' }]
|
||||
} else if (this.CriterionType === 19) {
|
||||
this.measuredTools = []
|
||||
} else if (this.CriterionType === 20) {
|
||||
this.measuredTools = []
|
||||
}
|
||||
this.rotateList[0] = '1'
|
||||
this.colorList[0] = ''
|
||||
@@ -1062,6 +1206,27 @@ export default {
|
||||
})
|
||||
},
|
||||
methods: {
|
||||
getTrialCriterion() {
|
||||
getCriterionReadingInfo({
|
||||
TrialId: this.trialId || this.$route.query.trialId,
|
||||
TrialReadingCriterionId: this.trialReadingCriterionId || this.$route.query.TrialReadingCriterionId
|
||||
})
|
||||
.then((res) => {
|
||||
this.trialCriterion = res.Result
|
||||
})
|
||||
.catch(() => {})
|
||||
},
|
||||
openUploadImage(status) {
|
||||
const idx = this.visitTaskList.findIndex(i => i.IsCurrentTask)
|
||||
if (idx > -1) {
|
||||
this.taskId = this.visitTaskList[idx].VisitTaskId
|
||||
}
|
||||
this.uploadSubjectCode = this.$route.query.subjectCode||localStorage.getItem("subjectCode")
|
||||
this.uploadSubjectId = this.$route.query.subjectId||localStorage.getItem("subjectId")
|
||||
this.uploadTrialCriterion = this.trialCriterion
|
||||
this.uploadStatus = status
|
||||
this[`${status}ImageVisible`] = true
|
||||
},
|
||||
async getWwcTpl() {
|
||||
// const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
@@ -2070,17 +2235,119 @@ export default {
|
||||
this.isFullscreen = false
|
||||
this.manualsDialog.visible = true
|
||||
},
|
||||
async skipTask() {
|
||||
// 是否确认跳过?
|
||||
const confirm = await this.$confirm(
|
||||
this.$t('trials:readingReport:message:skipConfirm'),
|
||||
{
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
// const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
const idx = this.visitTaskList.findIndex(i => i.IsCurrentTask)
|
||||
if (idx > -1) {
|
||||
var visitTaskId = this.visitTaskList[idx].VisitTaskId
|
||||
const res = await setSkipReadingCache({ visitTaskId: visitTaskId })
|
||||
if (res.IsSuccess) {
|
||||
window.location.reload()
|
||||
}
|
||||
}
|
||||
// loading.close()
|
||||
} catch (e) {
|
||||
// loading.close()
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
async submit() {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
const idx = this.visitTaskList.findIndex(i => i.IsCurrentTask)
|
||||
if (idx > -1) {
|
||||
var visitTaskId = this.visitTaskList[idx].VisitTaskId
|
||||
this.taskId = visitTaskId
|
||||
await verifyVisitTaskQuestions({ visitTaskId: visitTaskId })
|
||||
const { ImageAssessmentReportConfirmation } = const_.processSignature
|
||||
this.signCode = ImageAssessmentReportConfirmation
|
||||
this.signVisible = true
|
||||
}
|
||||
loading.close()
|
||||
} catch (e) {
|
||||
loading.close()
|
||||
}
|
||||
},
|
||||
// 关闭签名框
|
||||
closeSignDialog(isSign, signInfo) {
|
||||
if (isSign) {
|
||||
this.signConfirm(signInfo)
|
||||
} else {
|
||||
this.signVisible = false
|
||||
}
|
||||
},
|
||||
// 签名并确认
|
||||
async signConfirm(signInfo) {
|
||||
this.loading = true
|
||||
try {
|
||||
var params = {
|
||||
data: {
|
||||
visitTaskId: this.taskId
|
||||
},
|
||||
signInfo: signInfo
|
||||
}
|
||||
const res = await submitDicomVisitTask(params)
|
||||
if (res.IsSuccess) {
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
if (this.$refs['signForm']) {
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
}
|
||||
|
||||
this.signVisible = false
|
||||
|
||||
// 设置当前任务阅片状态为已读
|
||||
this.readingTaskState = 2
|
||||
await store.dispatch('reading/setVisitTaskReadingTaskState', { visitTaskId: this.visitTaskId, readingTaskState: 2 })
|
||||
await store.dispatch('reading/setCurrentReadingTaskState', 2)
|
||||
const res = await getAutoCutNextTask()
|
||||
var isAutoTask = res.Result.AutoCutNextTask
|
||||
if (isAutoTask) {
|
||||
window.location.reload()
|
||||
} else {
|
||||
// '当前阅片任务已完成,是否进入下一个阅片任务?'
|
||||
this.$confirm(this.$t('trials:readingReport:message:msg4'), {
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
})
|
||||
.then(() => {
|
||||
window.location.reload()
|
||||
})
|
||||
.catch(action => {
|
||||
changeURLStatic('visitTaskId', this.visitTaskId)
|
||||
})
|
||||
}
|
||||
|
||||
window.opener.postMessage('refreshTaskList', window.location)
|
||||
}
|
||||
this.loading = false
|
||||
} catch (e) {
|
||||
this.loading = false
|
||||
if (this.$refs['signForm'] && this.$refs['signForm'].btnLoading) {
|
||||
this.$refs['signForm'].btnLoading = false
|
||||
}
|
||||
}
|
||||
},
|
||||
handleFusion() {
|
||||
// https 或者 本地开发环境才是安全上下文
|
||||
if (!window.isSecureContext) {
|
||||
this.$alert(this.$t('components:uploadvideo:message:xf3'))
|
||||
return
|
||||
}
|
||||
// 顶部文档是否开启跨源隔离
|
||||
if (!window.crossOriginIsolated) {
|
||||
this.$alert(this.$t('components:uploadvideo:message:xf4'))
|
||||
return
|
||||
}
|
||||
// if (!window.isSecureContext) {
|
||||
// this.$alert(this.$t('components:uploadvideo:message:xf3'))
|
||||
// return
|
||||
// }
|
||||
// // 顶部文档是否开启跨源隔离
|
||||
// if (!window.crossOriginIsolated) {
|
||||
// this.$alert(this.$t('components:uploadvideo:message:xf4'))
|
||||
// return
|
||||
// }
|
||||
if (this.imageQualityIssues && parseInt(this.imageQualityIssues) === 6) {
|
||||
this.$alert(this.$t('trials:lugano:message:fusionWarn'))
|
||||
return
|
||||
@@ -2400,9 +2667,22 @@ export default {
|
||||
.form-container{
|
||||
// box-sizing: border-box;
|
||||
width: 350px;
|
||||
height: 100%;
|
||||
// height: 100vh;
|
||||
border: 1px solid #727272;
|
||||
// overflow-y: auto;
|
||||
// position: relative;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
|
||||
}
|
||||
.form-wrapper{
|
||||
flex-grow: 1;
|
||||
height: 0;
|
||||
overflow: hidden;
|
||||
}
|
||||
.form-footer{
|
||||
background: #000;
|
||||
padding: 10px 0;
|
||||
text-align: center;
|
||||
}
|
||||
.viewer-container{
|
||||
box-sizing: border-box;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="measurement-wrapper" :style="{'height':height+10+'px'}">
|
||||
<div class="measurement-wrapper">
|
||||
|
||||
<div class="container" :style="{'height':height+'px'}">
|
||||
<div class="container">
|
||||
<div class="basic-info">
|
||||
<h3 v-if="isReadingShowSubjectInfo">
|
||||
<span v-if="subjectCode">{{ subjectCode }} </span>
|
||||
@@ -203,7 +203,6 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
height: window.innerHeight - 140,
|
||||
questions: [],
|
||||
activeName: '',
|
||||
activeItem: {
|
||||
@@ -269,8 +268,6 @@ export default {
|
||||
DicomEvent.$on('split', measureData => {
|
||||
this.handleSplit(measureData.RowId, measureData.QuestionId)
|
||||
})
|
||||
|
||||
window.addEventListener('resize', this.setHeight)
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('setCollapseActive')
|
||||
@@ -457,9 +454,6 @@ export default {
|
||||
} catch (e) { console.log(e) }
|
||||
})
|
||||
},
|
||||
setHeight() {
|
||||
this.height = window.innerHeight - 140
|
||||
},
|
||||
getQuestionAnswer(questions, questionMark, answers) {
|
||||
var idx = questions.findIndex(i => i.QuestionMark === questionMark)
|
||||
if (idx > -1) {
|
||||
@@ -1183,6 +1177,7 @@ export default {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.measurement-wrapper{
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
// overflow: hidden;
|
||||
|
||||
|
||||
@@ -0,0 +1,874 @@
|
||||
<template>
|
||||
<div class="measurement-wrapper">
|
||||
|
||||
<div class="container">
|
||||
<div class="basic-info">
|
||||
<h3 v-if="isReadingShowSubjectInfo">
|
||||
<span v-if="subjectCode">{{ subjectCode }} </span>
|
||||
<span style="margin-left:5px;">{{ taskBlindName }}</span>
|
||||
</h3>
|
||||
<div v-if="readingTaskState < 2">
|
||||
<el-tooltip class="item" effect="dark" :content="$t('trials:dicomReading:message:confirmReset')" placement="bottom">
|
||||
<i
|
||||
class="el-icon-refresh-left"
|
||||
@click="resetMeasuredData"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 影像质量问题 -->
|
||||
<div class="lesions">
|
||||
<Questions
|
||||
ref="ecrf"
|
||||
:question-form-change-state="true"
|
||||
:question-form-change-num="0"
|
||||
:is-qulity-issues="false"
|
||||
:group-classify="1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 测量问题 -->
|
||||
<template v-if="questions.length > 0">
|
||||
<div v-for="(qs,index) in questions" :key="index" v-loading="loading" class="lesions lesions_wrapper" style="margin-bottom: 10px">
|
||||
<h4 v-if="qs.Type === 'group'" style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ language==='en'?qs.GroupEnName:qs.GroupName }}
|
||||
</h4>
|
||||
<div class="lesion_list">
|
||||
<el-form
|
||||
v-if="questions.length > 0"
|
||||
:ref="`questions${index}`"
|
||||
size="small"
|
||||
:model="questionForm"
|
||||
>
|
||||
<div class="table-wrapper">
|
||||
<div v-for="item in qs.Childrens" :key="item.Id">
|
||||
<div v-if="item.Type === 'basicTable'" class="flex-row" style="margin:3px 0;">
|
||||
<div class="title">{{ item.QuestionName }}</div>
|
||||
<div v-if="item.LesionType === 102 && readingTaskState < 2">
|
||||
<div class="add-icon" @click.prevent="downloadTpl">
|
||||
<i class="el-icon-download" />
|
||||
</div>
|
||||
<div class="add-icon" style="margin: 0 5px;" @click.prevent="uploadTpl(item.LesionType)">
|
||||
<i class="el-icon-upload2" />
|
||||
</div>
|
||||
<div class="add-icon" @click.prevent="handleAddOrEdit('add',item)">
|
||||
<i class="el-icon-plus" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<el-table
|
||||
v-if="item.Type === 'basicTable' && item.TableQuestions"
|
||||
:ref="item.Id"
|
||||
:data="item.TableQuestions.Answers"
|
||||
>
|
||||
<!-- <el-table-column :label="$t('CustomizeQuestionFormItem:label:OrderMark')" width="60px" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ getLesionName(item.OrderMark,scope.row.RowIndex) }}
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<!-- <el-table-column
|
||||
type="index"
|
||||
width="40px"
|
||||
/> -->
|
||||
<el-table-column
|
||||
v-for="q of item.TableQuestions.Questions"
|
||||
:key="q.Id"
|
||||
:prop="q.Id"
|
||||
:label="q.QuestionName"
|
||||
show-overflow-tooltip
|
||||
:render-header="renderHeader"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="q.Unit > 0 && !isNaN(parseFloat(scope.row[q.Id]))">
|
||||
{{ `${scope.row[q.Id]} ${$fd('ValueUnit', parseInt(q.Unit))}` }}
|
||||
</span>
|
||||
<span v-else-if="q.DictionaryCode">
|
||||
{{ `${$fd(q.DictionaryCode, parseInt(scope.row[q.Id]))}` }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ `${scope.row[q.Id]}` }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="readingTaskState < 2 && item.LesionType === 102"
|
||||
:label="$t('common:action:action')"
|
||||
width="90px"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="handleAddOrEdit('edit',item, scope.$index)">
|
||||
{{ $t('common:button:edit') }}
|
||||
</el-button>
|
||||
<el-button type="text" size="mini" @click="handleDelete(item, scope.$index)">
|
||||
{{ $t('common:button:delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<template v-else>
|
||||
<!-- 数值 -->
|
||||
<el-form-item
|
||||
v-if="item.ShowQuestion!==2"
|
||||
:key="item.Id"
|
||||
:label="`${item.QuestionName}`"
|
||||
:prop="item.Id"
|
||||
:rules="[
|
||||
{ required: (item.IsRequired === 0 || (item.IsRequired ===1 && item.RelevanceId && (item.RelevanceValue.includes(questionForm[item.RelevanceId])))) && item.Type!=='group' && item.Type!=='summary',
|
||||
message:['radio', 'select', 'checkbox'].includes(item.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur','change']},
|
||||
]"
|
||||
>
|
||||
<!-- 数值类型 -->
|
||||
<template v-if="item.Type==='textarea'">
|
||||
<el-input
|
||||
v-model="questionForm[qs.Id]"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:disabled="!isCurrentTask || readingTaskState>=2"
|
||||
@change="((val)=>{formItemChange(val, qs)})"
|
||||
/>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</div>
|
||||
<div
|
||||
v-if="isCurrentTask && readingTaskState<2 && qs.GroupClassify === 5"
|
||||
class="base-dialog-footer"
|
||||
style="text-align:right;margin-top:10px;"
|
||||
>
|
||||
<!-- 保存 -->
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
:disabled="!formChanged"
|
||||
@click="handleSave(index)"
|
||||
>
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 计算值 -->
|
||||
<Questions
|
||||
ref="ecrf2"
|
||||
:question-form-change-state="true"
|
||||
:question-form-change-num="0"
|
||||
:is-qulity-issues="false"
|
||||
:group-classify="4"
|
||||
style="margin-top:20px"
|
||||
/>
|
||||
|
||||
<!-- 评估结果 -->
|
||||
<Questions
|
||||
ref="ecrf3"
|
||||
:question-form-change-state="true"
|
||||
:question-form-change-num="0"
|
||||
:is-qulity-issues="false"
|
||||
:group-classify="5"
|
||||
/>
|
||||
<!-- 新增、编辑弹窗 -->
|
||||
<el-dialog
|
||||
v-if="addOrEdit.visible"
|
||||
:visible.sync="addOrEdit.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="addOrEdit.title"
|
||||
width="500px"
|
||||
>
|
||||
<el-form
|
||||
ref="tableQsForm"
|
||||
v-loading="loading"
|
||||
:model="qsForm"
|
||||
size="small"
|
||||
>
|
||||
<QuestionTableFormItem
|
||||
v-for="item in qsList"
|
||||
:key="item.Id"
|
||||
:question="item"
|
||||
:question-form="qsForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
@setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
/>
|
||||
<el-form-item style="text-align: right">
|
||||
<el-button
|
||||
size="small"
|
||||
@click="addOrEdit.visible = false"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button size="small" class="my_upload_btn" @click="saveFormData">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
<!-- 导入 -->
|
||||
<el-dialog
|
||||
v-if="upload.visible"
|
||||
:visible.sync="upload.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="upload.title"
|
||||
width="500px"
|
||||
>
|
||||
<UploadExcel
|
||||
:visit-task-id="visitTaskId"
|
||||
@close="uploadDlgClose"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { saveTaskQuestion, submitTableQuestion, deleteReadingRowAnswer } from '@/api/trials'
|
||||
import { resetReadingTask, getIVUSTemplate } from '@/api/reading'
|
||||
import DicomEvent from './../DicomEvent'
|
||||
import store from '@/store'
|
||||
import { mapGetters } from 'vuex'
|
||||
import Questions from './../Questions'
|
||||
import QuestionTableFormItem from './QuestionTableFormItem'
|
||||
import UploadExcel from './UploadExcel'
|
||||
export default {
|
||||
name: 'MeasurementList',
|
||||
components: {
|
||||
Questions,
|
||||
QuestionTableFormItem,
|
||||
UploadExcel
|
||||
},
|
||||
props: {
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
isReadingShowSubjectInfo: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
questionFormChangeState: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false
|
||||
}
|
||||
},
|
||||
questionFormChangeNum: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
questions: [],
|
||||
visitTaskId: '',
|
||||
isCurrentTask: false,
|
||||
loading: false,
|
||||
readingTaskState: 2,
|
||||
isBaseLineTask: false,
|
||||
taskBlindName: '',
|
||||
tableQuestions: [],
|
||||
CriterionType: null,
|
||||
subjectCode: '',
|
||||
questionForm: {},
|
||||
formChanged: false,
|
||||
digitPlaces: 2,
|
||||
addOrEdit: { visible: false, title: '' },
|
||||
upload: { visible: false, title: '' },
|
||||
qsList: [],
|
||||
answersList: [],
|
||||
qsForm: {},
|
||||
diffId: '',
|
||||
eemId: '',
|
||||
lumenId: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['visitTaskList', 'language', 'lastCanvasTaskId', 'currentReadingTaskState'])
|
||||
},
|
||||
watch: {
|
||||
lastCanvasTaskId: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if (val) {
|
||||
this.initList()
|
||||
}
|
||||
}
|
||||
},
|
||||
currentReadingTaskState: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if (val) {
|
||||
this.readingTaskState = val
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// this.subjectCode = this.$router.currentRoute.query.subjectCode
|
||||
this.subjectCode = localStorage.getItem('subjectCode')
|
||||
this.digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
window.addEventListener('message', this.receiveMsg)
|
||||
this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
|
||||
DicomEvent.$on('setCollapseActive', measureData => {
|
||||
this.setCollapseActive(measureData)
|
||||
console.log('setCollapseActive')
|
||||
})
|
||||
DicomEvent.$on('getAllUnSaveLesions', (callback) => {
|
||||
callback([])
|
||||
})
|
||||
DicomEvent.$on('refreshQuestions', _ => {
|
||||
this.refreshQuestions()
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('setCollapseActive')
|
||||
DicomEvent.$off('getUnSaveTarget')
|
||||
DicomEvent.$off('refreshQuestions')
|
||||
},
|
||||
methods: {
|
||||
async initList() {
|
||||
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.lastCanvasTaskId)
|
||||
if (i > -1) {
|
||||
this.visitTaskId = this.visitTaskList[i].VisitTaskId
|
||||
this.taskBlindName = this.visitTaskList[i].TaskBlindName
|
||||
this.readingTaskState = this.visitTaskList[i].ReadingTaskState
|
||||
this.isBaseLineTask = this.visitTaskList[i].IsBaseLineTask
|
||||
this.isCurrentTask = this.visitTaskList[i].IsCurrentTask
|
||||
if (!this.visitTaskList[i].IsInit) {
|
||||
var loading = this.$loading({ fullscreen: true })
|
||||
var triald = this.trialId = this.$router.currentRoute.query.trialId
|
||||
if (!this.visitTaskList[i].studyListInit) {
|
||||
await store.dispatch('reading/getStudyInfo', { trialId: triald, subjectVisitId: this.visitTaskList[i].VisitId, visitTaskId: this.visitTaskList[i].VisitTaskId, taskBlindName: this.visitTaskList[i].TaskBlindName })
|
||||
}
|
||||
if (!this.visitTaskList[i].readingQuestionsInit) {
|
||||
await store.dispatch('reading/getReadingQuestionAndAnswer', { trialId: triald, visitTaskId: this.visitTaskList[i].VisitTaskId })
|
||||
}
|
||||
if (!this.visitTaskList[i].questionsInit) {
|
||||
await store.dispatch('reading/getDicomReadingQuestionAnswer', { trialId: triald, visitTaskId: this.visitTaskList[i].VisitTaskId })
|
||||
}
|
||||
|
||||
await store.dispatch('reading/setStatus', { visitTaskId: this.visitTaskList[i].VisitTaskId })
|
||||
loading.close()
|
||||
}
|
||||
this.questions = this.visitTaskList[i].ReadingQuestions
|
||||
this.setQuestionForm(this.questions)
|
||||
this.$nextTick(() => {
|
||||
this.$refs['ecrf'].getQuestions(this.visitTaskId)
|
||||
this.$refs['ecrf2'].getQuestions(this.visitTaskId)
|
||||
this.$refs['ecrf3'].getQuestions(this.visitTaskId)
|
||||
})
|
||||
}
|
||||
},
|
||||
setQuestionForm(questions) {
|
||||
const type = ['number', 'radio', 'select', 'input', 'textarea', 'calculation']
|
||||
questions.forEach(item => {
|
||||
if (type.includes(item.Type)) {
|
||||
const answer = item.Type === 'number' || item.Type === 'calculation' ? isNaN(parseFloat(item.Answer)) ? null : parseFloat(item.Answer) : item.Answer
|
||||
this.$set(this.questionForm, item.Id, answer)
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.setQuestionForm(item.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
async resetQuestions(obj) {
|
||||
this.setQuestions(this.questions, obj)
|
||||
await store.dispatch('reading/setReadingQuestionAndAnswer', { questions: this.questions, visitTaskId: this.visitTaskId })
|
||||
|
||||
this.getTableQuestions()
|
||||
},
|
||||
setQuestions(questions, obj) {
|
||||
questions.forEach(item => {
|
||||
if ((item.Type === 'table' || item.Type === 'basicTable') && item.Id === obj.questionId) {
|
||||
var idx = item.TableQuestions.Answers.findIndex(i => i.RowIndex === obj.rowIndex)
|
||||
item.TableQuestions.Answers[idx].saveTypeEnum = obj.saveTypeEnum
|
||||
item.TableQuestions.Answers[idx].area1 = obj.area1
|
||||
item.TableQuestions.Answers[idx].area2 = obj.area2
|
||||
item.TableQuestions.Answers[idx].diff = obj.diff
|
||||
for (const i in obj.anwsers) {
|
||||
item.TableQuestions.Answers[idx][i] = String(obj.anwsers[i])
|
||||
}
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.setQuestions(item.Childrens, obj)
|
||||
}
|
||||
})
|
||||
},
|
||||
getQuestions(questions) {
|
||||
questions.forEach(item => {
|
||||
if ((item.Type === 'table' || item.Type === 'basicTable') && item.TableQuestions && item.TableQuestions.Answers.length > 0) {
|
||||
item.TableQuestions.Answers.forEach(answerObj => {
|
||||
if (answerObj.RowId) {
|
||||
var diffVal = this.getQuestionAnswer(item.TableQuestions.Questions, 1003, answerObj)
|
||||
this.$set(answerObj, 'saveTypeEnum', isNaN(parseFloat(diffVal)) ? 1 : 2)
|
||||
} else {
|
||||
this.$set(answerObj, 'saveTypeEnum', 0)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.getQuestions(item.Childrens)
|
||||
}
|
||||
})
|
||||
return questions
|
||||
},
|
||||
getReadingQuestionAndAnswer() {
|
||||
return new Promise(async resolve => {
|
||||
try {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
await store.dispatch('reading/refreshReadingQuestionAndAnswer', { trialId: this.$router.currentRoute.query.trialId, visitTaskId: this.visitTaskId }).then(() => {
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
if (idx > -1) {
|
||||
if (this.visitTaskList[idx].ReadingQuestions.length > 0) {
|
||||
this.questions = this.visitTaskList[idx].ReadingQuestions
|
||||
this.setQuestionForm(this.questions)
|
||||
}
|
||||
this.readingTaskState = this.visitTaskList[idx].ReadingTaskState
|
||||
this.isBaseLineTask = this.visitTaskList[idx].IsBaseLineTask
|
||||
this.isCurrentTask = this.visitTaskList[idx].IsCurrentTask
|
||||
}
|
||||
})
|
||||
loading.close()
|
||||
resolve()
|
||||
} catch (e) { console.log(e) }
|
||||
})
|
||||
},
|
||||
getQuestionAnswer(questions, questionMark, answers) {
|
||||
var idx = questions.findIndex(i => i.QuestionMark === questionMark)
|
||||
if (idx > -1) {
|
||||
var questionId = questions[idx].Id
|
||||
return answers[questionId]
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
isCanActiveTool(toolName) {
|
||||
return { isCanActiveTool: true, reason: '' }
|
||||
},
|
||||
getMaxRowIndex(answerList) {
|
||||
if (answerList.length > 0) {
|
||||
var arr = []
|
||||
answerList.forEach(item => {
|
||||
var rowIndex = item.RowIndex
|
||||
arr.push(parseInt(rowIndex))
|
||||
})
|
||||
var max = Math.max.apply(null, arr)
|
||||
return max
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
getLesionName(orderMark, rowIndex) {
|
||||
var lessionName = ''
|
||||
var rowIndexArr = rowIndex.split('.')
|
||||
var x = parseInt(rowIndexArr[0])
|
||||
var y = parseInt(rowIndexArr[1])
|
||||
if (y > 0) {
|
||||
y = String.fromCharCode(parseInt(rowIndexArr[1]) - 1 + 65 + 32)
|
||||
lessionName = `${orderMark}${String(x).padStart(2, '0')}${y}`
|
||||
} else {
|
||||
lessionName = `${orderMark}${String(x).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
return lessionName
|
||||
},
|
||||
modifyMeasuredData(measureObj) {
|
||||
},
|
||||
// 设置测量数据
|
||||
setMeasuredData(measureData) {
|
||||
|
||||
},
|
||||
formItemChange() {
|
||||
this.formChanged = true
|
||||
},
|
||||
limitBlur(qId, valueType) {
|
||||
const value = this.questionForm[qId]
|
||||
if (isNaN(parseInt(value))) {
|
||||
this.$set(this.questionForm, qId, '')
|
||||
} else {
|
||||
if (valueType === 0) {
|
||||
this.$set(this.questionForm, qId, parseInt(value))
|
||||
} else if (valueType === 3) {
|
||||
this.$set(this.questionForm, qId, parseFloat(value))
|
||||
} else {
|
||||
this.$set(this.questionForm, qId, this.numberToFixed(value))
|
||||
}
|
||||
}
|
||||
},
|
||||
numberToFixed(v) {
|
||||
if (this.digitPlaces > -1) {
|
||||
return isNaN(parseFloat(v)) ? null : `${parseFloat(v).toFixed(this.digitPlaces)}`
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
},
|
||||
async handleSave(index) {
|
||||
const refName = `questions${index}`
|
||||
const valid = await this.$refs[refName][0].validate()
|
||||
if (!valid) return
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
var answers = []
|
||||
for (const k in this.questionForm) {
|
||||
answers.push({ id: k, answer: this.questionForm[k] })
|
||||
}
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
answers: answers
|
||||
}
|
||||
try {
|
||||
await saveTaskQuestion(8, params)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
loading.close()
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
this.refreshQuestions()
|
||||
this.formChanged = false
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
loading.close()
|
||||
}
|
||||
},
|
||||
getECRFQuestions(obj) {
|
||||
this.$refs['ecrf'].getQuestions(obj.visitTaskId)
|
||||
this.$refs['ecrf2'].getQuestions(obj.visitTaskId)
|
||||
this.$refs['ecrf3'].getQuestions(obj.visitTaskId)
|
||||
},
|
||||
async resetMeasuredData() {
|
||||
const confirm = await this.$confirm(
|
||||
this.$t('trials:dicomReading:message:confirmReset1'),
|
||||
this.$t('trials:dicomReading:message:confirmReset2'),
|
||||
{
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
const res = await resetReadingTask({ visitTaskId: this.visitTaskId })
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
await this.getReadingQuestionAndAnswer(this.visitTaskId)
|
||||
const triald = this.$router.currentRoute.query.trialId
|
||||
await store.dispatch('reading/refreshDicomReadingQuestionAnswer', { trialId: triald, visitTaskId: this.visitTaskId })
|
||||
this.$refs['ecrf'].getQuestions(this.visitTaskId, true)
|
||||
this.$refs['ecrf2'].getQuestions(this.visitTaskId, true)
|
||||
this.$refs['ecrf3'].getQuestions(this.visitTaskId, true)
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
}
|
||||
loading.close()
|
||||
} catch (e) {
|
||||
loading.close()
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
async refreshQuestions() {
|
||||
const triald = this.$router.currentRoute.query.trialId
|
||||
await this.getReadingQuestionAndAnswer(this.visitTaskId)
|
||||
await store.dispatch('reading/refreshDicomReadingQuestionAnswer', { trialId: triald, visitTaskId: this.visitTaskId })
|
||||
this.$refs['ecrf'].getQuestions(this.visitTaskId, true)
|
||||
this.$refs['ecrf2'].getQuestions(this.visitTaskId, true)
|
||||
this.$refs['ecrf3'].getQuestions(this.visitTaskId, true)
|
||||
},
|
||||
receiveMsg(event) {
|
||||
},
|
||||
resetFormItemData(v) {
|
||||
this.qsForm[v] = null
|
||||
},
|
||||
setFormItemData(obj) {
|
||||
this.qsForm[obj.key] = obj.val
|
||||
if (obj.key === this.eemId || obj.key === this.lumenId) {
|
||||
const eem = this.qsForm[this.eemId]
|
||||
const lumen = this.qsForm[this.lumenId]
|
||||
if (isNaN(parseFloat(eem)) || isNaN(parseFloat(lumen))) {
|
||||
this.$set(this.qsForm, this.diffId, null)
|
||||
} else {
|
||||
const diff = parseFloat(eem) - parseFloat(lumen)
|
||||
this.$set(this.qsForm, this.diffId, this.numberToFixed(diff))
|
||||
}
|
||||
}
|
||||
},
|
||||
handleAddOrEdit(type, row, index) {
|
||||
this.addOrEdit.title = row.QuestionName
|
||||
this.qsList = row.TableQuestions.Questions
|
||||
this.qsForm = {}
|
||||
this.qsForm.questionId = row.Id
|
||||
this.qsForm.rowId = type === 'add' ? null : row.TableQuestions.Answers && row.TableQuestions.Answers[index] ? row.TableQuestions.Answers[index].RowId : null
|
||||
if (type === 'add') {
|
||||
var maxIndex = this.getMaxRowIndex(row.TableQuestions.Answers)
|
||||
this.qsForm.rowIndex = `${maxIndex + 1}.00`
|
||||
} else {
|
||||
this.qsForm.rowIndex = row.TableQuestions.Answers && row.TableQuestions.Answers[index] ? row.TableQuestions.Answers[index].RowIndex : null
|
||||
}
|
||||
row.TableQuestions.Questions.map(i => {
|
||||
if (i.QuestionMark === 1001) {
|
||||
this.eemId = i.Id
|
||||
}
|
||||
if (i.QuestionMark === 1002) {
|
||||
this.lumenId = i.Id
|
||||
}
|
||||
if (i.QuestionMark === 1003) {
|
||||
this.diffId = i.Id
|
||||
}
|
||||
let v = null
|
||||
if (type === 'add') {
|
||||
v = i.Type === 'number' ? undefined : null
|
||||
} else {
|
||||
v = row.TableQuestions.Answers && row.TableQuestions.Answers[index] ? row.TableQuestions.Answers[index][i.Id] : null
|
||||
}
|
||||
this.$set(this.qsForm, i.Id, v)
|
||||
})
|
||||
this.addOrEdit.visible = true
|
||||
},
|
||||
async saveFormData() {
|
||||
const valid = await this.$refs.tableQsForm.validate()
|
||||
if (!valid) return
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
var answers = []
|
||||
var reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/)
|
||||
for (const k in this.qsForm) {
|
||||
if (reg.test(k)) {
|
||||
if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
|
||||
answers.push({ tableQuestionId: k, answer: this.qsForm[k] })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var params = {
|
||||
questionId: this.qsForm.questionId,
|
||||
rowId: this.qsForm.rowId,
|
||||
rowIndex: this.qsForm.rowIndex,
|
||||
visitTaskId: this.visitTaskId,
|
||||
trialId: this.trialId,
|
||||
answerList: answers
|
||||
}
|
||||
const res = await submitTableQuestion(params)
|
||||
if (res.IsSuccess) {
|
||||
// this.refreshQuestions()
|
||||
await this.getReadingQuestionAndAnswer(this.visitTaskId)
|
||||
this.$refs['ecrf'].getQuestions(this.visitTaskId, true)
|
||||
this.$refs['ecrf2'].getQuestions(this.visitTaskId, true)
|
||||
this.$refs['ecrf3'].getQuestions(this.visitTaskId, true)
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
// 保存成功!
|
||||
this.addOrEdit.visible = false
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
loading.close()
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
loading.close()
|
||||
}
|
||||
},
|
||||
async handleDelete(row, index) {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
const confirm = await this.$confirm(
|
||||
this.$t('trials:reading:warnning:msg48'),
|
||||
{
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
if (row.TableQuestions.Answers[index].RowId) {
|
||||
var param = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
questionId: row.Id,
|
||||
rowId: row.TableQuestions.Answers[index].RowId
|
||||
}
|
||||
const res = await deleteReadingRowAnswer(param)
|
||||
if (res.IsSuccess) {
|
||||
await this.getReadingQuestionAndAnswer(this.visitTaskId)
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
// '删除成功!'
|
||||
this.$message.success(this.$t('common:message:deletedSuccessfully'))
|
||||
}
|
||||
}
|
||||
loading.close()
|
||||
} catch (e) {
|
||||
loading.close()
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
uploadTpl(lesionType) {
|
||||
this.upload.title = `导入( ${this.$fd('LesionType', lesionType)} )`
|
||||
this.upload.visible = true
|
||||
},
|
||||
async downloadTpl() {
|
||||
try {
|
||||
const params = {
|
||||
visitTaskId: this.visitTaskId
|
||||
}
|
||||
await getIVUSTemplate(params)
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
async uploadDlgClose() {
|
||||
await this.getReadingQuestionAndAnswer(this.visitTaskId)
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
this.upload.visible = false
|
||||
},
|
||||
renderHeader(h, { column, $index }) {
|
||||
const span = document.createElement('span')
|
||||
span.innerText = column.label
|
||||
document.body.appendChild(span)
|
||||
const w = span.getBoundingClientRect().width
|
||||
column.minWidth = w > 65 ? w + 10 : w > 60 ? w + 15 : w + 20
|
||||
document.body.removeChild(span)
|
||||
return h('span', column.label)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.measurement-wrapper{
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
.container{
|
||||
padding: 10px;
|
||||
.basic-info{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
h3{
|
||||
color: #ddd;
|
||||
padding: 5px 0px;
|
||||
margin: 0;
|
||||
}
|
||||
i{
|
||||
color: #fff;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
.title{
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #ddd;
|
||||
font-size: 15px;
|
||||
|
||||
}
|
||||
.add-icon{
|
||||
display: inline-block;
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #ddd;
|
||||
font-size: 15px;
|
||||
border: 1px solid #938b8b;
|
||||
margin-bottom: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.add-icon:hover{
|
||||
background-color: #607d8b;
|
||||
}
|
||||
|
||||
.flex-row{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
background-color: #424242;
|
||||
|
||||
}
|
||||
.lesion_list{
|
||||
position: relative;
|
||||
/deep/ .el-form-item__label{
|
||||
color: #c3c3c3;
|
||||
text-align: left;
|
||||
}
|
||||
/deep/ .el-input .el-input__inner{
|
||||
background-color: transparent;
|
||||
color: #ddd;
|
||||
border: 1px solid #5e5e5e;
|
||||
}
|
||||
/deep/ .el-textarea__inner{
|
||||
background-color: transparent;
|
||||
color: #ddd;
|
||||
border: 1px solid #5e5e5e;
|
||||
}
|
||||
/deep/ .el-form-item{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
/deep/ .el-form-item__content{
|
||||
flex: 1;
|
||||
}
|
||||
/deep/ .el-input.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
/deep/ .el-select.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
|
||||
.el-form-item__content
|
||||
.el-select{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.table-wrapper {
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 8px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
/deep/ .el-table,
|
||||
.el-table__expanded-cell {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border-color: #444444;
|
||||
}
|
||||
/deep/ .el-table th,
|
||||
.el-table tr {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border-color: #444444;
|
||||
}
|
||||
/deep/ .el-table__body tr > td {
|
||||
background-color: #000 !important;
|
||||
color: #fff;
|
||||
border-color: #444444;
|
||||
}
|
||||
/deep/ .el-table__body tr:hover > td {
|
||||
background-color: #858282 !important;
|
||||
color: #fff;
|
||||
border-color: #444444;
|
||||
}
|
||||
/deep/ .el-table--border th.gutter:last-of-type {
|
||||
border: none;
|
||||
}
|
||||
/deep/ .el-table__fixed-right {
|
||||
height: 100% !important;
|
||||
}
|
||||
// /deep/ .el-table .cell {
|
||||
// line-height: 20px;
|
||||
// }
|
||||
/deep/ .el-table__cell {
|
||||
padding: 5px 0;
|
||||
}
|
||||
/deep/.el-table__fixed-right-patch {
|
||||
background-color: #000 !important;
|
||||
border-color: #444444;
|
||||
}
|
||||
/deep/.el-table__fixed-body-wrapper tr:hover > td {
|
||||
background-color: #000 !important;
|
||||
}
|
||||
/deep/.el-table--scrollable-x .el-table__body-wrapper {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+297
@@ -0,0 +1,297 @@
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="!!question.GroupName && question.Type==='group'"
|
||||
>
|
||||
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ language==='en'?question.GroupEnName:question.GroupName }}
|
||||
</h4>
|
||||
</div>
|
||||
<template v-else>
|
||||
<el-form-item
|
||||
v-if="(question.ShowQuestion===1 && question.ParentTriggerValueList.includes(String(questionForm[question.ParentId]))) || question.ShowQuestion===0 "
|
||||
:label="`${question.QuestionName}`"
|
||||
:prop="question.Id"
|
||||
:rules="[
|
||||
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary',
|
||||
message: ['radio', 'select', 'checkbox'].includes(question.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change']},
|
||||
]"
|
||||
:class="[question.Type==='group' ? 'mb' : (question.Type==='upload' || question.QuestionName.length > 15) ?'uploadWrapper' : '']"
|
||||
>
|
||||
<!-- 输入框 -->
|
||||
<el-input
|
||||
v-if="question.Type==='input'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<!-- 多行文本输入框 -->
|
||||
<el-input
|
||||
v-else-if="question.Type==='textarea'"
|
||||
v-model="questionForm[question.Id]"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
maxlength="500"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-else-if="question.Type==='select'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || ((question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode)"
|
||||
clearable
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.TableQuestionType === 1">
|
||||
<el-option
|
||||
v-for="item in organList"
|
||||
:key="item.Id"
|
||||
:label="item[question.DataTableColumn]"
|
||||
:value="item[question.DataTableColumn]"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-option
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
<!-- 单选 -->
|
||||
<el-radio-group
|
||||
v-else-if="question.Type==='radio'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.DictionaryCode">
|
||||
<el-radio
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:label="String(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</template>
|
||||
<template v-else-if="question.TypeValue">
|
||||
<el-radio
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-radio>
|
||||
</template>
|
||||
</el-radio-group>
|
||||
<!-- 复选框 -->
|
||||
<el-checkbox-group
|
||||
v-else-if="question.Type==='checkbox'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<!-- 数值 -->
|
||||
<!-- <template v-else-if="question.Type==='number'">
|
||||
<el-input-number
|
||||
v-if="question.ValueType === 0"
|
||||
v-model="questionForm[question.Id]"
|
||||
:precision="0"
|
||||
:disabled="readingTaskState >= 2"
|
||||
style="width: 100%"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 3"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
style="width: 100%"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 1 || question.ValueType === 2"
|
||||
v-model="questionForm[question.Id]"
|
||||
:precision="digitPlaces"
|
||||
:disabled="readingTaskState >= 2"
|
||||
style="width: 100%"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
</template> -->
|
||||
<!-- 数值类型 -->
|
||||
<el-input
|
||||
v-else-if="question.Type==='number'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState>=2 "
|
||||
type="number"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-input
|
||||
v-else-if="question.Type==='calculation'"
|
||||
v-model="questionForm[question.Id]"
|
||||
disabled
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<QuestionTableFormItem
|
||||
v-for="item in question.Childrens"
|
||||
:key="item.Id"
|
||||
:question="item"
|
||||
:question-form="questionForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
@setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: 'QuestionTableFormItem',
|
||||
props: {
|
||||
questionForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
question: {
|
||||
type: Object,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
digitPlaces: 2
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['language'])
|
||||
},
|
||||
mounted() {
|
||||
this.digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
},
|
||||
methods: {
|
||||
formItemChange(v, question) {
|
||||
if (question.Childrens && question.Childrens.length > 0) {
|
||||
this.resetChild(question.Childrens)
|
||||
} else {
|
||||
if (question.Type === 'number') {
|
||||
v = this.limitBlur(question.ValueType, v)
|
||||
}
|
||||
this.$emit('setFormItemData', { key: question.Id, val: v })
|
||||
}
|
||||
},
|
||||
resetChild(obj) {
|
||||
obj.forEach(i => {
|
||||
this.$emit('resetFormItemData', i.Id)
|
||||
if (i.Childrens && i.Childrens.length > 0) {
|
||||
this.resetChild(i.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
limitBlur(valueType, value) {
|
||||
if (isNaN(parseInt(value))) {
|
||||
value = null
|
||||
} else {
|
||||
if (valueType === 0) {
|
||||
value = parseInt(value)
|
||||
} else if (valueType === 3) {
|
||||
value = parseFloat(value)
|
||||
} else {
|
||||
value = this.numberToFixed(value)
|
||||
}
|
||||
}
|
||||
return value
|
||||
},
|
||||
numberToFixed(v) {
|
||||
if (this.digitPlaces > -1) {
|
||||
return isNaN(parseFloat(v)) ? null : `${parseFloat(v).toFixed(this.digitPlaces)}`
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
},
|
||||
resetFormItemData(v) {
|
||||
this.$emit('resetFormItemData', v)
|
||||
},
|
||||
setFormItemData(obj) {
|
||||
this.$emit('setFormItemData', obj)
|
||||
},
|
||||
limitNumbersEvent(e) {
|
||||
// 通过正则保留两位小数点
|
||||
let val = e.target.value
|
||||
if (val.length > 6) val = val.slice(0, 6)
|
||||
e.target.value = (val.match(/^\d*(\.?\d{0,3})/g)[0]) || null
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.mb{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.disabled{
|
||||
/deep/ .el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.uploadWrapper{
|
||||
display: flex;
|
||||
flex-direction: column !important;
|
||||
align-items: flex-start;
|
||||
}
|
||||
/deep/ .el-input.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
/deep/ .el-input-group__append, .el-input-group__prepend{
|
||||
padding: 0 10px;
|
||||
}
|
||||
/deep/ .el-form-item__content {
|
||||
width: 100%;
|
||||
}
|
||||
/deep/ .el-select.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,117 @@
|
||||
<template>
|
||||
<el-form
|
||||
ref="uploadExcel"
|
||||
class="upload-excel-file"
|
||||
>
|
||||
<!-- 文件 -->
|
||||
<el-form-item :label="$t('trials:consistencyCheck:label:file')">
|
||||
<div class="upload-container">
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
action
|
||||
accept=".xlsx,.xls,.csv"
|
||||
:before-upload="beforeUpload"
|
||||
:http-request="handleUploadFile"
|
||||
:on-preview="handlePreview"
|
||||
:show-file-list="true"
|
||||
:limit="1"
|
||||
:on-exceed="handleExceed"
|
||||
>
|
||||
<el-button size="small" type="primary">
|
||||
{{ $t('trials:consistencyCheck:dialogButton:upload') }}
|
||||
</el-button>
|
||||
<span
|
||||
slot="tip"
|
||||
style="margin-left:10px;"
|
||||
class="el-upload__tip"
|
||||
>
|
||||
({{ $t('trials:consistencyCheck:message:excelFileOnly') }})
|
||||
</span>
|
||||
</el-upload>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { uploadIVUSTemplate } from '@/api/reading'
|
||||
export default {
|
||||
props: {
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
beforeUpload(file) {
|
||||
// 检测文件类型是否符合要求
|
||||
if (this.checkFileSuffix(file.name)) {
|
||||
return true
|
||||
} else {
|
||||
// Must be xls or xlsx format
|
||||
this.$alert(this.$t('trials:consistencyCheck:message:xlsx'))
|
||||
|
||||
return false
|
||||
}
|
||||
},
|
||||
async handleUploadFile(param) {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
var data = new FormData()
|
||||
data.append('file', param.file)
|
||||
data.append('visitTaskId', this.visitTaskId)
|
||||
await uploadIVUSTemplate(data)
|
||||
this.$emit('close')
|
||||
this.$message.success('导入成功!')
|
||||
loading.close()
|
||||
} catch (e) {
|
||||
loading.close()
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
handlePreview(file) {
|
||||
if (file.fullPath) {
|
||||
window.open(file.fullPath, '_blank')
|
||||
}
|
||||
},
|
||||
handleExceed(files, fileList) {
|
||||
// Upload is currently limited to 1 file
|
||||
this.$message.warning(this.$t('trials:consistencyCheck:message:onlyOneFile'))
|
||||
},
|
||||
checkFileSuffix(fileName) {
|
||||
var typeArr = ['xls', 'xlsx', 'csv']
|
||||
var extendName = fileName.substring(fileName.lastIndexOf('.') + 1).toLocaleLowerCase()
|
||||
if (typeArr.indexOf(extendName) !== -1) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.upload-excel-file{
|
||||
.upload-container .el-upload--text {
|
||||
border: none;
|
||||
width: 80px;
|
||||
height: 40px;
|
||||
}
|
||||
.upload-container .el-input--small {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.upload-container .el-icon-circle-check {
|
||||
color: #428bca;
|
||||
font-size: 13px;
|
||||
}
|
||||
.account_item_clear{
|
||||
.el-tag__close{
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="measurement-wrapper" :style="{'height':height+10+'px'}">
|
||||
<div class="measurement-wrapper">
|
||||
|
||||
<div class="container" :style="{'height':height+'px'}">
|
||||
<div class="container">
|
||||
<div class="basic-info">
|
||||
<h3 v-if="isReadingShowSubjectInfo">
|
||||
<span v-if="subjectCode">{{ subjectCode }} </span>
|
||||
@@ -262,7 +262,6 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
height: window.innerHeight - 140,
|
||||
questions: [],
|
||||
activeName: '',
|
||||
activeItem: {
|
||||
@@ -359,8 +358,6 @@ export default {
|
||||
}
|
||||
callback(true)
|
||||
})
|
||||
|
||||
window.addEventListener('resize', this.setHeight)
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('setCollapseActive')
|
||||
@@ -573,9 +570,6 @@ export default {
|
||||
} catch (e) { console.log(e) }
|
||||
})
|
||||
},
|
||||
setHeight() {
|
||||
this.height = window.innerHeight - 140
|
||||
},
|
||||
getQuestionAnswer(questions, questionMark, answers) {
|
||||
var idx = questions.findIndex(i => i.QuestionMark === questionMark)
|
||||
if (idx > -1) {
|
||||
@@ -1347,9 +1341,8 @@ export default {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.measurement-wrapper{
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
// overflow: hidden;
|
||||
|
||||
.container{
|
||||
padding: 10px;
|
||||
.basic-info{
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
<div class="right-wrapper">
|
||||
<div class="right-content">
|
||||
<iframe v-if="selected.filePath" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${selected.filePath}?userName=${currentUser}`" width="100%" height="100%" frameborder="0" />
|
||||
<iframe v-if="selected.filePath" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${selected.filePath}?userName=${currentUser}&COMPANY=${COMPANY}`" width="100%" height="100%" frameborder="0" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,7 +44,8 @@ export default {
|
||||
},
|
||||
fileList: [],
|
||||
loading: false,
|
||||
currentUser: zzSessionStorage.getItem('userName')
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
COMPANY:process.env.VUE_APP_COMPANY_NAME
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
@@ -0,0 +1,887 @@
|
||||
<template>
|
||||
<div class="measurement-wrapper">
|
||||
<div class="container">
|
||||
<div class="basic-info">
|
||||
<h3 v-if="isReadingShowSubjectInfo">
|
||||
<span v-if="subjectCode">{{ subjectCode }} </span>
|
||||
<span style="margin-left:5px;">{{ taskBlindName }}</span>
|
||||
</h3>
|
||||
<div v-if="readingTaskState < 2">
|
||||
<el-tooltip class="item" effect="dark" :content="$t('trials:dicomReading:message:confirmReset')" placement="bottom">
|
||||
<i
|
||||
class="el-icon-refresh-left"
|
||||
@click="resetMeasuredData"
|
||||
/>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 影像质量问题 -->
|
||||
<div class="lesions">
|
||||
<Questions
|
||||
ref="ecrf"
|
||||
:question-form-change-state="true"
|
||||
:question-form-change-num="0"
|
||||
:is-qulity-issues="false"
|
||||
:group-classify="1"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- 测量问题 -->
|
||||
<template v-if="questions.length > 0">
|
||||
<div v-for="(qs,index) in questions" :key="index" v-loading="loading" class="lesions lesions_wrapper" style="margin-bottom: 10px">
|
||||
<h4 v-if="qs.Type === 'group'" style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ language==='en'?qs.GroupEnName:qs.GroupName }}
|
||||
</h4>
|
||||
<div class="lesion_list">
|
||||
<el-form
|
||||
v-if="questions.length > 0"
|
||||
:ref="`questions${index}`"
|
||||
size="small"
|
||||
:model="questionForm"
|
||||
>
|
||||
<div class="table-wrapper">
|
||||
<div v-for="item in qs.Childrens" :key="item.Id">
|
||||
<div v-if="item.Type === 'basicTable'" class="flex-row" style="margin:3px 0;">
|
||||
<div class="title">{{ item.QuestionName }}</div>
|
||||
<div v-if="(item.LesionType === 112 || item.LesionType === 111) && readingTaskState < 2">
|
||||
<div class="add-icon" @click.prevent="downloadTpl(item.LesionType)">
|
||||
<i class="el-icon-download" />
|
||||
</div>
|
||||
<div class="add-icon" style="margin: 0 5px;" @click.prevent="uploadTpl(item.LesionType)">
|
||||
<i class="el-icon-upload2" />
|
||||
</div>
|
||||
<div class="add-icon" @click.prevent="handleAddOrEdit('add',item)">
|
||||
<i class="el-icon-plus" />
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
<el-table
|
||||
v-if="item.Type === 'basicTable' && item.TableQuestions"
|
||||
:ref="item.Id"
|
||||
:data="item.TableQuestions.Answers"
|
||||
max-height="600"
|
||||
>
|
||||
<!-- <el-table-column :label="$t('CustomizeQuestionFormItem:label:OrderMark')" width="60px" show-overflow-tooltip>
|
||||
<template slot-scope="scope">
|
||||
{{ getLesionName(item.OrderMark,scope.row.RowIndex) }}
|
||||
</template>
|
||||
</el-table-column> -->
|
||||
<!-- <el-table-column
|
||||
type="index"
|
||||
width="40px"
|
||||
/> -->
|
||||
<el-table-column
|
||||
v-for="q of item.TableQuestions.Questions"
|
||||
:key="q.Id"
|
||||
:prop="q.Id"
|
||||
:label="q.QuestionName"
|
||||
show-overflow-tooltip
|
||||
:render-header="renderHeader"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<span v-if="q.Unit > 0 && !isNaN(parseFloat(scope.row[q.Id]))">
|
||||
{{ `${scope.row[q.Id]} ${$fd('ValueUnit', parseInt(q.Unit))}` }}
|
||||
</span>
|
||||
<span v-else-if="q.DictionaryCode">
|
||||
{{ `${$fd(q.DictionaryCode, parseInt(scope.row[q.Id]))}` }}
|
||||
</span>
|
||||
<span v-else>
|
||||
{{ `${scope.row[q.Id]}` }}
|
||||
</span>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
v-if="readingTaskState < 2"
|
||||
:label="$t('common:action:action')"
|
||||
width="90px"
|
||||
fixed="right"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
<el-button type="text" size="mini" @click="handleAddOrEdit('edit',item, scope.$index)">
|
||||
{{ $t('common:button:edit') }}
|
||||
</el-button>
|
||||
<el-button v-if="item.LesionType === 112 || item.LesionType === 111" type="text" size="mini" @click="handleDelete(item, scope.$index)">
|
||||
{{ $t('common:button:delete') }}
|
||||
</el-button>
|
||||
</template>
|
||||
</el-table-column>
|
||||
</el-table>
|
||||
|
||||
<template v-else>
|
||||
<!-- 数值 -->
|
||||
<el-form-item
|
||||
v-if="item.ShowQuestion!==2"
|
||||
:key="item.Id"
|
||||
:label="`${item.QuestionName}`"
|
||||
:prop="item.Id"
|
||||
:rules="[
|
||||
{ required: (item.IsRequired === 0 || (item.IsRequired ===1 && item.RelevanceId && (item.RelevanceValue.includes(questionForm[item.RelevanceId])))) && item.Type!=='group' && item.Type!=='summary',
|
||||
message:['radio', 'select', 'checkbox'].includes(item.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur','change']},
|
||||
]"
|
||||
>
|
||||
<!-- 数值类型 -->
|
||||
<template v-if="item.Type==='textarea'">
|
||||
<el-input
|
||||
v-model="questionForm[qs.Id]"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
:disabled="!isCurrentTask || readingTaskState>=2"
|
||||
@change="((val)=>{formItemChange(val, qs)})"
|
||||
/>
|
||||
</template>
|
||||
</el-form-item>
|
||||
</template>
|
||||
</div>
|
||||
<div
|
||||
v-if="isCurrentTask && readingTaskState<2 && qs.GroupClassify === 5"
|
||||
class="base-dialog-footer"
|
||||
style="text-align:right;margin-top:10px;"
|
||||
>
|
||||
<!-- 保存 -->
|
||||
<el-button
|
||||
type="primary"
|
||||
size="mini"
|
||||
:disabled="!formChanged"
|
||||
@click="handleSave(index)"
|
||||
>
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</div>
|
||||
</div>
|
||||
</el-form>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 计算值 -->
|
||||
<Questions
|
||||
ref="ecrf2"
|
||||
:question-form-change-state="true"
|
||||
:question-form-change-num="0"
|
||||
:is-qulity-issues="false"
|
||||
:group-classify="4"
|
||||
style="margin-top:20px"
|
||||
/>
|
||||
|
||||
<!-- 评估结果 -->
|
||||
<Questions
|
||||
ref="ecrf3"
|
||||
:question-form-change-state="true"
|
||||
:question-form-change-num="0"
|
||||
:is-qulity-issues="false"
|
||||
:group-classify="5"
|
||||
/>
|
||||
<el-dialog
|
||||
v-if="addOrEdit.visible"
|
||||
:visible.sync="addOrEdit.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="addOrEdit.title"
|
||||
width="500px"
|
||||
>
|
||||
<el-form
|
||||
ref="tableQsForm"
|
||||
v-loading="loading"
|
||||
:model="qsForm"
|
||||
size="small"
|
||||
>
|
||||
<QuestionTableFormItem
|
||||
v-for="item in qsList"
|
||||
:key="item.Id"
|
||||
:question="item"
|
||||
:question-form="qsForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
@setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
/>
|
||||
<el-form-item style="text-align: right">
|
||||
<el-button
|
||||
size="small"
|
||||
@click="addOrEdit.visible = false"
|
||||
>
|
||||
{{ $t('common:button:cancel') }}
|
||||
</el-button>
|
||||
<!-- 保存 -->
|
||||
<el-button size="small" class="my_upload_btn" @click="saveFormData">
|
||||
{{ $t('common:button:save') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</el-dialog>
|
||||
<!-- 导入 -->
|
||||
<el-dialog
|
||||
v-if="upload.visible"
|
||||
:visible.sync="upload.visible"
|
||||
:close-on-click-modal="false"
|
||||
:title="upload.title"
|
||||
width="500px"
|
||||
>
|
||||
<UploadExcel
|
||||
:visit-task-id="visitTaskId"
|
||||
:lesion-type="upload.lesionType"
|
||||
@close="uploadDlgClose"
|
||||
/>
|
||||
</el-dialog>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { saveTaskQuestion, submitTableQuestion, deleteReadingRowAnswer } from '@/api/trials'
|
||||
import { resetReadingTask, getOCTFCTTemplate, getOCTLipidAngleTemplate } from '@/api/reading'
|
||||
import DicomEvent from './../DicomEvent'
|
||||
import store from '@/store'
|
||||
import { mapGetters } from 'vuex'
|
||||
import Questions from './../Questions'
|
||||
import QuestionTableFormItem from './QuestionTableFormItem'
|
||||
import UploadExcel from './UploadExcel'
|
||||
export default {
|
||||
name: 'MeasurementList',
|
||||
components: {
|
||||
Questions,
|
||||
QuestionTableFormItem,
|
||||
UploadExcel
|
||||
},
|
||||
props: {
|
||||
isShow: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
isReadingShowSubjectInfo: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
questionFormChangeState: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
return false
|
||||
}
|
||||
},
|
||||
questionFormChangeNum: {
|
||||
type: Number,
|
||||
default() {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
questions: [],
|
||||
visitTaskId: '',
|
||||
isCurrentTask: false,
|
||||
loading: false,
|
||||
readingTaskState: 2,
|
||||
isBaseLineTask: false,
|
||||
taskBlindName: '',
|
||||
tableQuestions: [],
|
||||
CriterionType: null,
|
||||
subjectCode: '',
|
||||
questionForm: {},
|
||||
formChanged: false,
|
||||
digitPlaces: 2,
|
||||
addOrEdit: { visible: false, title: '', lesionType: null },
|
||||
upload: { visible: false, title: '', lesionType: null },
|
||||
qsList: [],
|
||||
answersList: [],
|
||||
qsForm: {},
|
||||
m1Id: '',
|
||||
m2Id: '',
|
||||
m3Id: '',
|
||||
avgId: ''
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['visitTaskList', 'language', 'lastCanvasTaskId', 'currentReadingTaskState'])
|
||||
},
|
||||
watch: {
|
||||
lastCanvasTaskId: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if (val) {
|
||||
this.initList()
|
||||
}
|
||||
}
|
||||
},
|
||||
currentReadingTaskState: {
|
||||
immediate: true,
|
||||
handler(val) {
|
||||
if (val) {
|
||||
this.readingTaskState = val
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
// this.subjectCode = this.$router.currentRoute.query.subjectCode
|
||||
this.subjectCode = localStorage.getItem('subjectCode')
|
||||
this.digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
window.addEventListener('message', this.receiveMsg)
|
||||
this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
|
||||
DicomEvent.$on('setCollapseActive', measureData => {
|
||||
this.setCollapseActive(measureData)
|
||||
console.log('setCollapseActive')
|
||||
})
|
||||
DicomEvent.$on('getAllUnSaveLesions', (callback) => {
|
||||
callback([])
|
||||
})
|
||||
DicomEvent.$on('refreshQuestions', _ => {
|
||||
this.refreshQuestions()
|
||||
})
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('setCollapseActive')
|
||||
DicomEvent.$off('getUnSaveTarget')
|
||||
DicomEvent.$off('refreshQuestions')
|
||||
},
|
||||
methods: {
|
||||
async initList() {
|
||||
var i = this.visitTaskList.findIndex(i => i.VisitTaskId === this.lastCanvasTaskId)
|
||||
if (i > -1) {
|
||||
this.visitTaskId = this.visitTaskList[i].VisitTaskId
|
||||
this.taskBlindName = this.visitTaskList[i].TaskBlindName
|
||||
this.readingTaskState = this.visitTaskList[i].ReadingTaskState
|
||||
this.isBaseLineTask = this.visitTaskList[i].IsBaseLineTask
|
||||
this.isCurrentTask = this.visitTaskList[i].IsCurrentTask
|
||||
if (!this.visitTaskList[i].IsInit) {
|
||||
var loading = this.$loading({ fullscreen: true })
|
||||
var triald = this.trialId = this.$router.currentRoute.query.trialId
|
||||
if (!this.visitTaskList[i].studyListInit) {
|
||||
await store.dispatch('reading/getStudyInfo', { trialId: triald, subjectVisitId: this.visitTaskList[i].VisitId, visitTaskId: this.visitTaskList[i].VisitTaskId, taskBlindName: this.visitTaskList[i].TaskBlindName })
|
||||
}
|
||||
if (!this.visitTaskList[i].readingQuestionsInit) {
|
||||
await store.dispatch('reading/getReadingQuestionAndAnswer', { trialId: triald, visitTaskId: this.visitTaskList[i].VisitTaskId })
|
||||
}
|
||||
if (!this.visitTaskList[i].questionsInit) {
|
||||
await store.dispatch('reading/getDicomReadingQuestionAnswer', { trialId: triald, visitTaskId: this.visitTaskList[i].VisitTaskId })
|
||||
}
|
||||
|
||||
await store.dispatch('reading/setStatus', { visitTaskId: this.visitTaskList[i].VisitTaskId })
|
||||
loading.close()
|
||||
}
|
||||
this.questions = this.visitTaskList[i].ReadingQuestions
|
||||
this.setQuestionForm(this.questions)
|
||||
this.$nextTick(() => {
|
||||
this.$refs['ecrf'].getQuestions(this.visitTaskId)
|
||||
this.$refs['ecrf2'].getQuestions(this.visitTaskId)
|
||||
this.$refs['ecrf3'].getQuestions(this.visitTaskId)
|
||||
})
|
||||
}
|
||||
},
|
||||
setQuestionForm(questions) {
|
||||
const type = ['number', 'radio', 'select', 'input', 'textarea', 'calculation']
|
||||
questions.forEach(item => {
|
||||
if (type.includes(item.Type)) {
|
||||
const answer = item.Type === 'number' || item.Type === 'calculation' ? isNaN(parseFloat(item.Answer)) ? null : parseFloat(item.Answer) : item.Answer
|
||||
this.$set(this.questionForm, item.Id, answer)
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.setQuestionForm(item.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
async resetQuestions(obj) {
|
||||
this.setQuestions(this.questions, obj)
|
||||
await store.dispatch('reading/setReadingQuestionAndAnswer', { questions: this.questions, visitTaskId: this.visitTaskId })
|
||||
|
||||
this.getTableQuestions()
|
||||
},
|
||||
setQuestions(questions, obj) {
|
||||
questions.forEach(item => {
|
||||
if ((item.Type === 'table' || item.Type === 'basicTable') && item.Id === obj.questionId) {
|
||||
var idx = item.TableQuestions.Answers.findIndex(i => i.RowIndex === obj.rowIndex)
|
||||
item.TableQuestions.Answers[idx].saveTypeEnum = obj.saveTypeEnum
|
||||
item.TableQuestions.Answers[idx].area1 = obj.area1
|
||||
item.TableQuestions.Answers[idx].area2 = obj.area2
|
||||
item.TableQuestions.Answers[idx].diff = obj.diff
|
||||
for (const i in obj.anwsers) {
|
||||
item.TableQuestions.Answers[idx][i] = String(obj.anwsers[i])
|
||||
}
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.setQuestions(item.Childrens, obj)
|
||||
}
|
||||
})
|
||||
},
|
||||
getQuestions(questions) {
|
||||
questions.forEach(item => {
|
||||
if ((item.Type === 'table' || item.Type === 'basicTable') && item.TableQuestions && item.TableQuestions.Answers.length > 0) {
|
||||
item.TableQuestions.Answers.forEach(answerObj => {
|
||||
if (answerObj.RowId) {
|
||||
var diffVal = this.getQuestionAnswer(item.TableQuestions.Questions, 1003, answerObj)
|
||||
this.$set(answerObj, 'saveTypeEnum', isNaN(parseFloat(diffVal)) ? 1 : 2)
|
||||
} else {
|
||||
this.$set(answerObj, 'saveTypeEnum', 0)
|
||||
}
|
||||
})
|
||||
}
|
||||
if (item.Childrens.length > 0) {
|
||||
this.getQuestions(item.Childrens)
|
||||
}
|
||||
})
|
||||
return questions
|
||||
},
|
||||
getReadingQuestionAndAnswer() {
|
||||
return new Promise(async resolve => {
|
||||
try {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
await store.dispatch('reading/refreshReadingQuestionAndAnswer', { trialId: this.$router.currentRoute.query.trialId, visitTaskId: this.visitTaskId }).then(() => {
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
if (idx > -1) {
|
||||
if (this.visitTaskList[idx].ReadingQuestions.length > 0) {
|
||||
this.questions = this.visitTaskList[idx].ReadingQuestions
|
||||
this.setQuestionForm(this.questions)
|
||||
}
|
||||
this.readingTaskState = this.visitTaskList[idx].ReadingTaskState
|
||||
this.isBaseLineTask = this.visitTaskList[idx].IsBaseLineTask
|
||||
this.isCurrentTask = this.visitTaskList[idx].IsCurrentTask
|
||||
}
|
||||
})
|
||||
loading.close()
|
||||
resolve()
|
||||
} catch (e) { console.log(e) }
|
||||
})
|
||||
},
|
||||
getQuestionAnswer(questions, questionMark, answers) {
|
||||
var idx = questions.findIndex(i => i.QuestionMark === questionMark)
|
||||
if (idx > -1) {
|
||||
var questionId = questions[idx].Id
|
||||
return answers[questionId]
|
||||
} else {
|
||||
return ''
|
||||
}
|
||||
},
|
||||
isCanActiveTool(toolName) {
|
||||
return { isCanActiveTool: true, reason: '' }
|
||||
},
|
||||
getMaxRowIndex(answerList) {
|
||||
if (answerList.length > 0) {
|
||||
var arr = []
|
||||
answerList.forEach(item => {
|
||||
var rowIndex = item.RowIndex
|
||||
arr.push(parseInt(rowIndex))
|
||||
})
|
||||
var max = Math.max.apply(null, arr)
|
||||
return max
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
},
|
||||
getLesionName(orderMark, rowIndex) {
|
||||
var lessionName = ''
|
||||
var rowIndexArr = rowIndex.split('.')
|
||||
var x = parseInt(rowIndexArr[0])
|
||||
var y = parseInt(rowIndexArr[1])
|
||||
if (y > 0) {
|
||||
y = String.fromCharCode(parseInt(rowIndexArr[1]) - 1 + 65 + 32)
|
||||
lessionName = `${orderMark}${String(x).padStart(2, '0')}${y}`
|
||||
} else {
|
||||
lessionName = `${orderMark}${String(x).padStart(2, '0')}`
|
||||
}
|
||||
|
||||
return lessionName
|
||||
},
|
||||
modifyMeasuredData(measureObj) {
|
||||
},
|
||||
// 设置测量数据
|
||||
setMeasuredData(measureData) {
|
||||
|
||||
},
|
||||
formItemChange() {
|
||||
this.formChanged = true
|
||||
},
|
||||
limitBlur(qId, valueType) {
|
||||
const value = this.questionForm[qId]
|
||||
if (isNaN(parseInt(value))) return
|
||||
if (valueType === 0) {
|
||||
this.$set(this.questionForm, qId, parseInt(value))
|
||||
} else if (valueType === 3) {
|
||||
this.$set(this.questionForm, qId, parseFloat(value))
|
||||
} else {
|
||||
this.$set(this.questionForm, qId, this.numberToFixed(value))
|
||||
}
|
||||
},
|
||||
numberToFixed(v) {
|
||||
if (this.digitPlaces > -1) {
|
||||
return isNaN(parseFloat(v)) ? null : `${parseFloat(v).toFixed(this.digitPlaces)}`
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
},
|
||||
async handleSave(index) {
|
||||
const refName = `questions${index}`
|
||||
const valid = await this.$refs[refName][0].validate()
|
||||
if (!valid) return
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
var answers = []
|
||||
for (const k in this.questionForm) {
|
||||
answers.push({ id: k, answer: this.questionForm[k] })
|
||||
}
|
||||
var params = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
answers: answers
|
||||
}
|
||||
try {
|
||||
await saveTaskQuestion(8, params)
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
loading.close()
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
this.refreshQuestions()
|
||||
this.formChanged = false
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
loading.close()
|
||||
}
|
||||
},
|
||||
getECRFQuestions(obj) {
|
||||
this.$refs['ecrf'].getQuestions(obj.visitTaskId)
|
||||
this.$refs['ecrf2'].getQuestions(obj.visitTaskId)
|
||||
this.$refs['ecrf3'].getQuestions(obj.visitTaskId)
|
||||
},
|
||||
async resetMeasuredData() {
|
||||
const confirm = await this.$confirm(
|
||||
this.$t('trials:dicomReading:message:confirmReset1'),
|
||||
this.$t('trials:dicomReading:message:confirmReset2'),
|
||||
{
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
const res = await resetReadingTask({ visitTaskId: this.visitTaskId })
|
||||
this.loading = false
|
||||
if (res.IsSuccess) {
|
||||
await this.getReadingQuestionAndAnswer(this.visitTaskId)
|
||||
const triald = this.$router.currentRoute.query.trialId
|
||||
await store.dispatch('reading/refreshDicomReadingQuestionAnswer', { trialId: triald, visitTaskId: this.visitTaskId })
|
||||
this.$refs['ecrf'].getQuestions(this.visitTaskId, true)
|
||||
this.$refs['ecrf2'].getQuestions(this.visitTaskId, true)
|
||||
this.$refs['ecrf3'].getQuestions(this.visitTaskId, true)
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
}
|
||||
loading.close()
|
||||
} catch (e) {
|
||||
loading.close()
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
async refreshQuestions() {
|
||||
const triald = this.$router.currentRoute.query.trialId
|
||||
await this.getReadingQuestionAndAnswer(this.visitTaskId)
|
||||
await store.dispatch('reading/refreshDicomReadingQuestionAnswer', { trialId: triald, visitTaskId: this.visitTaskId })
|
||||
this.$refs['ecrf'].getQuestions(this.visitTaskId, true)
|
||||
this.$refs['ecrf2'].getQuestions(this.visitTaskId, true)
|
||||
this.$refs['ecrf3'].getQuestions(this.visitTaskId, true)
|
||||
},
|
||||
receiveMsg(event) {
|
||||
},
|
||||
resetFormItemData(v) {
|
||||
this.qsForm[v] = null
|
||||
},
|
||||
setFormItemData(obj) {
|
||||
this.qsForm[obj.key] = obj.val
|
||||
if (obj.key === this.m1Id || obj.key === this.m2Id || obj.key === this.m3Id) {
|
||||
const m1 = this.qsForm[this.m1Id]
|
||||
const m2 = this.qsForm[this.m2Id]
|
||||
const m3 = this.qsForm[this.m3Id]
|
||||
if (isNaN(parseFloat(m1)) || isNaN(parseFloat(m2)) || isNaN(parseFloat(m3))) {
|
||||
this.$set(this.qsForm, this.avgId, null)
|
||||
} else {
|
||||
const avg = (parseFloat(m1) + parseFloat(m2) + parseFloat(m3)) / 3
|
||||
this.$set(this.qsForm, this.avgId, this.numberToFixed(avg))
|
||||
}
|
||||
}
|
||||
},
|
||||
handleAddOrEdit(type, row, index) {
|
||||
this.addOrEdit.title = row.QuestionName
|
||||
this.qsList = row.TableQuestions.Questions
|
||||
this.qsForm = {}
|
||||
this.qsForm.questionId = row.Id
|
||||
this.qsForm.rowId = type === 'add' ? null : row.TableQuestions.Answers && row.TableQuestions.Answers[index] ? row.TableQuestions.Answers[index].RowId : null
|
||||
if (type === 'add') {
|
||||
var maxIndex = this.getMaxRowIndex(row.TableQuestions.Answers)
|
||||
this.qsForm.rowIndex = `${maxIndex + 1}.00`
|
||||
} else {
|
||||
this.qsForm.rowIndex = row.TableQuestions.Answers && row.TableQuestions.Answers[index] ? row.TableQuestions.Answers[index].RowIndex : null
|
||||
}
|
||||
row.TableQuestions.Questions.map(i => {
|
||||
if (i.QuestionMark === 1011) {
|
||||
this.m1Id = i.Id
|
||||
}
|
||||
if (i.QuestionMark === 1012) {
|
||||
this.m2Id = i.Id
|
||||
}
|
||||
if (i.QuestionMark === 1013) {
|
||||
this.m3Id = i.Id
|
||||
}
|
||||
if (i.QuestionMark === 1015) {
|
||||
this.avgId = i.Id
|
||||
}
|
||||
let v = null
|
||||
if (type === 'add') {
|
||||
v = i.Type === 'number' ? undefined : null
|
||||
} else {
|
||||
v = row.TableQuestions.Answers && row.TableQuestions.Answers[index] ? row.TableQuestions.Answers[index][i.Id] : null
|
||||
}
|
||||
this.$set(this.qsForm, i.Id, v)
|
||||
})
|
||||
this.addOrEdit.visible = true
|
||||
this.addOrEdit.lesionType = row.LesionType
|
||||
},
|
||||
async saveFormData() {
|
||||
const valid = await this.$refs.tableQsForm.validate()
|
||||
if (!valid) return
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
var answers = []
|
||||
var reg = new RegExp(/^[0-9a-zA-Z]{8}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{4}-[0-9a-zA-Z]{12}$/)
|
||||
for (const k in this.qsForm) {
|
||||
if (reg.test(k)) {
|
||||
if (answers.findIndex(i => i.tableQuestionId === k) === -1) {
|
||||
answers.push({ tableQuestionId: k, answer: this.qsForm[k] })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var params = {
|
||||
questionId: this.qsForm.questionId,
|
||||
rowId: this.qsForm.rowId,
|
||||
rowIndex: this.qsForm.rowIndex,
|
||||
visitTaskId: this.visitTaskId,
|
||||
trialId: this.trialId,
|
||||
answerList: answers
|
||||
}
|
||||
if (this.addOrEdit.lesionType === 101) {
|
||||
params.computationTrigger = 9
|
||||
}
|
||||
const res = await submitTableQuestion(params)
|
||||
if (res.IsSuccess) {
|
||||
// this.refreshQuestions()
|
||||
await this.getReadingQuestionAndAnswer(this.visitTaskId)
|
||||
this.$refs['ecrf'].getQuestions(this.visitTaskId, true)
|
||||
this.$refs['ecrf2'].getQuestions(this.visitTaskId, true)
|
||||
this.$refs['ecrf3'].getQuestions(this.visitTaskId, true)
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
// 保存成功!
|
||||
this.addOrEdit.visible = false
|
||||
this.$message.success(this.$t('common:message:savedSuccessfully'))
|
||||
}
|
||||
loading.close()
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
loading.close()
|
||||
}
|
||||
},
|
||||
async handleDelete(row, index) {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
const confirm = await this.$confirm(
|
||||
this.$t('trials:reading:warnning:msg48'),
|
||||
{
|
||||
type: 'warning',
|
||||
distinguishCancelAndClose: true
|
||||
}
|
||||
)
|
||||
if (confirm !== 'confirm') return
|
||||
if (row.TableQuestions.Answers[index].RowId) {
|
||||
var param = {
|
||||
visitTaskId: this.visitTaskId,
|
||||
questionId: row.Id,
|
||||
rowId: row.TableQuestions.Answers[index].RowId
|
||||
}
|
||||
const res = await deleteReadingRowAnswer(param)
|
||||
if (res.IsSuccess) {
|
||||
await this.getReadingQuestionAndAnswer(this.visitTaskId)
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
// '删除成功!'
|
||||
this.$message.success(this.$t('common:message:deletedSuccessfully'))
|
||||
}
|
||||
}
|
||||
loading.close()
|
||||
} catch (e) {
|
||||
loading.close()
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
uploadTpl(lesionType) {
|
||||
this.upload.lesionType = lesionType
|
||||
this.upload.title = `导入( ${this.$fd('LesionType', lesionType)} )`
|
||||
this.upload.visible = true
|
||||
},
|
||||
async downloadTpl(lesionType) {
|
||||
try {
|
||||
const params = {
|
||||
visitTaskId: this.visitTaskId
|
||||
}
|
||||
if (lesionType === 112) {
|
||||
await getOCTFCTTemplate(params)
|
||||
} else {
|
||||
await getOCTLipidAngleTemplate(params)
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
async uploadDlgClose() {
|
||||
await this.getReadingQuestionAndAnswer(this.visitTaskId)
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
this.upload.visible = false
|
||||
},
|
||||
renderHeader(h, { column, $index }) {
|
||||
const span = document.createElement('span')
|
||||
span.innerText = column.label
|
||||
document.body.appendChild(span)
|
||||
const w = span.getBoundingClientRect().width
|
||||
column.minWidth = w > 65 ? w + 10 : w > 60 ? w + 15 : w + 30
|
||||
document.body.removeChild(span)
|
||||
return h('span', column.label)
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.measurement-wrapper{
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
// overflow: hidden;
|
||||
|
||||
.container{
|
||||
padding: 10px;
|
||||
.basic-info{
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
h3{
|
||||
color: #ddd;
|
||||
padding: 5px 0px;
|
||||
margin: 0;
|
||||
}
|
||||
i{
|
||||
color: #fff;
|
||||
font-size: 22px;
|
||||
font-weight: bold;
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
}
|
||||
.title{
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #ddd;
|
||||
font-size: 15px;
|
||||
|
||||
}
|
||||
.add-icon{
|
||||
display: inline-block;
|
||||
padding: 5px;
|
||||
font-weight: bold;
|
||||
color: #ddd;
|
||||
font-size: 15px;
|
||||
border: 1px solid #938b8b;
|
||||
margin-bottom: 2px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.add-icon:hover{
|
||||
background-color: #607d8b;
|
||||
}
|
||||
|
||||
.flex-row{
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
background-color: #424242;
|
||||
|
||||
}
|
||||
.lesion_list{
|
||||
position: relative;
|
||||
/deep/ .el-form-item__label{
|
||||
color: #c3c3c3;
|
||||
text-align: left;
|
||||
}
|
||||
/deep/ .el-input .el-input__inner{
|
||||
background-color: transparent;
|
||||
color: #ddd;
|
||||
border: 1px solid #5e5e5e;
|
||||
}
|
||||
/deep/ .el-textarea__inner{
|
||||
background-color: transparent;
|
||||
color: #ddd;
|
||||
border: 1px solid #5e5e5e;
|
||||
}
|
||||
/deep/ .el-form-item{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
justify-content: flex-start;
|
||||
}
|
||||
/deep/ .el-form-item__content{
|
||||
flex: 1;
|
||||
}
|
||||
/deep/ .el-input.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
/deep/ .el-select.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
|
||||
.el-form-item__content
|
||||
.el-select{
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
.table-wrapper {
|
||||
::-webkit-scrollbar {
|
||||
width: 5px;
|
||||
height: 8px;
|
||||
}
|
||||
::-webkit-scrollbar-thumb {
|
||||
border-radius: 10px;
|
||||
background: #d0d0d0;
|
||||
}
|
||||
/deep/ .el-table,
|
||||
.el-table__expanded-cell {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border-color: #444444;
|
||||
}
|
||||
/deep/ .el-table th,
|
||||
.el-table tr {
|
||||
background-color: #000;
|
||||
color: #fff;
|
||||
border-color: #444444;
|
||||
}
|
||||
/deep/ .el-table__body tr > td {
|
||||
background-color: #000 !important;
|
||||
color: #fff;
|
||||
border-color: #444444;
|
||||
}
|
||||
/deep/ .el-table__body tr:hover > td {
|
||||
background-color: #858282 !important;
|
||||
color: #fff;
|
||||
border-color: #444444;
|
||||
}
|
||||
/deep/ .el-table--border th.gutter:last-of-type {
|
||||
border: none;
|
||||
}
|
||||
/deep/ .el-table__fixed-right {
|
||||
height: 100% !important;
|
||||
}
|
||||
// /deep/ .el-table .cell {
|
||||
// line-height: 20px;
|
||||
// }
|
||||
/deep/ .el-table__cell {
|
||||
padding: 5px 0;
|
||||
}
|
||||
/deep/.el-table__fixed-right-patch {
|
||||
background-color: #000 !important;
|
||||
border-color: #444444;
|
||||
}
|
||||
/deep/.el-table__fixed-body-wrapper tr:hover > td {
|
||||
background-color: #000 !important;
|
||||
}
|
||||
/deep/.el-table--scrollable-x .el-table__body-wrapper {
|
||||
z-index: 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
+297
@@ -0,0 +1,297 @@
|
||||
<template>
|
||||
<div>
|
||||
<div
|
||||
v-if="!!question.GroupName && question.Type==='group'"
|
||||
>
|
||||
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;">
|
||||
{{ language==='en'?question.GroupEnName:question.GroupName }}
|
||||
</h4>
|
||||
</div>
|
||||
<template v-else>
|
||||
<el-form-item
|
||||
v-if="(question.ShowQuestion===1 && question.ParentTriggerValueList.includes(String(questionForm[question.ParentId]))) || question.ShowQuestion===0 "
|
||||
:label="`${question.QuestionName}`"
|
||||
:prop="question.Id"
|
||||
:rules="[
|
||||
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary',
|
||||
message: ['radio', 'select', 'checkbox'].includes(question.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change']},
|
||||
]"
|
||||
:class="[question.Type==='group' ? 'mb' : (question.Type==='upload' || question.QuestionName.length > 15) ?'uploadWrapper' : '']"
|
||||
>
|
||||
<!-- 输入框 -->
|
||||
<el-input
|
||||
v-if="question.Type==='input'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<!-- 多行文本输入框 -->
|
||||
<el-input
|
||||
v-else-if="question.Type==='textarea'"
|
||||
v-model="questionForm[question.Id]"
|
||||
type="textarea"
|
||||
:autosize="{ minRows: 2, maxRows: 4}"
|
||||
maxlength="500"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<!-- 下拉框 -->
|
||||
<el-select
|
||||
v-else-if="question.Type==='select'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || ((question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode)"
|
||||
clearable
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.TableQuestionType === 1">
|
||||
<el-option
|
||||
v-for="item in organList"
|
||||
:key="item.Id"
|
||||
:label="item[question.DataTableColumn]"
|
||||
:value="item[question.DataTableColumn]"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
|
||||
<el-option
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:value="String(item.value)"
|
||||
:label="item.label"
|
||||
/>
|
||||
</template>
|
||||
<template v-else>
|
||||
<el-option
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
:value="val"
|
||||
/>
|
||||
</template>
|
||||
</el-select>
|
||||
<!-- 单选 -->
|
||||
<el-radio-group
|
||||
v-else-if="question.Type==='radio'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.DictionaryCode">
|
||||
<el-radio
|
||||
v-for="item of $d[question.DictionaryCode]"
|
||||
:key="item.id"
|
||||
:label="String(item.value)"
|
||||
>
|
||||
{{ item.label }}
|
||||
</el-radio>
|
||||
</template>
|
||||
<template v-else-if="question.TypeValue">
|
||||
<el-radio
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-radio>
|
||||
</template>
|
||||
</el-radio-group>
|
||||
<!-- 复选框 -->
|
||||
<el-checkbox-group
|
||||
v-else-if="question.Type==='checkbox'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<el-checkbox
|
||||
v-for="val in question.TypeValue.split('|')"
|
||||
:key="val"
|
||||
:label="val"
|
||||
>
|
||||
{{ val }}
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<!-- 数值 -->
|
||||
<!-- <template v-else-if="question.Type==='number'">
|
||||
<el-input-number
|
||||
v-if="question.ValueType === 0"
|
||||
v-model="questionForm[question.Id]"
|
||||
:precision="0"
|
||||
:disabled="readingTaskState >= 2"
|
||||
style="width: 100%"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 3"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
style="width: 100%"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 1 || question.ValueType === 2"
|
||||
v-model="questionForm[question.Id]"
|
||||
:precision="digitPlaces"
|
||||
:disabled="readingTaskState >= 2"
|
||||
style="width: 100%"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
/>
|
||||
</template> -->
|
||||
<!-- 数值类型 -->
|
||||
<el-input
|
||||
v-else-if="question.Type==='number'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState>=2 "
|
||||
type="number"
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
|
||||
<el-input
|
||||
v-else-if="question.Type==='calculation'"
|
||||
v-model="questionForm[question.Id]"
|
||||
disabled
|
||||
@change="((val)=>{formItemChange(val, question)})"
|
||||
>
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
</el-form-item>
|
||||
</template>
|
||||
|
||||
<QuestionTableFormItem
|
||||
v-for="item in question.Childrens"
|
||||
:key="item.Id"
|
||||
:question="item"
|
||||
:question-form="questionForm"
|
||||
:reading-task-state="readingTaskState"
|
||||
@setFormItemData="setFormItemData"
|
||||
@resetFormItemData="resetFormItemData"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { mapGetters } from 'vuex'
|
||||
export default {
|
||||
name: 'QuestionTableFormItem',
|
||||
props: {
|
||||
questionForm: {
|
||||
type: Object,
|
||||
default() {
|
||||
return {}
|
||||
}
|
||||
},
|
||||
question: {
|
||||
type: Object,
|
||||
default() {
|
||||
return []
|
||||
}
|
||||
},
|
||||
readingTaskState: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
digitPlaces: 2
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
...mapGetters(['language'])
|
||||
},
|
||||
mounted() {
|
||||
this.digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
},
|
||||
methods: {
|
||||
formItemChange(v, question) {
|
||||
if (question.Childrens && question.Childrens.length > 0) {
|
||||
this.resetChild(question.Childrens)
|
||||
} else {
|
||||
if (question.Type === 'number') {
|
||||
v = this.limitBlur(question.ValueType, v)
|
||||
}
|
||||
this.$emit('setFormItemData', { key: question.Id, val: v })
|
||||
}
|
||||
},
|
||||
resetChild(obj) {
|
||||
obj.forEach(i => {
|
||||
this.$emit('resetFormItemData', i.Id)
|
||||
if (i.Childrens && i.Childrens.length > 0) {
|
||||
this.resetChild(i.Childrens)
|
||||
}
|
||||
})
|
||||
},
|
||||
limitBlur(valueType, value) {
|
||||
if (isNaN(parseInt(value))) {
|
||||
value = null
|
||||
} else {
|
||||
if (valueType === 0) {
|
||||
value = parseInt(value)
|
||||
} else if (valueType === 3) {
|
||||
value = parseFloat(value)
|
||||
} else {
|
||||
value = this.numberToFixed(value)
|
||||
}
|
||||
}
|
||||
return value
|
||||
},
|
||||
numberToFixed(v) {
|
||||
if (this.digitPlaces > -1) {
|
||||
return isNaN(parseFloat(v)) ? null : `${parseFloat(v).toFixed(this.digitPlaces)}`
|
||||
} else {
|
||||
return v
|
||||
}
|
||||
},
|
||||
resetFormItemData(v) {
|
||||
this.$emit('resetFormItemData', v)
|
||||
},
|
||||
setFormItemData(obj) {
|
||||
this.$emit('setFormItemData', obj)
|
||||
},
|
||||
limitNumbersEvent(e) {
|
||||
// 通过正则保留两位小数点
|
||||
let val = e.target.value
|
||||
if (val.length > 6) val = val.slice(0, 6)
|
||||
e.target.value = (val.match(/^\d*(\.?\d{0,3})/g)[0]) || null
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.mb{
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
.disabled{
|
||||
/deep/ .el-upload--picture-card {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.uploadWrapper{
|
||||
display: flex;
|
||||
flex-direction: column !important;
|
||||
align-items: flex-start;
|
||||
}
|
||||
/deep/ .el-input.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
/deep/ .el-input-group__append, .el-input-group__prepend{
|
||||
padding: 0 10px;
|
||||
}
|
||||
/deep/ .el-form-item__content {
|
||||
width: 100%;
|
||||
}
|
||||
/deep/ .el-select.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,125 @@
|
||||
<template>
|
||||
<el-form
|
||||
ref="uploadExcel"
|
||||
class="upload-excel-file"
|
||||
>
|
||||
<!-- 文件 -->
|
||||
<el-form-item :label="$t('trials:consistencyCheck:label:file')">
|
||||
<div class="upload-container">
|
||||
<el-upload
|
||||
class="upload-demo"
|
||||
action
|
||||
accept=".xlsx,.xls,.csv"
|
||||
:before-upload="beforeUpload"
|
||||
:http-request="handleUploadFile"
|
||||
:on-preview="handlePreview"
|
||||
:show-file-list="true"
|
||||
:limit="1"
|
||||
:on-exceed="handleExceed"
|
||||
>
|
||||
<el-button size="small" type="primary">
|
||||
{{ $t('trials:consistencyCheck:dialogButton:upload') }}
|
||||
</el-button>
|
||||
<span
|
||||
slot="tip"
|
||||
style="margin-left:10px;"
|
||||
class="el-upload__tip"
|
||||
>
|
||||
({{ $t('trials:consistencyCheck:message:excelFileOnly') }})
|
||||
</span>
|
||||
</el-upload>
|
||||
</div>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
</template>
|
||||
<script>
|
||||
import { uploadOCTFCTTemplate, uploadOCTLipidAngleTemplate } from '@/api/reading'
|
||||
export default {
|
||||
props: {
|
||||
visitTaskId: {
|
||||
type: String,
|
||||
required: true
|
||||
},
|
||||
lesionType: {
|
||||
type: Number,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
beforeUpload(file) {
|
||||
// 检测文件类型是否符合要求
|
||||
if (this.checkFileSuffix(file.name)) {
|
||||
return true
|
||||
} else {
|
||||
// Must be xls or xlsx format
|
||||
this.$alert(this.$t('trials:consistencyCheck:message:xlsx'))
|
||||
|
||||
return false
|
||||
}
|
||||
},
|
||||
async handleUploadFile(param) {
|
||||
const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
var data = new FormData()
|
||||
data.append('file', param.file)
|
||||
data.append('visitTaskId', this.visitTaskId)
|
||||
if (this.lesionType === 112) {
|
||||
await uploadOCTFCTTemplate(data)
|
||||
} else {
|
||||
await uploadOCTLipidAngleTemplate(data)
|
||||
}
|
||||
this.$emit('close')
|
||||
this.$message.success('导入成功!')
|
||||
loading.close()
|
||||
} catch (e) {
|
||||
loading.close()
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
handlePreview(file) {
|
||||
if (file.fullPath) {
|
||||
window.open(file.fullPath, '_blank')
|
||||
}
|
||||
},
|
||||
handleExceed(files, fileList) {
|
||||
// Upload is currently limited to 1 file
|
||||
this.$message.warning(this.$t('trials:consistencyCheck:message:onlyOneFile'))
|
||||
},
|
||||
checkFileSuffix(fileName) {
|
||||
var typeArr = ['xls', 'xlsx', 'csv']
|
||||
var extendName = fileName.substring(fileName.lastIndexOf('.') + 1).toLocaleLowerCase()
|
||||
if (typeArr.indexOf(extendName) !== -1) {
|
||||
return true
|
||||
} else {
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<style lang="scss">
|
||||
.upload-excel-file{
|
||||
.upload-container .el-upload--text {
|
||||
border: none;
|
||||
width: 80px;
|
||||
height: 40px;
|
||||
}
|
||||
.upload-container .el-input--small {
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
.upload-container .el-icon-circle-check {
|
||||
color: #428bca;
|
||||
font-size: 13px;
|
||||
}
|
||||
.account_item_clear{
|
||||
.el-tag__close{
|
||||
display: none !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="measurement-wrapper" :style="{'height':height+10+'px'}">
|
||||
<div class="measurement-wrapper">
|
||||
|
||||
<div class="container" :style="{'height':height+'px'}">
|
||||
<div class="container">
|
||||
<div class="basic-info">
|
||||
<h3 v-if="isReadingShowSubjectInfo">
|
||||
<span v-if="subjectCode">{{ subjectCode }} </span>
|
||||
@@ -147,7 +147,6 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
height: window.innerHeight - 140,
|
||||
questions: [],
|
||||
activeName: '',
|
||||
activeItem: {
|
||||
@@ -212,8 +211,6 @@ export default {
|
||||
callback(list)
|
||||
console.log('getAllUnSaveLesions')
|
||||
})
|
||||
|
||||
window.addEventListener('resize', this.setHeight)
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('setCollapseActive')
|
||||
@@ -802,6 +799,7 @@ export default {
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.measurement-wrapper{
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
// overflow: hidden;
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
{ required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary',
|
||||
message: ['radio', 'select', 'checkbox'].includes(question.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change']},
|
||||
]"
|
||||
:class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']"
|
||||
:class="[question.Type==='group' ? 'mb' : (question.Type==='upload' || question.QuestionName.length > 15) ?'uploadWrapper' : '']"
|
||||
>
|
||||
<template v-if="question.QuestionType === 60 || question.QuestionType === 61">
|
||||
<div style="display: flex;flex-direction: row;justify-content: flex-start;align-items: center;">
|
||||
@@ -211,16 +211,40 @@
|
||||
</el-checkbox>
|
||||
</el-checkbox-group>
|
||||
<!-- 数值 -->
|
||||
<el-input-number
|
||||
<!-- <el-input-number
|
||||
v-else-if="question.Type==='number'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask"
|
||||
/>
|
||||
:precision="2"
|
||||
/> -->
|
||||
<template v-else-if="question.Type==='number'">
|
||||
<el-input-number
|
||||
v-if="question.ValueType === 0"
|
||||
v-model="questionForm[question.Id]"
|
||||
:precision="0"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 3"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 1 || question.ValueType === 2"
|
||||
v-model="questionForm[question.Id]"
|
||||
:precision="digitPlaces"
|
||||
:disabled="readingTaskState >= 2 || isFirstChangeTask"
|
||||
/>
|
||||
</template>
|
||||
<el-input
|
||||
v-else-if="question.Type==='calculation'"
|
||||
v-model="questionForm[question.Id]"
|
||||
disabled
|
||||
/>
|
||||
>
|
||||
<template v-if="question.Unit" slot="append">
|
||||
{{ $fd('ValueUnit', parseInt(question.Unit)) }}
|
||||
</template>
|
||||
</el-input>
|
||||
<!-- 上传图像 -->
|
||||
<el-upload
|
||||
v-else-if="question.Type==='upload'"
|
||||
@@ -326,7 +350,8 @@ export default {
|
||||
accept: '.png,.jpg,.jpeg',
|
||||
imgVisible: false,
|
||||
imageUrl: '',
|
||||
urls: []
|
||||
urls: [],
|
||||
digitPlaces: 2
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -352,6 +377,8 @@ export default {
|
||||
})
|
||||
}
|
||||
}
|
||||
var digitPlaces = Number(localStorage.getItem('digitPlaces'))
|
||||
this.digitPlaces = digitPlaces === -1 ? this.digitPlaces : digitPlaces
|
||||
},
|
||||
methods: {
|
||||
formItemChange(v, question) {
|
||||
@@ -461,7 +488,7 @@ export default {
|
||||
}
|
||||
.uploadWrapper{
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-direction: column !important;
|
||||
align-items: flex-start;
|
||||
}
|
||||
/deep/ .el-input.is-disabled .el-input__inner{
|
||||
@@ -470,6 +497,9 @@ export default {
|
||||
/deep/ .el-input-group__append, .el-input-group__prepend{
|
||||
padding: 0 10px;
|
||||
}
|
||||
/deep/ .el-form-item__content {
|
||||
width: 100%;
|
||||
}
|
||||
/deep/ .el-select.is-disabled .el-input__inner{
|
||||
background-color: #646464a1;
|
||||
}
|
||||
|
||||
@@ -88,7 +88,7 @@ export default {
|
||||
spleenInfo: null,
|
||||
calculateSpleenStatus: '',
|
||||
formChanged: false,
|
||||
digitPlaces: null
|
||||
digitPlaces: 2
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
@@ -374,7 +374,8 @@ export default {
|
||||
DicomEvent.$emit('getReportInfo', true)
|
||||
// DicomEvent.$emit('readingPageUpdate', {})
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
if (idx > -1 && !this.visitTaskList[idx].IsBaseLineTask) {
|
||||
const criterionType = parseInt(localStorage.getItem('CriterionType'))
|
||||
if (idx > -1 && !this.visitTaskList[idx].IsBaseLineTask && (criterionType === 1 || criterionType === 2 || criterionType === 3 || criterionType === 17)) {
|
||||
if (parseInt(imageQuality) === 2) {
|
||||
this.$confirm(this.$t('trials:reading:warnning:unableEvaluate'), '', {
|
||||
type: 'warning'
|
||||
@@ -856,6 +857,7 @@ export default {
|
||||
.ecrf-wrapper{
|
||||
/deep/ .el-form-item__label{
|
||||
color: #c3c3c3;
|
||||
text-align: left;
|
||||
}
|
||||
/deep/ .el-input__inner{
|
||||
background-color: transparent;
|
||||
|
||||
@@ -57,6 +57,7 @@
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
:is-reading-task-view-in-order="isReadingTaskViewInOrder"
|
||||
:is-exists-manual="isExistsManual"
|
||||
:iseCRFShowInDicomReading="iseCRFShowInDicomReading"
|
||||
@previewCD="previewCD"
|
||||
/>
|
||||
</div>
|
||||
@@ -136,6 +137,10 @@ export default {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
iseCRFShowInDicomReading: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
},
|
||||
questionFormChangeState: {
|
||||
type: Boolean,
|
||||
default() {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="measurement-wrapper" :style="{'height':height+10+'px'}">
|
||||
<div class="measurement-wrapper">
|
||||
|
||||
<div class="container" :style="{'height':height+'px'}">
|
||||
<div class="container">
|
||||
<div class="basic-info">
|
||||
<h3 v-if="isReadingShowSubjectInfo">
|
||||
<span v-if="subjectCode">{{ subjectCode }} </span>
|
||||
@@ -169,7 +169,6 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
height: window.innerHeight - 140,
|
||||
questions: [],
|
||||
activeName: '',
|
||||
activeItem: {
|
||||
@@ -234,8 +233,6 @@ export default {
|
||||
DicomEvent.$on('split', measureData => {
|
||||
this.handleSplit(measureData.RowId, measureData.QuestionId)
|
||||
})
|
||||
|
||||
window.addEventListener('resize', this.setHeight)
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('setCollapseActive')
|
||||
@@ -416,9 +413,6 @@ export default {
|
||||
} catch (e) { console.log(e) }
|
||||
})
|
||||
},
|
||||
setHeight() {
|
||||
this.height = window.innerHeight - 140
|
||||
},
|
||||
getQuestionAnswer(questions, questionMark, answers) {
|
||||
var idx = questions.findIndex(i => i.QuestionMark === questionMark)
|
||||
if (idx > -1) {
|
||||
@@ -1065,6 +1059,7 @@ export default {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.measurement-wrapper{
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
// overflow: hidden;
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<template>
|
||||
<div class="measurement-wrapper" :style="{'height':height+10+'px'}">
|
||||
<div class="measurement-wrapper">
|
||||
|
||||
<div class="container" :style="{'height':height+'px'}">
|
||||
<div class="container">
|
||||
<div class="basic-info">
|
||||
<h3 v-if="isReadingShowSubjectInfo">
|
||||
<span v-if="subjectCode">{{ subjectCode }} </span>
|
||||
@@ -165,7 +165,6 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
height: window.innerHeight - 140,
|
||||
questions: [],
|
||||
activeName: '',
|
||||
activeItem: {
|
||||
@@ -229,8 +228,6 @@ export default {
|
||||
DicomEvent.$on('split', measureData => {
|
||||
this.handleSplit(measureData.RowId, measureData.QuestionId)
|
||||
})
|
||||
|
||||
window.addEventListener('resize', this.setHeight)
|
||||
},
|
||||
beforeDestroy() {
|
||||
DicomEvent.$off('loadMeasurementList')
|
||||
@@ -409,9 +406,6 @@ export default {
|
||||
} catch (e) { console.log(e) }
|
||||
})
|
||||
},
|
||||
setHeight() {
|
||||
this.height = window.innerHeight - 140
|
||||
},
|
||||
getQuestionAnswer(questions, questionMark, answers) {
|
||||
var idx = questions.findIndex(i => i.QuestionMark === questionMark)
|
||||
if (idx > -1) {
|
||||
@@ -994,6 +988,7 @@ export default {
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.measurement-wrapper{
|
||||
height: 100%;
|
||||
overflow-y: auto;
|
||||
// overflow: hidden;
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<span :style="{color: ((scope.row.isLymphNodes === 1 && scope.row.QuestionMark === 1) || (scope.row.isLymphNodes === 0 && scope.row.QuestionMark === 0)) && (scope.row.LesionType === 0 || scope.row.LesionType === 5) || (scope.row.QuestionMark === 12) || scope.row.HighlightAnswerList.includes(`${scope.row.Answers[task.VisitTaskId]}`) ? '#f66' : '#fff'}" >
|
||||
<span :style="{color: ((scope.row.isLymphNodes === 1 && scope.row.QuestionMark === 1) || (scope.row.isLymphNodes === 0 && scope.row.QuestionMark === 0)) && (scope.row.LesionType === 0 || scope.row.LesionType === 5) || (scope.row.QuestionMark === 12) || scope.row.HighlightAnswerList.includes(`${scope.row.Answers[task.VisitTaskId]}`) ? '#f66' : '#fff'}">
|
||||
<template v-if="task.VisitTaskId === visitTaskId && readingTaskState < 2 && [13,14,15,42].includes(scope.row.QuestionType)">
|
||||
<!-- 是否存在疾病(基线时可修改) -->
|
||||
<template v-if="task.IsBaseLine && scope.row.QuestionType=== 15">
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
>
|
||||
<div>
|
||||
<div>{{ instance.InstanceNumber }}</div>
|
||||
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}</div>
|
||||
<div>{{ `${instance.NumberOfFrames > 0 ? instance.KeyFramesList.length > 0 ? instance.KeyFramesList.length : instance.NumberOfFrames : 1} frame` }}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -294,7 +294,14 @@ export default {
|
||||
store.dispatch('reading/setImageloadedInfo', item)
|
||||
}
|
||||
})
|
||||
var i = res.findIndex(s => s.isCurrentTask)
|
||||
var i = -1
|
||||
var isReadingTaskViewInOrder = parseInt(this.$router.currentRoute.query.isReadingTaskViewInOrder)
|
||||
if (isReadingTaskViewInOrder === 2) {
|
||||
// 受试者内随机
|
||||
i = res.length === 2 ? 1 : -1
|
||||
} else {
|
||||
i = res.findIndex(s => s.isCurrentTask)
|
||||
}
|
||||
if (i > -1) {
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
if (idx > -1) {
|
||||
@@ -342,8 +349,9 @@ export default {
|
||||
this.studyList = this.visitTaskList[idx].StudyList
|
||||
var sIdx = this.studyList.findIndex(s => s.IsDicom)
|
||||
if (sIdx > -1) {
|
||||
this.studyIndex = sIdx
|
||||
this.seriesIndex = 0
|
||||
console.log(this.studyIndex, this.studyIndex)
|
||||
// this.studyIndex = sIdx
|
||||
// c = 0
|
||||
this.activeNames = [`${this.studyList[sIdx].StudyId}`]
|
||||
// 下载关键序列
|
||||
const i = this.studyList.findIndex(i => i.IsCriticalSequence)
|
||||
@@ -377,8 +385,23 @@ export default {
|
||||
var isReadingTaskViewInOrder = parseInt(this.$router.currentRoute.query.isReadingTaskViewInOrder)
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
this.studyList = this.visitTaskList[idx].StudyList
|
||||
if (this.visitTaskList[idx].IsBaseLineTask || isReadingTaskViewInOrder !== 1) {
|
||||
// 基线
|
||||
const studyList = this.visitTaskList[idx].StudyList.filter(i => i.IsDicom)
|
||||
const seriesArr = studyList.map(s => s.SeriesList).flat()
|
||||
if (isReadingTaskViewInOrder === 2) {
|
||||
// 受试者内随机
|
||||
if (seriesArr.length === 1) {
|
||||
seriesList.push(seriesArr[0], seriesArr[0])
|
||||
this.studyIndex = seriesArr[0].studyIndex
|
||||
this.seriesIndex = seriesArr[0].seriesIndex
|
||||
this.activeNames = [`${seriesArr[0].studyId}`]
|
||||
} else if (seriesArr.length > 1) {
|
||||
seriesList.push(seriesArr[0], seriesArr[1])
|
||||
this.studyIndex = seriesArr[1].studyIndex
|
||||
this.seriesIndex = seriesArr[1].seriesIndex
|
||||
this.activeNames = [`${seriesArr[1].studyId}`]
|
||||
}
|
||||
} else if (this.visitTaskList[idx].IsBaseLineTask || isReadingTaskViewInOrder === 0) {
|
||||
// 基线任务或完全随机
|
||||
const obj = this.getFirstMarkedSeries(this.visitTaskList[idx].MeasureData, [...this.visitTaskList[idx].StudyList])
|
||||
if (Object.keys(obj).length !== 0) {
|
||||
this.studyIndex = obj.studyIndex
|
||||
@@ -387,9 +410,13 @@ export default {
|
||||
this.activeNames = [`${this.studyList[ this.studyIndex].StudyId}`]
|
||||
this.studyList[ obj.studyIndex].SeriesList[obj.seriesIndex].isFirstRender = true
|
||||
} else {
|
||||
// 初始化问题表单
|
||||
if (this.studyList.length > 0) {
|
||||
this.activeNames = [`${this.studyList[0].StudyId}`]
|
||||
// 初始化问题表单
|
||||
this.studyIndex = seriesArr[0].studyIndex
|
||||
this.seriesIndex = seriesArr[0].seriesIndex
|
||||
this.activeNames = [`${seriesArr[0].studyId}`]
|
||||
seriesList.push(seriesArr[0])
|
||||
// this.activeNames = [`${this.studyList[0].StudyId}`]
|
||||
}
|
||||
|
||||
// DicomEvent.$emit('loadMeasurementList', { visitTaskId: this.visitTaskList[idx].VisitTaskId, taskBlindName: this.visitTaskList[idx].TaskBlindName })
|
||||
@@ -413,6 +440,7 @@ export default {
|
||||
|
||||
const firstObj = this.getFirstMarkedSeries(this.visitTaskList[bsIdx].MeasureData, [...this.visitTaskList[bsIdx].StudyList])
|
||||
seriesList.push(firstObj.series)
|
||||
|
||||
const secondObj = this.getSecondMarkedSeries(firstObj, { ...this.visitTaskList[idx] })
|
||||
this.studyIndex = secondObj.studyIndex
|
||||
this.seriesIndex = secondObj.seriesIndex
|
||||
@@ -552,22 +580,20 @@ export default {
|
||||
obj.series = seriesObj.series
|
||||
obj.seriesId = seriesObj.series.seriesId
|
||||
obj.isMarked = false
|
||||
} else {
|
||||
const sIdx = studyList.findIndex(s => s.IsDicom)
|
||||
if (sIdx > -1) {
|
||||
// 判断是否存在层厚为5的序列,否则显示第一个检查的第一个序列
|
||||
const series = studyList[sIdx].SeriesList[0]
|
||||
var imageIdIndex = series.imageIds.length > 1 ? Math.floor(series.imageIds.length / 2) - 1 : 0
|
||||
obj.studyIndex = sIdx
|
||||
obj.seriesIndex = 0
|
||||
obj.series = series
|
||||
obj.series.imageIdIndex = imageIdIndex >= 0 ? imageIdIndex : 0
|
||||
obj.seriesId = series.seriesId
|
||||
obj.isMarked = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(obj).length === 0) {
|
||||
const sIdx = studyList.findIndex(s => s.IsDicom)
|
||||
if (sIdx > -1) {
|
||||
obj.studyIndex = sIdx
|
||||
obj.seriesIndex = 0
|
||||
obj.series = studyList[obj.studyIndex].SeriesList[obj.seriesIndex]
|
||||
const imageIdIndex = Math.floor(obj.series.imageIds.length / 2)
|
||||
obj.series.imageIdIndex = imageIdIndex >= 0 ? imageIdIndex : 0
|
||||
// obj.seriesId = series.seriesId
|
||||
obj.isMarked = false
|
||||
}
|
||||
}
|
||||
return obj
|
||||
},
|
||||
strSimilarity2Number(s, t) {
|
||||
@@ -668,7 +694,11 @@ export default {
|
||||
this.currentSeriesIndex = seriesIndex
|
||||
var idx = this.visitTaskIdx
|
||||
const imageIds = []
|
||||
if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
|
||||
if (instanceInfo.KeyFramesList.length > 0) {
|
||||
instanceInfo.KeyFramesList.map(i => {
|
||||
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?frame=${i}&instanceId=${instanceInfo.Id}&visitTaskId=${this.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${idx}`)
|
||||
})
|
||||
} else if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
|
||||
for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
|
||||
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?frame=${j}&instanceId=${instanceInfo.Id}&visitTaskId=${this.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${idx}`)
|
||||
}
|
||||
|
||||
@@ -1064,16 +1064,15 @@ export default {
|
||||
var frame = imageInfo.frame
|
||||
this.stack.frame = this.stack.isExistMutiFrames ? parseInt(frame) : null
|
||||
this.stack.instanceId = instanceId
|
||||
const element = this.$refs.canvas
|
||||
cornerstone.enable(element)
|
||||
element.tabIndex = 0
|
||||
element.focus()
|
||||
const ToolStateManager = cornerstoneTools.globalImageIdSpecificToolStateManager
|
||||
ToolStateManager.clearImageIdToolState(dicomSeries.imageIds)
|
||||
this.toggleClipPlay(false)
|
||||
this.toolState.viewportInvert = false
|
||||
this.toolState.dicomInfoVisible = false
|
||||
|
||||
const element = this.$refs.canvas
|
||||
cornerstone.enable(element)
|
||||
element.tabIndex = 0
|
||||
element.focus()
|
||||
var scope = this
|
||||
// var p = parseInt(new Date().getTime())
|
||||
// requestPoolManager.loadAndCacheImagePlus(this.stack.imageIds[this.stack.currentImageIdIndex], this.stack.seriesId, p*100).then(image=>{
|
||||
@@ -1637,7 +1636,7 @@ export default {
|
||||
resetWwwc() {
|
||||
this.toolState.viewportInvert = false
|
||||
var viewport = cornerstone.getViewport(this.canvas)
|
||||
viewport.invert = false
|
||||
// viewport.invert = false
|
||||
var image = cornerstone.getImage(this.canvas)
|
||||
viewport.voi.windowWidth = image.windowWidth
|
||||
viewport.voi.windowCenter = image.windowCenter
|
||||
|
||||
@@ -106,7 +106,8 @@
|
||||
v-if="item.val === 1"
|
||||
class="divider"
|
||||
content-position="center"
|
||||
>{{ ` ${$t("trials:reading:title:preset")}` }}</el-divider>
|
||||
>{{ ` ${$t('trials:reading:title:preset')}` }}</el-divider
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -163,7 +164,7 @@
|
||||
<svg-icon icon-class="magnifier" class="svg-icon" />
|
||||
</div>
|
||||
<!-- 缩放 -->
|
||||
<div class="text">{{ $t("trials:reading:button:zoom") }}</div>
|
||||
<div class="text">{{ $t('trials:reading:button:zoom') }}</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
|
||||
@@ -183,7 +184,7 @@
|
||||
<svg-icon icon-class="move" class="svg-icon" />
|
||||
</div>
|
||||
<!-- 移动 -->
|
||||
<div class="text">{{ $t("trials:reading:button:move") }}</div>
|
||||
<div class="text">{{ $t('trials:reading:button:move') }}</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
|
||||
@@ -210,7 +211,7 @@
|
||||
</div>
|
||||
<!-- 旋转 -->
|
||||
<div class="text">
|
||||
{{ $t("trials:reading:button:rotate")
|
||||
{{ $t('trials:reading:button:rotate')
|
||||
}}<i class="el-icon-caret-bottom" />
|
||||
</div>
|
||||
<div class="dropdown-content">
|
||||
@@ -223,7 +224,8 @@
|
||||
<a
|
||||
href="#"
|
||||
@click.prevent="setDicomCanvasRotate(rotate.val)"
|
||||
>{{ rotate.label }}</a>
|
||||
>{{ rotate.label }}</a
|
||||
>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
@@ -258,8 +260,8 @@
|
||||
<div class="text">
|
||||
{{
|
||||
fitType === 1
|
||||
? $t("trials:reading:button:fitWindow")
|
||||
: $t("trials:reading:button:fitImage")
|
||||
? $t('trials:reading:button:fitWindow')
|
||||
: $t('trials:reading:button:fitImage')
|
||||
}}
|
||||
</div>
|
||||
</div>
|
||||
@@ -282,7 +284,7 @@
|
||||
</div>
|
||||
<!-- 同步 -->
|
||||
<div class="text">
|
||||
{{ $t("trials:reading:button:imageIndexSync") }}
|
||||
{{ $t('trials:reading:button:imageIndexSync') }}
|
||||
</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
@@ -307,7 +309,7 @@
|
||||
<svg-icon icon-class="image" class="svg-icon" />
|
||||
</div>
|
||||
<!-- 截屏 -->
|
||||
<div class="text">{{ $t("trials:reading:button:screenShot") }}</div>
|
||||
<div class="text">{{ $t('trials:reading:button:screenShot') }}</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
|
||||
@@ -316,7 +318,7 @@
|
||||
<div slot="content">
|
||||
<div v-if="tool.disabledReason">
|
||||
<h4 style="margin: 0; padding-bottom: 2px">{{ tool.text }}</h4>
|
||||
<br>{{ tool.disabledReason }}
|
||||
<br />{{ tool.disabledReason }}
|
||||
</div>
|
||||
<div v-else>{{ tool.text }}</div>
|
||||
</div>
|
||||
@@ -365,7 +367,7 @@
|
||||
<svg-icon icon-class="clear" class="svg-icon" />
|
||||
</div>
|
||||
<!-- 缩放 -->
|
||||
<div class="text">{{ $t("trials:dicom-show:Eraser") }}</div>
|
||||
<div class="text">{{ $t('trials:dicom-show:Eraser') }}</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<div class="tool-frame">
|
||||
@@ -467,11 +469,13 @@
|
||||
<div class="icon" @click.prevent="resetViewport">
|
||||
<svg-icon icon-class="refresh" class="svg-icon" />
|
||||
</div>
|
||||
<div class="text">{{ $t("trials:reading:button:reset") }}</div>
|
||||
<div class="text">{{ $t('trials:reading:button:reset') }}</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
v-if="trialCriterion.ImageUploadEnum > 0"
|
||||
v-if="
|
||||
trialCriterion.ImageUploadEnum > 0 && currentReadingTaskState < 2
|
||||
"
|
||||
v-hasPermi="['role:ir']"
|
||||
class="item"
|
||||
effect="dark"
|
||||
@@ -482,7 +486,7 @@
|
||||
<div class="icon" @click.prevent="openUploadImage('upload')">
|
||||
<i class="el-icon-upload2 svg-icon" />
|
||||
</div>
|
||||
<div class="text">{{ $t("trials:reading:button:upload") }}</div>
|
||||
<div class="text">{{ $t('trials:reading:button:upload') }}</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
<el-tooltip
|
||||
@@ -505,7 +509,7 @@
|
||||
<div class="icon" @click.prevent="openUploadImage('download')">
|
||||
<i class="el-icon-download svg-icon" />
|
||||
</div>
|
||||
<div class="text">{{ $t("trials:reading:button:download") }}</div>
|
||||
<div class="text">{{ $t('trials:reading:button:download') }}</div>
|
||||
</div>
|
||||
</el-tooltip>
|
||||
|
||||
@@ -515,17 +519,19 @@
|
||||
v-if="isExistsManual"
|
||||
type="text"
|
||||
@click="previewManuals"
|
||||
>{{ $t("trials:reading:button:handbooks") }}</el-button>
|
||||
>{{ $t('trials:reading:button:handbooks') }}</el-button
|
||||
>
|
||||
<!-- 临床数据 -->
|
||||
<el-button
|
||||
v-if="isExistsClinicalData"
|
||||
type="text"
|
||||
@click="previewCD"
|
||||
>{{ $t("trials:reading:button:clinicalData") }}</el-button>
|
||||
>{{ $t('trials:reading:button:clinicalData') }}</el-button
|
||||
>
|
||||
<!-- <el-button v-if="isExistsNoDicomFile" type="text" @click="previewNoneDicoms">非Dicom文件</el-button> -->
|
||||
|
||||
<el-button type="text" @click="previewConfig">{{
|
||||
$t("trials:reading:button:customCfg")
|
||||
$t('trials:reading:button:customCfg')
|
||||
}}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
@@ -625,7 +631,7 @@
|
||||
:fullscreen="isFullscreen"
|
||||
>
|
||||
<span slot="title" class="dialog-footer">
|
||||
<span>{{ $t("trials:reading:button:handbooks") }}</span>
|
||||
<span>{{ $t('trials:reading:button:handbooks') }}</span>
|
||||
<span style="position: absolute; right: 20px; font-size: 20px">
|
||||
<svg-icon
|
||||
:icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'"
|
||||
@@ -646,12 +652,29 @@
|
||||
<!-- <button :title="$t('trials:dicom-show:Eraser')" class="btn-link" data-tool="Eraser" @click="setToolActive($event,'Eraser')">-->
|
||||
<!-- <svg-icon icon-class="clear" style="font-size:20px;" />-->
|
||||
<!-- </button>-->
|
||||
<upload-image
|
||||
<!-- <upload-image
|
||||
v-if="uploadImageVisible"
|
||||
:visible.sync="uploadImageVisible"
|
||||
:subject-id="subjectId"
|
||||
:criterion="trialCriterion"
|
||||
:status="uploadStatus"
|
||||
/> -->
|
||||
<upload-dicom-and-nonedicom
|
||||
v-if="uploadImageVisible"
|
||||
:SubjectId="uploadSubjectId"
|
||||
:SubjectCode="uploadSubjectCode"
|
||||
:Criterion="uploadTrialCriterion"
|
||||
:visible.sync="uploadImageVisible"
|
||||
:VisitTaskId="taskId"
|
||||
:isReadingTaskViewInOrder="isReadingTaskViewInOrder"
|
||||
/>
|
||||
<download-dicom-and-nonedicom
|
||||
v-if="downloadImageVisible"
|
||||
:SubjectId="uploadSubjectId"
|
||||
:SubjectCode="uploadSubjectCode"
|
||||
:Criterion="uploadTrialCriterion"
|
||||
:TaskId="taskId"
|
||||
:visible.sync="downloadImageVisible"
|
||||
/>
|
||||
</div>
|
||||
</template>
|
||||
@@ -676,7 +699,8 @@ import DicomEvent from './../components/DicomEvent'
|
||||
import { mapGetters } from 'vuex'
|
||||
import store from '@/store'
|
||||
import { getDoctorShortcutKey, getUserWLTemplateList } from '@/api/user'
|
||||
import uploadImage from '@/components/uploadImage'
|
||||
import uploadDicomAndNonedicom from '@/components/uploadDicomAndNonedicom'
|
||||
import downloadDicomAndNonedicom from '@/components/downloadDicomAndNonedicom'
|
||||
import { getCriterionReadingInfo } from '@/api/trials'
|
||||
export default {
|
||||
name: 'DicomViewer',
|
||||
@@ -688,48 +712,49 @@ export default {
|
||||
Others,
|
||||
Manuals,
|
||||
MeasurementList,
|
||||
'upload-image': uploadImage
|
||||
'download-dicom-and-nonedicom': downloadDicomAndNonedicom,
|
||||
'upload-dicom-and-nonedicom': uploadDicomAndNonedicom,
|
||||
},
|
||||
props: {
|
||||
isExistsClinicalData: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
isExistsNoDicomFile: {
|
||||
type: Boolean,
|
||||
default: false
|
||||
default: false,
|
||||
},
|
||||
isExistsManual: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
isReadingShowSubjectInfo: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
isReadingTaskViewInOrder: {
|
||||
type: Number,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
IseCRFShowInDicomReading: {
|
||||
type: Boolean,
|
||||
required: true
|
||||
required: true,
|
||||
},
|
||||
subjectId: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
trialReadingCriterionId: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: ''
|
||||
default: '',
|
||||
},
|
||||
trialId: {
|
||||
type: String,
|
||||
required: true,
|
||||
default: ''
|
||||
}
|
||||
default: '',
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
@@ -738,7 +763,7 @@ export default {
|
||||
{ index: 0, row: 1, col: 1, name: 'A' },
|
||||
{ index: 1, row: 1, col: 2, name: 'A|A' },
|
||||
{ index: 2, row: 1, col: 2, name: 'A|B' },
|
||||
{ index: 3, row: 2, col: 2, name: 'A|A|A|A' }
|
||||
{ index: 3, row: 2, col: 2, name: 'A|A|A|A' },
|
||||
// { index: 2, row: 2, col: 1 },
|
||||
// { index: 3, row: 2, col: 2 }
|
||||
],
|
||||
@@ -747,7 +772,7 @@ export default {
|
||||
{ label: this.$t('trials:reading:button:rotateVertical'), val: 2 }, // 垂直翻转
|
||||
{ label: this.$t('trials:reading:button:rotateHorizontal'), val: 3 }, // 水平翻转
|
||||
{ label: this.$t('trials:reading:button:rotateTurnLeft'), val: 4 }, // 左转90度
|
||||
{ label: this.$t('trials:reading:button:rotateTurnRight'), val: 5 } // 右转90度
|
||||
{ label: this.$t('trials:reading:button:rotateTurnRight'), val: 5 }, // 右转90度
|
||||
],
|
||||
maxCanvas: 1,
|
||||
layoutRow: 1,
|
||||
@@ -755,8 +780,8 @@ export default {
|
||||
currentDicomCanvasIndex: 0,
|
||||
currentDicomCanvas: {
|
||||
toolState: {
|
||||
clipPlaying: false
|
||||
}
|
||||
clipPlaying: false,
|
||||
},
|
||||
},
|
||||
colormapsList: [],
|
||||
rotateList: [],
|
||||
@@ -773,7 +798,7 @@ export default {
|
||||
text: this.$t('trials:reading:button:length'),
|
||||
icon: 'length',
|
||||
isDisabled: false,
|
||||
disabledReason: ''
|
||||
disabledReason: '',
|
||||
},
|
||||
// 长短径测量
|
||||
{
|
||||
@@ -781,7 +806,7 @@ export default {
|
||||
text: this.$t('trials:reading:button:bidirectional'),
|
||||
icon: 'bidirection',
|
||||
isDisabled: false,
|
||||
disabledReason: ''
|
||||
disabledReason: '',
|
||||
},
|
||||
// 矩形工具
|
||||
{
|
||||
@@ -789,7 +814,7 @@ export default {
|
||||
text: this.$t('trials:reading:button:rectangle'),
|
||||
icon: 'rectangle',
|
||||
isDisabled: false,
|
||||
disabledReason: ''
|
||||
disabledReason: '',
|
||||
},
|
||||
// 圆形工具
|
||||
{
|
||||
@@ -797,7 +822,7 @@ export default {
|
||||
text: this.$t('trials:reading:button:elliptical'),
|
||||
icon: 'oval',
|
||||
isDisabled: false,
|
||||
disabledReason: ''
|
||||
disabledReason: '',
|
||||
},
|
||||
// 箭头工具
|
||||
{
|
||||
@@ -805,8 +830,8 @@ export default {
|
||||
text: this.$t('trials:reading:button:arrowAnnotate'),
|
||||
icon: 'arrow',
|
||||
isDisabled: false,
|
||||
disabledReason: ''
|
||||
}
|
||||
disabledReason: '',
|
||||
},
|
||||
],
|
||||
|
||||
fitType: 0,
|
||||
@@ -818,25 +843,25 @@ export default {
|
||||
label: this.$t('trials:reading:button:wwwcDefault'),
|
||||
val: -1,
|
||||
ww: null,
|
||||
wc: null
|
||||
wc: null,
|
||||
}, // 默认值
|
||||
{
|
||||
label: this.$t('trials:reading:button:wwwcCustom'),
|
||||
val: 0,
|
||||
ww: null,
|
||||
wc: null
|
||||
wc: null,
|
||||
}, // 自定义
|
||||
{
|
||||
label: this.$t('trials:reading:button:wwwcRegion'),
|
||||
val: 1,
|
||||
ww: null,
|
||||
wc: null
|
||||
wc: null,
|
||||
}, // 区域窗宽
|
||||
{ label: 'CT Brain', wc: 40, ww: 80 },
|
||||
{ label: 'CT Lungs', wc: -400, ww: 1500 },
|
||||
{ label: 'CT Abdomen', wc: 60, ww: 400 },
|
||||
{ label: 'CT Liver', wc: 40, ww: 400 },
|
||||
{ label: 'CT Bone', wc: 300, ww: 1500 }
|
||||
{ label: 'CT Bone', wc: 300, ww: 1500 },
|
||||
],
|
||||
activeSeries: {},
|
||||
seriesStack: [],
|
||||
@@ -844,13 +869,13 @@ export default {
|
||||
isScrollSync: false,
|
||||
imageIndexSync: {
|
||||
sourceCanvas: '',
|
||||
targetCanvas: []
|
||||
targetCanvas: [],
|
||||
},
|
||||
isFirstRender: false,
|
||||
customWwc: { visible: false, title: null }, // 自定义调窗
|
||||
personalConfigDialog: {
|
||||
visible: false,
|
||||
title: this.$t('trials:reading:button:customCfg')
|
||||
title: this.$t('trials:reading:button:customCfg'),
|
||||
}, // 个性化配置
|
||||
layout: '',
|
||||
isFirstNotLinked: false,
|
||||
@@ -861,15 +886,20 @@ export default {
|
||||
manualsDialog: { visible: false },
|
||||
clipPlaying: false,
|
||||
fps: 15,
|
||||
// 上传
|
||||
uploadImageVisible: false,
|
||||
trialCriterion: {},
|
||||
uploadStatus: 'upload'
|
||||
// 上传
|
||||
downloadImageVisible: false,
|
||||
uploadImageVisible: false,
|
||||
uploadSubjectId: null,
|
||||
uploadSubjectCode: null,
|
||||
uploadTrialCriterion: {},
|
||||
uploadStatus: 'upload',
|
||||
taskId: '',
|
||||
}
|
||||
},
|
||||
|
||||
computed: {
|
||||
...mapGetters(['visitTaskList', 'currentReadingTaskState'])
|
||||
...mapGetters(['visitTaskList', 'currentReadingTaskState']),
|
||||
},
|
||||
watch: {
|
||||
currentReadingTaskState: {
|
||||
@@ -888,7 +918,7 @@ export default {
|
||||
this.activeTool = ''
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
currentDicomCanvasIndex: {
|
||||
immediate: true,
|
||||
@@ -905,8 +935,8 @@ export default {
|
||||
this.clipPlaying = false
|
||||
this.fps = 15
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
this.getTrialCriterion()
|
||||
@@ -919,7 +949,7 @@ export default {
|
||||
// cornerstone.imageCache.setMaximumSizeBytes(maximumSizeInBytes)
|
||||
this.customWwc = {
|
||||
visible: false,
|
||||
title: this.$t('trials:reading:dagTitle:wwwcCustom')
|
||||
title: this.$t('trials:reading:dagTitle:wwwcCustom'),
|
||||
}
|
||||
this.CriterionType = parseInt(localStorage.getItem('CriterionType'))
|
||||
if (this.CriterionType === 10) {
|
||||
@@ -929,15 +959,15 @@ export default {
|
||||
text: this.$t('trials:reading:button:arrowAnnotate'),
|
||||
icon: 'arrow',
|
||||
isDisabled: false,
|
||||
disabledReason: ''
|
||||
disabledReason: '',
|
||||
},
|
||||
{
|
||||
toolName: 'RectangleRoi',
|
||||
text: this.$t('trials:reading:button:rectangle'),
|
||||
icon: 'rectangle',
|
||||
isDisabled: false,
|
||||
disabledReason: ''
|
||||
}
|
||||
disabledReason: '',
|
||||
},
|
||||
]
|
||||
} else if (this.CriterionType === 17) {
|
||||
this.measuredTools = [
|
||||
@@ -946,22 +976,22 @@ export default {
|
||||
text: this.$t('trials:reading:button:length'),
|
||||
icon: 'length',
|
||||
isDisabled: false,
|
||||
disabledReason: ''
|
||||
disabledReason: '',
|
||||
},
|
||||
{
|
||||
toolName: 'RectangleRoi',
|
||||
text: this.$t('trials:reading:button:rectangle'),
|
||||
icon: 'rectangle',
|
||||
isDisabled: false,
|
||||
disabledReason: ''
|
||||
disabledReason: '',
|
||||
},
|
||||
{
|
||||
toolName: 'ArrowAnnotate',
|
||||
text: this.$t('trials:reading:button:arrowAnnotate'),
|
||||
icon: 'arrow',
|
||||
isDisabled: false,
|
||||
disabledReason: ''
|
||||
}
|
||||
disabledReason: '',
|
||||
},
|
||||
]
|
||||
}
|
||||
this.rotateList[0] = '1'
|
||||
@@ -976,7 +1006,7 @@ export default {
|
||||
window.addEventListener('resize', this.setCanvasStyle)
|
||||
|
||||
// DicomEvent.$on('updateImage', (instanceId) => {
|
||||
|
||||
|
||||
// for (let i = 0; i < this.maxCanvas; i++) {
|
||||
// var stack = this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].stack
|
||||
// if (stack.studyId) {
|
||||
@@ -993,7 +1023,7 @@ export default {
|
||||
}
|
||||
console.log('getMeasureData')
|
||||
})
|
||||
|
||||
|
||||
DicomEvent.$on('getScreenshots', (callback) => {
|
||||
var base64Str =
|
||||
this.$refs[
|
||||
@@ -1041,7 +1071,7 @@ export default {
|
||||
getTrialCriterion() {
|
||||
getCriterionReadingInfo({
|
||||
TrialId: this.trialId,
|
||||
TrialReadingCriterionId: this.trialReadingCriterionId
|
||||
TrialReadingCriterionId: this.trialReadingCriterionId,
|
||||
})
|
||||
.then((res) => {
|
||||
this.trialCriterion = res.Result
|
||||
@@ -1049,26 +1079,32 @@ export default {
|
||||
.catch(() => {})
|
||||
},
|
||||
openUploadImage(status) {
|
||||
const idx = this.visitTaskList.findIndex((i) => i.IsCurrentTask)
|
||||
if (idx > -1) {
|
||||
this.taskId = this.visitTaskList[idx].VisitTaskId
|
||||
}
|
||||
this.uploadSubjectCode = this.$route.query.subjectCode||localStorage.getItem("subjectCode")
|
||||
this.uploadSubjectId = this.$route.query.subjectId||localStorage.getItem("subjectId")
|
||||
this.uploadTrialCriterion = this.trialCriterion
|
||||
this.uploadStatus = status
|
||||
this.uploadImageVisible = true
|
||||
this[`${status}ImageVisible`] = true
|
||||
},
|
||||
async getWwcTpl() {
|
||||
// const loading = this.$loading({ fullscreen: true })
|
||||
try {
|
||||
let res = await getUserWLTemplateList()
|
||||
this.customWwcTpl = []
|
||||
res.Result.map((i) => {
|
||||
this.customWwcTpl.push({
|
||||
label: i.TemplateName,
|
||||
wc: i.WL,
|
||||
ww: i.WW
|
||||
})
|
||||
res.Result.map((i) => {
|
||||
this.customWwcTpl.push({
|
||||
label: i.TemplateName,
|
||||
wc: i.WL,
|
||||
ww: i.WW,
|
||||
})
|
||||
this.wwwcArr = [...this.defaultWwwc, ...this.customWwcTpl]
|
||||
} catch(e) {
|
||||
})
|
||||
this.wwwcArr = [...this.defaultWwwc, ...this.customWwcTpl]
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
|
||||
},
|
||||
async getHotKeys() {
|
||||
// const loading = this.$loading({ fullscreen: true })
|
||||
@@ -1084,11 +1120,11 @@ export default {
|
||||
key: item.Keyboardkey,
|
||||
code: item.Code,
|
||||
text: item.Text,
|
||||
shortcutKeyEnum: item.ShortcutKeyEnum
|
||||
shortcutKeyEnum: item.ShortcutKeyEnum,
|
||||
})
|
||||
})
|
||||
this.bindHotKey()
|
||||
} catch(e) {
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
}
|
||||
},
|
||||
@@ -1105,7 +1141,7 @@ export default {
|
||||
key: item.keys.controlKey.key,
|
||||
code: item.keys.controlKey.code,
|
||||
text: item.keys.text,
|
||||
shortcutKeyEnum: item.label
|
||||
shortcutKeyEnum: item.label,
|
||||
})
|
||||
})
|
||||
|
||||
@@ -1148,7 +1184,7 @@ export default {
|
||||
DicomEvent.$emit('selectSeries', {
|
||||
seriesId: series.seriesId,
|
||||
studyId: series.studyId,
|
||||
offset: -1
|
||||
offset: -1,
|
||||
})
|
||||
} else if (shortcutKeyEnum === 4) {
|
||||
// 下一个序列
|
||||
@@ -1157,7 +1193,7 @@ export default {
|
||||
DicomEvent.$emit('selectSeries', {
|
||||
seriesId: series.seriesId,
|
||||
studyId: series.studyId,
|
||||
offset: 1
|
||||
offset: 1,
|
||||
})
|
||||
} else if (shortcutKeyEnum === 5) {
|
||||
// 上一张图像
|
||||
@@ -1287,7 +1323,7 @@ export default {
|
||||
top: '72px',
|
||||
left: '205px',
|
||||
right: '350px',
|
||||
zIndex: 10
|
||||
zIndex: 10,
|
||||
}
|
||||
this.canvasW = window.innerWidth - 570 + 'px'
|
||||
this.canvasH = window.innerHeight - 130 + 'px'
|
||||
@@ -1387,10 +1423,7 @@ export default {
|
||||
// this.$refs['measurementList'].initPage(dicomSeries)
|
||||
store.dispatch('reading/setActiveSeries', dicomSeries)
|
||||
if (this.currentDicomCanvasIndex === this.maxCanvas - 1) {
|
||||
store.dispatch(
|
||||
'reading/setLastCanvasTaskId',
|
||||
dicomSeries.visitTaskId
|
||||
)
|
||||
store.dispatch('reading/setLastCanvasTaskId', dicomSeries.visitTaskId)
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -1421,10 +1454,7 @@ export default {
|
||||
|
||||
store.dispatch('reading/setActiveSeries', dicomSeries)
|
||||
if (this.currentDicomCanvasIndex === this.maxCanvas - 1) {
|
||||
store.dispatch(
|
||||
'reading/setLastCanvasTaskId',
|
||||
dicomSeries.visitTaskId
|
||||
)
|
||||
store.dispatch('reading/setLastCanvasTaskId', dicomSeries.visitTaskId)
|
||||
}
|
||||
})
|
||||
},
|
||||
@@ -1474,7 +1504,7 @@ export default {
|
||||
visitTaskId = this.visitTaskList[i].VisitTaskId
|
||||
}
|
||||
this.getFirstSeries(activeSeries, visitTaskId).then(
|
||||
async(baseSerires) => {
|
||||
async (baseSerires) => {
|
||||
this.seriesStack = [baseSerires, activeSeries]
|
||||
this.currentDicomCanvasIndex = 1
|
||||
store.dispatch(
|
||||
@@ -1502,7 +1532,7 @@ export default {
|
||||
activeSeries,
|
||||
activeSeries,
|
||||
activeSeries,
|
||||
activeSeries
|
||||
activeSeries,
|
||||
]
|
||||
this.currentDicomCanvasIndex = 3
|
||||
store.dispatch(
|
||||
@@ -1521,9 +1551,7 @@ export default {
|
||||
for (let i = 0; i < this.maxCanvas && i < seriesStack.length; i++) {
|
||||
this.canvasObj[i] = seriesStack[i]
|
||||
let s = Object.assign({}, seriesStack[i])
|
||||
promiseArr.push(
|
||||
this.$refs[`dicomCanvas${i}`][0].loadImageStack(s)
|
||||
)
|
||||
promiseArr.push(this.$refs[`dicomCanvas${i}`][0].loadImageStack(s))
|
||||
}
|
||||
Promise.all(promiseArr)
|
||||
.then(() => {
|
||||
@@ -1585,24 +1613,24 @@ export default {
|
||||
trialId: this.trialId,
|
||||
subjectVisitId: this.visitTaskList[taskIdx].VisitId,
|
||||
visitTaskId: this.visitTaskList[taskIdx].VisitTaskId,
|
||||
taskBlindName: this.visitTaskList[taskIdx].TaskBlindName
|
||||
taskBlindName: this.visitTaskList[taskIdx].TaskBlindName,
|
||||
})
|
||||
}
|
||||
if (!this.visitTaskList[taskIdx].readingQuestionsInit) {
|
||||
await store.dispatch('reading/getReadingQuestionAndAnswer', {
|
||||
trialId: this.trialId,
|
||||
visitTaskId: this.visitTaskList[taskIdx].VisitTaskId
|
||||
visitTaskId: this.visitTaskList[taskIdx].VisitTaskId,
|
||||
})
|
||||
}
|
||||
if (!this.visitTaskList[taskIdx].questionsInit) {
|
||||
await store.dispatch('reading/getDicomReadingQuestionAnswer', {
|
||||
trialId: this.trialId,
|
||||
visitTaskId: this.visitTaskList[taskIdx].VisitTaskId
|
||||
visitTaskId: this.visitTaskList[taskIdx].VisitTaskId,
|
||||
})
|
||||
}
|
||||
|
||||
await store.dispatch('reading/setStatus', {
|
||||
visitTaskId: this.visitTaskList[taskIdx].VisitTaskId
|
||||
visitTaskId: this.visitTaskList[taskIdx].VisitTaskId,
|
||||
})
|
||||
}
|
||||
firstAddSeries = this.getSeriesInfoByMark(firstAddVisitTaskId, obj)
|
||||
@@ -1696,8 +1724,7 @@ export default {
|
||||
var studyList = this.visitTaskList[index].StudyList
|
||||
var studyId = this.visitTaskList[index].MeasureData[idx].StudyId
|
||||
var seriesId = this.visitTaskList[index].MeasureData[idx].SeriesId
|
||||
var instanceId =
|
||||
this.visitTaskList[index].MeasureData[idx].InstanceId
|
||||
var instanceId = this.visitTaskList[index].MeasureData[idx].InstanceId
|
||||
var studyIdx = studyList.findIndex(
|
||||
(study) => study.StudyId === studyId
|
||||
)
|
||||
@@ -1706,10 +1733,15 @@ export default {
|
||||
(s) => s.seriesId === seriesId
|
||||
)
|
||||
if (seriesIdx > -1) {
|
||||
var series = studyList[studyIdx].SeriesList[seriesIdx];
|
||||
let frame = this.visitTaskList[index].MeasureData[idx].MeasureData.frame
|
||||
let filterStr = series.isExistMutiFrames ? `frame=${frame}&instanceId=${instanceId}` : `instanceId=${instanceId}`
|
||||
var instanceIdx = series.imageIds.findIndex(imageId => imageId.includes(filterStr))
|
||||
var series = studyList[studyIdx].SeriesList[seriesIdx]
|
||||
let frame =
|
||||
this.visitTaskList[index].MeasureData[idx].MeasureData.frame
|
||||
let filterStr = series.isExistMutiFrames
|
||||
? `frame=${frame}&instanceId=${instanceId}`
|
||||
: `instanceId=${instanceId}`
|
||||
var instanceIdx = series.imageIds.findIndex((imageId) =>
|
||||
imageId.includes(filterStr)
|
||||
)
|
||||
// var instanceIdx = series.instanceList.findIndex(
|
||||
// (imageId) => !!~imageId.indexOf(instanceId)
|
||||
// );
|
||||
@@ -1738,16 +1770,14 @@ export default {
|
||||
i.description,
|
||||
baseSeries.description
|
||||
),
|
||||
index
|
||||
index,
|
||||
}
|
||||
})
|
||||
similarArr = similarArr.sort((a, b) => {
|
||||
return b.similar - a.similar
|
||||
})
|
||||
const i =
|
||||
similarArr[0] && similarArr[0].similar > 0.85
|
||||
? similarArr[0].index
|
||||
: -1
|
||||
similarArr[0] && similarArr[0].similar > 0.85 ? similarArr[0].index : -1
|
||||
if (i > -1) {
|
||||
obj = seriesList[i]
|
||||
}
|
||||
@@ -1822,7 +1852,7 @@ export default {
|
||||
trialId: this.trialId,
|
||||
subjectVisitId: this.visitTaskList[index].VisitId,
|
||||
visitTaskId: this.visitTaskList[index].VisitTaskId,
|
||||
taskBlindName: this.visitTaskList[index].TaskBlindName
|
||||
taskBlindName: this.visitTaskList[index].TaskBlindName,
|
||||
})
|
||||
|
||||
await store.dispatch(
|
||||
@@ -1841,16 +1871,14 @@ export default {
|
||||
i.description,
|
||||
baseSeries.description
|
||||
),
|
||||
index
|
||||
index,
|
||||
}
|
||||
})
|
||||
similarArr = similarArr.sort((a, b) => {
|
||||
return b.similar - a.similar
|
||||
})
|
||||
const i =
|
||||
similarArr[0] && similarArr[0].similar > 0.85
|
||||
? similarArr[0].index
|
||||
: -1
|
||||
similarArr[0] && similarArr[0].similar > 0.85 ? similarArr[0].index : -1
|
||||
if (i > -1) {
|
||||
obj = seriesList[i]
|
||||
}
|
||||
@@ -2025,9 +2053,7 @@ export default {
|
||||
},
|
||||
// 鼠标移入测量工具时,判断工具是否可激活
|
||||
enter(e, toolName) {
|
||||
var i = this.measuredTools.findIndex(
|
||||
(item) => item.toolName === toolName
|
||||
)
|
||||
var i = this.measuredTools.findIndex((item) => item.toolName === toolName)
|
||||
if (i === -1) return
|
||||
var isCurrentTask =
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0]
|
||||
@@ -2089,8 +2115,11 @@ export default {
|
||||
`dicomCanvas${this.currentDicomCanvasIndex}`
|
||||
][0].setToolActive(toolName)
|
||||
}
|
||||
} else if (dicomSeries.isCurrentTask &&
|
||||
isMeasuredTool && dicomSeries.readingTaskState >= 2) {
|
||||
} else if (
|
||||
dicomSeries.isCurrentTask &&
|
||||
isMeasuredTool &&
|
||||
dicomSeries.readingTaskState >= 2
|
||||
) {
|
||||
if (this.activeTool === toolName) {
|
||||
this.$refs[
|
||||
`dicomCanvas${this.currentDicomCanvasIndex}`
|
||||
@@ -2162,9 +2191,7 @@ export default {
|
||||
][0].fitToWindow()
|
||||
} else if (toolName === 'fitToImage') {
|
||||
this.fitType = 1
|
||||
this.$refs[
|
||||
`dicomCanvas${this.currentDicomCanvasIndex}`
|
||||
][0].fitToImage()
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].fitToImage()
|
||||
}
|
||||
this.activeTool = toolName
|
||||
},
|
||||
@@ -2181,7 +2208,9 @@ export default {
|
||||
const isLoaded = this.getSeriesLoadStatus()
|
||||
if (!isLoaded) return
|
||||
this.clipPlaying = isPlay
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setFps(this.fps)
|
||||
this.$refs[`dicomCanvas${this.currentDicomCanvasIndex}`][0].setFps(
|
||||
this.fps
|
||||
)
|
||||
this.$refs[
|
||||
`dicomCanvas${this.currentDicomCanvasIndex}`
|
||||
][0].toggleClipPlay(isPlay)
|
||||
@@ -2297,8 +2326,8 @@ export default {
|
||||
previewManuals() {
|
||||
this.isFullscreen = false
|
||||
this.manualsDialog.visible = true
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
|
||||
@@ -25,14 +25,14 @@
|
||||
</div>
|
||||
<div class="questions-footer">
|
||||
<i class="el-icon-question feedback-icon" @click="openFeedBackTable" />
|
||||
<el-button v-if="readingTaskState<2" style="margin-right: 10px" size="small" @click="handleSave(true)">
|
||||
<el-button v-if="readingTaskState<2" style="margin-right: 10px" type="primary" size="small" @click="handleSave(true)">
|
||||
{{$t('common:button:save')}}
|
||||
</el-button>
|
||||
<el-button v-if="readingTaskState<2 && IseCRFShowInDicomReading" type="primary" size="small" @click="skipTask">
|
||||
<el-button v-if="readingTaskState<2 && IseCRFShowInDicomReading" type="primary" style="margin-right: 10px" size="small" @click="skipTask">
|
||||
<!-- 跳过 -->
|
||||
{{ $t('trials:readingReport:button:skip') }}
|
||||
</el-button>
|
||||
<el-button style="margin-right: 10px" size="small" v-if="readingTaskState<2 && IseCRFShowInDicomReading" @click="handleConfirm">
|
||||
<el-button style="margin-right: 10px" type="primary" size="small" v-if="readingTaskState<2 && IseCRFShowInDicomReading" @click="handleConfirm">
|
||||
{{ $t('common:button:submit') }}</el-button>
|
||||
</div>
|
||||
<!-- 签名框 -->
|
||||
@@ -244,6 +244,7 @@ export default {
|
||||
params.StudyId = params.questionInfo.StudyId
|
||||
params.SeriesId = params.questionInfo.SeriesId
|
||||
params.InstanceId = params.questionInfo.InstanceId
|
||||
params.NumberOfFrames = measureData.frame
|
||||
submitCustomTag(params).then(() => {
|
||||
this.measuredDataVisible = false
|
||||
DicomEvent.$emit('updateImage')
|
||||
@@ -282,6 +283,7 @@ export default {
|
||||
} else {
|
||||
let params = JSON.parse(JSON.stringify(this.measureData))
|
||||
params.measureData = JSON.stringify(this.measureData)
|
||||
params.NumberOfFrames = this.measureData.frame
|
||||
submitCustomTag(params).then(async (res) => {
|
||||
this.measuredDataVisible = false
|
||||
this.form.measuredDataName = ''
|
||||
|
||||
+1
-1
@@ -82,7 +82,7 @@ export default {
|
||||
var answers = []
|
||||
for (const k in this.questionForm) {
|
||||
if (this.questionForm[k] instanceof Array) {} else {
|
||||
answers.push({ id: k, answer: this.questionForm[k].toString() })
|
||||
answers.push({ id: k, answer: this.questionForm[k] })
|
||||
}
|
||||
}
|
||||
var params = {
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
</div> -->
|
||||
<div>
|
||||
<div>{{ instance.InstanceNumber }}</div>
|
||||
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}</div>
|
||||
<div>{{ `${instance.NumberOfFrames > 0 ? instance.KeyFramesList.length > 0 ? instance.KeyFramesList.length : instance.NumberOfFrames : 1} frame` }}</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -279,7 +279,14 @@ export default {
|
||||
store.dispatch('reading/setImageloadedInfo', item)
|
||||
}
|
||||
})
|
||||
var i = res.findIndex(s => s.isCurrentTask)
|
||||
var i = -1
|
||||
var isReadingTaskViewInOrder = parseInt(this.$router.currentRoute.query.isReadingTaskViewInOrder)
|
||||
if (isReadingTaskViewInOrder === 2) {
|
||||
// 受试者内随机
|
||||
i = res.length === 2 ? 1 : -1
|
||||
} else {
|
||||
i = res.findIndex(s => s.isCurrentTask)
|
||||
}
|
||||
if (i > -1) {
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
if (idx > -1) {
|
||||
@@ -356,7 +363,22 @@ export default {
|
||||
var isReadingTaskViewInOrder = JSON.parse(this.$router.currentRoute.query.isReadingTaskViewInOrder)
|
||||
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
|
||||
this.studyList = this.visitTaskList[idx].StudyList
|
||||
if (this.visitTaskList[idx].IsBaseLineTask || isReadingTaskViewInOrder !== 1) {
|
||||
if (isReadingTaskViewInOrder === 2) {
|
||||
// 受试者内随机
|
||||
const studyList = this.visitTaskList[idx].StudyList.filter(i => i.IsDicom)
|
||||
const seriesArr = studyList.map(s => s.SeriesList).flat()
|
||||
if (seriesArr.length === 1) {
|
||||
seriesList.push(seriesArr[0], seriesArr[0])
|
||||
this.studyIndex = seriesArr[0].studyIndex
|
||||
this.seriesIndex = seriesArr[0].seriesIndex
|
||||
this.activeNames = [`${seriesArr[0].studyId}`]
|
||||
} else if (seriesArr.length > 1) {
|
||||
seriesList.push(seriesArr[0], seriesArr[1])
|
||||
this.studyIndex = seriesArr[1].studyIndex
|
||||
this.seriesIndex = seriesArr[1].seriesIndex
|
||||
this.activeNames = [`${seriesArr[1].studyId}`]
|
||||
}
|
||||
} else if (this.visitTaskList[idx].IsBaseLineTask || isReadingTaskViewInOrder === 0){
|
||||
// 基线
|
||||
const obj = this.getFirstMarkedSeries(this.visitTaskList[idx].MeasureData, [...this.visitTaskList[idx].StudyList])
|
||||
if (Object.keys(obj).length !== 0) {
|
||||
@@ -533,19 +555,18 @@ export default {
|
||||
obj.series = seriesObj.series
|
||||
obj.seriesId = seriesObj.series.seriesId
|
||||
obj.isMarked = false
|
||||
} else {
|
||||
const sIdx = studyList.findIndex(s => s.IsDicom)
|
||||
if (sIdx > -1) {
|
||||
// 判断是否存在层厚为5的序列,否则显示第一个检查的第一个序列
|
||||
const series = studyList[sIdx].SeriesList[0]
|
||||
var imageIdIndex = series.imageIds.length > 1 ? Math.floor(series.imageIds.length / 2) - 1 : 0
|
||||
obj.studyIndex = sIdx
|
||||
obj.seriesIndex = 0
|
||||
obj.series = series
|
||||
obj.series.imageIdIndex = imageIdIndex >= 0 ? imageIdIndex : 0
|
||||
obj.seriesId = series.seriesId
|
||||
obj.isMarked = false
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Object.keys(obj).length === 0) {
|
||||
const sIdx = studyList.findIndex(s => s.IsDicom)
|
||||
if (sIdx > -1) {
|
||||
obj.studyIndex = sIdx
|
||||
obj.seriesIndex = 0
|
||||
obj.series = studyList[obj.studyIndex].SeriesList[obj.seriesIndex]
|
||||
const imageIdIndex = Math.floor(obj.series.imageIds.length / 2)
|
||||
obj.series.imageIdIndex = imageIdIndex >= 0 ? imageIdIndex : 0
|
||||
// obj.seriesId = series.seriesId
|
||||
obj.isMarked = false
|
||||
}
|
||||
}
|
||||
|
||||
@@ -652,7 +673,11 @@ export default {
|
||||
this.studyList[studyIndex].SeriesList[seriesIndex].measureData = this.measureData
|
||||
var dicomStatck = Object.assign({},this.studyList[studyIndex].SeriesList[seriesIndex])
|
||||
const imageIds = []
|
||||
if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
|
||||
if (instanceInfo.KeyFramesList.length > 0) {
|
||||
instanceInfo.KeyFramesList.map(i => {
|
||||
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?frame=${i}&instanceId=${instanceInfo.Id}&visitTaskId=${this.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${idx}`)
|
||||
})
|
||||
} else if (instanceInfo.NumberOfFrames && instanceInfo.NumberOfFrames > 1) {
|
||||
for (let j = 0; j < instanceInfo.NumberOfFrames; j++) {
|
||||
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?frame=${j}&instanceId=${instanceInfo.Id}&visitTaskId=${this.visitTaskId}&idx=${studyIndex}|${seriesIndex}|${idx}`)
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
</div>
|
||||
<div class="right-wrapper">
|
||||
<div class="right-content">
|
||||
<iframe v-if="selected.filePath" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${selected.filePath}?userName=${currentUser}`" width="100%" height="100%" frameborder="0" />
|
||||
<iframe v-if="selected.filePath" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${selected.filePath}?userName=${currentUser}&COMPANY=${COMPANY}`" width="100%" height="100%" frameborder="0" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -44,7 +44,8 @@ export default {
|
||||
},
|
||||
fileList: [],
|
||||
loading: false,
|
||||
currentUser: zzSessionStorage.getItem('userName')
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
COMPANY:process.env.VUE_APP_COMPANY_NAME
|
||||
}
|
||||
},
|
||||
mounted() {
|
||||
|
||||
@@ -19,11 +19,12 @@
|
||||
:is-exists-clinical-data="isExistsClinicalData"
|
||||
:is-exists-no-dicom-file="isExistsNoDicomFile"
|
||||
:is-exists-manual="isExistsManual"
|
||||
:ise-c-r-f-show-in-dicom-reading="IseCRFShowInDicomReading"
|
||||
@previewCD="previewCD"
|
||||
/>
|
||||
</el-tab-pane>
|
||||
<!-- 报告 -->
|
||||
<el-tab-pane :label="$t('trials:reading:tabTitle:report')" name="report">
|
||||
<el-tab-pane v-if="!IseCRFShowInDicomReading" :label="$t('trials:reading:tabTitle:report')" name="report">
|
||||
<ReportPage v-if="tabs.includes('report') && isShow" ref="reportPage" :question-form-change-state="questionFormChangeState" :visit-task-id="visitTaskId" />
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
@@ -267,7 +268,7 @@ export default {
|
||||
// this.readingTool = this.$router.currentRoute.query.readingTool
|
||||
this.TrialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
// this.isNewSubject = this.$router.currentRoute.query.isNewSubject
|
||||
localStorage.setItem('isReadingTaskViewInOrder', this.isReadingTaskViewInOrder)
|
||||
|
||||
// if (this.isNewSubject && this.isReadingTaskViewInOrder !== 0) {
|
||||
// // 已开始受试者${this.subjectCode}阅片任务
|
||||
// var msg = this.$t('trials:reading:warnning:msg1')
|
||||
@@ -318,6 +319,7 @@ export default {
|
||||
// }
|
||||
// }
|
||||
this.subjectId = res.Result.SubjectId
|
||||
localStorage.setItem('subjectId', res.Result.SubjectId)
|
||||
this.subjectCode = res.Result.SubjectCode
|
||||
localStorage.setItem('subjectCode', res.Result.SubjectCode)
|
||||
this.taskBlindName = res.Result.TaskBlindName
|
||||
@@ -332,6 +334,7 @@ export default {
|
||||
this.digitPlaces = res.Result.DigitPlaces
|
||||
this.IseCRFShowInDicomReading = res.Result.IseCRFShowInDicomReading
|
||||
this.isReadingTaskViewInOrder = res.Result.IsReadingTaskViewInOrder
|
||||
localStorage.setItem('isReadingTaskViewInOrder', this.isReadingTaskViewInOrder)
|
||||
localStorage.setItem('CriterionType', res.Result.CriterionType)
|
||||
localStorage.setItem('digitPlaces', res.Result.DigitPlaces)
|
||||
this.readingCategory = res.Result.ReadingCategory
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
</div>
|
||||
<!-- 文件层级 -->
|
||||
<div v-if="study.NoneDicomStudyFileList.length === 0" class="empty-text">
|
||||
<slot name="empty">暂无数据</slot>
|
||||
<slot name="empty">{{ $t('trials:audit:message:noData') }}</slot>
|
||||
</div>
|
||||
<div v-else id="imgList" style="height:100%;">
|
||||
<div
|
||||
@@ -28,7 +28,14 @@
|
||||
class="img-box"
|
||||
@click="selected(item,i,j,true)"
|
||||
>
|
||||
{{ `${j+1}. ${item.FileName}` }}
|
||||
<div v-if="item.FileName.length < 15" class="img-text">
|
||||
{{ `${j+1}. ${item.FileName}` }}
|
||||
</div>
|
||||
<el-tooltip v-else :content="item.FileName" placement="bottom">
|
||||
<div class="img-text">
|
||||
{{ `${j+1}. ${item.FileName}` }}
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -96,7 +103,7 @@ export default {
|
||||
visistTaskId: '',
|
||||
taskBlindName: '',
|
||||
readingTaskState: 2,
|
||||
bp:[]
|
||||
bp: []
|
||||
}
|
||||
},
|
||||
async mounted() {
|
||||
@@ -188,7 +195,7 @@ export default {
|
||||
}
|
||||
var arr = bodyPart.split(separator)
|
||||
var newArr = arr.map(i => {
|
||||
return this.$fd('Bodypart', i.trim(),'Code',{Bodypart:this.bp},'Name')
|
||||
return this.$fd('Bodypart', i.trim(), 'Code', { Bodypart: this.bp }, 'Name')
|
||||
})
|
||||
return newArr.join(' | ')
|
||||
}
|
||||
@@ -265,13 +272,19 @@ export default {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 2px solid #f3f3f3;
|
||||
width: 180px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
cursor: pointer;
|
||||
// margin-bottom: 5px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
.img-text{
|
||||
display: inline-block;
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; /* 用省略号表示溢出的文本 */
|
||||
white-space: nowrap;
|
||||
}
|
||||
.img-box:nth-last-child(1){
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
@@ -486,9 +486,13 @@ export default {
|
||||
}
|
||||
/deep/ .el-upload-list__item {
|
||||
transition: none !important;
|
||||
width: 140px;
|
||||
height: 140px;
|
||||
margin: 0 10px 5px 0;
|
||||
}
|
||||
/deep/ .el-upload-list__item-thumbnail {
|
||||
/* 图片在方框内显示长边 */
|
||||
width: 100%;
|
||||
object-fit: scale-down !important;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<template>
|
||||
<div v-loading="loading" style="min-height:500px">
|
||||
<div style="min-height:500px">
|
||||
<h3 v-if="isReadingShowSubjectInfo" style="padding: 5px 0px;margin: 0;">
|
||||
<span v-if="subjectCode">{{ subjectCode }} </span>
|
||||
<span style="margin-left:5px;">{{ taskBlindName }}</span>
|
||||
|
||||
@@ -120,11 +120,26 @@
|
||||
</el-checkbox-group>
|
||||
<!-- 数值 -->
|
||||
<!-- :precision="2" :step="0.1" :max="10" -->
|
||||
<el-input-number
|
||||
v-if="question.Type==='number'"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
/>
|
||||
<template v-if="question.Type==='number'">
|
||||
<el-input-number
|
||||
v-if="question.ValueType === 0"
|
||||
v-model="questionForm[question.Id]"
|
||||
precision="0"
|
||||
:disabled="readingTaskState >= 2"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 3"
|
||||
v-model="questionForm[question.Id]"
|
||||
:disabled="readingTaskState >= 2"
|
||||
/>
|
||||
<el-input-number
|
||||
v-else-if="question.ValueType === 1 || question.ValueType === 2"
|
||||
v-model="questionForm[question.Id]"
|
||||
:precision="digitPlaces"
|
||||
:disabled="readingTaskState >= 2"
|
||||
/>
|
||||
</template>
|
||||
|
||||
<!-- 上传图像 -->
|
||||
<el-upload
|
||||
v-if="question.Type==='upload'"
|
||||
@@ -222,7 +237,8 @@ export default {
|
||||
accept: '.png,.jpg,.jpeg',
|
||||
imgVisible: false,
|
||||
imageUrl: '',
|
||||
urls: []
|
||||
urls: [],
|
||||
digitPlaces: null
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -245,6 +261,7 @@ export default {
|
||||
})
|
||||
}
|
||||
}
|
||||
this.digitPlaces = parseInt(localStorage.getItem('digitPlaces'))
|
||||
},
|
||||
methods: {
|
||||
formItemChange(v, question) {
|
||||
|
||||
@@ -20,17 +20,17 @@
|
||||
<!-- 跳过 -->
|
||||
{{ $t('trials:readingReport:button:skip') }}
|
||||
</el-button>
|
||||
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="getReportInfo">{{$t('trials:readingReport:button:refresh')}}</el-button>
|
||||
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="handleSave(true)">{{$t('common:button:save')}}</el-button>
|
||||
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="handleConfirm">{{$t('common:button:submit')}}</el-button>
|
||||
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="getReportInfo">{{ $t('trials:readingReport:button:refresh') }}</el-button>
|
||||
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="handleSave(true)">{{ $t('common:button:save') }}</el-button>
|
||||
<el-button v-if="readingTaskState<2" type="primary" size="small" @click="handleConfirm">{{ $t('common:button:submit') }}</el-button>
|
||||
</div>
|
||||
</div>
|
||||
<div style="flex: 1">
|
||||
<el-table
|
||||
v-if="taskQuestions.length > 0"
|
||||
ref="reportList"
|
||||
v-adaptive="{bottomOffset:0}"
|
||||
:data="taskQuestions"
|
||||
v-if="taskQuestions.length > 0"
|
||||
row-key="Id"
|
||||
border
|
||||
default-expand-all
|
||||
@@ -69,30 +69,29 @@
|
||||
<div>
|
||||
{{ task.BlindName }}
|
||||
<el-button type="text" size="small" @click="previewDicoms(task)">
|
||||
<span class="el-icon-view"></span>
|
||||
<span class="el-icon-view" />
|
||||
</el-button>
|
||||
</div>
|
||||
<!-- <div v-if="task.LatestScanDate">-->
|
||||
<!-- {{ task.LatestScanDate.split(' ')[0] }}-->
|
||||
<!-- </div>-->
|
||||
<!-- <div v-if="task.LatestScanDate">-->
|
||||
<!-- {{ task.LatestScanDate.split(' ')[0] }}-->
|
||||
<!-- </div>-->
|
||||
<!-- {{ `(影像点击跳转)` }} -->
|
||||
<!-- {{ $t('trials:readingReport:button:jump') }}-->
|
||||
</div>
|
||||
</template>
|
||||
<template slot-scope="scope">
|
||||
<template v-if="readingTaskState<2 && task.VisitTaskId === visitTaskId && (scope.row.Type==='input' || scope.row.Type==='number' || scope.row.Type==='select' || scope.row.Type==='textarea' || scope.row.Type==='radio')">
|
||||
<template v-if="readingTaskState<2 && task.VisitTaskId === visitTaskId && (scope.row.Type==='input' || scope.row.Type==='number' || scope.row.Type==='select' || scope.row.Type==='textarea' || scope.row.Type==='radio')">
|
||||
<template>
|
||||
<!-- 输入框 -->
|
||||
<div>
|
||||
<template v-if="!((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)">
|
||||
</template>
|
||||
<template v-if="!((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)" />
|
||||
<el-input
|
||||
v-else-if="questionForm[scope.row.QuestionId] instanceof Array && (scope.row.Type==='input' || scope.row.Type==='textarea') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
v-else-if="questionForm[scope.row.QuestionId] instanceof Array && (scope.row.Type==='input' || scope.row.Type==='textarea') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
v-model="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
|
||||
size="mini"
|
||||
/>
|
||||
<span v-else-if="questionForm[scope.row.QuestionId] instanceof Array && (scope.row.Type==='input' || scope.row.Type==='textarea')">
|
||||
{{questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]}}
|
||||
{{ questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId] }}
|
||||
</span>
|
||||
<el-input
|
||||
v-else-if="(scope.row.Type==='input' || scope.row.Type==='textarea') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
@@ -100,10 +99,10 @@
|
||||
size="mini"
|
||||
/>
|
||||
<span v-else-if="scope.row.Type==='input' || scope.row.Type==='textarea'">
|
||||
{{questionForm[scope.row.QuestionId]}}
|
||||
{{ questionForm[scope.row.QuestionId] }}
|
||||
</span>
|
||||
<el-select
|
||||
v-else-if="questionForm[scope.row.QuestionId] instanceof Array && (scope.row.Type==='select' || scope.row.Type==='radio') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
v-else-if="questionForm[scope.row.QuestionId] instanceof Array && (scope.row.Type==='select' || scope.row.Type==='radio') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
v-model="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
|
||||
size="mini"
|
||||
clearable
|
||||
@@ -118,7 +117,7 @@
|
||||
</template>
|
||||
</el-select>
|
||||
<span v-else-if="questionForm[scope.row.QuestionId] instanceof Array && scope.row.Type==='select'">
|
||||
{{questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]}}
|
||||
{{ questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId] }}
|
||||
</span>
|
||||
<el-select
|
||||
v-else-if="(scope.row.Type==='select' || scope.row.Type==='radio') && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
@@ -136,19 +135,18 @@
|
||||
</template>
|
||||
</el-select>
|
||||
<span v-else-if="scope.row.Type==='select' || scope.row.Type==='radio'">
|
||||
{{questionForm[scope.row.QuestionId]}}
|
||||
{{ questionForm[scope.row.QuestionId] }}
|
||||
</span>
|
||||
<el-input
|
||||
v-else-if="scope.row.DataSource !== 1 && questionForm[scope.row.QuestionId] instanceof Array && scope.row.Type==='number' && (scope.row.xfIndex || scope.row.xfIndex === 0) && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
v-model="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
|
||||
:disabled="scope.row.DataSource === 1"
|
||||
onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')))"
|
||||
@input="limitInput($event, questionForm[scope.row.QuestionId][scope.row.xfIndex], scope.row.TableQuestionId)"
|
||||
size="mini"
|
||||
@blur="limitBlur(questionForm[scope.row.QuestionId][scope.row.xfIndex], scope.row.TableQuestionId, scope.row.ValueType)"
|
||||
@focus="() => {questionId = scope.row.QuestionId}"
|
||||
>
|
||||
<template slot="append" v-if="scope.row.Unit !== 0">{{scope.row.Unit !== 4 ? $fd('ValueUnit', scope.row.Unit) : scope.row.CustomUnit}}</template>
|
||||
<template slot="append" v-else-if="scope.row.ValueType === 2">%</template>
|
||||
<template v-if="scope.row.Unit !== 0" slot="append">{{ scope.row.Unit !== 4 ? $fd('ValueUnit', scope.row.Unit) : scope.row.CustomUnit }}</template>
|
||||
<template v-else-if="scope.row.ValueType === 2" slot="append">%</template>
|
||||
</el-input>
|
||||
<span v-else-if="questionForm[scope.row.QuestionId] instanceof Array && scope.row.Type==='number' && (scope.row.xfIndex || scope.row.xfIndex === 0)">
|
||||
<template v-if="(scope.row.ValueType === 0 || scope.row.ValueType === 1) && scope.row.Unit">
|
||||
@@ -165,13 +163,12 @@
|
||||
v-else-if="scope.row.DataSource !== 1 && scope.row.Type==='number' && !scope.row.IsShowInDicom && ((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)"
|
||||
v-model="questionForm[scope.row.QuestionId]"
|
||||
:disabled="scope.row.DataSource === 1"
|
||||
onblur="value=parseFloat(value).toFixed(parseInt(localStorage.getItem('digitPlaces')))"
|
||||
@input="limitInput($event, questionForm, scope.row.QuestionId)"
|
||||
size="mini"
|
||||
@blur="limitBlur(questionForm, scope.row.QuestionId, scope.row.ValueType)"
|
||||
@focus="() => {questionId = scope.row.QuestionId}"
|
||||
>
|
||||
<template slot="append" v-if="scope.row.Unit !== 0">{{scope.row.Unit !== 4 ? $fd('ValueUnit', scope.row.Unit) : scope.row.CustomUnit}}</template>
|
||||
<template slot="append" v-else-if="scope.row.ValueType === 2">%</template>
|
||||
<template v-if="scope.row.Unit !== 0" slot="append">{{ scope.row.Unit !== 4 ? $fd('ValueUnit', scope.row.Unit) : scope.row.CustomUnit }}</template>
|
||||
<template v-else-if="scope.row.ValueType === 2" slot="append">%</template>
|
||||
</el-input>
|
||||
<span v-else-if="scope.row.Type==='number'">
|
||||
<template v-if="(scope.row.ValueType === 0 || scope.row.ValueType === 1) && scope.row.Unit">
|
||||
@@ -181,49 +178,49 @@
|
||||
{{ isNaN(parseInt(questionForm[scope.row.QuestionId])) ? questionForm[scope.row.QuestionId]:`${questionForm[scope.row.QuestionId]} %` }}
|
||||
</template>
|
||||
<template v-else>
|
||||
{{ isNaN(parseInt(questionForm[scope.row.QuestionId])) ? questionForm[scope.row.QuestionId] : questionForm[scope.row.QuestionId]}}
|
||||
{{ isNaN(parseInt(questionForm[scope.row.QuestionId])) ? questionForm[scope.row.QuestionId] : questionForm[scope.row.QuestionId] }}
|
||||
</template>
|
||||
</span>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else-if="task.VisitTaskId === visitTaskId && scope.row.Type === 'upload'">
|
||||
<UploadFile
|
||||
v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)"
|
||||
:visitTaskId="visitTaskId"
|
||||
:question="scope.row"
|
||||
:task="task"
|
||||
:readingTaskState="readingTaskState"
|
||||
:initUrl="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
|
||||
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url, scope.row.RowId)}"
|
||||
></UploadFile>
|
||||
<UploadFile
|
||||
v-else-if="scope.row.Type==='upload'"
|
||||
:visitTaskId="visitTaskId"
|
||||
:question="scope.row"
|
||||
:task="task"
|
||||
:readingTaskState="readingTaskState"
|
||||
:initUrl="questionForm[scope.row.QuestionId]"
|
||||
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url)}"
|
||||
></UploadFile>
|
||||
<UploadFile
|
||||
v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)"
|
||||
:visit-task-id="visitTaskId"
|
||||
:question="scope.row"
|
||||
:task="task"
|
||||
:reading-task-state="readingTaskState"
|
||||
:init-url="questionForm[scope.row.QuestionId][scope.row.xfIndex][scope.row.TableQuestionId]"
|
||||
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url, scope.row.RowId)}"
|
||||
/>
|
||||
<UploadFile
|
||||
v-else-if="scope.row.Type==='upload'"
|
||||
:visit-task-id="visitTaskId"
|
||||
:question="scope.row"
|
||||
:task="task"
|
||||
:reading-task-state="readingTaskState"
|
||||
:init-url="questionForm[scope.row.QuestionId]"
|
||||
@setImageUrl="(url) => {setImageUrl(scope.row.QuestionId, scope.row.xfIndex, scope.row.TableQuestionId, url)}"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="scope.row.Type === 'upload'">
|
||||
<UploadFile
|
||||
v-if="scope.row.Type==='upload' && (scope.row.xfIndex || scope.row.xfIndex === 0)"
|
||||
:visitTaskId="visitTaskId"
|
||||
:visit-task-id="visitTaskId"
|
||||
:question="scope.row"
|
||||
:task="task"
|
||||
:readingTaskState="readingTaskState"
|
||||
:initUrl="scope.row.Answers[task.VisitTaskId]"
|
||||
></UploadFile>
|
||||
:reading-task-state="readingTaskState"
|
||||
:init-url="scope.row.Answers[task.VisitTaskId]"
|
||||
/>
|
||||
<UploadFile
|
||||
v-else-if="scope.row.Type==='upload'"
|
||||
:visitTaskId="visitTaskId"
|
||||
:visit-task-id="visitTaskId"
|
||||
:question="scope.row"
|
||||
:task="task"
|
||||
:readingTaskState="readingTaskState"
|
||||
:initUrl="scope.row.Answers[task.VisitTaskId]"
|
||||
></UploadFile>
|
||||
:reading-task-state="readingTaskState"
|
||||
:init-url="scope.row.Answers[task.VisitTaskId]"
|
||||
/>
|
||||
</template>
|
||||
<template v-else-if="scope.row.QuestionType=== 22">
|
||||
{{ scope.row.Answers[task.VisitTaskId] === '-1' ? '未知' : scope.row.Answers[task.VisitTaskId] }}
|
||||
@@ -234,8 +231,7 @@
|
||||
<template v-else-if="CriterionType === 10">
|
||||
{{ isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))?scope.row.Answers[task.VisitTaskId]:`${scope.row.Answers[task.VisitTaskId]}` }}
|
||||
</template>
|
||||
<template v-else-if="!((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)">
|
||||
</template>
|
||||
<template v-else-if="!((task.IsBaseLine && scope.row.LimitEdit === 1) || (!task.IsBaseLine && scope.row.LimitEdit === 2) || scope.row.LimitEdit === 0)" />
|
||||
<template v-else-if="(scope.row.ValueType === 0 || scope.row.ValueType === 1) && scope.row.Unit">
|
||||
{{ isNaN(parseInt(scope.row.Answers[task.VisitTaskId]))?scope.row.Answers[task.VisitTaskId]:`${scope.row.Answers[task.VisitTaskId]} ${scope.row.Unit !== 4 ? $fd('ValueUnit',scope.row.Unit) : scope.row.CustomUnit}` }}
|
||||
</template>
|
||||
@@ -268,7 +264,7 @@
|
||||
</div>
|
||||
</template>
|
||||
<script>
|
||||
import { changeCalculationAnswer, getReadingReportEvaluation, changeDicomReadingQuestionAnswer, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
|
||||
import { changeCalculationAnswer, getReadingReportEvaluation, submitDicomVisitTask, verifyVisitTaskQuestions, getQuestionCalculateRelation } from '@/api/trials'
|
||||
import { setSkipReadingCache } from '@/api/reading'
|
||||
import DicomEvent from '@/views/trials/trials-panel/reading/dicoms/components/DicomEvent'
|
||||
import UploadFile from './UploadFile'
|
||||
@@ -368,12 +364,14 @@ export default {
|
||||
DicomEvent.$off('getReportInfo')
|
||||
},
|
||||
methods: {
|
||||
limitInput(value, a, b) {
|
||||
if (value.indexOf('.') > -1) {
|
||||
if (value.split('.')[1].length >= this.digitPlaces) {
|
||||
this.$set(a, b, parseFloat(value).toFixed(this.digitPlaces))
|
||||
}
|
||||
limitBlur(questionForm, id, valueType) {
|
||||
const value = questionForm[id]
|
||||
if (valueType === 0) {
|
||||
this.$set(questionForm, id, parseInt(value))
|
||||
} else if (valueType === 3) {
|
||||
this.$set(questionForm, id, parseFloat(value))
|
||||
} else {
|
||||
this.$set(questionForm, id, parseFloat(value).toFixed(this.digitPlaces))
|
||||
}
|
||||
},
|
||||
setImageUrl(qid, index, tqid, url, RowId) {
|
||||
@@ -388,11 +386,10 @@ export default {
|
||||
}
|
||||
},
|
||||
getTagterAnswers(list, questionId) {
|
||||
let Answers
|
||||
list.forEach(v => {
|
||||
if (v.QuestionId === questionId) {
|
||||
return Object.assign({}, v.Answers)
|
||||
} else if (v.Childrens.length > 0){
|
||||
} else if (v.Childrens.length > 0) {
|
||||
return this.getTagterAnswers(v.Childrens, questionId)
|
||||
}
|
||||
})
|
||||
@@ -455,7 +452,15 @@ export default {
|
||||
// this.$set(v, 'xfIndex', i)
|
||||
}
|
||||
if (v.Type === 'number') {
|
||||
this.$set(this.questionForm, v.QuestionId, v.Answers[this.visitTaskId] === '' ? parseFloat(0).toFixed(this.digitPlaces) : v.Answers[this.visitTaskId])
|
||||
let val = null
|
||||
if (v.ValueType === 0) {
|
||||
val = parseInt(v.Answers[this.visitTaskId])
|
||||
} else if (v.ValueType === 3) {
|
||||
val = v.Answers[this.visitTaskId]
|
||||
} else {
|
||||
val = v.Answers[this.visitTaskId] === '' ? parseFloat(0).toFixed(this.digitPlaces) : v.Answers[this.visitTaskId]
|
||||
}
|
||||
this.$set(this.questionForm, v.QuestionId, val)
|
||||
}
|
||||
if (v.Childrens.length > 0) {
|
||||
this.setChild(v.Childrens)
|
||||
@@ -473,7 +478,15 @@ export default {
|
||||
this.$set(this.questionForm, i.QuestionId, tableAnswers)
|
||||
}
|
||||
if (i.Type === 'number') {
|
||||
this.$set(this.questionForm, i.QuestionId, i.Answers[this.visitTaskId] === '' ? parseFloat(0).toFixed(this.digitPlaces) : i.Answers[this.visitTaskId])
|
||||
let val = null
|
||||
if (i.ValueType === 0) {
|
||||
val = parseInt(i.Answers[this.visitTaskId])
|
||||
} else if (i.ValueType === 3) {
|
||||
val = i.Answers[this.visitTaskId]
|
||||
} else {
|
||||
val = i.Answers[this.visitTaskId] === '' ? parseFloat(0).toFixed(this.digitPlaces) : i.Answers[this.visitTaskId]
|
||||
}
|
||||
this.$set(this.questionForm, i.QuestionId, val)
|
||||
}
|
||||
if (i.Childrens && i.Childrens.length > 0 && i.Type !== 'table') {
|
||||
this.setChild(i.Childrens)
|
||||
@@ -507,7 +520,7 @@ export default {
|
||||
num *= parseFloat(q[o.TableQuestionId])
|
||||
}
|
||||
})
|
||||
break;
|
||||
break
|
||||
case 6:
|
||||
this.questionForm[o.QuestionId].forEach((q, qi) => {
|
||||
if (qi === 0) {
|
||||
@@ -516,7 +529,7 @@ export default {
|
||||
num += isNaN(parseFloat(q[o.TableQuestionId])) ? null : parseFloat(q[o.TableQuestionId])
|
||||
}
|
||||
})
|
||||
break;
|
||||
break
|
||||
case 7:
|
||||
this.questionForm[o.QuestionId].forEach((q, qi) => {
|
||||
if (qi === 0) {
|
||||
@@ -526,21 +539,22 @@ export default {
|
||||
}
|
||||
})
|
||||
num = this.questionForm[o.QuestionId].length === 0 ? 0 : num / this.questionForm[o.QuestionId].length
|
||||
break;
|
||||
break
|
||||
case 8:
|
||||
var arr = []
|
||||
this.questionForm[o.QuestionId].forEach(q => {
|
||||
arr.push(q[o.TableQuestionId])
|
||||
})
|
||||
num = arr.length === 0 ? 0 : Math.max(...arr)
|
||||
break;
|
||||
break
|
||||
case 9:
|
||||
// eslint-disable-next-line no-redeclare
|
||||
var arr = []
|
||||
this.questionForm[o.QuestionId].forEach(q => {
|
||||
arr.push(q[o.TableQuestionId])
|
||||
})
|
||||
num = arr.length === 0 ? 0 : Math.min(...arr)
|
||||
break;
|
||||
break
|
||||
}
|
||||
} else {
|
||||
num = parseFloat(this.questionForm[o.TableQuestionId])
|
||||
@@ -549,17 +563,17 @@ export default {
|
||||
switch (rules.CustomCalculateMark) {
|
||||
case 1:
|
||||
num += parseFloat(this.questionForm[o.TableQuestionId])
|
||||
break;
|
||||
break
|
||||
case 2:
|
||||
num -= parseFloat(this.questionForm[o.TableQuestionId])
|
||||
break;
|
||||
break
|
||||
case 3:
|
||||
num *= parseFloat(this.questionForm[o.TableQuestionId])
|
||||
break;
|
||||
break
|
||||
case 4:
|
||||
num /= parseFloat(this.questionForm[o.TableQuestionId])
|
||||
// num /= parseFloat(this.questionForm[o.TableQuestionId])
|
||||
break;
|
||||
break
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -599,12 +613,12 @@ export default {
|
||||
setScrollTop(a) {
|
||||
setTimeout(() => {
|
||||
this.$nextTick(() => {
|
||||
if(this.$refs.reportList){
|
||||
if (this.$refs.reportList) {
|
||||
this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight
|
||||
this.$refs.reportList.bodyWrapper.scrollTop = this.$refs.reportList.bodyWrapper.scrollHeight
|
||||
}
|
||||
})
|
||||
},50)
|
||||
}, 50)
|
||||
},
|
||||
getQuestions(questions, isNTFilterLength, lesionType, isLymphNodes) {
|
||||
const arr = []
|
||||
@@ -668,7 +682,15 @@ export default {
|
||||
// obj.Answers[i.VisitTaskId] = i.Answer ? parseInt(i.Answer) : null
|
||||
} else {
|
||||
if (item.Type === 'number') {
|
||||
this.$set(obj.Answers, i.VisitTaskId, isNaN(parseFloat(i.Answer)) ? i.Answer : parseFloat(i.Answer).toFixed(digitPlaces))
|
||||
let val = null
|
||||
if (item.ValueType === 0) {
|
||||
val = parseInt(i.Answer)
|
||||
} else if (item.ValueType === 3) {
|
||||
val = i.Answer
|
||||
} else {
|
||||
val = isNaN(parseFloat(i.Answer)) ? i.Answer : parseFloat(i.Answer).toFixed(digitPlaces)
|
||||
}
|
||||
this.$set(obj.Answers, i.VisitTaskId, val)
|
||||
} else {
|
||||
this.$set(obj.Answers, i.VisitTaskId, i.Answer)
|
||||
}
|
||||
@@ -739,7 +761,7 @@ export default {
|
||||
},
|
||||
handleResize() {
|
||||
this.$nextTick(() => {
|
||||
this.$refs.reportList.doLayout()
|
||||
this.$refs.reportList ? this.$refs.reportList.doLayout() : ''
|
||||
})
|
||||
},
|
||||
// 关闭签名框
|
||||
@@ -813,7 +835,7 @@ export default {
|
||||
var criterionType = this.criterionType
|
||||
var readingTool = this.readingTool
|
||||
var trialReadingCriterionId = this.$router.currentRoute.query.TrialReadingCriterionId
|
||||
var path = `/readingDicoms?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${task.VisitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
var path = `/noneDicomReading?TrialReadingCriterionId=${trialReadingCriterionId}&trialId=${trialId}&subjectCode=${subjectCode}&subjectId=${subjectId}&visitTaskId=${task.VisitTaskId}&isReadingTaskViewInOrder=${isReadingTaskViewInOrder}&criterionType=${criterionType}&readingTool=${readingTool}&TokenKey=${token}`
|
||||
const routeData = this.$router.resolve({ path })
|
||||
window.open(routeData.href, '_blank')
|
||||
},
|
||||
@@ -831,7 +853,7 @@ export default {
|
||||
questionId: k,
|
||||
answer: v[o],
|
||||
tableQuestionId: o,
|
||||
rowId: v[o+'_RowId']
|
||||
rowId: v[o + '_RowId']
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<template>
|
||||
<div v-loading="loading" class="img-container">
|
||||
<el-card class="box-card left">
|
||||
<div class="img-container">
|
||||
<el-card v-loading="loading" class="box-card left">
|
||||
<div v-if="isReadingShowSubjectInfo" class="title">
|
||||
<h4>{{ subjectCode }} </h4>
|
||||
<h4>{{ taskBlindName }}</h4>
|
||||
@@ -30,7 +30,14 @@
|
||||
class="img-box"
|
||||
@click="selected(item,i,j,true)"
|
||||
>
|
||||
{{ `${j+1}. ${item.FileName}` }}
|
||||
<div v-if="item.FileName.length < 15" class="img-text">
|
||||
{{ `${j+1}. ${item.FileName}` }}
|
||||
</div>
|
||||
<el-tooltip v-else :content="item.FileName" placement="bottom">
|
||||
<div class="img-text">
|
||||
{{ `${j+1}. ${item.FileName}` }}
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
@@ -53,9 +60,15 @@
|
||||
class="img-box"
|
||||
@click="handleImageRead(task)"
|
||||
>
|
||||
{{ `${j+1}. ${task.TaskBlindName}` }}
|
||||
<div v-if="task.TaskBlindName.length < 15" class="img-text">
|
||||
{{ `${j+1}. ${task.TaskBlindName}` }}
|
||||
</div>
|
||||
<el-tooltip v-else :content="task.TaskBlindName" placement="bottom">
|
||||
<div class="img-text">
|
||||
{{ `${j+1}. ${task.TaskBlindName}` }}
|
||||
</div>
|
||||
</el-tooltip>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
@@ -63,7 +76,7 @@
|
||||
|
||||
</el-card>
|
||||
<!-- 预览图像 -->
|
||||
<el-card class="box-card right">
|
||||
<el-card v-loading="loading" class="box-card right">
|
||||
<div style="width:100%;height: 100%;">
|
||||
<Preview
|
||||
v-if="previewImage.imgList.length > 0"
|
||||
@@ -93,10 +106,10 @@
|
||||
:subject-id="subjectId"
|
||||
:visit-task-id="visitTaskId"
|
||||
:criterion-id="otherInfo.TrialCriterionId"
|
||||
:subjectCode="subjectCode"
|
||||
:taskBlindName="taskBlindName"
|
||||
:isReadingShowSubjectInfo="isReadingShowSubjectInfo"
|
||||
:iseCRFShowInDicomReading="iseCRFShowInDicomReading"
|
||||
:subject-code="subjectCode"
|
||||
:task-blind-name="taskBlindName"
|
||||
:is-reading-show-subject-info="isReadingShowSubjectInfo"
|
||||
:ise-c-r-f-show-in-dicom-reading="iseCRFShowInDicomReading"
|
||||
/>
|
||||
</el-card>
|
||||
</div>
|
||||
@@ -402,13 +415,19 @@ export default {
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
border-bottom: 2px solid #f3f3f3;
|
||||
width: 180px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
cursor: pointer;
|
||||
// margin-bottom: 5px;
|
||||
padding-left: 5px;
|
||||
}
|
||||
.img-text{
|
||||
display: inline-block;
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
line-height: 50px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis; /* 用省略号表示溢出的文本 */
|
||||
white-space: nowrap;
|
||||
}
|
||||
.img-box:nth-last-child(1){
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
v-if="
|
||||
(isReadingTaskViewInOrder === 1 ||
|
||||
isReadingTaskViewInOrder === 2) &&
|
||||
TrialReadingCriterionId === item.TrialReadingCriterionId
|
||||
TrialReadingCriterionId === item.TrialReadingCriterionId
|
||||
"
|
||||
>
|
||||
<div slot="search-container">
|
||||
@@ -41,7 +41,7 @@
|
||||
icon="el-icon-search"
|
||||
@click="handleSearch"
|
||||
>
|
||||
{{ $t("common:button:search") }}
|
||||
{{ $t('common:button:search') }}
|
||||
</el-button>
|
||||
<!-- 重置 -->
|
||||
<el-button
|
||||
@@ -49,7 +49,7 @@
|
||||
icon="el-icon-refresh-left"
|
||||
@click="handleReset"
|
||||
>
|
||||
{{ $t("common:button:reset") }}
|
||||
{{ $t('common:button:reset') }}
|
||||
</el-button>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
@@ -75,10 +75,11 @@
|
||||
scope.row.UrgentColor === 1
|
||||
? 'danger'
|
||||
: scope.row.UrgentColor === 2
|
||||
? 'warning'
|
||||
: 'primary'
|
||||
? 'warning'
|
||||
: 'primary'
|
||||
"
|
||||
>{{ $fd("YesOrNo", scope.row.IsUrgent) }}</el-tag>
|
||||
>{{ $fd('YesOrNo', scope.row.IsUrgent) }}</el-tag
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 受试者编号 -->
|
||||
@@ -113,10 +114,11 @@
|
||||
scope.row.UrgentColor === 1
|
||||
? '#F56C6C'
|
||||
: scope.row.UrgentColor === 2
|
||||
? '#E6A23C'
|
||||
: '#409EFF',
|
||||
? '#E6A23C'
|
||||
: '#409EFF',
|
||||
}"
|
||||
>{{ scope.row.UrgentCount }}</span>
|
||||
>{{ scope.row.UrgentCount }}</span
|
||||
>
|
||||
</template>
|
||||
</el-table-column>
|
||||
<!-- 建议完成时间 -->
|
||||
@@ -130,7 +132,7 @@
|
||||
sortable="custom"
|
||||
>
|
||||
<template slot-scope="scope">
|
||||
{{ scope.row.SuggesteFinishedTime.split(":")[0] + ":00:00" }}
|
||||
{{ scope.row.SuggesteFinishedTime.split(':')[0] + ':00:00' }}
|
||||
</template>
|
||||
</el-table-column>
|
||||
<el-table-column
|
||||
@@ -146,8 +148,8 @@
|
||||
:title="
|
||||
scope.row.ExistReadingApply
|
||||
? $t(
|
||||
'trials:pendingReadingTasks:button:ExistReadingApply'
|
||||
)
|
||||
'trials:pendingReadingTasks:button:ExistReadingApply'
|
||||
)
|
||||
: $t('trials:pendingReadingTasks:button:review')
|
||||
"
|
||||
icon="el-icon-edit-outline"
|
||||
@@ -156,9 +158,9 @@
|
||||
<!-- 上传 -->
|
||||
<el-button
|
||||
v-if="
|
||||
item.CriterionType === 0 &&
|
||||
item.ImageUploadEnum > 0 &&
|
||||
item.IsReadingTaskViewInOrder > 0
|
||||
item.ImageUploadEnum > 0 &&
|
||||
item.IsReadingTaskViewInOrder > 1 &&
|
||||
!scope.row.IsSubjectJudge
|
||||
"
|
||||
v-hasPermi="['role:ir']"
|
||||
circle
|
||||
@@ -169,9 +171,9 @@
|
||||
<!-- 下载 -->
|
||||
<el-button
|
||||
v-if="
|
||||
item.CriterionType === 0 &&
|
||||
item.ImageDownloadEnum === 1 &&
|
||||
item.IsReadingTaskViewInOrder > 0
|
||||
item.ImageDownloadEnum > 0 &&
|
||||
item.IsReadingTaskViewInOrder > 1 &&
|
||||
!scope.row.IsSubjectJudge
|
||||
"
|
||||
v-hasPermi="['role:ir']"
|
||||
circle
|
||||
@@ -194,7 +196,7 @@
|
||||
<div
|
||||
v-else-if="
|
||||
isReadingTaskViewInOrder === 0 &&
|
||||
TrialReadingCriterionId === item.TrialReadingCriterionId
|
||||
TrialReadingCriterionId === item.TrialReadingCriterionId
|
||||
"
|
||||
>
|
||||
<el-descriptions :column="2" border style="width: 800px">
|
||||
@@ -248,48 +250,66 @@
|
||||
:disabled="
|
||||
randomReadInfo.UnReadTaskCount +
|
||||
randomReadInfo.UnReadJudgeTaskCount ===
|
||||
0
|
||||
0
|
||||
"
|
||||
@click="handleOutOfOrderReading"
|
||||
>
|
||||
{{ $t("trials:pendingReadingTasks:button:beginRandomReview") }}
|
||||
{{ $t('trials:pendingReadingTasks:button:beginRandomReview') }}
|
||||
</el-button>
|
||||
</el-descriptions-item>
|
||||
</el-descriptions>
|
||||
</div>
|
||||
</el-tab-pane>
|
||||
</el-tabs>
|
||||
<upload-image
|
||||
<!-- <upload-image
|
||||
v-if="uploadImageVisible"
|
||||
:visible.sync="uploadImageVisible"
|
||||
:subject-id="uploadSubjectId"
|
||||
:criterion="uploadTrialCriterion"
|
||||
:status="uploadStatus"
|
||||
@getList="getList"
|
||||
/> -->
|
||||
<upload-dicom-and-nonedicom
|
||||
v-if="uploadImageVisible"
|
||||
:SubjectId="uploadSubjectId"
|
||||
:SubjectCode="uploadSubjectCode"
|
||||
:Criterion="uploadTrialCriterion"
|
||||
:isReadingTaskViewInOrder="isReadingTaskViewInOrder"
|
||||
:visible.sync="uploadImageVisible"
|
||||
/>
|
||||
<download-dicom-and-nonedicom
|
||||
v-if="downloadImageVisible"
|
||||
:SubjectId="uploadSubjectId"
|
||||
:SubjectCode="uploadSubjectCode"
|
||||
:Criterion="uploadTrialCriterion"
|
||||
:visible.sync="downloadImageVisible"
|
||||
/>
|
||||
</BaseContainer>
|
||||
</template>
|
||||
<script>
|
||||
import {
|
||||
getIRUnReadSubjectTaskList,
|
||||
verifyReadingRestTime
|
||||
} from '@/api/trials'
|
||||
import { getIRUnReadSubjectTaskList, verifyReadingRestTime } from '@/api/trials'
|
||||
import { getTrialCriterionList } from '@/api/trials/reading'
|
||||
import { clearSkipReadingCache } from '@/api/reading'
|
||||
import BaseContainer from '@/components/BaseContainer'
|
||||
import uploadImage from '@/components/uploadImage'
|
||||
import uploadDicomAndNonedicom from '@/components/uploadDicomAndNonedicom'
|
||||
import downloadDicomAndNonedicom from '@/components/downloadDicomAndNonedicom'
|
||||
import Pagination from '@/components/Pagination'
|
||||
import { getToken } from '@/utils/auth'
|
||||
const searchDataDefault = () => {
|
||||
return {
|
||||
SubjectCode: '',
|
||||
PageIndex: 1,
|
||||
PageSize: 20
|
||||
PageSize: 20,
|
||||
}
|
||||
}
|
||||
export default {
|
||||
name: 'ReadingTaskList',
|
||||
components: { BaseContainer, Pagination, 'upload-image': uploadImage },
|
||||
components: {
|
||||
BaseContainer,
|
||||
Pagination,
|
||||
'upload-dicom-and-nonedicom': uploadDicomAndNonedicom,
|
||||
'download-dicom-and-nonedicom': downloadDicomAndNonedicom,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
searchData: searchDataDefault(),
|
||||
@@ -308,10 +328,12 @@ export default {
|
||||
openWindow: null,
|
||||
|
||||
// 上传
|
||||
downloadImageVisible: false,
|
||||
uploadImageVisible: false,
|
||||
uploadSubjectId: null,
|
||||
uploadSubjectCode: null,
|
||||
uploadTrialCriterion: {},
|
||||
uploadStatus: 'upload'
|
||||
uploadStatus: 'upload',
|
||||
}
|
||||
},
|
||||
watch: {
|
||||
@@ -319,7 +341,7 @@ export default {
|
||||
if (v) {
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
window.addEventListener('message', this.receiveMsg)
|
||||
@@ -335,10 +357,11 @@ export default {
|
||||
methods: {
|
||||
// 打开上传下载弹框
|
||||
openUploadImage(item, trialCriterion, status) {
|
||||
this.uploadSubjectCode = item.SubjectCode
|
||||
this.uploadSubjectId = item.SubjectId
|
||||
this.uploadTrialCriterion = trialCriterion
|
||||
this.uploadStatus = status
|
||||
this.uploadImageVisible = true
|
||||
this[`${status}ImageVisible`] = true
|
||||
},
|
||||
async getTrialCriterionList() {
|
||||
try {
|
||||
@@ -360,8 +383,7 @@ export default {
|
||||
this.isRender = false
|
||||
const res = await getIRUnReadSubjectTaskList(this.searchData)
|
||||
if (res.IsSuccess) {
|
||||
this.isReadingTaskViewInOrder =
|
||||
res.OtherInfo.IsReadingTaskViewInOrder
|
||||
this.isReadingTaskViewInOrder = res.OtherInfo.IsReadingTaskViewInOrder
|
||||
this.readingTool = res.OtherInfo.ReadingTool
|
||||
this.criterionType = res.OtherInfo.CriterionType
|
||||
if (res.OtherInfo.IsReadingTaskViewInOrder) {
|
||||
@@ -395,7 +417,10 @@ export default {
|
||||
await clearSkipReadingCache()
|
||||
await verifyReadingRestTime()
|
||||
this.loading = false
|
||||
window.localStorage.setItem('TrialReadingCriterionId', this.TrialReadingCriterionId)
|
||||
window.localStorage.setItem(
|
||||
'TrialReadingCriterionId',
|
||||
this.TrialReadingCriterionId
|
||||
)
|
||||
var token = getToken()
|
||||
var path = ''
|
||||
if (this.readingTool === 0) {
|
||||
@@ -420,7 +445,10 @@ export default {
|
||||
await clearSkipReadingCache()
|
||||
await verifyReadingRestTime()
|
||||
this.loading = false
|
||||
window.localStorage.setItem('TrialReadingCriterionId', this.TrialReadingCriterionId)
|
||||
window.localStorage.setItem(
|
||||
'TrialReadingCriterionId',
|
||||
this.TrialReadingCriterionId
|
||||
)
|
||||
var token = getToken()
|
||||
var path = ''
|
||||
if (this.readingTool === 0) {
|
||||
@@ -450,7 +478,7 @@ export default {
|
||||
this.searchData.SortField = column.prop
|
||||
this.searchData.PageIndex = 1
|
||||
this.getList()
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -381,7 +381,7 @@
|
||||
/>
|
||||
<!-- 退回 -->
|
||||
<el-button
|
||||
:disabled="scope.row.ReadingTaskState === 2 || scope.row.ReadingCategory !== 1 || scope.row.TaskState !== 0"
|
||||
:disabled="scope.row.ReadingTaskState === 2 || scope.row.ReadingCategory !== 1 || scope.row.TaskState !== 0 || scope.row.IsManualGeneration"
|
||||
v-if="hasPermi(['trials:trials-panel:readingTracking:edit'])"
|
||||
icon="el-icon-back"
|
||||
circle
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
/>
|
||||
<!-- <embed v-else-if="fileType.indexOf('pdf') !== -1" :src="filePath" style="width: 100%; height: 100%"> -->
|
||||
<!-- <iframe v-else-if="fileType.indexOf('pdf') !== -1" :src="`/static/pdfjs/web/viewer.html?file=${filePath}`" width="100%" height="100%" frameborder="0" /> -->
|
||||
<iframe v-else-if="fileType.indexOf('pdf') !== -1" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${filePath}?userName=${currentUser}`" width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
|
||||
<iframe v-else-if="fileType.indexOf('pdf') !== -1" :src="`/static/pdfjs/web/viewer.html?file=${OSSclientConfig.basePath}${filePath}?userName=${currentUser}&COMPANY=${COMPANY}`" width="100%" height="100%" frameborder="0" crossorigin="anonymous" />
|
||||
<div v-else>
|
||||
{{ $t('common:message:downloadFile') }}
|
||||
<el-link type="primary" @click="downLoadFile">{{ $t('common:button:download') }}</el-link>
|
||||
@@ -32,7 +32,8 @@ export default {
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
currentUser: zzSessionStorage.getItem('userName')
|
||||
currentUser: zzSessionStorage.getItem('userName'),
|
||||
COMPANY:process.env.VUE_APP_COMPANY_NAME
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user