7 Commits

Author SHA1 Message Date
caiyiling aedd35a729 自定义阅片自动对齐bug修复 2024-04-13 14:26:22 +08:00
wangxiaoshuang a98c44ee66 v1.3.2 2024-04-12 08:55:44 +08:00
wangxiaoshuang 5a2b1ca457 v1.3.2 2024-04-11 18:40:32 +08:00
wangxiaoshuang 43f398df19 合并改动 2024-04-11 18:06:18 +08:00
wangxiaoshuang 3f85e1bb4b 临床数据访视者级别显示问题 2024-04-11 16:02:59 +08:00
wangxiaoshuang 4c350071eb Revert "临床数据访视者级别显示问题"
This reverts commit 6ed8c9fac9.
2024-04-11 15:50:33 +08:00
wangxiaoshuang 6ed8c9fac9 临床数据访视者级别显示问题 2024-04-11 15:48:59 +08:00
367 changed files with 14093 additions and 30845 deletions
+1 -7
View File
@@ -14,9 +14,6 @@ VUE_CLI_BABEL_TRANSPILE_MODULES = false
# 是否开启登陆限制 true:是 false:否
VUE_APP_LOGIN_FOR_PERMISSION = false
# 是否开启长时间无操作锁定弹框MFA验证 true:是 false:否
VUE_APP_LOCK_FOR_PERMISSION_MFA = false
# 是否开启长时间无操作锁定弹框 true:是 false:否
VUE_APP_LOCK_FOR_PERMISSION = false
@@ -30,7 +27,7 @@ VUE_APP_LOGOUT_FOR_PERMISSION = false
VUE_APP_LOGOUT_FOR_TIME = 1800
# 是否开启密码正则验证 true:是 false:否
VUE_APP_PASSWORD_FOR_PERMISSION = false
VUE_APP_PASSWORD_FOR_PERMISSION = true
# 密码校验规则
VUE_APP_PASSWORD_FOR_REGULAR = ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-_.@^+\$!%#*?&\$~])[A-Za-z0-9-~_.@^+\$~!%#*?&]{8,32}$
@@ -38,9 +35,6 @@ VUE_APP_PASSWORD_FOR_REGULAR = ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-_.@^+\$!
# 是否开启文档签署验证 true:是 false:否
VUE_APP_WORD_FOR_PERMISSION = false
# 公司名称
VUE_APP_COMPANY_NAME = "Extensive Imaging"
# dicom文件地址
VUE_APP_DICOM_PATH = 'https://zyypacs.oss-cn-shanghai.aliyuncs.com'
-6
View File
@@ -8,9 +8,6 @@ VUE_APP_BASE_PATH = '/'
# 是否开启登陆限制 true:是 false:否
VUE_APP_LOGIN_FOR_PERMISSION = true
# 是否开启长时间无操作锁定弹框MFA验证 true:是 false:否
VUE_APP_LOCK_FOR_PERMISSION_MFA = false
# 是否开启长时间无操作锁定弹框 true:是 false:否
VUE_APP_LOCK_FOR_PERMISSION = true
@@ -32,9 +29,6 @@ VUE_APP_PASSWORD_FOR_REGULAR = ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-_.@^+\$!
# 是否开启文档签署验证 true:是 false:否
VUE_APP_WORD_FOR_PERMISSION = true
# 公司名称
VUE_APP_COMPANY_NAME = "Extensive Imaging"
# dicom文件地址
# VUE_APP_DICOM_PATH = 'http://101.132.193.237:7080'
VUE_APP_DICOM_PATH = 'https://zyypacs-prod.oss-cn-shanghai.aliyuncs.com'
-3
View File
@@ -9,9 +9,6 @@ VUE_APP_IS_TEST = true
# 是否开启登陆限制 true:是 false:否
VUE_APP_LOGIN_FOR_PERMISSION = false
# 是否开启长时间无操作锁定弹框MFA验证 true:是 false:否
VUE_APP_LOCK_FOR_PERMISSION_MFA = false
# 是否开启长时间无操作锁定弹框 true:是 false:否
VUE_APP_LOCK_FOR_PERMISSION = false
-3
View File
@@ -5,9 +5,6 @@ NODE_ENV = 'prop'
# 是否开启登陆限制 true:是 false:否
VUE_APP_LOGIN_FOR_PERMISSION = true
# 是否开启长时间无操作锁定弹框MFA验证 true:是 false:否
VUE_APP_LOCK_FOR_PERMISSION_MFA = false
# 是否开启长时间无操作锁定弹框 true:是 false:否
VUE_APP_LOCK_FOR_PERMISSION = true
-6
View File
@@ -10,9 +10,6 @@ VUE_APP_BASE_PATH = '/'
# 是否开启登陆限制 true:是 false:否
VUE_APP_LOGIN_FOR_PERMISSION = true
# 是否开启长时间无操作锁定弹框MFA验证 true:是 false:否
VUE_APP_LOCK_FOR_PERMISSION_MFA = false
# 是否开启长时间无操作锁定弹框 true:是 false:否
VUE_APP_LOCK_FOR_PERMISSION = true
@@ -34,9 +31,6 @@ VUE_APP_PASSWORD_FOR_REGULAR = ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-_.@^+\$!
# 是否开启文档签署验证 true:是 false:否
VUE_APP_WORD_FOR_PERMISSION = true
# 公司名称
VUE_APP_COMPANY_NAME = "Extensive Imaging"
# dicom文件地址
VUE_APP_DICOM_PATH = 'https://zyypacs-uat.oss-cn-shanghai.aliyuncs.com'
+3 -9
View File
@@ -1,15 +1,12 @@
# just a flag
ENV = 'usa'
NODE_ENV = 'usa'
ENV = 'production'
NODE_ENV = 'production'
# base public path
VUE_APP_BASE_PATH = 'https://ei-code-prod.s3.amazonaws.com/2024-04-30/'
VUE_APP_BASE_PATH = 'https://ei-code-prod.s3.amazonaws.com/2024-01-31/'
# 是否开启登陆限制 true:是 false:否
VUE_APP_LOGIN_FOR_PERMISSION = false
# 是否开启长时间无操作锁定弹框MFA验证 true:是 false:否
VUE_APP_LOCK_FOR_PERMISSION_MFA = true
# 是否开启长时间无操作锁定弹框 true:是 false:否
VUE_APP_LOCK_FOR_PERMISSION = false
@@ -31,9 +28,6 @@ VUE_APP_PASSWORD_FOR_REGULAR = ^(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[-_.@^+\$!
# 是否开启文档签署验证 true:是 false:否
VUE_APP_WORD_FOR_PERMISSION = true
# 公司名称
VUE_APP_COMPANY_NAME = "Elevate Imaging"
# dicom文件地址
VUE_APP_DICOM_PATH = 'https://zyypacs-usa.oss-us-west-1.aliyuncs.com'
+3 -3
View File
@@ -10,7 +10,7 @@ clone:
disable: true #禁用默认克隆
server:
host: 106.14.89.110
host: 192.168.3.68
user: root
password:
from_secret: local_pwd
@@ -19,7 +19,7 @@ steps:
- name: publish-test-irc-vue
commands:
- echo start publish test-irc-vue
- cd /opt/1panel/hang/vue/test-irc
- cd /opt/hang/vue/test-irc
- sh test-irc.sh v${DRONE_BUILD_NUMBER}
trigger:
@@ -41,7 +41,7 @@ clone:
disable: true #禁用默认克隆
server:
host: 106.14.89.110
host: 123.56.94.154
user: root
password:
from_secret: local_pwd
-9
View File
@@ -11520,15 +11520,6 @@
"resolved": "https://registry.npmmirror.com/moment/-/moment-2.29.4.tgz",
"integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w=="
},
"moment-timezone": {
"version": "0.5.45",
"resolved": "https://registry.npmmirror.com/moment-timezone/-/moment-timezone-0.5.45.tgz",
"integrity": "sha512-HIWmqA86KcmCAhnMAN0wuDOARV/525R2+lOLotuGFzn4HO+FH+/645z2wx0Dt3iDv6/p61SIvKnDstISainhLQ==",
"dev": true,
"requires": {
"moment": "^2.29.4"
}
},
"move-concurrently": {
"version": "1.0.1",
"resolved": "https://registry.npmmirror.com/move-concurrently/-/move-concurrently-1.0.1.tgz",
+2 -3
View File
@@ -1,8 +1,8 @@
{
"name": "EICS",
"version": "1.0.0",
"version": "1.3.2",
"scripts": {
"dev": "vue-cli-service serve --open --mode development",
"dev": "vue-cli-service serve --open",
"build": "vue-cli-service build",
"build:prod": "vue-cli-service build --mode prod",
"build:uat": "vue-cli-service build --mode uat",
@@ -83,7 +83,6 @@
"eslint-plugin-vue": "^6.2.2",
"html-webpack-plugin": "3.2.0",
"minio": "^7.1.3",
"moment-timezone": "^0.5.45",
"node-xlsx": "^0.21.0",
"runjs": "^4.3.2",
"script-ext-html-webpack-plugin": "2.1.3",
+103 -155
View File
@@ -1,213 +1,169 @@
<template>
<div id="app" style="position: relative">
<router-view />
<div
v-show="show"
v-adaptive
@click="openI18n"
style="
position: fixed;
bottom: 50px;
left: 50px;
z-index: 100000;
width: 50px;
height: 50px;
background: #409eff88;
line-height: 50px;
text-align: center;
color: #fff;
border-radius: 50%;
cursor: pointer;
"
>
<div v-show="show" v-adaptive @click="openI18n" style="position: fixed;bottom: 50px;left: 50px;z-index: 100000;width: 50px;height: 50px;background: #409eff88;line-height: 50px;text-align: center;color:#fff;border-radius: 50%;cursor: pointer">
i18n
</div>
<el-drawer title="国际化" :visible.sync="drawer" direction="rtl" size="80%">
<el-drawer
title="国际化"
:visible.sync="drawer"
direction="rtl"
size="80%">
<div style="width: 320px">
<el-form label-width="100px" @submit.native.prevent size="small">
<el-form
label-width="100px"
@submit.native.prevent
size="small"
>
<el-form-item label="关键字">
<el-input v-model="key" @input="keyChange" />
<el-input v-model="key" @input="keyChange"/>
</el-form-item>
</el-form>
</div>
<el-table
:data="tableData"
v-adaptive="{ bottomOffset: 50 }"
v-adaptive="{bottomOffset:50}"
height="100"
style="width: 100%"
>
<el-table-column prop="Code" label="标签" width="300">
style="width: 100%">
<el-table-column
prop="Code"
label="标签"
width="300">
</el-table-column>
<!-- <el-table-column-->
<!-- prop="Description"-->
<!-- label="路由"-->
<!-- show-overflow-tooltip-->
<!-- width="180">-->
<!-- <template slot-scope="scope">-->
<!-- {{scope.row.Description}}-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column prop="Value" label="英文">
<!-- <el-table-column-->
<!-- prop="Description"-->
<!-- label="路由"-->
<!-- show-overflow-tooltip-->
<!-- width="180">-->
<!-- <template slot-scope="scope">-->
<!-- {{scope.row.Description}}-->
<!-- </template>-->
<!-- </el-table-column>-->
<el-table-column
prop="Value"
label="英文">
<template slot-scope="scope">
<el-input
v-model="scope.row.Value"
@input="
(e) => {
$set(scope.row, 'Value', e);
}
"
size="mini"
></el-input>
<el-input v-model="scope.row.Value" @input="(e) => {$set(scope.row, 'Value', e)}" size="mini"></el-input>
</template>
</el-table-column>
<el-table-column prop="ValueCN" label="中文">
<el-table-column
prop="ValueCN"
label="中文">
<template slot-scope="scope">
<el-input
v-model="scope.row.ValueCN"
@input="
(e) => {
$set(scope.row, 'ValueCN', e);
}
"
size="mini"
></el-input>
<el-input v-model="scope.row.ValueCN" @input="(e) => {$set(scope.row, 'ValueCN', e)}" size="mini"></el-input>
</template>
</el-table-column>
</el-table>
<div style="text-align: right; padding-top: 10px; padding-right: 10px">
<el-button size="mini" @click="drawer = false">取消 </el-button>
<el-button size="mini" type="primary" @click="handleSave"
>保存</el-button
>
<div style="text-align: right;padding-top: 10px;padding-right: 10px;">
<el-button size="mini" @click="drawer = false">取消
</el-button>
<el-button size="mini" type="primary" @click="handleSave">保存</el-button>
</div>
</el-drawer>
</div>
</template>
<script>
import {
batchAddOrUpdateFrontInternationalization,
getFrontInternationalizationList,
} from "@/api/dictionary/dictionary";
import { batchAddOrUpdateFrontInternationalization, getFrontInternationalizationList } from '@/api/dictionary/dictionary'
import Vue from "vue";
import i18n from "./lang";
export default {
name: "App",
data() {
name: 'App',
data () {
return {
drawer: false,
tableData: [],
show: false,
key: null,
arr: [],
};
arr: []
}
},
mounted() {
this.show = process.env.VUE_APP_OSS_PATH === "/test/dist";
this.show = process.env.VUE_APP_OSS_PATH === '/test/dist'
},
methods: {
changeValue(target, attr, e) {
this.$set(target, attr, e);
this.$set(target, attr, e)
},
keyChange(v) {
if (this.key) {
this.tableData = Object.assign(
[],
this.arr.filter(
(v) =>
~v.Code.indexOf(this.key) ||
~v.Value.indexOf(this.key) ||
~v.ValueCN.indexOf(this.key)
)
);
this.tableData = Object.assign([], this.arr.filter(v => ~v.Code.indexOf(this.key) || ~v.Value.indexOf(this.key) || ~v.ValueCN.indexOf(this.key)))
} else {
this.tableData = Object.assign([], this.arr);
this.tableData = Object.assign([], this.arr)
}
},
handleSave() {
this.$confirm("确定修改当前页面国际化内容?").then(() => {
batchAddOrUpdateFrontInternationalization(this.tableData).then(
async (res) => {
var zhMessages = {},
enMessages = {};
var Internationalization = await getFrontInternationalizationList();
Vue.prototype.$tl = Internationalization.Result;
this.tableData.forEach((v) => {
// zhMessages[v.Description + '_' + v.Code] = v.ValueCN
// enMessages[v.Description + '_' + v.Code] = v.Value
zhMessages[v.Code] = v.ValueCN;
enMessages[v.Code] = v.Value;
});
i18n.mergeLocaleMessage("zh", zhMessages);
i18n.mergeLocaleMessage("en", enMessages);
this.drawer = false;
this.$message.success("国际化修改成功");
}
);
});
this.$confirm('确定修改当前页面国际化内容?').then(() => {
batchAddOrUpdateFrontInternationalization(this.tableData).then(async res => {
var zhMessages = {}, enMessages = {}
var Internationalization = await getFrontInternationalizationList()
Vue.prototype.$tl = Internationalization.Result
this.tableData.forEach(v => {
// zhMessages[v.Description + '_' + v.Code] = v.ValueCN
// enMessages[v.Description + '_' + v.Code] = v.Value
zhMessages[v.Code] = v.ValueCN
enMessages[v.Code] = v.Value
})
i18n.mergeLocaleMessage('zh', zhMessages)
i18n.mergeLocaleMessage('en', enMessages)
this.drawer = false
this.$message.success('国际化修改成功')
})
})
},
openI18n() {
this.tableData = [];
this.key = null;
this.drawer = true;
let arr = [];
let tableData = this.$tl.map((v) => {
let a = { ...v };
this.tableData = []
this.key = null
this.drawer = true
let arr = []
let tableData = this.$tl.map(v => {
let a = {...v}
// if (!a.Description) {
// a.Description = this.$route.path
// }
return a;
});
tableData = tableData.filter((v) => {
return a
})
tableData = tableData.filter(v => {
// return ~this.$path.indexOf(v.Description + '_' + v.Code)
return ~this.$path.indexOf(v.Code);
});
this.$path.forEach((v) => {
let o = tableData.find((a) => {
return a.Code === v;
});
return ~this.$path.indexOf(v.Code)
})
this.$path.forEach(v => {
let o = tableData.find(a => {
return a.Code === v
})
if (o) {
arr.push(o);
arr.push(o)
} else {
arr.push({
Code: v,
Description: null,
Value: null,
ValueCN: null,
});
ValueCN: null
})
}
});
this.arr = arr;
})
this.arr = arr
if (this.key) {
this.tableData = Object.assign(
[],
this.arr.filter(
(v) =>
~v.Code.indexOf(this.key) ||
~v.Value.indexOf(this.key) ||
~v.ValueCN.indexOf(this.key)
)
);
this.tableData = Object.assign([], this.arr.filter(v => ~v.Code.indexOf(this.key) || ~v.Value.indexOf(this.key) || ~v.ValueCN.indexOf(this.key)))
} else {
this.tableData = Object.assign([], this.arr);
this.tableData = Object.assign([], this.arr)
}
// console.log(JSON.stringify(this.$path))
// console.log(JSON.stringify(this.tableData))
},
},
};
console.log(JSON.stringify(this.$path))
console.log(JSON.stringify(this.tableData))
}
}
}
</script>
<style lang="scss">
$light_gray: #606266;
.el-tooltip__popper {
.el-tooltip__popper{
max-width: 400px;
}
.my_multiple {
.el-input--medium .el-input__inner {
height: 36px !important;
.my_multiple{
.el-input--medium .el-input__inner{
height: 36px!important;
}
.el-select__tags {
.el-select__tags{
flex-wrap: nowrap;
overflow: hidden;
white-space: nowrap;
@@ -224,29 +180,21 @@ input[type="number"] {
-moz-appearance: textfield !important;
}
.viewer-fixed.viewer-container {
.viewer-fixed.viewer-container{
z-index: 10000;
}
textarea {
textarea{
white-space: break-spaces;
word-break: normal;
}
* {
word-break: normal !important;
*{
word-break: normal!important;
}
.box-body .el-button.is-circle:not(.is-disabled) i:before {
.box-body .el-button.is-circle:not(.is-disabled) i:before{
color: #428bca;
}
.box-body .el-button.is-circle i.el-icon-question:before {
.box-body .el-button.is-circle i.el-icon-question:before{
color: #fff;
}
.system-title {
font-size: 35px;
color: $light_gray;
text-align: center;
font-weight: bold;
font-family: 'Times New Roman';
text-shadow:1px 0.5px 1.5px #666;
}
</style>
-8
View File
@@ -1006,11 +1006,3 @@ export function deleteCommonDocument(commonDocumentId) {
method: 'delete'
})
}
//getTrialSiteList
export function getTrialSiteList(params) {
return request({
url: `/site/getTrialSiteList`,
method: 'post',
data: params
})
}
-8
View File
@@ -76,11 +76,3 @@ export function fullyReplicated(param) {
})
}
// 获取所有字典key
export function getDictionaryCodeList() {
return request({
url: `/Dictionary/getAllDictionaryKey`,
method: 'post',
})
}
+2 -2
View File
@@ -22,9 +22,9 @@ export function getBasicDataSelects(param) {
})
}
export function getBasicDataAllSelect(params, isSystem) {
export function getBasicDataAllSelect(params) {
return request({
url: params ? (isSystem ? `/Dictionary/getBasicDataAllSelect?SystemReadingCriterionId=${params}` : `/Dictionary/getBasicDataAllSelect?TrialReadingCriterionId=${params}`) : `/Dictionary/getBasicDataAllSelect`,
url: params ? `/Dictionary/getBasicDataAllSelect?TrialReadingCriterionId=${params}` : `/Dictionary/getBasicDataAllSelect`,
method: 'get'
})
}
+4 -6
View File
@@ -14,19 +14,17 @@ export function getHospitalList() {
})
}
export function getAllSponsorList(params) {
export function getAllSponsorList() {
return request({
url: '/sponsor/getAllSponsorList',
method: 'get',
params
method: 'get'
})
}
export function getAllCROList(params) {
export function getAllCROList() {
return request({
url: '/cro/getAllCROList',
method: 'get',
params
method: 'get'
})
}
export function getAllSiteList() {
-42
View File
@@ -1,42 +0,0 @@
import request from '@/utils/request'
// 下载打包影像
export function requestPackageAndAnonymizImage(params) {
return request({
url: '/DownloadAndUpload/requestPackageAndAnonymizImage',
method: 'post',
params
})
}
// 获取影像上传列表
export function getSubjectImageUploadList(params) {
return request({
url: '/DownloadAndUpload/getSubjectImageUploadList',
method: 'get',
params
})
}
// 预上传
export function preArchiveDicomStudy(data) {
return request({
url: '/DownloadAndUpload/preArchiveDicomStudy',
method: 'post',
data
})
}
// 归档
export function addOrUpdateArchiveTaskStudy(data) {
return request({
url: '/DownloadAndUpload/addOrUpdateArchiveTaskStudy',
method: 'post',
data
})
}
// 删除上传文件
export function deleteTaskStudy(params) {
return request({
url: '/DownloadAndUpload/deleteTaskStudy',
method: 'delete',
params
})
}
+2 -158
View File
@@ -1364,9 +1364,9 @@ export function getForwardList(param) {
})
}
export function getNoneDicomStudyList(subjectVisitId, sudyId = '', isFilterZip = false) {
export function getNoneDicomStudyList(subjectVisitId, sudyId = '') {
return request({
url: `/NoneDicomStudy/getNoneDicomStudyList?subjectVisitId=${subjectVisitId}&nonedicomStudyId=${sudyId}&isFilterZip=${isFilterZip}`,
url: `/NoneDicomStudy/getNoneDicomStudyList?subjectVisitId=${subjectVisitId}&nonedicomStudyId=${sudyId}`,
method: 'get'
})
}
@@ -1747,21 +1747,6 @@ export function deleteTrialExternalUser(id) {
method: 'delete'
})
}
export function getUserTobeDoneRecord() {
return request({
url: `/PersonalWorkstation/getUserTobeDoneRecord`,
method: 'get'
})
}
export function getNeedSignTrialDocTrialIdList() {
return request({
url: `/PersonalWorkstation/getNeedSignTrialDocTrialIdList`,
method: 'get'
})
}
export function getBasicStat() {
return request({
url: `/PersonalWorkstation/getBasicStat`,
@@ -2810,29 +2795,6 @@ export function saveImageQuality(param) {
data: param
})
}
export function getIsSuvMaxLesion(param) {
return request({
url: `/LuganoCalculate/getIsSuvMaxLesion`,
method: 'post',
data: param
})
}
export function getCanChooseNotMerge(param) {
return request({
url: `/LuganoCalculate/getCanChooseNotMerge`,
method: 'post',
data: param
})
}
export function saveTaskQuestion(saveQuestionType, param) {
return request({
url: `/SaveTaskQuestion/${saveQuestionType}`,
method: 'post',
data: param
})
}
export function deleteReadingRowAnswer(param) {
return request({
url: `/ReadingImageTask/deleteReadingRowAnswer`,
@@ -2902,14 +2864,6 @@ export function asyncTrialCriterionDictionary(param) {
})
}
export function configTrialProcessInfoVerification(param) {
return request({
url: `/TrialConfig/configTrialProcessInfoVerification`,
method: 'post',
data: param
})
}
export function getTrialEmailNoticeConfigList(param) {
return request({
url: `/TrialEmailNoticeConfig/getTrialEmailNoticeConfigList`,
@@ -3565,113 +3519,3 @@ export function getTrialSiteSurveySelectList(param) {
data: param
})
}
export function getCanMergeLesion(param) {
return request({
url: `/ReadingImageTask/getCanMergeLesion`,
method: 'post',
data: param
})
}
export function mergeLesion(param) {
return request({
url: `/ReadingImageTask/mergeLesion`,
method: 'post',
data: param
})
}
export function resetAndAsyncCriterion(param) {
return request({
url: `/Inspection/ReadingCriterion/ResetAndAsyncCriterion`,
method: 'post',
data: param
})
}
export function batchSetCriterionJoinJoinAnalysis(param) {
return request({
url: `/DoctorWorkload/batchSetCriterionJoinJoinAnalysis`,
method: 'post',
data: param
})
}
export function updateTrialVirtualSiteCode(param) {
return request({
url: `/TaskConsistentRule/updateTrialVirtualSiteCode`,
method: 'post',
data: param
})
}
export function getUpdateVirtualSiteCodeList(param) {
return request({
url: `/TaskConsistentRule/getUpdateVirtualSiteCodeList?trialId=${param.trialId}`,
method: 'get'
})
}
export function addDefaultQuestions(param) {
return request({
url: `/ReadingMedicineQuestion/addDefaultQuestions`,
method: 'post',
data: param
})
}
export function getReadingCalculationData(param) {
return request({
url: `/ReadingImageTask/getReadingCalculationData`,
method: 'post',
data: param
})
}
export function getTrialSignDocumentList(param) {
return request({
url: `/TrialDocument/getTrialSignDocumentList`,
method: 'post',
data: param
})
}
export function getPreviousOtherPicturePath(param) {
return request({
url: `/ReadingImageTask/getPreviousOtherPicturePath`,
method: 'post',
data: param
})
}
export function verifyIsCanConfirm(param) {
return request({
url: `/ReadingMedicineQuestion/verifyIsCanConfirm`,
method: 'post',
data: param
})
}
export function getPTAndCtSeries(param) {
return request({
url: `/SubjectVisit/getPTAndCtSeries`,
method: 'post',
data: param
})
}
export function getDicomSeriesInfo(param) {
return request({
url: `/SubjectVisit/getDicomSeriesInfo`,
method: 'post',
data: param
})
}
export function getTrialSiteSelectList(params) {
return request({
url: `/trialMaintenance/getTrialSiteSelectList`,
method: 'get',
params
})
}
+2 -2
View File
@@ -436,9 +436,9 @@ export function addSubjectCancelDoctorNote(params) {
})
}
export function getSubjectCancelDoctorHistoryList(SubjectId, TrialReadingCriterionId) {
export function getSubjectCancelDoctorHistoryList(SubjectId) {
return request({
url: `/TaskAllocationRule/getSubjectCancelDoctorHistoryList?SubjectId=${SubjectId}&&TrialReadingCriterionId=${TrialReadingCriterionId}`,
url: `/TaskAllocationRule/getSubjectCancelDoctorHistoryList?SubjectId=${SubjectId}`,
method: 'get'
})
}
-16
View File
@@ -94,20 +94,4 @@ export function getTrialJudgyInfo(params) {
data: params
})
}
// 获取检查部位列表
export function getTrialBodyPartList(params) {
return request({
url: `/TrialConfig/getTrialBodyPartList`,
method: 'get',
params
})
}
// 新增检查部位
export function addOrUpdateTrialBodyPart(data) {
return request({
url: `/TrialConfig/addOrUpdateTrialBodyPart`,
method: 'post',
data
})
}
+1 -34
View File
@@ -7,13 +7,7 @@ export function login(data) {
data
})
}
export function loginOut(params) {
return request({
url: `/User/loginOut`,
method: 'get',
params
})
}
export function getAllDictionary() {
return request({
url: '/dictionary/getAllDictionary',
@@ -158,30 +152,3 @@ export function getUserLogList(params) {
data: params
})
}
// 获取登录用户
export function getTrialUserList(params) {
return request({
url: `/TrialMaintenance/getTrialUserList`,
method: 'get',
params
})
}
// 验证MFA邮件
export function verifyMFACode(params) {
return request({
url: `/User/verifyMFACode`,
method: 'post',
params
})
}
// 发送MFA邮件
export function sendMFAEmail(params) {
return request({
url: `/User/sendMFAEmail`,
method: 'post',
params
})
}
File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 145 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 55 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

+41 -122
View File
@@ -2,28 +2,18 @@
<template>
<div class="base-search-form">
<el-form :size="size" :inline="true" :label-width="labelWidth">
<el-form-item
v-for="item in searchForm"
:key="item.prop"
:label="item.label"
>
<el-form-item v-for="item in searchForm" :key="item.prop" :label="item.label">
<!-- 输入框 -->
<el-input
v-if="item.type === 'Input'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder"
size="mini"
:style="{ width: item.width }"
:readonly="item.readonly"
/>
<el-input v-if="item.type==='Input'" v-model="searchData[item.prop]" :placeholder="item.placeholder" size="mini" :style="{width:item.width}" :readonly="item.readonly" />
<!-- 下拉框 -->
<el-select
v-if="item.type === 'Select'"
v-if="item.type==='Select'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder"
size="mini"
:style="{ width: item.width }"
@change="item.change && item.change(that, searchData[item.prop])"
:style="{width:item.width}"
@change="item.change && item.change(that,searchData[item.prop])"
>
<el-option
v-for="op in item.options"
@@ -33,122 +23,49 @@
/>
</el-select>
<el-select
v-if="item.type === 'Select2'"
v-if="item.type==='Select2'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder"
size="mini"
:style="{ width: item.width }"
@change="item.change && item.change(that, searchData[item.prop])"
:style="{width:item.width}"
@change="item.change && item.change(that,searchData[item.prop])"
>
<el-option
v-for="(key, value) of item.options"
v-for="(key,value) of item.options"
:key="key"
:label="key"
:value="value"
/>
</el-select>
<!-- 单选 -->
<el-radio-group
v-if="item.type === 'Radio'"
v-model="searchData[item.prop]"
:style="{ width: item.width }"
>
<el-radio
v-for="ra in item.radios"
:key="ra.value"
:label="ra.value"
>{{ ra.label }}</el-radio
>
<el-radio-group v-if="item.type==='Radio'" v-model="searchData[item.prop]" :style="{width:item.width}">
<el-radio v-for="ra in item.radios" :key="ra.value" :label="ra.value">{{ ra.label }}</el-radio>
</el-radio-group>
<!-- 单选按钮 -->
<el-radio-group
v-if="item.type === 'RadioButton'"
v-model="searchData[item.prop]"
:style="{ width: item.width }"
@change="item.change && item.change(searchData[item.prop])"
>
<el-radio-button
v-for="ra in item.radios"
:key="ra.value"
:label="ra.value"
>{{ ra.label }}</el-radio-button
>
<el-radio-group v-if="item.type==='RadioButton'" v-model="searchData[item.prop]" :style="{width:item.width}" @change="item.change && item.change(searchData[item.prop])">
<el-radio-button v-for="ra in item.radios" :key="ra.value" :label="ra.value">{{ ra.label }}</el-radio-button>
</el-radio-group>
<!-- 复选框 -->
<el-checkbox-group
v-if="item.type === 'Checkbox'"
v-model="searchData[item.prop]"
:style="{ width: item.width }"
>
<el-checkbox
v-for="ch in item.checkboxs"
:key="ch.value"
:label="ch.value"
>{{ ch.label }}</el-checkbox
>
<el-checkbox-group v-if="item.type==='Checkbox'" v-model="searchData[item.prop]" :style="{width:item.width}">
<el-checkbox v-for="ch in item.checkboxs" :key="ch.value" :label="ch.value">{{ ch.label }}</el-checkbox>
</el-checkbox-group>
<!-- 日期 -->
<el-date-picker
v-if="item.type === 'Date'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder"
:style="{ width: item.width }"
value-format="yyyy-MM-dd"
format="yyyy-MM-dd"
:picker-options="item.pickerOption"
/>
<el-date-picker v-if="item.type==='Date'" v-model="searchData[item.prop]" :placeholder="item.placeholder" :style="{width:item.width}" value-format="yyyy-MM-dd" format="yyyy-MM-dd" :picker-options="item.pickerOption" />
<!-- 时间 -->
<el-time-select
v-if="item.type === 'Time'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder"
type=""
:style="{ width: item.width }"
/>
<el-time-select v-if="item.type==='Time'" v-model="searchData[item.prop]" :placeholder="item.placeholder" type="" :style="{width:item.width}" />
<!-- 日期时间 -->
<el-date-picker
v-if="item.type === 'DateTime'"
v-model="searchData[item.prop]"
:placeholder="item.placeholder"
type="datetime"
value-format="yyyy-MM-dd HH:mm:ss"
:disabled="item.disable && item.disable(searchData[item.prop])"
:style="{ width: item.width }"
/>
<!-- 日期时间段 -->
<el-date-picker
v-if="item.type === 'Daterange'"
v-model="searchData[item.prop]"
type="datetimerange"
range-separator=""
start-placeholder="开始时间"
end-placeholder="结束时间"
value-format="yyyy-MM-dd HH:mm:ss"
format="yyyy-MM-dd HH:mm:ss"
:style="{ width: item.width }"
clearable
/>
<el-date-picker v-if="item.type==='DateTime'" v-model="searchData[item.prop]" :placeholder="item.placeholder" type="datetime" :disabled="item.disable && item.disable(searchData[item.prop])" :style="{width:item.width}" />
<!-- 滑块 -->
<!-- <el-slider v-if="item.type==='Slider'" v-model="searchData[item.prop]"></el-slider> -->
<!-- 开关 -->
<el-switch
v-if="item.type === 'Switch'"
v-model="searchData[item.prop]"
:style="{ width: item.width }"
/>
<el-switch v-if="item.type==='Switch'" v-model="searchData[item.prop]" :style="{width:item.width}" />
<!-- 具名slot -->
<slot v-if="item.type === 'Custom'" :name="item.slot" />
<slot v-if="item.type==='Custom'" :name="item.slot" />
</el-form-item>
<el-form-item v-for="item in searchHandle" :key="item.label">
<slot v-if="item.slot" :name="item.slot" />
<el-button
v-else
:type="item.type"
:size="item.size || size"
:icon="item.icon || ''"
@click="handleClick(item.emitKey)"
>{{ item.label }}</el-button
>
<el-button v-else :type="item.type" :size="item.size || size" :icon="item.icon || ''" @click="handleClick(item.emitKey)">{{ item.label }}</el-button>
</el-form-item>
</el-form>
</div>
@@ -159,45 +76,47 @@ export default {
props: {
that: {
type: Object,
default: this,
default: this
},
isHandle: {
type: Boolean,
default: true,
default: true
},
labelWidth: {
type: String,
default: "",
default: ''
},
size: {
type: String,
default: "mini",
default: 'mini'
},
searchForm: {
type: Array,
default: () => [],
default: () => []
},
searchHandle: {
type: Array,
default: () => [],
default: () => []
},
searchData: {
type: Object,
default: () => {},
},
default: () => {}
}
},
methods: {
handleClick(emitKey) {
// emit事件
this.$emit(`${emitKey}`);
},
},
};
this.$emit(`${emitKey}`)
}
}
}
</script>
<style lang="scss">
.base-search-form {
.el-form-item {
margin-bottom: 0px;
.base-search-form{
.el-form-item{
margin-bottom: 0px;
}
}
}
</style>
+29 -44
View File
@@ -1,16 +1,6 @@
<template>
<div class="base-model-wrapper">
<el-dialog
v-if="config.visible"
v-dialogDrag
:title="config.title"
:append-to-body="config.appendToBody"
:visible.sync="config.visible"
:close-on-click-modal="false"
:show-close="config.showClose"
:width="config.width"
:fullscreen="config.fullscreen"
>
<el-dialog v-if="config.visible" v-dialogDrag :title="config.title" :append-to-body="config.appendToBody" :visible.sync="config.visible" :close-on-click-modal="false" :show-close="config.showClose" :width="config.width" :fullscreen="config.fullscreen">
<div class="base-modal-body">
<slot name="dialog-body" />
</div>
@@ -22,51 +12,46 @@
</template>
<script>
export default {
name: "BaseDialog",
name: 'BaseDialog',
props: {
config: {
type: Object,
default: () => {
return {
visible: false,
title: "",
title: '',
closeOnClickModal: false,
showClose: true,
appendToBody: false,
width: "100px",
fullscreen: false,
};
},
},
},
};
width: '100px',
fullscreen: false
}
}
}
}
}
</script>
<style lang="scss">
.base-model-wrapper {
.el-dialog__header {
padding: 10px;
.el-dialog__headerbtn {
top: 10px;
right: 10px;
}
}
.el-dialog__body {
padding: 10px 10px 10px 10px;
.base-modal-body {
min-height: 100px;
max-height: 650px;
overflow-y: auto;
.base-model-wrapper{
.el-dialog__header{
padding: 10px;
.el-dialog__headerbtn{
top: 10px;
right: 10px;
}
}
.el-dialog__body{
padding:10px 10px 10px 10px;
.base-modal-body{
min-height: 100px;
max-height:650px;
overflow-y: auto;
padding: 10px;
border: 1px solid #e0e0e0;
}
}
.el-dialog__footer{
padding: 10px;
border: 1px solid #e0e0e0;
}
}
.el-dialog__footer {
padding: 10px;
}
}
.notFooter {
.is-fullscreen .el-dialog__footer {
display: none;
}
}
</style>
+1 -1
View File
@@ -1,7 +1,7 @@
<template>
<div class="chat-wrapper">
<div class="chat-content">
<div v-for="(record,index) in recordContent" :key="`${record.chatTime}${index}`">
<div v-for="(record,index) in recordContent" :key="index">
<div v-if="!record.mineMsg" class="word">
<!-- <img :src="record.headUrl"> -->
<img src="@/assets/CRC.png">
+27 -58
View File
@@ -8,6 +8,7 @@
style="width:100%;height:100%;position:relative;"
class="cornerstone-element"
@contextmenu.prevent="onContextmenu"
@mousemove="sliderMousemove"
@mouseup="sliderMouseup"
>
<div v-show="dicomInfo.series" class="info-series">
@@ -53,7 +54,7 @@
<!-- <div v-show="dicomInfo.acc">ACC {{ dicomInfo.acc }}</div> -->
<!-- <div>{{ dicomInfo.time }}</div> -->
</div>
<div ref="sliderBox" class="my_slider_box" style="position: absolute;right: 1px;height: calc(100% - 100px);transform: translateY(-50%);top: calc(50% - 30px);width: 10px;background: #333;cursor: pointer" @click.stop="goViewer($event)">
<div ref="sliderBox" class="my_slider_box" style="position: absolute;right: 1px;height: calc(100% - 100px);transform: translateY(-50%);top: calc(50% - 30px);width: 10px;background: #333;cursor: pointer">
<div :style="{top: height + '%'}" style="z-index:10;background: #9e9e9e;height: 20px;width: 100%;position: absolute;top: 0;cursor: move" @mousedown="sliderMousedown($event)" />
</div>
<div style="position: absolute;left: 50%;top: 15px;color: #f44336;">
@@ -162,9 +163,7 @@ export default {
isMove: false
},
mousePosition: { x: '', y: '', mo: '' },
markers: { top: '', right: '', bottom: '', left: '' },
orientationMarkers: [],
originalMarkers: []
markers: { top: '', right: '', bottom: '', left: '' }
}
},
@@ -187,9 +186,6 @@ export default {
document.addEventListener('mouseup', () => {
this.sliderMouseup()
})
document.addEventListener('mousemove', (e) => {
this.sliderMousemove(e)
})
this.canvas.addEventListener('cornerstonetoolsstackscroll', this.stackScrollCallback)
},
@@ -209,7 +205,7 @@ export default {
var instanceId = imageId.split('/')[imageId.split('/').length - 1]
instanceId = instanceId.split('.')[0]
this.stack.instanceId = instanceId
this.toolState.clipPlaying = false
if (this.toolState.clipPlaying) this.toggleClipPlay()
const element = this.$refs.canvas
cornerstone.enable(element)
this.loading = true
@@ -217,9 +213,7 @@ export default {
cornerstone.loadAndCacheImage(this.stack.imageIds[this.stack.currentImageIdIndex])
.then(image => {
this.loading = false
if (this.stack.imageIds.indexOf(image.imageId) !== -1) {
this.onFirstImageLoaded(image)
}
this.onFirstImageLoaded(image)
}).catch((error) => {
this.loading = false
if (error.error && error.error.message) {
@@ -362,12 +356,6 @@ export default {
if (this.dicomInfo.thick) {
this.dicomInfo.thick = this.dicomInfo.thick.toFixed(2)
}
let newImageIdIndex = this.stack.imageIds.findIndex(i=>i===e.detail.image.imageId)
if(newImageIdIndex === -1) return
this.stack.currentImageIdIndex = newImageIdIndex
this.stack.imageIdIndex = newImageIdIndex
this.series.imageIdIndex = newImageIdIndex
this.height = (this.stack.currentImageIdIndex) * 100 / (this.stack.imageIds.length - 1)
},
stackScrollCallback(e) {
const { detail } = e
@@ -415,7 +403,6 @@ export default {
this.dicomInfo.location = position
},
getOrientationMarker(element) {
console.log('getOrientationMarker')
const enabledElement = cornerstone.getEnabledElement(element)
const imagePlane = cornerstone.metaData.get(
'imagePlaneModule',
@@ -439,7 +426,6 @@ export default {
if (!markers) {
return
}
this.orientationMarkers = [oppositeColumn, row, column, oppositeRow]
this.originalMarkers = [oppositeColumn, row, column, oppositeRow]
this.setMarkers()
@@ -452,10 +438,10 @@ export default {
}
},
onImageLoaded(e) {
// var image = e.detail.image
// // var seriesIndex = -1
// var seriesUid = image.data.string('x0020000e')
// console.log(seriesUid)
var image = e.detail.image
// var seriesIndex = -1
var seriesUid = image.data.string('x0020000e')
console.log(seriesUid)
},
getToolForElement(toolName) {
var isExist = false
@@ -535,9 +521,6 @@ export default {
this.sliderInfo.oldB = parseInt(e.srcElement.style.top) * boxHeight / 100
this.sliderInfo.oldM = e.clientY
this.sliderInfo.isMove = true
e.stopImmediatePropagation()
e.stopPropagation()
e.preventDefault()
},
sliderMousemove(e) {
if (!this.sliderInfo.isMove) return
@@ -557,13 +540,6 @@ export default {
sliderMouseup(e) {
this.sliderInfo.isMove = false
},
goViewer(e) {
// console.log(this.$refs['sliderBox'].clientHeight)
var height = e.offsetY * 100 / this.$refs['sliderBox'].clientHeight
this.height = height
var index = Math.trunc(this.stack.imageIds.length * this.height / 100)
scroll(this.canvas, index)
},
onClipStopped() {
this.toolState.clipPlaying = false
},
@@ -634,7 +610,6 @@ export default {
enabledElement.renderingTools.renderCanvasData = renderCanvasData
},
scrollPage(offset) {
if(this.loading) return
var index = this.stack.currentImageIdIndex + offset
if (index < 0) index = 0
else if (index >= this.stack.imageIds.length) {
@@ -646,7 +621,6 @@ export default {
},
toggleClipPlay() {
if(this.loading) return
if (this.toolState.clipPlaying) {
cornerstoneTools.stopClip(this.canvas)
this.toolState.clipPlaying = false
@@ -701,11 +675,8 @@ export default {
},
resetRotate() {
if (this.originalMarkers.length > 0) {
this.orientationMarkers = [...this.originalMarkers]
this.setMarkers()
}
this.orientationMarkers = [...this.originalMarkers]
this.setMarkers()
var viewport = cornerstone.getViewport(this.canvas)
viewport.hflip = false
viewport.vflip = false
@@ -714,26 +685,24 @@ export default {
},
setRotate(hflip, vflip, angle, type) {
if (this.orientationMarkers.length > 0) {
var markers = [...this.orientationMarkers]
if (type === 2) {
// 垂直翻转
this.orientationMarkers[1] = markers[3]
var markers = [...this.orientationMarkers]
if (type === 2) {
// 垂直翻转
this.orientationMarkers[1] = markers[3]
this.orientationMarkers[3] = markers[1]
} else if (type === 3) {
// 水平翻转
this.orientationMarkers[0] = markers[2]
this.orientationMarkers[2] = markers[0]
} else if (type === 4) {
// 左转90度
this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
} else if (type === 5) {
// 右转90度
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
}
this.setMarkers()
this.orientationMarkers[3] = markers[1]
} else if (type === 3) {
// 水平翻转
this.orientationMarkers[0] = markers[2]
this.orientationMarkers[2] = markers[0]
} else if (type === 4) {
// 左转90度
this.orientationMarkers = markers.slice(1, 4).concat(markers[0])
} else if (type === 5) {
// 右转90度
this.orientationMarkers = [markers[3]].concat(markers.slice(0, 3))
}
this.setMarkers()
var viewport = cornerstone.getViewport(this.canvas)
if (hflip) viewport.hflip = !viewport.hflip
if (vflip) viewport.vflip = !viewport.vflip
+20 -34
View File
@@ -162,19 +162,6 @@
<button :title="$t('trials:dicom-show:lens')" class="btn-link" data-tool="Magnify" @click="setToolActive($event,'Magnify')">
<svg-icon icon-class="zoom" style="font-size:20px;" />
</button>
<button :title="$t('trials:reading:button:rotate')" class="btn-link dropdown" data-tool="Rotate">
<svg-icon icon-class="rotate" style="font-size:20px;" />
<div class="dropdown-content">
<div @click.stop="setDicomCanvasRotate(1)">{{ $t('trials:reading:button:rotateDefault') }}</div>
<div @click.stop="setDicomCanvasRotate(2)">{{ $t('trials:reading:button:rotateHorizontal') }}</div>
<div @click.stop="setDicomCanvasRotate(3)">{{ $t('trials:reading:button:rotateVertical') }}</div>
<div @click.stop="setDicomCanvasRotate(4)">{{ $t('trials:reading:button:rotateTurnLeft') }}</div>
<div @click.stop="setDicomCanvasRotate(5)">{{ $t('trials:reading:button:rotateTurnRight') }}</div>
</div>
</button>
<button :title="$t('trials:reading:button:move')" class="btn-link" data-tool="Pan" @click="setToolActive($event,'Pan')">
<svg-icon icon-class="move" style="font-size:20px;" />
</button>
<button :title="$t('trials:reading:button:fitWindow')" class="btn-link" data-tool="fitToWindow" @click="fitToType($event,'fitToWindow')">
<svg-icon icon-class="fitToWindow" style="font-size:20px;" />
</button>
@@ -182,7 +169,19 @@
<svg-icon icon-class="fitToImage" style="font-size:20px;" />
</button>
<!-- <button title="旋转" class="btn-link dropdown" data-tool="Rotate" @click="setToolActive($event,'Rotate')"> -->
<button :title="$t('trials:reading:button:rotate')" class="btn-link dropdown" data-tool="Rotate">
<svg-icon icon-class="rotate" style="font-size:20px;" />
<div class="dropdown-content">
<p @click.stop="setDicomCanvasRotate(1)">{{ $t('trials:reading:button:rotateDefault') }}</p>
<p @click.stop="setDicomCanvasRotate(2)">{{ $t('trials:reading:button:rotateHorizontal') }}</p>
<p @click.stop="setDicomCanvasRotate(3)">{{ $t('trials:reading:button:rotateVertical') }}</p>
<p @click.stop="setDicomCanvasRotate(4)">{{ $t('trials:reading:button:rotateTurnLeft') }}</p>
<p @click.stop="setDicomCanvasRotate(5)">{{ $t('trials:reading:button:rotateTurnRight') }}</p>
</div>
</button>
<button :title="$t('trials:reading:button:move')" class="btn-link" data-tool="Pan" @click="setToolActive($event,'Pan')">
<svg-icon icon-class="move" style="font-size:20px;" />
</button>
</div>
</div>
<!-- 测量标注 -->
@@ -248,7 +247,7 @@
<svg-icon icon-class="previousframe" style="font-size:20px;" />
</button>
<!-- 播放 -->
<button class="btn-link" :title="$t('trials:dicom-show:play')" @click="clipPlay">
<button class="btn-link" :title="$t('trials:dicom-show:play')" @click="currentDicomCanvas.toggleClipPlay()">
<svg-icon
:icon-class="currentDicomCanvas.toolState.clipPlaying ? 'stop' : 'play'"
style="font-size:20px;"
@@ -262,10 +261,9 @@
<button class="btn-link" :title="$t('trials:dicom-show:lastframe')" @click="currentDicomCanvas.scrollPage(9999)">
<svg-icon icon-class="lastframe" style="font-size:20px;" />
</button>
<select v-model="fps" class="sidetool-select" style="width:60px" @change="setDicomCanvasfps($event)">
<select class="sidetool-select" style="width:60px" @change="setDicomCanvasfps($event)">
<!-- 默认值 -->
<option :value="5">5</option>
<option :value="10">10</option>
<option :value="10">{{ $t('trials:dicom-show:default') }}</option>
<option :value="15">15</option>
<option :value="20">20</option>
<option :value="30">30</option>
@@ -388,22 +386,20 @@ export default {
wwwcList: [],
layout: null,
seriesList: [],
customWwc: { visible: false, title: null },
fps: 15
customWwc: { visible: false, title: null }
}
},
mounted() {
this.customWwc = { visible: false, title: this.$t('DicomViewer:data:customWwc') }
this.rotateList[0] = '1'
this.colorList[0] = ''
this.wwwcList[0] = '-1'
this.wwwcList[0] = '1'
this.colormapsList = cornerstone.colors.getColormapsList()
this.currentDicomCanvas = this.$refs['dicomCanvas0']
},
methods: {
loadImageStack(dicomSeries) {
this.currentDicomCanvas.toolState.clipPlaying = false
this.$nextTick(() => {
this.currentDicomCanvas.loadImageStack(dicomSeries)
})
@@ -448,7 +444,7 @@ export default {
this.colorList[this.currentDicomCanvasIndex] = ''
}
if (!this.wwwcList[this.currentDicomCanvasIndex]) {
this.wwwcList[this.currentDicomCanvasIndex] = '-1'
this.wwwcList[this.currentDicomCanvasIndex] = '1'
}
}
},
@@ -569,10 +565,6 @@ export default {
setDicomCanvasfps(event) {
this.currentDicomCanvas.setFps(event.target.value)
},
clipPlay() {
this.currentDicomCanvas.setFps(this.fps)
this.currentDicomCanvas.toggleClipPlay()
},
fitToType(e, type) {
const toolButtons = document.querySelectorAll('[data-tool]')
Array.from(toolButtons).forEach((toolBtn) => {
@@ -887,19 +879,13 @@ export default {
background-color: #323232;
min-width: 80px;
box-shadow: 0px 8px 16px 0px rgba(0,0,0,0.2);
border: 1px solid #4e4e4e;
padding: 5px;
}
.dicom-wrapper .dropdown:hover .dropdown-content {
display: block;
}
.dicom-wrapper .dropdown-content div{
height: 25px;
line-height: 25px;
.dicom-wrapper .dropdown-content p{
cursor:point;
}
.dicom-wrapper .dropdown-content div:hover{
background-color: #16477b90;
}
</style>
-26
View File
@@ -1,26 +0,0 @@
import Vue from "vue";
import MFACOMP from "./index.vue";
const MFAConstructor = Vue.extend(MFACOMP);
const MFA = options => {
const { UserId, username, EMail, callBack, cancelBack, status = 'login' } = options;
if (!UserId) throw `UserId is requred.but ${UserId}`
const id = `MFA${new Date().getTime()}`;
const instance = new MFAConstructor();
instance.id = id;
instance.vm = instance.$mount();
if (instance.vm.visible) return;
document.body.appendChild(instance.vm.$el);
instance.vm.open({ UserId, username, EMail, status });
instance.vm.$on("success", (Id) => {
if (callBack) callBack(Id)
});
instance.vm.$on("closed", () => {
if (cancelBack) cancelBack();
document.body.removeChild(instance.vm.$el);
instance.vm.$destroy();
});
return instance.vm;
}
export default MFA;
-7
View File
@@ -1,7 +0,0 @@
import MFACOMP from "./index.vue";
import MFA from "./fun";
export default Vue => {
Vue.component(MFACOMP.name, MFACOMP);
Vue.prototype.$MFA = MFA;
};
-204
View File
@@ -1,204 +0,0 @@
<template>
<!--MFA-->
<el-dialog
v-if="visible"
:visible.sync="visible"
width="540px"
:close-on-click-modal="false"
append-to-body
center
:show-close="status === 'login'"
@close="cancel"
>
<div slot="title">
{{ status === "login" ? $t("mfa:title") : $t("mfa:lock:title") }}
</div>
<el-form
ref="mfaForm"
label-position="right"
:model="form"
:rules="rules"
label-width="100px"
>
<!-- 邮箱 -->
<p class="tip">
<i class="el-icon-warning" style="color: #409eff"></i>
<span>{{ tip }}</span>
</p>
<!-- 用户名 -->
<el-form-item :label="$t('mfa:form:username')" prop="username">
<span>{{ form.username }}</span>
</el-form-item>
<!-- 验证码 -->
<el-form-item :label="$t('mfa:form:MFACode')" prop="Code">
<el-input
:placeholder="$t('mfa:form:input:placeholder:Codes')"
v-model="form.Code"
style="width: 240px; margin-right: 10px"
/>
<el-button
type="primary"
size="small"
@click.stop="sendMFACode"
:disabled="flag || sendFlag"
>{{ flag ? `${second}s` : $t("mfa:form:sendMFACode") }}</el-button
>
</el-form-item>
</el-form>
<div slot="footer">
<!-- 取消 -->
<!-- <el-button size="small" @click="cancel" v-if="status === 'login'">
{{ $t("mfa:button:cancel") }}
</el-button> -->
<!-- 保存 -->
<el-button
type="primary"
size="small"
@click="save"
:loading="loading"
style="width: 80%"
>
{{
status === "login"
? $t("mfa:button:save")
: $t("mfa:lock:button:save")
}}
</el-button>
</div>
</el-dialog>
</template>
<script>
import { sendMFAEmail, verifyMFACode } from "@/api/user.js";
export default {
name: "MFA",
data() {
return {
status: "login", // lock
tip: null,
visible: false,
loading: false,
timer: null,
flag: false,
sendFlag: false,
second: 60,
form: {
Code: null,
UserId: null,
EMail: null,
username: null,
},
rules: {
Code: [
{
required: true,
message: this.$t("common:ruleMessage:specify"),
trigger: "blur",
},
],
EMail: [
{
required: true,
message: this.$t("common:ruleMessage:specify"),
trigger: "blur",
},
],
username: [
{
required: true,
message: this.$t("common:ruleMessage:specify"),
trigger: "blur",
},
],
},
};
},
methods: {
open(data) {
let { UserId, status, username, EMail } = data;
this.form.UserId = UserId;
this.status = status ? status : "login";
this.form.username = username;
this.form.EMail = EMail;
this.visible = true;
this.tip = this.$t("mfa:tip").replace("xx", EMail);
},
cancel() {
this.visible = false;
this.$emit("closed");
},
async save() {
try {
let validate = await this.$refs.mfaForm.validate();
if (!validate) return;
this.loading = true;
let res = await verifyMFACode(this.form);
this.loading = false;
if (res.IsSuccess) {
if (this.status === "login") {
this.$message.success(this.$t("mfa:message:verifySuccess"));
}
this.$emit("success", this.form.UserId);
this.cancel();
}
} catch (err) {
console.log(err);
this.loading = false;
}
},
async sendMFACode() {
try {
if (this.flag || this.sendFlag) return;
this.sendFlag = true;
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
let data = {
UserId: this.form.UserId,
};
if (this.status === "lock") {
data.MfaType = 1;
}
let res = await sendMFAEmail(data);
this.sendFlag = false;
if (res.IsSuccess) {
this.flag = true;
this.second = 60;
this.timer = setInterval(() => {
this.second--;
if (this.second <= 0) {
clearInterval(this.timer);
this.timer = null;
}
}, 1000);
}
} catch (err) {
console.log(err);
this.flag = false;
this.sendFlag = false;
}
},
},
destroyed() {
if (this.timer) {
clearInterval(this.timer);
this.timer = null;
}
},
};
</script>
<style lang="scss" scoped>
.tip {
width: 86%;
margin: auto;
margin-bottom: 20px;
text-align: left;
padding: 0 10px;
line-height: 30px;
border-radius: 5px;
background-color: #eee;
i {
margin-right: 5px;
}
}
</style>
-22
View File
@@ -1,22 +0,0 @@
import Vue from "vue";
import Preview from "./index.vue";
const PreviewConstructor = Vue.extend(Preview);
const preview = options => {
const { path, type, title } = options;
if (!path) throw `path is requred.but ${path}`
const id = `Preview_${new Date().getTime()}`;
const instance = new PreviewConstructor();
instance.id = id;
instance.vm = instance.$mount();
if (instance.vm.visible) return;
document.body.appendChild(instance.vm.$el);
instance.vm.open(path, type, title);
instance.vm.$on("closed", () => {
document.body.removeChild(instance.vm.$el);
instance.vm.$destroy();
});
return instance.vm;
}
export default preview;
-7
View File
@@ -1,7 +0,0 @@
import Preview from "./index.vue";
import preview from "./fun";
export default Vue => {
Vue.component(Preview.name, Preview);
Vue.prototype.$preview = preview;
};
-41
View File
@@ -1,41 +0,0 @@
<template>
<el-dialog
v-if="visible"
:visible.sync="visible"
:title="title"
:fullscreen="true"
append-to-body
custom-class="base-dialog-wrapper"
@close="handleClose"
>
<div class="base-modal-body" style="border: 2px solid #ccc; padding: 10px">
<PreviewFile v-if="visible" :file-path="path" :file-type="type" />
</div>
</el-dialog>
</template>
<script>
import PreviewFile from "@/components/PreviewFile";
export default {
name: "preview",
components: { PreviewFile },
data() {
return {
visible: false,
path: null,
type: null,
title: null,
};
},
methods: {
open(path, type, title) {
this.path = path;
this.type = type;
this.title = title;
this.visible = true;
},
handleClose() {
this.$emit("closed");
},
},
};
</script>
+2 -2
View File
@@ -2,13 +2,13 @@
<template>
<div class="trialsTab">
<el-tabs v-model="trialsTab" @tab-click="clickTab">
<el-tab-pane v-for="item of trialsRouter.children.find(v => {return v.name == 'TrialsPanel'}).children" :key="`tab${item.path}`" :disabled="TotalNeedSignTrialDocCount !== 0 && item.path !== '/trials/trials-panel/attachments'" :label="$t(item.LanguageMark)" :name="item.path">
<el-tab-pane v-for="item of trialsRouter.children.find(v => {return v.name == 'TrialsPanel'}).children" :key="`tab${item.path}`" :disabled="TotalNeedSignTrialDocCount !== 0" :label="$t(item.LanguageMark)" :name="item.path">
<el-tabs v-if="!item.tabHiddn" v-model="trialsTabChild" @tab-click="clickTab">
<el-tab-pane
v-for="item1 of item.children"
v-if="TrialConfig && isShow(item1.path)"
:key="`tab1${item1.path}`"
:disabled="TotalNeedSignTrialDocCount !== 0 && item1.path !== '/trials/trials-panel/attachments/self-attachment' || (TrialStatusStr === 'Initializing' && (item1.path === '/trials/trials-panel/setting/personnel-manage' || item1.path === '/trials/trials-panel/setting/qc-question' || item1.path === '/trials/trials-panel/setting/reading-unit' || item1.path === '/trials/trials-panel/setting/medical-audit' || item1.path === '/trials/trials-panel/setting/email-manage'))"
:disabled="TotalNeedSignTrialDocCount !== 0 || (TrialStatusStr === 'Initializing' && (item1.path === '/trials/trials-panel/setting/personnel-manage' || item1.path === '/trials/trials-panel/setting/qc-question' || item1.path === '/trials/trials-panel/setting/reading-unit' || item1.path === '/trials/trials-panel/setting/medical-audit' || item1.path === '/trials/trials-panel/setting/email-manage'))"
:label="$t(item1.LanguageMark)"
:name="item1.path"
/>
+3 -4
View File
@@ -14,8 +14,8 @@
:on-exceed="handleExceed"
accept=".pdf"
>
<el-button size="small" type="primary" :disabled="btnDisabled || $route.query.ReviewStatus === '1'" >{{ $t('system:GcpCertificate:upload:Upload') }}</el-button>
<span slot="tip" class="el-upload__tip">{{$t('system:GcpCertificate:tap:must2') }}</span>
<el-button size="small" type="primary" :disabled="btnDisabled || $route.query.ReviewStatus === '1'" >Upload</el-button>
<span slot="tip" class="el-upload__tip">(must be in pdf format. 1/2 pages, please confirm information integrity)</span>
</el-upload>
</div>
</template>
@@ -45,7 +45,6 @@ export default {
},
methods: {
initFileList() {
if(!this.doctorId) return
getAttachmentByType(this.doctorId, this.type)
.then(res => {
if (res.IsSuccess) {
@@ -130,7 +129,7 @@ export default {
this.fileList = []
this.$emit('getFileList', '', '')
this.$message({
message: this.$t('common:message:deletedSuccessfully'),
message: 'Deleted successfully!',
type: 'success'
})
}
+4 -4
View File
@@ -9,7 +9,7 @@
:file-list="fileList"
:accept="accept"
>
<el-button size="small" type="primary" :disabled="isDisabled">{{ $t('common:button:upload') }}</el-button>
<el-button size="small" type="primary" :disabled="isDisabled">Upload</el-button>
</el-upload>
</div>
</template>
@@ -39,7 +39,6 @@ export default {
}
},
mounted() {
if(!this.doctorId) return
this.initFileList()
},
methods: {
@@ -144,7 +143,8 @@ export default {
this.$confirm('Sure to remove?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
}).then(() => {
deleteAttachment(file.Id, file.Path)
.then(res => {
@@ -152,7 +152,7 @@ export default {
this.fileList.splice(this.fileList.findIndex(item => item.Id === file.Id), 1)
this.$emit('getFileList', this.fileList)
this.$message({
message: this.$t('common:message:deletedSuccessfully'),
message: 'Deleted successfully!',
type: 'success'
})
}
@@ -64,7 +64,7 @@
</template>
</el-table-column>
<el-table-column
v-if="hasPermi(['trials:trials-panel:visit:crc-upload:edit']) && allowAddOrEdit"
v-if="hasPermi(['trials:trials-panel:visit:crc-upload:upload']) && allowAddOrEdit"
:label="$t('common:action:action')"
min-width="120"
>
@@ -81,6 +81,7 @@
<!-- 移除 -->
<el-button
v-if="(data.SubmitState*1 < 2 || (data.SubmitState === 2 && data.IsQCConfirmedReupload))"
v-hasPermi="['trials:trials-panel:visit:crc-upload:upload']"
icon="el-icon-delete"
circle
:title="$t('common:button:delete')"
@@ -126,7 +127,7 @@
</el-table-column>
<el-table-column
v-if="hasPermi(['trials:trials-panel:visit:crc-upload:edit']) && allowAddOrEdit"
v-if="hasPermi(['trials:trials-panel:visit:crc-upload:upload']) && allowAddOrEdit"
:label="$t('common:action:action')"
min-width="200"
>
@@ -143,6 +144,7 @@
<!-- 移除 -->
<el-button
v-if="data.SubmitState*1 < 2 || (data.SubmitState === 2 && data.IsQCConfirmedReupload)"
v-hasPermi="['trials:trials-panel:visit:crc-upload:upload']"
icon="el-icon-delete"
circle
:title="$t('common:button:delete')"
@@ -198,7 +200,7 @@
</el-table-column>
<el-table-column
v-if="hasPermi(['trials:trials-panel:visit:crc-upload:edit']) && allowAddOrEdit"
v-if="hasPermi(['trials:trials-panel:visit:crc-upload:upload']) && allowAddOrEdit"
:label="$t('common:action:action')"
min-width="200"
>
@@ -235,7 +237,7 @@
icon="el-icon-download"
size="small"
:loading="downloadLoading"
@click.native.prevent="handleDownloadTpl(cd)"
@click.native.prevent="handleDownloadTpl(cd.ClinicalDataTrialSetId)"
>
{{ $t('trials:uploadClinicalData:button:downloadTemplate') }}
</el-button>
@@ -549,8 +551,11 @@ export default {
})
})
},
handleDownloadTpl(cd) {
window.open(this.OSSclientConfig.basePath + cd.Path)
handleDownloadTpl(clinicalDataTrialSetId) {
this.downloadLoading = true
DownloadTrialClinicalFile(clinicalDataTrialSetId).then(data => {
this.downloadLoading = false
}).catch(() => { this.downloadLoading = false })
}
}
@@ -1,95 +0,0 @@
<template>
<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')"
/>
<!--检查模态-->
<el-table-column
prop="Modalities"
:label="$t('trials:uploadImage:table:Modalities')"
/>
<!--检查部位-->
<el-table-column
prop="BodyPartForEdit"
:label="$t('trials:uploadImage:table:BodyPartForEdit')"
/>
<!--序列数量-->
<el-table-column
prop="SeriesCount"
:label="$t('trials:uploadImage:table:SeriesCount')"
/>
<!--图像数量-->
<el-table-column
prop="InstanceCount"
:label="$t('trials:uploadImage:table:InstanceCount')"
/>
<!--检查时间-->
<el-table-column
prop="StudyTime"
:label="$t('trials:uploadImage:table:StudyTime')"
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:download')"
@click.stop="preview(scope.row)"
/>
</template>
</el-table-column>
</el-table>
</div>
</base-model>
</template>
<script>
import baseModel from "@/components/BaseModel";
import { getToken } from "@/utils/auth";
export default {
name: "studyView",
props: {
model_cfg: {
type: Object,
default: () => {
return {};
},
},
modelList: {
type: Array,
default: () => {
return [];
},
},
},
components: {
"base-model": baseModel,
},
methods: {
// 预览
preview(row) {
var token = getToken();
const routeData = this.$router.resolve({
path: `/showdicom?studyId=${row.Id}&TokenKey=${token}&type=Study`,
});
window.open(routeData.href, "_blank");
},
},
};
</script>
<style lang="scss" scoped>
</style>
@@ -1,766 +0,0 @@
<template>
<div class="uploadList">
<el-divider content-position="left">{{
$t("trials:uploadImage:button:uploadTableTitle")
}}</el-divider>
<div class="top" style="margin-bottom: 10px">
<el-button
type="primary"
size="small"
v-if="!isLoad"
style="position: relative;
}"
>
<span style="opacity: 0">{{
$t("trials:uploadImage:button:selectFolder")
}}</span>
<label for="file">
{{ $t("trials:uploadImage:button:selectFolder") }}
</label>
</el-button>
<el-button
type="primary"
size="small"
class="el-icon-upload2"
@click.stop="notUp"
v-else
>
{{ $t("trials:uploadImage:button:selectFolder") }}
</el-button>
<input
type="file"
name="file"
id="file"
ref="file"
style="display: none"
webkitdirectory
multiple
@change="beginScanFiles($event)"
/>
</div>
<!--本地影像检查-->
<el-table
:data="uploadList"
style="width: 100%"
v-adaptive="{ bottomOffset: 50 }"
>
<el-table-column type="index" width="40" />
<!--检查信息-->
<el-table-column min-width="200" show-overflow-tooltip>
<template slot="header">
<el-tooltip placement="top">
<div slot="content">
{{ $t("trials:uploadImage:table:studyDetail1") }}<br />
{{ $t("trials:uploadImage:table:studyDetail2") }}<br />
{{ $t("trials:uploadedDicoms:table:studyDate") }}
</div>
<span>{{ $t("trials:uploadImage:table:studyInfo") }}</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<div style="line-height: 15px">
<div>
<div>
<span>
<span style="font-weight: 500">Acc:</span>
<span
:class="{
colorOfRed: !scope.row.dicomInfo.AccessionNumber,
}"
>{{ scope.row.dicomInfo.AccessionNumber || "N/A" }}</span
>
</span>
</div>
<div style="display: inline-block; margin-right: 2px">
<span v-if="scope.row.dicomInfo.Modalities.length > 0">
{{ scope.row.dicomInfo.Modalities.join("") }},
</span>
<span v-else style="color: #f44336">N/A,</span>
</div>
<div style="display: inline-block; margin-right: 2px">
<span v-if="scope.row.SeriesInstanceUidList.length"
>{{ scope.row.SeriesInstanceUidList.length }} Series,
</span>
<span v-else style="color: #f44336">N/A,</span>
</div>
<div style="display: inline-block">
<span v-if="scope.row.count"
>{{ scope.row.count }} Instances
</span>
<span v-else style="color: #f44336">N/A</span>
</div>
</div>
<div>
<div style="display: inline-block; margin-right: 2px">
<span v-if="scope.row.dicomInfo.seriesBodyPartExamined">
{{ scope.row.dicomInfo.seriesBodyPartExamined }},
</span>
<span v-else style="color: #f44336">N/A, </span>
</div>
<div style="display: inline-block">
<span v-if="scope.row.dicomInfo.StudyDescription">
{{ scope.row.dicomInfo.StudyDescription }}</span
>
<span v-else style="color: #f44336">N/A</span>
</div>
</div>
<div>
{{ scope.row.dicomInfo.StudyTime }}
</div>
</div>
</template>
</el-table-column>
<!--患者信息-->
<el-table-column min-width="130" show-overflow-tooltip>
<template slot="header">
<el-tooltip placement="top">
<div slot="content">
{{ $t("trials:uploadImage:table:pId") }}<br />
{{ $t("trials:uploadImage:table:patientName") }}<br />
{{ $t("trials:uploadImage:table:pInfo") }}
</div>
<span>{{ $t("trials:uploadImage:table:patientInfo") }}</span>
</el-tooltip>
</template>
<template slot-scope="scope">
<div style="line-height: 15px">
<div>
<span v-if="scope.row.dicomInfo.PatientId"
><span style="font-weight: 500">PID: </span
>{{ scope.row.dicomInfo.PatientId }}</span
>
<span v-else style="color: #f44336">N/A</span>
</div>
<div>
<span
:class="[scope.row.dicomInfo.PatientName ? '' : 'colorOfRed']"
>
{{ scope.row.dicomInfo.PatientName || "N/A" }}
</span>
</div>
<div>
<span
:class="[scope.row.dicomInfo.PatientSex ? '' : 'colorOfRed']"
>
{{ scope.row.dicomInfo.PatientSex || "N/A" }},
</span>
<span
:class="[scope.row.dicomInfo.PatientAge ? '' : 'colorOfRed']"
>
{{ scope.row.dicomInfo.PatientAge || "N/A" }},
</span>
<span
:class="[
scope.row.dicomInfo.PatientBirthDate ? '' : 'colorOfRed',
]"
>
{{ scope.row.dicomInfo.PatientBirthDate || "N/A" }}
</span>
</div>
</div>
</template>
</el-table-column>
<!--上传进度-->
<el-table-column
prop="schedule"
:label="$t('trials:uploadImage:table:schedule')"
min-width="150"
>
<template slot-scope="scope">
<el-progress
color="#409eff"
:percentage="scope.row.schedule"
v-if="scope.row.schedule || scope.row.schedule === 0"
/>
</template>
</el-table-column>
<!--上传状态-->
<el-table-column
prop="status"
:label="$t('trials:uploadImage:table:status')"
min-width="120"
>
<template slot-scope="scope">
<el-tag
:type="
['warning', 'success', 'danger', 'primary', 'success', 'danger'][
scope.row.status
]
"
v-if="scope.row.status || scope.row.status === 0"
>{{ $fd("UploadStatus", scope.row.status) }}
</el-tag>
</template>
</el-table-column>
<!--已有/成功/失败-->
<el-table-column
prop="scheduleNum"
:label="$t('trials:uploadImage:table:scheduleNum')"
min-width="140"
>
<template slot-scope="scope">
<span v-if="scope.row.count">{{
`${scope.row.count} /${scope.row.successCount} / ${scope.row.failCount}`
}}</span>
</template>
</el-table-column>
<el-table-column
:label="$t('common:action:action')"
fixed="right"
width="140"
>
<!-- <template slot-scope="scope">
</template> -->
</el-table-column>
</el-table>
</div>
</template>
<script>
import {
preArchiveDicomStudy,
addOrUpdateArchiveTaskStudy,
} from "@/api/load.js";
import { parseDicom, getThumbnail, dicomToOSS } from "@/utils/parseDicom.js";
export default {
name: "uploadList",
props: {
SopInstanceUidList: {
type: Array,
default: () => {
return [];
},
},
StudyInstanceUidList: {
type: Array,
default: () => {
return [];
},
},
UploadStudyList: {
type: Array,
default: () => {
return [];
},
},
visible: {
type: Boolean,
default: false,
},
},
data() {
return {
isLoad: false,
uploadList: [], // 待上传文件列表
dicomList: [], // 上传的文件列表
requestNum: 6,
hasOtherStudy: false, // 是否上传文件检查与列表不一致
isClose: false,
};
},
watch: {
isLoad() {
if (!this.isLoad) {
this.$refs.file.value = null;
if (this.dicomList.some((item) => item.isUpload === 3)) {
this.$confirm(this.$t("trials:uploadImage:confirm:failUpload"), {
type: "warning",
distinguishCancelAndClose: true,
confirmButtonText: this.$t("common:button:confirm"),
cancelButtonText: this.$t("common:button:cancel"),
})
.then(() => {
this.againUpload();
})
.catch((err) => {
console.log(err);
});
}
}
},
},
methods: {
// 失败重传
againUpload() {
for (let i = 0; i < this.uploadList.length; i++) {
let item = this.uploadList[i];
if (item.status > 2) continue;
item.status = 0;
item.failCount = 0;
item.schedule = Math.floor(
((item.successCount + item.failCount) / item.count) * 100
);
let arr = this.dicomList.filter(
(dicom) =>
dicom.StudyInstanceUid === item.StudyInstanceUid &&
dicom.isUpload === 3
);
arr.forEach((item) => (item.isUpload = 0));
this.setUploadTask(arr);
}
},
async setUploadTask(arr) {
let num = arr.length > this.requestNum ? this.requestNum : arr.length;
let funArr = [];
for (let i = 0; i < num; i++) {
funArr.push(this.handleUploadTask(arr, i));
}
if (funArr.length > 0) {
let res = await Promise.all(funArr);
}
},
// 预上传
async preArchiveDicomStudy(post, index) {
try {
let res = await preArchiveDicomStudy(post);
if (res.IsSuccess) {
let item = this.uploadList[index];
item.StudyMonitorId = res.Result;
let arr = this.dicomList.filter(
(dicom) => dicom.StudyInstanceUid === item.StudyInstanceUid
);
this.setUploadTask(arr);
} else {
return false;
}
} catch (err) {
console.log(err);
return false;
}
},
// 上传
async beginScanFiles(e) {
let files = e.target.files;
try {
this.dicomList = [];
this.hasOtherStudy = false;
for (var i = 0; i < files.length; ++i) {
if (files[i].name.indexOf("DICOMDIR") >= 0) continue;
let dicom = await parseDicom(files[i]);
if (!dicom) continue;
let has = this.dicomList.some(
(item) => item.SopInstanceUid === dicom.SopInstanceUid
);
if (has) continue;
has = this.StudyInstanceUidList.some(
(item) => item.StudyInstanceUid === dicom.StudyInstanceUid
);
if (!has) {
this.hasOtherStudy = true;
continue;
}
if (this.SopInstanceUidList.includes(dicom.SopInstanceUid)) continue;
this.isLoad = true;
dicom.file = files[i];
dicom.isUpload = 0;
this.StudyInstanceUidList.some((item) => {
if (item.StudyInstanceUid === dicom.StudyInstanceUid) {
dicom.params = {
TrialId: this.$route.query.trialId,
SubjectId: item.SubjectId,
VisitTaskId: item.VisitTaskId,
SourceSubjectVisitId: item.SourceSubjectVisitId,
};
let uploadHas = this.uploadList.some((uploadData) => {
if (uploadData.StudyInstanceUid === dicom.StudyInstanceUid) {
if (uploadData.status > 0) {
uploadData.count = 1;
uploadData.successCount = 0;
uploadData.failCount = 0;
uploadData.schedule = 0;
uploadData.status = 0;
uploadData.FileSize = dicom.file.size;
uploadData.SeriesInstanceUidList = [
dicom.SeriesInstanceUid,
];
uploadData.dicomInfo = {
AccessionNumber: dicom.AccessionNumber,
Modalities: dicom.Modalities,
seriesBodyPartExamined: dicom.seriesBodyPartExamined,
StudyDescription: dicom.StudyDescription,
StudyTime: this.getTime(dicom.StudyDate, dicom.StudyTime),
PatientName: dicom.PatientName,
PatientId: dicom.PatientId,
PatientAge: dicom.PatientAge,
PatientSex: dicom.PatientSex,
PatientBirthDate: dicom.PatientBirthDate,
};
} else {
uploadData.FileSize += dicom.file.size;
uploadData.count++;
}
if (
!uploadData.SeriesInstanceUidList.includes(
dicom.SeriesInstanceUid
)
) {
uploadData.SeriesInstanceUidList.push(
dicom.SeriesInstanceUid
);
}
}
return uploadData.StudyInstanceUid === dicom.StudyInstanceUid;
});
if (!uploadHas) {
let uploadData = {
TrialId: this.$route.query.trialId,
SubjectId: item.SubjectId,
SourceSubjectVisitId: item.SourceSubjectVisitId,
StudyId: dicom.StudyId,
StudyInstanceUid: dicom.StudyInstanceUid,
FileSize: dicom.file.size,
count: 1,
successCount: 0,
failCount: 0,
schedule: 0,
status: 0,
SeriesInstanceUidList: [dicom.SeriesInstanceUid],
IsDicomReUpload: false,
dicomInfo: {
AccessionNumber: dicom.AccessionNumber,
Modalities: dicom.Modalities,
seriesBodyPartExamined: dicom.seriesBodyPartExamined,
StudyDescription: dicom.StudyDescription,
StudyTime: this.getTime(dicom.StudyDate, dicom.StudyTime),
PatientName: dicom.PatientName,
PatientId: dicom.PatientId,
PatientAge: dicom.PatientAge,
PatientSex: dicom.PatientSex,
PatientBirthDate: dicom.PatientBirthDate,
},
};
if (
this.UploadStudyList.some(
(d) => d.StudyInstanceUid === uploadData.StudyInstanceUid
)
) {
uploadData.IsDicomReUpload = true;
}
this.uploadList.push(uploadData);
}
}
return item.StudyInstanceUid === dicom.StudyInstanceUid;
});
this.dicomList.push(dicom);
}
if (this.dicomList.length <= 0 && this.hasOtherStudy) {
let confirm = await this.$confirm(
this.$t("trials:uploadImage:confirmMessage:failSubject"),
{
type: "warning",
distinguishCancelAndClose: true,
confirmButtonText: this.$t("common:button:confirm"),
cancelButtonText: this.$t("common:button:cancel"),
}
);
if (confirm !== "confirm") return false;
this.$refs.file.click();
return false;
}
let funArr = [];
for (let i = 0; i < this.uploadList.length; i++) {
let item = this.uploadList[i];
let data = {
TrialId: item.TrialId,
SubjectId: item.SubjectId,
SubjectVisitId: item.SourceSubjectVisitId,
FileSize: item.FileSize,
IsDicomReUpload: item.IsDicomReUpload,
FileCount: item.count,
};
funArr.push(this.preArchiveDicomStudy(data, i));
}
if (funArr && funArr.length > 0) {
let res = await Promise.all(funArr);
}
} catch (err) {
console.log(err);
this.$refs.file.value = null;
}
},
// 并发上传
async handleUploadTask(arr, index) {
if (this.isClose) return false;
arr[index].isUpload = 1;
let path = `/${arr[index].params.TrialId}/TaskImage/${
arr[index].params.SubjectId
}/${arr[index].params.VisitTaskId}/${
arr[index].StudyInstanceUid
}/${this.getGuid(
arr[index].StudyInstanceUid +
arr[index].SeriesInstanceUid +
arr[index].SOPInstanceUid +
arr[index].params.TrialId +
arr[index].params.VisitTaskId
)}`;
let uploadDicom = this.uploadList.filter(
(item) => item.StudyInstanceUid === arr[index].StudyInstanceUid
)[0];
let res = await dicomToOSS(arr[index].file, path);
if (res) {
arr[index].path = res;
uploadDicom.successCount++;
arr[index].isUpload = 2;
} else {
uploadDicom.status = 2;
uploadDicom.failCount++;
arr[index].isUpload = 3;
}
uploadDicom.schedule = Math.floor(
((uploadDicom.successCount + uploadDicom.failCount) /
uploadDicom.count) *
100
);
if (uploadDicom.schedule >= 100) {
if (uploadDicom.successCount === uploadDicom.count) {
uploadDicom.status = 1;
if (!uploadDicom.Study) {
let res = await this.formatDicom(arr, arr[index].StudyInstanceUid);
if (res) {
uploadDicom.Study = res[arr[index].StudyId];
uploadDicom.status = 3;
}
}
try {
res = await addOrUpdateArchiveTaskStudy(uploadDicom);
if (res.IsSuccess) {
uploadDicom.status = 4;
this.$emit("getList");
let ind = this.uploadList.findIndex(
(item) => item.StudyInstanceUid === uploadDicom.StudyInstanceUid
);
this.uploadList.splice(ind, 1);
} else {
uploadDicom.status = 5;
}
let flag = this.dicomList.every((item) => item.isUpload > 1);
if (flag) this.isLoad = false;
} catch (err) {
uploadDicom.status = 5;
let flag = this.dicomList.every((item) => item.isUpload > 1);
if (flag) this.isLoad = false;
}
} else if (
uploadDicom.count ===
uploadDicom.successCount + uploadDicom.failCount
) {
let flag = this.dicomList.every((item) => item.isUpload > 1);
if (flag) this.isLoad = false;
}
}
let ind = arr.findIndex((item) => !item.isUpload);
if (ind >= 0) {
return this.handleUploadTask(arr, ind);
} else {
return false;
}
},
// 数据整理
async formatDicom(arr, StudyInstanceUid) {
let studyObj = {};
for (let i = 0; i < arr.length; i++) {
let dicom = arr[i];
if (dicom.StudyInstanceUid !== StudyInstanceUid) continue;
let thumbnailPath = `/${dicom.params.TrialId}/TaskImage/${dicom.params.SubjectId}/${dicom.params.VisitTaskId}/${dicom.StudyInstanceUid}/${dicom.SeriesInstanceUid}.png`;
if (!studyObj[dicom.StudyId]) {
studyObj[dicom.StudyId] = {
StudyId: dicom.StudyId,
StudyInstanceUid: dicom.StudyInstanceUid,
StudyTime: this.getTime(dicom.StudyDate, dicom.StudyTime),
Modalities: dicom.Modalities,
Description: dicom.StudyDescription,
SeriesCount: 1,
InstanceCount: 1,
InstitutionName: dicom.InstitutionName,
PatientId: dicom.PatientId,
PatientName: dicom.PatientName,
PatientAge: dicom.PatientAge,
PatientSex: dicom.PatientSex,
AccessionNumber: dicom.AccessionNumber,
PatientBirthDate: dicom.PatientBirthDate,
AcquisitionTime: dicom.AcquisitionTime,
AcquisitionNumber: dicom.AcquisitionNumber,
TriggerTime: dicom.TriggerTime,
BodyPartExamined: dicom.BodyPartExamined,
SeriesList: [
{
StudyInstanceUid: dicom.StudyInstanceUid,
SeriesInstanceUid: dicom.SeriesInstanceUid,
SeriesNumber: dicom.SeriesNumber,
SeriesTime: this.getTime(dicom.SeriesDate, dicom.SeriesTime),
Modality: dicom.Modality,
Description: dicom.SeriesDescription,
InstanceCount: 1,
SliceThickness: dicom.SliceThickness,
ImagePositionPatient: dicom.ImagePosition,
ImageOrientationPatient: dicom.ImageOrientation,
BodyPartExamined: dicom.seriesBodyPartExamined,
SequenceName: dicom.SequenceName,
ProtocolName: dicom.ProtocolName,
ImagerPixelSpacing: dicom.ImagePixelSpacing,
AcquisitionTime: dicom.AcquisitionTime,
AcquisitionNumber: dicom.AcquisitionNumber,
TriggerTime: dicom.TriggerTime,
ImageResizePath: await getThumbnail(
dicom.file,
thumbnailPath,
dicom
),
InstanceList: [
{
StudyInstanceUid: dicom.StudyInstanceUid,
SeriesInstanceUid: dicom.SeriesInstanceUid,
SopInstanceUid: dicom.SopInstanceUid,
InstanceNumber: dicom.ImageOrInstanceNumber,
InstanceTime: this.getTime(
dicom.ContentDate,
dicom.ContentTime
),
ImageRows: dicom.Rows || 0,
ImageColumns: dicom.Columns || 0,
SliceLocation: dicom.SliceLocation,
SliceThickness: dicom.SliceThickness,
NumberOfFrames: dicom.NumberOfFrames || 0,
PixelSpacing: dicom.PixelSpacing,
ImagerPixelSpacing: dicom.ImagePixelSpacing,
FrameOfReferenceUID: dicom.FrameOfReferenceUID,
WindowCenter: dicom.WindowCenter,
WindowWidth: dicom.WindowWidth,
Path: dicom.path,
HtmlPath: "",
},
],
},
],
};
} else {
let seriesHas = studyObj[dicom.StudyId].SeriesList.some((item) => {
if (item.SeriesInstanceUid === dicom.SeriesInstanceUid) {
item.InstanceCount++;
let instance = {
StudyInstanceUid: dicom.StudyInstanceUid,
SeriesInstanceUid: dicom.SeriesInstanceUid,
SopInstanceUid: dicom.SopInstanceUid,
InstanceNumber: dicom.ImageOrInstanceNumber,
InstanceTime: this.getTime(
dicom.ContentDate,
dicom.ContentTime
),
ImageRows: dicom.Rows || 0,
ImageColumns: dicom.Columns || 0,
SliceLocation: dicom.SliceLocation,
SliceThickness: dicom.SliceThickness,
NumberOfFrames: dicom.NumberOfFrames || 0,
PixelSpacing: dicom.PixelSpacing,
ImagerPixelSpacing: dicom.ImagePixelSpacing,
FrameOfReferenceUID: dicom.FrameOfReferenceUID,
WindowCenter: dicom.WindowCenter,
WindowWidth: dicom.WindowWidth,
Path: dicom.path,
HtmlPath: "",
};
item.InstanceList.push(instance);
}
return item.SeriesInstanceUid === dicom.SeriesInstanceUid;
});
if (!seriesHas) {
studyObj[dicom.StudyId].SeriesCount++;
let series = {
StudyInstanceUid: dicom.StudyInstanceUid,
SeriesInstanceUid: dicom.SeriesInstanceUid,
SeriesNumber: dicom.SeriesNumber,
SeriesTime: this.getTime(dicom.SeriesDate, dicom.SeriesTime),
Modality: dicom.Modality,
Description: dicom.SeriesDescription,
InstanceCount: 1,
SliceThickness: dicom.SliceThickness,
ImagePositionPatient: dicom.ImagePosition,
ImageOrientationPatient: dicom.ImageOrientation,
BodyPartExamined: dicom.seriesBodyPartExamined,
SequenceName: dicom.SequenceName,
ProtocolName: dicom.ProtocolName,
ImagerPixelSpacing: dicom.ImagePixelSpacing,
AcquisitionTime: dicom.AcquisitionTime,
AcquisitionNumber: dicom.AcquisitionNumber,
TriggerTime: dicom.TriggerTime,
ImageResizePath: await getThumbnail(
dicom.file,
thumbnailPath,
dicom
),
InstanceList: [
{
StudyInstanceUid: dicom.StudyInstanceUid,
SeriesInstanceUid: dicom.SeriesInstanceUid,
SopInstanceUid: dicom.SopInstanceUid,
InstanceNumber: dicom.ImageOrInstanceNumber,
InstanceTime: this.getTime(
dicom.ContentDate,
dicom.ContentTime
),
ImageRows: dicom.Rows || 0,
ImageColumns: dicom.Columns || 0,
SliceLocation: dicom.SliceLocation,
SliceThickness: dicom.SliceThickness,
NumberOfFrames: dicom.NumberOfFrames || 0,
PixelSpacing: dicom.PixelSpacing,
ImagerPixelSpacing: dicom.ImagePixelSpacing,
FrameOfReferenceUID: dicom.FrameOfReferenceUID,
WindowCenter: dicom.WindowCenter,
WindowWidth: dicom.WindowWidth,
Path: dicom.path,
HtmlPath: "",
},
],
};
studyObj[dicom.StudyId].SeriesList.push(series);
}
studyObj[dicom.StudyId].InstanceCount++;
}
}
return studyObj;
},
// dicom时间转换
getTime(date, time) {
let studyTime = "";
if (date) {
date = `${date.substring(0, 4)}-${date.substring(
4,
6
)}-${date.substring(6, 8)}`;
}
if (time) {
time = `${time.substring(0, 2)}:${time.substring(
2,
4
)}:${time.substring(4, 6)}`;
}
if (date) {
studyTime = time ? `${date} ${time}` : `${date} 00:00:00`;
}
return studyTime;
},
},
beforeDestroy() {
this.isClose = true;
},
};
</script>
<style lang="scss" scoped>
.colorOfRed {
color: #f44336;
}
label {
cursor: pointer;
position: absolute;
top: 0;
bottom: 0;
right: 0;
left: 0;
padding: 9px 15px;
}
</style>
-271
View File
@@ -1,271 +0,0 @@
<template>
<el-dialog
:visible.sync="visible"
:fullscreen="true"
:close-on-click-modal="false"
custom-class="upload-dialog"
:before-close="beforeClose"
class="uploadImage"
>
<span slot="title">{{ title }}</span>
<el-divider content-position="left">{{
$t("trials:uploadImage:button:uploadTableTitle1")
}}</el-divider>
<!--已上传影像检查-->
<el-table
:data="list"
style="width: 100%"
height="300"
v-adaptive="{ bottomOffset: 50, notAdaptive: isUpload }"
:loading="loading"
>
<!--受试者-->
<el-table-column
prop="SubjectCode"
:label="$t('trials:uploadImage:table:subjectCode')"
/>
<!--任务名称-->
<el-table-column
prop="TaskBlindName"
:label="$t('trials:uploadImage:table:taskBlindName')"
/>
<!--原始检查数-->
<el-table-column
prop="OrginalStudyList"
:label="$t('trials:uploadImage:table:orginalStudyListNum')"
>
<template slot-scope="scope">
<el-button
v-if="
scope.row.OrginalStudyList &&
scope.row.OrginalStudyList.length >= 1
"
type="text"
@click="handleOpenDialog(scope.row, 'OrginalStudyList')"
>
<span>{{ scope.row.OrginalStudyList.length }}</span>
</el-button>
<span v-else>0</span>
</template>
</el-table-column>
<!--后处理检查数-->
<el-table-column
prop="UploadStudyList"
:label="$t('trials:uploadImage:table:uploadStudyListNum')"
>
<template slot-scope="scope">{{
scope.row.UploadStudyList && Array.isArray(scope.row.UploadStudyList)
? scope.row.UploadStudyList.length
: 0
}}</template>
</el-table-column>
<el-table-column
:label="$t('common:action:action')"
fixed="right"
width="140"
>
<template slot-scope="scope">
<!--下载--->
<el-button
v-if="!isUpload && Criterion.ImageDownloadEnum > 0"
circle
icon="el-icon-download"
:title="$t('trials:uploadImage:button:download')"
@click.stop="downloadImage(scope.row)"
/>
<!--删除--->
<el-button
v-if="isUpload"
circle
icon="el-icon-delete"
:title="$t('trials:uploadImage:button:delete')"
@click.stop="remove(scope.row)"
/>
</template>
</el-table-column>
</el-table>
<upload-list
v-if="Criterion.ImageUploadEnum > 0 && isUpload"
:StudyInstanceUidList="StudyInstanceUidList"
:SopInstanceUidList="SopInstanceUidList"
:UploadStudyList="UploadStudyList"
@getList="getList"
/>
<study-view
v-if="model_cfg.visible"
:model_cfg="model_cfg"
:modelList="modelList"
/>
</el-dialog>
</template>
<script>
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";
export default {
name: "uploadImage",
props: {
visible: {
type: Boolean,
default: false,
},
SubjectId: {
type: String,
default: "",
},
Criterion: {
type: Object,
default: () => {
return {};
},
},
status: {
type: String,
default: "upload",
},
},
components: {
"upload-list": uploadList,
"study-view": studyView,
},
data() {
return {
list: [],
StudyInstanceUidList: [],
SopInstanceUidList: [],
UploadStudyList: [],
// 检查数弹框
model_cfg: {
visible: false,
showClose: true,
width: "1000px",
title: "",
appendToBody: true,
},
modelList: [],
};
},
computed: {
title() {
let str = this.$t("trials:uploadImage:title:uploadImages");
if (this.status === "download") {
str = this.$t("trials:uploadImage:title:uploadImagesDownLoad");
}
return str;
},
isUpload() {
return this.status === "upload";
},
},
created() {
this.getList();
},
methods: {
beforeClose() {
this.$emit("update:visible", false);
},
notUp() {
this.$confirm(this.$t("trials:uploadImage:confirmMessage:notUp"), {
type: "warning",
distinguishCancelAndClose: true,
confirmButtonText: this.$t("common:button:confirm"),
cancelButtonText: this.$t("common:button:cancel"),
});
},
// 获取列表
async getList() {
try {
let params = {
SubjectId: this.SubjectId,
TrialReadingCriterionId: this.Criterion.TrialReadingCriterionId,
};
this.loading = true;
let res = await getSubjectImageUploadList(params);
this.loading = false;
if (res.IsSuccess) {
this.StudyInstanceUidList = [];
this.SopInstanceUidList = [];
this.UploadStudyList = [];
this.list = res.Result;
res.Result.forEach((item) => {
if (item.OrginalStudyList && Array.isArray(item.OrginalStudyList)) {
item.OrginalStudyList.forEach((data) => {
data.SubjectId = item.SubejctId;
data.VisitTaskId = item.VisitTaskId;
data.SourceSubjectVisitId = item.SourceSubjectVisitId;
this.StudyInstanceUidList.push(data);
});
}
if (item.UploadStudyList && Array.isArray(item.UploadStudyList)) {
item.UploadStudyList.forEach((data) => {
data.SopInstanceUidList &&
this.SopInstanceUidList.push(...data.SopInstanceUidList);
this.UploadStudyList.push(data);
});
}
});
}
} catch (err) {
console.log(err);
this.loading = false;
}
},
// 删除
async remove(item) {
try {
let confirm = await this.$confirm(
this.$t("trials:uploadImage: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,
};
let res = await deleteTaskStudy(params);
if (res.IsSuccess) {
this.getList();
this.$message.success(
this.$t("trials:uploadImage:message:delSuccess")
);
}
} catch (err) {
console.log(err);
}
},
// 打开弹窗
handleOpenDialog(item, list) {
this.model_cfg.title = `${item.SubejctCode || ""}>${item.TaskBlindName}`;
this.modelList = item[list];
this.model_cfg.visible = true;
},
// 打包下载
async downloadImage(item) {
try {
await downloadImage(
this.$route.query.trialId,
item.SourceSubjectVisitId
);
} catch (err) {
console.log(err);
}
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .el-dialog {
.el-dialog__header {
padding-top: 15px;
}
}
.uploadImage {
background-color: #fff;
}
</style>
-1
View File
@@ -27,7 +27,6 @@ export default
ReadingUnitConfirmation: 108, // 医学审核问题确认
MedicalAudit: 215,// 医学审核
HeavyReadingApproval: 216,// 重阅审批
ResetAndAsyncCriterion: 218, //同步签名
}
}
</script>
+2 -3
View File
@@ -4,12 +4,11 @@ import {
} from 'element-ui/src/utils/resize-event'
// 设置表格高度
const doResize = async (el, binding, vnode) => {
const doResize = async(el, binding, vnode) => {
// 获取表格Dom对象
const { componentInstance: $table } = await vnode
// 获取调用传递过来的数据
const { value } = binding
if (value && value.notAdaptive) return;
// 获取距底部距离(用于展示页码等信息)
const bottomOffset = (value && value.bottomOffset) || 40
if (!$table) return
@@ -25,7 +24,7 @@ export default {
// 初始化设置
bind(el, binding, vnode) {
// 设置resize监听方法
el.resizeListener = async () => {
el.resizeListener = async() => {
await doResize(el, binding, vnode)
}
// 绑定监听方法到addResizeListener
-1
View File
@@ -1 +0,0 @@
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1710814433132" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6202" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M509.48 9.666C232.874 9.666 8.666 233.874 8.666 510.48c0 276.618 224.206 500.818 500.814 500.818 276.618 0 500.818-224.202 500.818-500.818 0-276.606-224.2-500.814-500.818-500.814z m0 896.198c-218.384 0-395.378-176.994-395.378-395.382 0-218.384 176.996-395.378 395.378-395.378 218.388 0 395.382 176.996 395.382 395.378 0.002 218.388-176.992 395.382-395.382 395.382z m26.362-390.848v-189.042c0-29.136-23.578-52.718-52.718-52.718s-52.716 23.582-52.716 52.718v210.87c0 0.18 0.012 0.356 0.014 0.534 0.006 0.686 0.018 1.37 0.052 2.054 0.026 0.52 0.072 1.036 0.112 1.55 0.026 0.334 0.042 0.666 0.076 1 0.06 0.632 0.142 1.258 0.226 1.884 0.028 0.21 0.05 0.422 0.08 0.63 0.102 0.698 0.222 1.388 0.35 2.076 0.026 0.136 0.046 0.276 0.074 0.412 0.142 0.732 0.304 1.458 0.476 2.178 0.022 0.098 0.042 0.196 0.068 0.292 0.182 0.744 0.382 1.48 0.596 2.21l0.068 0.244c0.22 0.74 0.46 1.474 0.71 2.202l0.078 0.228c0.256 0.732 0.532 1.454 0.818 2.17 0.032 0.076 0.06 0.154 0.09 0.23 0.292 0.718 0.602 1.428 0.926 2.13l0.104 0.228c0.334 0.716 0.684 1.424 1.05 2.124 0.032 0.058 0.06 0.12 0.09 0.178 0.386 0.732 0.79 1.454 1.208 2.164l0.044 0.078a52.9 52.9 0 0 0 8.716 11.054l148.508 148.506c20.594 20.598 53.956 20.598 74.548 0 20.586-20.586 20.586-53.95 0-74.542l-133.648-133.642z" fill="#FFFFFF" p-id="6203"></path></svg>

Before

Width:  |  Height:  |  Size: 1.6 KiB

+11 -10
View File
@@ -23,22 +23,23 @@
<div style="margin-left:20px;">
<el-dropdown class="dropdown-container" trigger="click">
<span class="el-dropdown-link">
{{ `${name} (${userTypeShortName})` }}
<!-- {{ name }}
<span v-if="userTypeShortName"> ({{ userTypeShortName }}) </span> -->
{{ name }}
<span v-if="userTypeShortName">({{ userTypeShortName }})</span>
<i class="el-icon-caret-bottom" />
</span>
<el-dropdown-menu slot="dropdown" class="user-dropdown">
<el-dropdown-item v-if="!isReviewer">
<span style="display:block;" @click="editInfo">{{$t('system:navbar:button:Profile')}}</span>
<span style="display:block;" @click="editInfo">Edit Info</span>
</el-dropdown-item>
<el-dropdown-item>
<span style="display:block;" @click="account">Account</span>
</el-dropdown-item>
<el-dropdown-item divided>
<span style="display:block;" @click="logout">{{$t('system:navbar:button:Log Out')}}</span>
<span style="display:block;" @click="logout">Log Out</span>
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</div>
<TopLang></TopLang>
</div>
</div>
</div>
@@ -49,15 +50,12 @@ import {mapGetters, mapMutations} from 'vuex'
import Breadcrumb from '@/components/Breadcrumb'
import Hamburger from '@/components/Hamburger'
import Screenfull from '@/components/Screenfull'
import TopLang from './topLang'
export default {
components: {
Breadcrumb,
Hamburger,
Screenfull,
TopLang
Screenfull
},
data() {
return {
@@ -91,6 +89,9 @@ export default {
editInfo() {
this.$router.push({ name: 'BaiscInfo' })
},
account() {
this.$router.push({ name: 'Account' })
}
}
}
</script>
-54
View File
@@ -1,54 +0,0 @@
<template>
<el-dropdown
style="height:50px;line-height: 60px;"
@command="handleSetLanguage"
>
<span class="el-dropdown-link">
<svg-icon icon-class="language" style="font-size:25px;margin:0 10px;" />
<!-- {{ language==='zh'?'语言:中文':'Language: English' }} -->
<!-- <i class="el-icon-arrow-down el-icon--right" /> -->
</span>
<el-dropdown-menu slot="dropdown">
<el-dropdown-item
:disabled="language==='zh'"
command="zh"
>中文
</el-dropdown-item>
<el-dropdown-item
:disabled="language==='en'"
command="en"
>English
</el-dropdown-item>
</el-dropdown-menu>
</el-dropdown>
</template>
<script>
import { mapGetters, mapMutations } from 'vuex'
export default {
name: 'TopLang',
data() {
return {}
},
computed: {
...mapGetters({
language: 'language'
})
},
methods: {
...mapMutations({ setLanguage: 'lang/setLanguage' }),
handleSetLanguage(lang) {
this.$i18n.locale = lang
this.setLanguage(lang)
this.$updateDictionary()
window.location.reload()
}
}
}
</script>
<style lang="scss" scoped>
</style>
+68 -124
View File
@@ -4,7 +4,6 @@ import 'normalize.css/normalize.css' // A modern alternative to CSS resets
import ElementUI, { MessageBox } from 'element-ui'
import { getBasicDataAllSelect, getFrontInternationalizationList } from '@/api/dictionary/dictionary'
import { sendMFAEmail } from "@/api/user.js";
import { resetReadingRestTime } from '@/api/trials/reading'
// import 'element-ui/lib/theme-chalk/index.css'
import './assets/css/theme-blue/index.css' // 浅绿色主题
@@ -25,6 +24,7 @@ Vue.use(VueClipboard)
// import htmlToPdf from './utils/htmlToPdf'
// Vue.use(htmlToPdf)
import permission from './utils/permission'
import { OSSclient } from './utils/oss'
Vue.use(permission)
import Viewer from 'v-viewer'
@@ -57,18 +57,14 @@ Vue.use(hasPermi)
// Vue.use(ElementUI, { locale, size: 'medium' })
import upload from '@/components/element-ui/upload'
Vue.use(upload)
import Preview from '@/components/Preview/index'
Vue.use(Preview)
import MFA from '@/components/MFA/index'
Vue.use(MFA)
import adaptive from '@/directive/adaptive/index'
// 表格自适应指令
Vue.use(adaptive)
import dialogDrag from '@/directive/dialogDrag'
// 窗口拖拽
Vue.use(dialogDrag)
if (!String.prototype.replaceAll) {
String.prototype.replaceAll = function (str, newStr) {
if(!String.prototype.replaceAll){
String.prototype.replaceAll = function(str, newStr){
// 正则表达式
if (Object.prototype.toString.call(str).toLowerCase() === '[object regexp]') {
return this.replace(str, newStr)
@@ -84,7 +80,6 @@ import DictTag from '@/components/DictTag'
import DictData from '@/components/DictData'
import { getBasicDataSelect } from '@/api/dictionary/dictionary'
import { checkConfig } from '@/const/check/index'
import { getTrialBodyPartList } from "@/api/trials/setting";
// 全局方法挂载
var $q = params
Vue.prototype.checkConfig = checkConfig
@@ -101,14 +96,12 @@ Vue.prototype.selectDictLabel = selectDictLabel
// Vue.prototype.download = download
Vue.prototype.handleTree = handleTree
Vue.prototype.$getObjectName = (url) => {
// console.log(url,'url')
// console.log(Vue.prototype.OSSclientConfig.viewEndpoint,'url')
var value = url;
let basePath = Vue.prototype.OSSclientConfig.viewEndpoint;
if (Vue.prototype.OSSclientConfig.ObjectStoreUse === 'AliyunOSS') {
basePath = Vue.prototype.OSSclientConfig.endPoint.split('https://').length > 1 ? Vue.prototype.OSSclientConfig.endPoint.split('https://')[1] : Vue.prototype.OSSclientConfig.endPoint;
}
return value.split(basePath)[1];
// console.log(url)
var value = url
var str = value.split("//"); //https://进行分割,
var index = str[1].indexOf("/")+1; //indexOf 获取第一个斜杠的索引,
// console.log(str[1].substring(index)); //substring 截取,
return '/' + str[1].substring(index)
}
Vue.prototype.getGuid = (text) => {
text = md5(text)
@@ -124,14 +117,14 @@ Vue.prototype.getGuid = (text) => {
t9 = text.substr(16, 4)
t10 = text.substr(20, 12)
// console.log(`${t4+t3+t2+t1}-${t6+t5}-${t8+t7}-${t9}-${t10}`)
return `${t4 + t3 + t2 + t1}-${t6 + t5}-${t8 + t7}-${t9}-${t10}`
return `${t4+t3+t2+t1}-${t6+t5}-${t8+t7}-${t9}-${t10}`
}
Vue.prototype.$validatePassword = (rule, value, callback) => {
var lang = zzSessionStorage.getItem('lang') ? zzSessionStorage.getItem('lang') : 'zh'
var lang = zzSessionStorage.getItem('lang')?zzSessionStorage.getItem('lang'):'zh'
/* eslint-disable */
var reg1 = eval(process.env.VUE_APP_PASSWORD_FOR_PERMISSION) ? new RegExp(`${process.env.VUE_APP_PASSWORD_FOR_REGULAR}`) : /.*/g; //密码必须是8位以上、必须含有字母、数字、特殊符号
if (!reg1.test(value)) {
callback(lang === 'zh' ? new Error("密码必须包含:1)8 – 32 个字符;2)至少1个数字;3) 至少1个大写字母;4)至少1个小写字母;5)至少1个特殊字符 (~!-@#$%^&*_+?)") : new Error('Passwords must have: 1) 8 - 32 characters; 2) At least 1 number; 3) At least 1 uppercase letter; 4) At least 1 lowercase letter; 5) At least 1 special character (~!-@#$%^&*_+?) '))
callback(lang==='zh' ? new Error("密码必须包含:1)8 – 32 个字符;2)至少1个数字;3) 至少1个大写字母;4)至少1个小写字母;5)至少1个特殊字符 (~!-@#$%^&*_+?)") : new Error('Passwords must have: 1) 8 - 32 characters; 2) At least 1 number; 3) At least 1 uppercase letter; 4) At least 1 lowercase letter; 5) At least 1 special character (~!-@#$%^&*_+?) '))
} else {
callback();
}
@@ -165,18 +158,12 @@ Vue.prototype.fileToBlob = (file) => {
}
var _vm
async function VueInit() {
async function VueInit () {
var params
var res
if (~window.location.href.indexOf('/readingDicoms') || ~window.location.href.indexOf('/noneDicomReading') || ~window.location.href.indexOf('/criterionquestions') || ~window.location.href.indexOf('/petct')) {
params = $q('TrialReadingCriterionId')
res = await getBasicDataAllSelect(params)
} else if (~window.location.href.indexOf('/ecrfPreview')) {
params = $q('SystemReadingCriterionId')
res = await getBasicDataAllSelect(params, true)
} else {
res = await getBasicDataAllSelect(params)
}
var res = await getBasicDataAllSelect(params)
var Internationalization = await getFrontInternationalizationList()
Vue.prototype.$tl = Internationalization.Result
let zhMessages = {}, enMessages = {}
@@ -186,24 +173,6 @@ async function VueInit() {
zhMessages[v.Code] = v.ValueCN
enMessages[v.Code] = v.Value
})
// 获取检查部位
Vue.prototype.$getBodyPart = (id) => {
return new Promise(async (resolve, reject) => {
try {
let params = {
TrialId: id
}
let BodyPart = await getTrialBodyPartList(params)
if (BodyPart.IsSuccess) {
resolve(BodyPart.Result);
} else {
reject(BodyPart);
}
} catch (err) {
reject(err)
}
})
}
i18n.mergeLocaleMessage('zh', zhMessages)
i18n.mergeLocaleMessage('en', enMessages)
Vue.use(ElementUI, {
@@ -212,14 +181,14 @@ async function VueInit() {
})
let d = function (code) {
var dictInfo = res.Result
var lang = zzSessionStorage.getItem('lang') ? zzSessionStorage.getItem('lang') : 'zh'
var lang = zzSessionStorage.getItem('lang')?zzSessionStorage.getItem('lang'):'zh'
try {
for (var code in dictInfo) {
var dictList = (dictInfo[code] && dictInfo[code].length > 0) ? dictInfo[code].map(dict => {
var dictList = (dictInfo[code] && dictInfo[code].length > 0) ? dictInfo[code].map(dict => {
return {
id: dict.Id,
label: lang === 'zh' ? dict.ValueCN : dict.Value,
value: dict.DataTypeEnum === 3 ? eval(dict.Code) : dict.IsEnumInt ? parseInt(dict.Code) : dict.Code,
label: lang==='zh' ? dict.ValueCN : dict.Value,
value: dict.DataTypeEnum === 3 ? eval(dict.Code) : dict.IsEnumInt ? parseInt(dict.Code): dict.Code,
raw: Object.assign({}, dict),
IsBaseLineUse: false,
IsFollowVisitUse: false
@@ -227,36 +196,35 @@ async function VueInit() {
}) : []
dictInfo[code] = dictList
}
} catch (e) {
} catch (e){
console.error(e)
}
return dictInfo
}()
Vue.prototype.$d = d
Vue.prototype.$fd = function (code, v, type, arr, key = 'label') {
Vue.prototype.$fd = function (code, v, type) {
try {
let data = arr || d;
type = type || 'value';
// code === 'YesOrNo' ? console.log(d) : ''
return data[code].find(i => {
type = type || 'value'
return d[code].find(i => {
return i[type] === v
}) ? data[code].find(i => {
}) ? d[code].find(i => {
return i[type] === v
})[key] : ''
}).label : ''
} catch (e) {
}
}
Vue.prototype.$updateDictionary = function () {
Vue.prototype.$updateDictionary = function() {
Vue.prototype.$d = function (code) {
var dictInfo = res.Result
var lang = zzSessionStorage.getItem('lang') ? zzSessionStorage.getItem('lang') : 'zh'
var lang = zzSessionStorage.getItem('lang')?zzSessionStorage.getItem('lang'):'zh'
try {
for (var code in dictInfo) {
var dictList = (dictInfo[code] && dictInfo[code].length > 0) ? dictInfo[code].map(dict => {
var dictList = (dictInfo[code] && dictInfo[code].length > 0) ? dictInfo[code].map(dict => {
return {
id: dict.raw.Id,
label: lang === 'zh' ? dict.raw.ValueCN : dict.raw.Value,
value: dict.raw.DataTypeEnum === 3 ? eval(dict.raw.Code) : dict.raw.IsEnumInt ? parseInt(dict.raw.Code) : dict.raw.Code,
label: lang==='zh' ? dict.raw.ValueCN : dict.raw.Value,
value: dict.raw.DataTypeEnum === 3 ? eval(dict.raw.Code) : dict.raw.IsEnumInt ? parseInt(dict.raw.Code): dict.raw.Code,
raw: Object.assign({}, dict.raw),
IsBaseLineUse: false,
IsFollowVisitUse: false
@@ -264,7 +232,7 @@ async function VueInit() {
}) : []
_vm.$set(dictInfo, code, dictList)
}
} catch (e) {
} catch (e){
console.error(e)
}
return dictInfo
@@ -300,14 +268,14 @@ async function VueInit() {
let count = 0;
if (eval(process.env.VUE_APP_LOGIN_FOR_PERMISSION)) {
setInterval(() => {
var lang = zzSessionStorage.getItem('lang') ? zzSessionStorage.getItem('lang') : 'zh'
if (_vm.$route.path === '/ReviewersResearchForm' || _vm.$route.path === '/ReviewersResearch' || _vm.$route.path === '/login' || _vm.$route.path === '/researchForm' || _vm.$route.path === '/researchLogin' || _vm.$route.path === '/email-recompose' || _vm.$route.path === '/recompose' || _vm.$route.path === '/resetpassword' || _vm.$route.path === '/error') {
var lang = zzSessionStorage.getItem('lang')?zzSessionStorage.getItem('lang'):'zh'
if ( _vm.$route.path === '/ReviewersResearchForm' || _vm.$route.path === '/ReviewersResearch' || _vm.$route.path === '/login' || _vm.$route.path === '/researchForm' || _vm.$route.path === '/researchLogin' || _vm.$route.path === '/email-recompose' || _vm.$route.path === '/recompose' || _vm.$route.path === '/resetpassword' || _vm.$route.path === '/error') {
return
}
if (_vm.$store.state.user.userId !== zzSessionStorage.getItem('userId')) {
window.location.href = `/login`
zzSessionStorage.removeItem('lastWorkbench')
_vm.$alert(lang === 'en' ? 'The same browser only allows one user account to be logged in at a time.' : '同一浏览器只允许同时登陆一个账户', {
_vm.$alert(lang === 'en'? 'The same browser only allows one user account to be logged in at a time.' : '同一浏览器只允许同时登陆一个账户', {
type: 'warning',
})
}
@@ -321,10 +289,10 @@ async function VueInit() {
function countTime() {
count++
localStorage.setItem('count', count)
if (count == parseInt(second2) || isLock === 'true') {
if (count == parseInt(second2) || isLock === 'true') {
callback2();
}
if (count >= second) {
if (count >= second) {
callback();
count = 0;
localStorage.removeItem('count')
@@ -358,27 +326,24 @@ async function VueInit() {
}
const h = _vm.$createElement
/* eslint-disable */
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.$route.path === '/ReviewersResearchForm' || _vm.$route.path === '/ReviewersResearch' || _vm.$route.path === '/login' || _vm.$route.path === '/researchForm' || _vm.$route.path === '/researchLogin' || _vm.$route.path === '/email-recompose' || _vm.$route.path === '/recompose' || _vm.$route.path === '/resetpassword' || _vm.$route.path === '/error') {
count = 0;
localStorage.setItem('count', '0')
return
}
_vm.$store.dispatch('user/logout').then(res => {
// window.location.href = `/login`
router.push("/login")
}).then(() => {
_vm.$alert(lang === 'zh' ? '由于您长时间未操作,为保护您的数据安全已强制将您下线,如果需要继续操作请重新登陆!' : 'No operation for a long time non-operation, you have been forced logout to protect data security. If continue to operate, please login again!', {
var lang = zzSessionStorage.getItem('lang')?zzSessionStorage.getItem('lang'):'zh'
if ( _vm.$route.path === '/ReviewersResearchForm' || _vm.$route.path === '/ReviewersResearch' || _vm.$route.path === '/login' || _vm.$route.path === '/researchForm' || _vm.$route.path === '/researchLogin' || _vm.$route.path === '/email-recompose' || _vm.$route.path === '/recompose' || _vm.$route.path === '/resetpassword' || _vm.$route.path === '/error') {
count = 0;
localStorage.setItem('count', '0')
return
}
_vm.$store.dispatch('user/logout').then(res => {
window.location.href = `/login`
})
_vm.$alert(lang === 'zh' ? '由于您长时间未操作,为保护您的数据安全已强制将您下线,如果需要继续操作请重新登陆!' : 'No operation for a long time non-operation, you have been forced logout to protect data security. If continue to operate, please login again!', {
type: 'warning',
})
})
} : () => { }, process.env.VUE_APP_LOGOUT_FOR_TIME,
} : () => {}, process.env.VUE_APP_LOGOUT_FOR_TIME,
eval(process.env.VUE_APP_LOCK_FOR_PERMISSION) ? () => {
var lang = zzSessionStorage.getItem('lang') ? zzSessionStorage.getItem('lang') : 'zh'
if (_vm.$route.path === '/ReviewersResearchForm' || _vm.$route.path === '/ReviewersResearch' || _vm.$route.path === '/login' || _vm.$route.path === '/researchForm' || _vm.$route.path === '/researchLogin' || _vm.$route.path === '/email-recompose' || _vm.$route.path === '/recompose' || _vm.$route.path === '/resetpassword' || _vm.$route.path === '/error') {
var lang = zzSessionStorage.getItem('lang')?zzSessionStorage.getItem('lang'):'zh'
if ( _vm.$route.path === '/ReviewersResearchForm' || _vm.$route.path === '/ReviewersResearch' || _vm.$route.path === '/login' || _vm.$route.path === '/researchForm' || _vm.$route.path === '/researchLogin' || _vm.$route.path === '/email-recompose' || _vm.$route.path === '/recompose' || _vm.$route.path === '/resetpassword' || _vm.$route.path === '/error') {
count = 0;
localStorage.setItem('count', '0')
if (_vm.$route.path === '/login') {
@@ -409,59 +374,38 @@ async function VueInit() {
}
var my_username = zzSessionStorage.getItem('my_username')
var my_password = zzSessionStorage.getItem('my_password')
let my_userid = zzSessionStorage.getItem('userId')
let my_EMail = zzSessionStorage.getItem('my_EMail')
if (md5(_vm.unlock.my_password) === my_password && my_username === _vm.unlock.my_username) {
resetReadingRestTime().then(() => {
})
const closeLock = (_vm) => {
_vm.$message.success(lang === 'zh' ? '解锁成功,请继续操作' : 'Unlocked successfully. Please continue operation.')
_vm.unlock = {
my_username: null,
my_password: null
}
isOpen = false
count = 0;
isLock = null
zzSessionStorage.removeItem('isLock')
localStorage.setItem('count', '0')
document.querySelector('#my_username').value = null
document.querySelector('#my_password').value = null
setTimeout(() => {
done()
}, 500)
_vm.$message.success(lang === 'zh' ? '解锁成功,请继续操作' : 'Unlocked successfully. Please continue operation.')
_vm.unlock = {
my_username: null,
my_password: null
}
if (eval(process.env.VUE_APP_LOCK_FOR_PERMISSION_MFA)) {
sendMFAEmail({ UserId: my_userid, MfaType: 1 }).then((res) => {
done();
Vue.prototype.$MFA({
status: "lock",
UserId: my_userid,
EMail: my_EMail,
username: my_username,
callBack: () => {
closeLock(_vm)
},
})
})
} else {
closeLock(_vm)
}
isOpen = false
count = 0;
isLock = null
zzSessionStorage.removeItem('isLock')
localStorage.setItem('count', '0')
document.querySelector('#my_username').value = null
document.querySelector('#my_password').value = null
setTimeout(() => {
done()
}, 500)
} else {
// console.log(111)
_vm.$message.error(lang === 'zh' ? '请输入正确用户名密码' : 'Please enter the correct password.')
}
}
},
message: h('div', {}, [
message: h('div', {} , [
h('el-form', {
props: { labelWidth: "80px" }
}, [
h('el-form-item', {
props: { label: lang === 'zh' ? '用户名' : 'Username' },
props: {label: lang === 'zh' ? '用户名' : 'Username'},
}, [
h('input', {
h('input',{
props: {
value: _vm.unlock.my_username
},
@@ -481,7 +425,7 @@ async function VueInit() {
})
]),
h('el-form-item', {
props: { label: lang === 'zh' ? '密码' : 'Password' },
props: {label: lang === 'zh' ? '密码' : 'Password'},
}, [
h('input', {
props: {
@@ -506,7 +450,7 @@ async function VueInit() {
])
])
})
} : () => { }, process.env.VUE_APP_LOCK_FOR_TIME)
} : () => {}, process.env.VUE_APP_LOCK_FOR_TIME)
}
VueInit()
+1 -4
View File
@@ -34,7 +34,7 @@ router.beforeEach(async(to, from, next) => {
NProgress.done()
} else {
OSSclient()
const hasGetUserInfo = store.getters.userId
const hasGetUserInfo = store.getters.name
if (hasGetUserInfo) {
next()
} else {
@@ -56,9 +56,6 @@ router.beforeEach(async(to, from, next) => {
/* has no token*/
if (whiteList.indexOf(to.path) !== -1) {
// 在免登录whiteList中,直接进入
if (to.path === '/readingDicoms' || to.path === '/noneDicomReading'){
OSSclient()
}
next()
} else {
if (to.path === '/researchForm') {
+5 -12
View File
@@ -139,13 +139,6 @@ export const constantRoutes = [
hidden: true,
component: () => import('@/views/trials/trials-panel/reading/dicoms/components/Fusion/PetCt')
},
{
path: '/historyScreenshot',
name: 'historyScreenshot',
hidden: true,
component: () => import('@/views/trials/trials-panel/reading/dicoms/components/Fusion/HistoryScreenshot')
},
{
path: '/visitDicomReview',
name: 'visitDicomReview',
@@ -249,11 +242,6 @@ export const constantRoutes = [
component: () => import('@/views/404'),
hidden: true
},
{
path: '/ecrfPreview',
component: () => import('@/views/dictionary/template/components/ECRF'),
hidden: true
},
{
path: '/editUser',
component: Layout,
@@ -263,6 +251,11 @@ export const constantRoutes = [
path: 'baiscInfo',
name: 'BaiscInfo',
component: () => import('@/views/user/editInfo')
},
{
path: 'account',
name: 'Account',
component: () => import('@/views/user/account')
}
]
}
-1
View File
@@ -40,7 +40,6 @@ const getters = {
activeSeries: state => state.reading.activeSeries,
lastCanvasTaskId: state => state.reading.lastCanvasTaskId,
imageQuality: state => state.reading.imageQuality,
imageQualityIssues: state => state.reading.imageQualityIssues,
language: state => state.lang.language,
TotalNeedSignSystemDocCount: state => state.user.TotalNeedSignSystemDocCount,
TotalNeedSignTrialDocCount: state => state.user.TotalNeedSignTrialDocCount,
+51 -91
View File
@@ -20,8 +20,8 @@ const hangingAgreement = [
]
const getDefaultState = () => {
return {
visitTaskList: [],
// visitTaskList: sessionStorage.getItem('visitTaskList') ? JSON.parse(sessionStorage.getItem('visitTaskList')) : [],
// visitTaskList: [],
visitTaskList: sessionStorage.getItem('visitTaskList') ? JSON.parse(sessionStorage.getItem('visitTaskList')) : [],
organList: [],
seriesStack: [],
activeHangingAgreement: hangingAgreement[0],
@@ -29,8 +29,7 @@ const getDefaultState = () => {
currentReadingTaskState: 2,
activeSeries: {},
lastCanvasTaskId: '',
imageQuality: null,
imageQualityIssues: null
imageQuality: null
}
}
function getQuestions(questions) {
@@ -166,7 +165,7 @@ const actions = {
item.IsInit = false
})
state.visitTaskList = res.Result
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
const currentTaskIdx = res.Result.findIndex(item => item.IsCurrentTask)
if (currentTaskIdx > -1) {
state.currentTaskId = res.Result[currentTaskIdx].VisitTaskId
@@ -178,19 +177,17 @@ const actions = {
},
resetVisitTasks({ state }) {
return new Promise(resolve => {
// sessionStorage.setItem('visitTaskList', '')
sessionStorage.setItem('visitTaskList', '')
state.visitTaskList = []
state.currentTaskId = ''
state.activeSeries = {}
state.lastCanvasTaskId = ''
state.imageQuality = null
state.imageQualityIssues = null
resolve()
})
},
getMasterSeries({ state }, obj) {
return new Promise(resolve => {
console.log('getMasterSeries')
var seriesInfo = {}
var i = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
getReadingVisitStudyList(obj.trialId, obj.visitId, obj.visitTaskId).then(res => {
@@ -210,28 +207,14 @@ const actions = {
var seriesList = []
study.SeriesList.forEach((series, index) => {
const imageIds = []
const instanceList = []
// series.InstancePathList.forEach((path) => {
// imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${path}`)
// })
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=0|0`
imageIds.push(imageId)
}
} else {
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=0|0`
imageIds.push(imageId)
}
instance.ImageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=0|0`
instanceList.push(instance.Id)
series.InstancePathList.forEach((path) => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${path}`)
})
seriesList.push({
isDicom: study.IsDicom,
imageIds: imageIds,
instanceInfoList: series.InstanceInfoList,
instanceList: instanceList,
instanceList: series.InstanceList,
seriesId: series.Id,
imageIdIndex: 0,
seriesUid: series.SeriesInstanceUid,
@@ -302,7 +285,7 @@ const actions = {
}
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}).catch(() => { resolve() })
})
@@ -318,7 +301,7 @@ const actions = {
})
})
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
},
@@ -337,7 +320,7 @@ const actions = {
state.visitTaskList[index].Questions = res.Result
state.visitTaskList[index].questionsInit = true
state.visitTaskList[index].QuestionMarkInfoList = res.OtherInfo.QuestionMarkInfoList
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}).catch(() => { resolve() })
}
@@ -355,7 +338,7 @@ const actions = {
state.visitTaskList[index].Questions = res.Result
state.visitTaskList[index].questionsInit = true
state.visitTaskList[index].QuestionMarkInfoList = res.OtherInfo.QuestionMarkInfoList
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}).catch(() => { resolve() })
})
@@ -374,7 +357,7 @@ const actions = {
var list = getQuestions(res.Result.SinglePage)
state.visitTaskList[index].ReadingQuestions = list
state.visitTaskList[index].readingQuestionsInit = true
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}).catch(() => { resolve() })
}
@@ -391,7 +374,7 @@ const actions = {
var list = getQuestions(res.Result.SinglePage)
state.visitTaskList[index].ReadingQuestions = list
state.visitTaskList[index].readingQuestionsInit = true
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}).catch(() => { resolve() })
})
@@ -402,7 +385,7 @@ const actions = {
if (index > -1) {
state.visitTaskList[index].ReadingQuestions = obj.questions
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
},
@@ -414,7 +397,7 @@ const actions = {
questions = findQuestionAndAddLesion(questions, obj)
state.visitTaskList[index].ReadingQuestions = questions
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
},
@@ -426,7 +409,7 @@ const actions = {
questions = findQuestionAndUpdateLesion(questions, obj)
state.visitTaskList[index].ReadingQuestions = questions
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
},
@@ -438,7 +421,7 @@ const actions = {
questions = findQuestionAndRemoveLesion(questions, obj)
state.visitTaskList[index].ReadingQuestions = questions
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
},
@@ -459,7 +442,7 @@ const actions = {
})
state.visitTaskList[index].MeasureData = arr
state.visitTaskList[index].measureDataInit = true
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}).catch(() => { resolve() })
}
@@ -486,7 +469,7 @@ const actions = {
})
state.visitTaskList[index].MeasureData = arr
state.visitTaskList[index].measureDataInit = true
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}).catch(() => { resolve() })
}
@@ -526,7 +509,7 @@ const actions = {
await deleteCustomTag(obj.questionInfo.Id)
state.visitTaskList[index].MeasureData = measureData
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
},
@@ -544,7 +527,7 @@ const actions = {
})
state.visitTaskList[index].MeasureData = arr
state.visitTaskList[index].measureDataInit = true
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}).catch(() => { resolve() })
})
@@ -563,7 +546,7 @@ const actions = {
})
state.visitTaskList[index].MeasureData = arr
state.visitTaskList[index].measureDataInit = true
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}).catch(() => { resolve() })
})
@@ -595,7 +578,7 @@ const actions = {
state.visitTaskList[index].MeasureData.push(obj.data)
console.log('新增标记成功')
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
console.log(state.visitTaskList)
resolve()
})
@@ -617,7 +600,7 @@ const actions = {
state.visitTaskList[index].MeasureData.push(obj.data)
console.log('新增标记成功')
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
},
@@ -637,7 +620,7 @@ const actions = {
}
state.visitTaskList[index].MeasureData = measureData
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
},
@@ -656,7 +639,7 @@ const actions = {
Id: obj.Id
})
console.log('新增标记成功')
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}
var idx = measureData.findIndex(item => item.Id === obj.questionInfo.Id)
@@ -672,7 +655,7 @@ const actions = {
state.visitTaskList[index].MeasureData.push(obj.MeasureData.data)
console.log('新增标记成功')
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
},
@@ -717,7 +700,7 @@ const actions = {
// state.visitTaskList[index].MeasureData = measureData
// }
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
},
@@ -730,18 +713,19 @@ const actions = {
measureData[idx].MeasureData.data.status = obj.status
state.visitTaskList[index].MeasureData = measureData
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
},
getStudyInfo({ state }, obj) {
console.log('getStudyInfo')
return new Promise(resolve => {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
if (state.visitTaskList[index].studyListInit) {
resolve()
} else {
var studyList = []
// getVisitStudyList
// getReadingVisitStudyList
getReadingVisitStudyList(obj.trialId, obj.subjectVisitId, obj.visitTaskId).then(res => {
res.Result.forEach((study, studyIndex) => {
const data = {}
@@ -757,34 +741,19 @@ const actions = {
var seriesList = []
study.SeriesList.forEach((series, seriesIndex) => {
const imageIds = []
const instanceList = []
// try {
// series.InstancePathList.forEach((path) => {
// imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${path}`)
// })
// } catch (e) {
// console.log(e)
// }
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}`
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}`
} else {
const imageId = `wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&visitTaskId=${obj.visitTaskId}&idx=${studyIndex}|${seriesIndex}`
imageIds.push(imageId)
instance.ImageId = imageId
}
instanceList.push(instance.Id)
})
try {
// if (~window.location.href.indexOf('3c210000-3e2c-0016-4247-08dabf28e96b')) {
series.InstancePathList.forEach((path) => {
// var path = id.split('/')[id.split('/').length - 1]
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? Vue.prototype.OSSclientConfig.basePath : Vue.prototype.OSSclientConfig.basePath}${path}`)
})
} catch (e) {
console.log(e)
}
seriesList.push({
isDicom: study.IsDicom,
imageIds: imageIds,
instanceInfoList: series.InstanceInfoList,
instanceList: instanceList,
instanceList: series.InstanceList,
seriesId: series.Id,
imageIdIndex: 0,
seriesUid: series.SeriesInstanceUid,
@@ -811,8 +780,7 @@ const actions = {
isLoading: false,
isBeMark: series.IsBeMark,
ww: series.WindowWidth,
wc: series.WindowCenter,
isExistMutiFrames: series.IsExistMutiFrames
wc: series.WindowCenter
})
})
data.SeriesList = seriesList
@@ -820,7 +788,7 @@ const actions = {
})
state.visitTaskList[index].StudyList = studyList
state.visitTaskList[index].studyListInit = true
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
}).catch(() => { resolve() })
}
@@ -853,7 +821,7 @@ const actions = {
}
}
state.visitTaskList[index].StudyList = studyList
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
} else {
// console.log(obj)
}
@@ -873,7 +841,7 @@ const actions = {
studyList[obj.studyIndex].SeriesList[obj.seriesIndex].loadStatus = true
}
state.visitTaskList[obj.visitTaskindex].StudyList = studyList
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
}
resolve()
})
@@ -881,7 +849,7 @@ const actions = {
setStatus({ state }, obj) {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
state.visitTaskList[index].IsInit = true
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
},
setActiveSeries({ state }, series) {
return new Promise(resolve => {
@@ -891,12 +859,7 @@ const actions = {
},
setLastCanvasTaskId({ state }, taskId) {
return new Promise(resolve => {
var isReadingTaskViewInOrder = localStorage.getItem('isReadingTaskViewInOrder')
if (parseInt(isReadingTaskViewInOrder) === 2) {
if (!state.lastCanvasTaskId) state.lastCanvasTaskId = taskId
} else {
state.lastCanvasTaskId = taskId
}
state.lastCanvasTaskId = taskId
resolve()
})
},
@@ -912,9 +875,6 @@ const actions = {
setImageQuality({ state }, imageQuality) {
state.imageQuality = isNaN(parseInt(imageQuality)) ? null : parseInt(imageQuality)
},
setImageQualityIssues({ state }, imageQualityIssues) {
state.imageQualityIssues = isNaN(parseInt(imageQualityIssues)) ? null : parseInt(imageQualityIssues)
},
addQuestionMeasuredData({ state }, obj) {
return new Promise(resolve => {
var index = state.visitTaskList.findIndex(i => i.VisitTaskId === obj.visitTaskId)
@@ -931,7 +891,7 @@ const actions = {
state.visitTaskList[index].QuestionMarkInfoList.push(obj.data)
console.log('新增标记成功')
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
},
@@ -947,7 +907,7 @@ const actions = {
}
state.visitTaskList[index].QuestionMarkInfoList = measureData
}
// sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
sessionStorage.setItem('visitTaskList', state.visitTaskList.length > 0 ? JSON.stringify(state.visitTaskList) : '')
resolve()
})
}
+14 -32
View File
@@ -1,5 +1,5 @@
import { getToken, setToken, removeToken, setName, removeName } from '@/utils/auth'
import { login, loginOut, getUserMenuTree, getUserPermissions } from '@/api/user'
import { login, getUserMenuTree, getUserPermissions } from '@/api/user'
import { resetRouter } from '@/router'
import md5 from 'js-md5'
@@ -78,32 +78,22 @@ const mutations = {
}
const actions = {
changeUserName({ commit }, userName) {
commit('SET_USERNAME', userName)
},
// user login
login({ commit }, userInfo) {
const { username, password, UserId } = userInfo
const { username, password } = userInfo
return new Promise((resolve, reject) => {
let data = {
UserName: username.trim(), Password: md5(password)
}
if (UserId) {
data.UserId = UserId;
}
login(data).then(async response => {
login({ UserName: username.trim(), Password: md5(password) }).then(async response => {
if (response.IsSuccess) {
zzSessionStorage.removeItem('lastWorkbench')
zzSessionStorage.setItem('my_username', username.trim())
zzSessionStorage.setItem('my_password', md5(password))
zzSessionStorage.setItem('my_EMail', response.Result.BasicInfo.EMail)
const data = response.Result
if (data.BasicInfo.IsFirstAdd || data.BasicInfo.LoginState === 1) {
if (data.BasicInfo.IsFirstAdd) {
try {
zzSessionStorage.setItem('userId', data.BasicInfo.Id)
commit('SET_TOKEN', data.JWTStr)
setToken(data.JWTStr)
resolve(response.Result)
resolve(false)
} catch (e) {
console.log(e)
}
@@ -114,7 +104,6 @@ const actions = {
zzSessionStorage.setItem('userName', data.BasicInfo.UserName)
commit('SET_TOKEN', data.JWTStr)
commit('SET_NAME', data.BasicInfo.RealName)
zzSessionStorage.setItem('realName', data.BasicInfo.RealName)
zzSessionStorage.setItem('isTestUser', data.BasicInfo.IsTestUser)
commit('SET_ISTESTUSER', data.BasicInfo.IsTestUser)
commit('SET_USERNAME', data.BasicInfo.UserName)
@@ -169,13 +158,13 @@ const actions = {
commit('SET_PERMISSIONS', JSON.parse(zzSessionStorage.getItem('permissions')))
commit('SET_ISTESTUSER', zzSessionStorage.getItem('isTestUser'))
const user = JSON.parse(userString)
commit('SET_NAME', zzSessionStorage.getItem('realName'))
commit('SET_NAME', user.realName)
commit('SET_USERID', user.id)
commit('SET_USERNAME', zzSessionStorage.getItem('userName'))
commit('SET_NEED_SIGN_SYSTEM_DOC_COUNT', parseInt(zzSessionStorage.getItem('TotalNeedSignSystemDocCount')))
commit('SET_NEED_SIGN_TRIALS_DOC_COUNT', parseInt(zzSessionStorage.getItem('TotalNeedSignTrialDocCount')))
console.log(zzSessionStorage.getItem('TotalNeedSignSystemDocCount'))
console.log(zzSessionStorage.getItem('TotalNeedSignTrialDocCount'))
console.log( zzSessionStorage.getItem('TotalNeedSignSystemDocCount'))
console.log( zzSessionStorage.getItem('TotalNeedSignTrialDocCount'))
zzSessionStorage.setItem('userName', user.name)
zzSessionStorage.setItem('userId', user.id)
zzSessionStorage.setItem('userTypeShortName', user.userTypeShortName)
@@ -186,19 +175,12 @@ const actions = {
commit('SET_NAME', zzSessionStorage.getItem('realName'))
},
// user logout
async logout({ commit, state }) {
try {
removeToken() // must remove token first
await loginOut({
Userd: zzSessionStorage.getItem('userId')
})
resetRouter()
removeName()
zzSessionStorage.clear()
commit('RESET_STATE')
} catch (e) {
console.log(e)
}
logout({ commit, state }) {
removeToken() // must remove token first
resetRouter()
removeName()
zzSessionStorage.clear()
commit('RESET_STATE')
},
setToken({ commit }, token) {
commit('SET_TOKEN', token)
+7 -12
View File
@@ -1,6 +1,6 @@
import dicomParser from "dicom-parser";
import dcmjs from './dcmjs'
import { encoder } from "./encoder";
import {encoder} from "./encoder";
export const anonymization = function (file, config) {
return new Promise(async (resolve, reject) => {
@@ -32,7 +32,7 @@ export const anonymization = function (file, config) {
if (AnonymizeNotFixed.Group + AnonymizeNotFixed.Element === '00100020') {
console.log(`${DicomStoreInfo.TrialCode}_${DicomStoreInfo.SubjectCode}`)
if (dataset.dict[AnonymizeNotFixed.Group + AnonymizeNotFixed.Element]) {
dataset.dict[AnonymizeNotFixed.Group + AnonymizeNotFixed.Element].Value[0] = `${DicomStoreInfo.TrialCode}-${DicomStoreInfo.SubjectCode}`
dataset.dict[AnonymizeNotFixed.Group + AnonymizeNotFixed.Element].Value[0] = `${DicomStoreInfo.TrialCode}-${DicomStoreInfo.SubjectCode}`
} else {
dataset.dict[AnonymizeNotFixed.Group + AnonymizeNotFixed.Element] = {
vr: AnonymizeNotFixed.ValueRepresentation,
@@ -54,16 +54,11 @@ export const anonymization = function (file, config) {
}
}
}
// console.log(dataset)
try {
let newDicomFile = dataset.write()
const bufferArray = new Uint8Array(newDicomFile)
const blob = new Blob([bufferArray], { type: 'application/octet-stream' })
resolve({ blob, pixelDataElement })
} catch (err) {
console.log(err)
resolve(false);
}
console.log(dataset)
let newDicomFile = dataset.write()
const bufferArray = new Uint8Array(newDicomFile)
const blob = new Blob([bufferArray], { type: 'application/octet-stream' })
resolve({blob, pixelDataElement})
};
reader.readAsArrayBuffer(file);
} catch (e) {
+5 -6
View File
@@ -1,13 +1,12 @@
import Vue from 'vue'
import { encoder } from './encoder'
import { anonymization } from './anonymization'
export const dcmUpload = async function (name, file, config) {
export const dcmUpload = async function(name, file, config){
return new Promise(async resolve => {
try {
// let blob = await encoder(file, config)
let blob = await fileToBlob(file)
if (config) {
blob = await anonymization(file, config)
}
// let blob = await fileToBlob(file)
let blob = await anonymization(file, config)
let res = await Vue.prototype.OSSclient.put(name, blob.blob)
resolve({
...res,
@@ -36,7 +35,7 @@ function fileToBlob(file) {
} else {
blob = e.target.result
}
resolve({ blob })
resolve(blob)
})
// FileReader 以 ArrayBuffer 格式 读取 File 对象中数据
reader.readAsArrayBuffer(file)
-1
View File
@@ -8359,7 +8359,6 @@
allowInvalidVRLength: false
};
var allowInvalidVRLength = writeOptions.allowInvalidVRLength;
allowInvalidVRLength = true
var valid = true,
valarr = Array.isArray(value) ? value : [value],
total = 0;
+6 -16
View File
@@ -20,7 +20,6 @@ function blobToBuffer(blob, fileName) {
async function ossGenerateSTS() {
let res = await GetObjectStoreToken()
Vue.prototype.OSSclientConfig = { ...res.Result[res.Result.ObjectStoreUse] }
Vue.prototype.OSSclientConfig.ObjectStoreUse = res.Result.ObjectStoreUse;
Vue.prototype.OSSclientConfig.basePath = Vue.prototype.OSSclientConfig.viewEndpoint
switch (res.Result.ObjectStoreUse) {
case 'AliyunOSS':
@@ -41,7 +40,7 @@ async function ossGenerateSTS() {
if (res && res.url) {
resolve({
name: objectName,
url: res.url
url: Vue.prototype.OSSclientConfig.viewEndpoint + objectName
})
} else {
reject()
@@ -71,14 +70,14 @@ async function ossGenerateSTS() {
reader.onload = (ex) => {
const bufferStream = new stream.PassThrough()
bufferStream.end(Buffer.from(ex.target.result))
minioClient.putObject(Vue.prototype.OSSclientConfig.bucketName, objectName, bufferStream, function (err, etag) {
minioClient.putObject(Vue.prototype.OSSclientConfig.bucketName, objectName, bufferStream, function(err,etag) {
if (err) {
console.log(err)
reject()
} else {
resolve({
name: objectName,
url: Vue.prototype.OSSclientConfig.viewEndpoint + decodeUtf8(objectName)
url: 'http://www.abc.com' + objectName
})
}
})
@@ -108,15 +107,14 @@ async function ossGenerateSTS() {
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) {
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)
url: 'http://www.abc.com' + objectName
})
}
})
@@ -131,15 +129,7 @@ async function ossGenerateSTS() {
}
return
}
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 const OSSclient = ossGenerateSTS
-202
View File
@@ -1,202 +0,0 @@
import * as dicomParser from "dicom-parser";
import * as cornerstone from "cornerstone-core";
import * as cornerstoneWADOImageLoader from "cornerstone-wado-image-loader";
cornerstoneWADOImageLoader.external.dicomParser = dicomParser;
cornerstoneWADOImageLoader.external.cornerstone = cornerstone;
import { convertBytes } from "@/utils/dicom-character-set";
import Vue from 'vue';
import { dcmUpload } from "@/utils/dcmUpload/dcmUpload";
let dicom = {
PatientName: "x00100010", // 患者姓名
PatientId: "x00100020", // 患者ID
PatientBirthDate: "x00100030", // 患者出生日期
PatientBirthTime: "x00100032", // 患者出生时间
PatientSex: "x00100040", // 患者性别
PatientWeight: "x00101030", // 患者体重
PregnancyStatus: "x001021c0", // 怀孕状态
PatientAge: "x00101010", // 患者年龄(做检查时刻的患者年龄,而不是此刻患者的真实年龄)
AcquisitionTime: "x00080032",
AcquisitionNumber: "x00200012",
TriggerTime: "x00181060",
AccessionNumber: "x00080050", // 检查号
StudyId: "x00200010", // 检查ID
StudyInstanceUid: "x0020000d", // 检查实例号
StudyDate: "x00080020", // 检查日期
StudyTime: "x00080030", // 检查时间
Modalities: "x00080061", // 一个检查中含有的不同检查类型
BodyPartExamined: "x00080015", // 检查的部位
StudyDescription: "x00081030", // 检查的描述
InstitutionName: "x00080080",
SeriesNumber: "x00200011", // 序列号
SeriesInstanceUid: "x0020000e", // 序列实例号
Modality: "x00080060", // 检查模态
SeriesDescription: "x0008103e", // 检查描述和说明
SeriesDate: "x00080021", // 检查日期
SeriesTime: "x00080031", // 检查时间
SequenceName: "x00180024",
ProtocolName: "x00181030",
ImagePosition: "x00200032", // 图像位置
ImageOrientation: "x00200037", // 图像方位
ImagePixelSpacing: "x00181164",
SliceThickness: "x00180050", // 层厚
SpacingBetweenSlices: "x00180088", // 层间距
SliceLocation: "x00201041", // 相对位置
MRAcquisition: "x00180023",
seriesBodyPartExamined: "x00180015", // 身体部位
ImageType: "x00080008",
SopInstanceUid: "x00080018", // SOP实例UID
ContentDate: "x00080023", // 影像拍摄日期
ContentTime: "x00080033", // 影像拍摄时间
ImageOrInstanceNumber: "x00200013", // 图像码
SamplesPerPixel: "x00280002", // 图像采样率
PhotometricInterpretation: "x00280004", // 光度计(对于CT图像,用两个枚举值MONOCHROME1MONOCHROME2 用来判断图像是否是彩色的;MONOCHROME 1/2是灰度图,RGB则是真彩色图)
Rows: "x00280010", // 行数
Columns: "x00280011", // 列数
NumberOfFrames: "x00280008",
PixelSpacing: "x00280030", // 像素间距
BitsAllocated: "x00280100", // 分配的位数
BitsStored: "x00280101", // 存储的位数
HighBit: "x00280102", // 高位
PixelRepresentation: "x00280103", // 像素数据的表现类型(一个枚举值,分别为十六进制数0000和0001.0000H = 无符号整型,0001H = 2的补码)
WindowCenter: "x00281050", // 窗位
WindowWidth: "x002811051", // 窗宽
RescaleIntercept: "x00281052", // 截距
RescaleSlope: "x00281053", // 斜率
RescaleType: "x00281054", // 输出值的单位
ParsingFormat: "x00080005",
FrameOfReferenceUID: "x00200052",
};
// 需要设置默认值
let defaultKey = ['Rows', 'Columns', 'SliceLocation', 'NumberOfFrames'];
let uintKey = ['Rows', 'Columns'];
let intStringKey = ['SliceLocation', 'NumberOfFrames'];
// 需要格式解析
let pormatParseKey = ['PatientName', 'SeriesDescription', 'StudyDescription'];
// 解析dicom文件
export const parseDicom = (file, name = false) => {
return new Promise(function (resolve) {
let reader = new FileReader();
reader.onload = function (e) {
try {
let data = dicomParser.parseDicom(new Uint8Array(e.target.result));
let res = {};
if (name && Array.isArray(name)) {
name.forEach((item) => {
if (dicom[item]) {
res[item] = data.string(dicom[item]) || '';
}
});
} else if (name) {
if (dicom[name]) {
res[name] = data.string(dicom[name]) || '';
} else {
console.log("name is inexistence");
resolve(false)
}
} else {
Object.keys(dicom).forEach((key) => {
res[key] = data.string(dicom[key]) || '';
});
}
pormatParseKey.forEach(key => {
if (res[key]) {
const Element = data.elements[dicom[key]];
const Bytes = new Uint8Array(
data.byteArray.buffer,
Element ? Element.dataOffset : 0,
Element ? Element.length : 0
);
res[key] = convertBytes(
res.ParsingFormat,
Bytes
);
}
})
uintKey.forEach(key => {
res[key] = data.uint16(dicom[key])
})
intStringKey.forEach(key => {
res[key] = data.intString(dicom[key])
})
defaultKey.forEach(key => {
if (!res[key] && res.hasOwnProperty(key)) {
res[key] = 0;
}
})
resolve(res);
} catch (error) {
console.log(error)
resolve(false);
}
};
reader.onerror = function (e) {
console.log(e)
resolve(false);
};
reader.readAsArrayBuffer(file);
});
};
// 影像上传
// 影像上传
export const dicomToOSS = async (file, path) => {
try {
let res = await dcmUpload(path, file);
if (!res || !res.url) return false;
return Vue.prototype.$getObjectName(res.url);
} catch (err) {
console.log(err);
return false;
}
};
// 获取缩略图
export const getThumbnail = async (file, ossPath, dicomInfo) => {
try {
if (dicomInfo.modality !== "SR") {
let fileId = cornerstoneWADOImageLoader.wadouri.fileManager.add(file);
let blob = await dicomToPng(
fileId,
dicomInfo.Columns,
dicomInfo.Rows
);
if (!blob) return "";
let OSSclient = Vue.prototype.OSSclient;
let seriesRes = await OSSclient.put(ossPath, blob);
if (seriesRes && seriesRes.url) {
return Vue.prototype.$getObjectName(seriesRes.url);
} else {
return "";
}
} else {
return "";
}
} catch (err) {
console.log(err);
return "";
}
};
const canvasToBlob = (canvas) => {
return new Promise((resolve) => {
canvas.toBlob((blob) => {
resolve(blob);
});
});
};
const dicomToPng = (imageId, width, height) => {
return new Promise((resolve) => {
cornerstone.loadImage(imageId).then(async (image) => {
let canvas = document.createElement("canvas");
canvas.width = width;
canvas.height = height;
if (image) {
cornerstone.renderToCanvas(canvas, image);
// 将 Canvas 图像对象转换为 PNG 格式
let blob = await canvasToBlob(canvas);
resolve(blob);
} else {
resolve(false);
}
});
}).catch((reason) => {
reason();
});
};
+36 -61
View File
@@ -3,8 +3,6 @@ import { Message, MessageBox, Alert } from 'element-ui'
import store from '@/store'
import router from '@/router'
import Vue from 'vue'
import moment from 'moment-timezone';
console.log(moment.tz.guess())
axios.defaults.withCredentials = false
const service = axios.create({
baseURL: '/api',
@@ -20,8 +18,7 @@ service.interceptors.request.use(
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()
config.headers['Accept-Language'] = language === 'en'?'en-US,en;q=0.5':'zh-CN,zh;q=0.9'
if (store.getters.token) {
config.headers.Authorization = `Bearer ${store.getters.token}`
}
@@ -33,7 +30,7 @@ service.interceptors.request.use(
if (store.state.user.userId !== zzSessionStorage.getItem('userId')) {
window.location.href = `/login`
zzSessionStorage.removeItem('lastWorkbench')
Alert(store.state.lang.language === 'en' ? 'The same browser only allows one user account to be logged in at a time.' : '同一浏览器只允许同时登陆一个账户', {
Alert(store.state.lang.language === 'en'? 'The same browser only allows one user account to be logged in at a time.' : '同一浏览器只允许同时登陆一个账户', {
type: 'warning',
})
}
@@ -49,24 +46,20 @@ service.interceptors.request.use(
}
)
let timer = null;
let time = 1000;
var isConfirm = true
service.interceptors.response.use(
response => {
const res = response.data
if (res.IsSuccess) {
isConfirm = true
return Promise.resolve(res)
} else if (res.IsSuccess === false) {
if (res.Code !== 5) {
MessageBox.confirm(res.ErrorMessage, {
MessageBox.confirm(res.ErrorMessage, {
type: 'warning',
showCancelButton: false,
callback: action => {
if (res.Code === 6) {
window.close()
}
}
callback: action => {}
})
}
return Promise.reject(res)
@@ -78,7 +71,7 @@ service.interceptors.response.use(
var message = ''
if (error && error.response) {
const status = error.response.status
if (error.response.data && (error.response.data.Code === -1 || error.response.data.Code === -2)) {
if (error.response.data && error.response.data.Code === -1) {
store.dispatch('user/logout').then(() => {
router.push(`/login`)
this.$i18n.locale = 'zh'
@@ -87,29 +80,29 @@ service.interceptors.response.use(
})
}
switch (status) {
case 400: message = store.state.lang.language === 'en' ? 'Request error' : '请求错误'; break
case 401: message = store.state.lang.language === 'en' ? 'Not authorized or login timed out. Please log in again.' : '未授权或登陆超时,请重新登录'; break
case 400: message = store.state.lang.language === 'en'? 'Request error' : '请求错误'; break
case 401: message = store.state.lang.language === 'en'? 'Not authorized or login timed out. Please log in again.' : '未授权或登陆超时,请重新登录'; break
case 403: message = error.response.data.ErrorMessage; break
case 404: message = store.state.lang.language === 'en' ? 'Request address error' : `请求地址出错`; break
case 405: message = store.state.lang.language === 'en' ? 'Interface parameter error or request method inconsistency' : `接口参数传递错误,或者请求方法不一致`; break
case 408: message = store.state.lang.language === 'en' ? 'Request timed out' : '请求超时'; break
case 429: message = store.state.lang.language === 'en' ? 'The application service limits the traffic. Your requests are too frequent. Please try again later.' : '应用服务限流,您的请求过于频繁,请稍后再试'; break
case 500: message = store.state.lang.language === 'en' ? 'Internal server error, and unable to complete the request. Software release might be in process. Please contact the administrator.' : '服务器内部错误,无法完成请求;可能正在发布中,请联系管理员处理'; break
case 501: message = store.state.lang.language === 'en' ? 'Service has not been implemented.' : '服务未实现'; break
case 502: message = store.state.lang.language === 'en' ? 'System is being upgraded. Please wait patiently.' : '系统正在升级,请耐心等待。'; break
case 503: message = store.state.lang.language === 'en' ? 'Service is not available' : '服务不可用'; break
case 504: message = store.state.lang.language === 'en' ? 'Gateway timed out' : '网关超时'; break
case 505: message = store.state.lang.language === 'en' ? 'HTTP version is not supported' : 'HTTP版本不受支持'; break
case 404: message = store.state.lang.language === 'en'? 'Request address error' : `请求地址出错`; break
case 405: message = store.state.lang.language === 'en'? 'Interface parameter error or request method inconsistency' : `接口参数传递错误,或者请求方法不一致`; break
case 408: message = store.state.lang.language === 'en'? 'Request timed out' : '请求超时'; break
case 429: message = store.state.lang.language === 'en'? 'The application service limits the traffic. Your requests are too frequent. Please try again later.' : '应用服务限流,您的请求过于频繁,请稍后再试'; break
case 500: message = store.state.lang.language === 'en'? 'Internal server error, and unable to complete the request. Software release might be in process. Please contact the administrator.' : '服务器内部错误,无法完成请求;可能正在发布中,请联系管理员处理'; break
case 501: message = store.state.lang.language === 'en'? 'Service has not been implemented.' : '服务未实现'; break
case 502: message = store.state.lang.language === 'en'? 'System is being upgraded. Please wait patiently.' : '系统正在升级,请耐心等待。'; break
case 503: message = store.state.lang.language === 'en'? 'Service is not available' : '服务不可用'; break
case 504: message = store.state.lang.language === 'en'? 'Gateway timed out' : '网关超时'; break
case 505: message = store.state.lang.language === 'en'? 'HTTP version is not supported' : 'HTTP版本不受支持'; break
default: break
}
if (error.response.status === 401) {
if (store.getters.token) {
if (message !== '') {
setTimer({
if(message !== ''){
Message({
message: message,
type: 'warning',
showClose: true
}, 'message')
})
}
store.dispatch('user/logout').then(() => {
router.push(`/login`)
@@ -118,52 +111,34 @@ service.interceptors.response.use(
this.$updateDictionary()
})
} else {
setTimer({
message: store.state.lang.language === 'en' ? 'You are not authorized to access the interface' : '您无权访问接口',
Message({
message: store.state.lang.language === 'en'? 'You are not authorized to access the interface' : '您无权访问接口',
type: 'warning',
showClose: true
}, 'message')
})
}
} else {
if (message !== '') {
setTimer([message, store.state.lang.language === 'en' ? 'Warning' : '警告', {
if(message !== '' && isConfirm){
MessageBox.confirm(message, store.state.lang.language === 'en'? 'Warning' : '警告', {
type: 'warning',
showCancelButton: false,
callback: action => { }
}], 'confirm')
callback: action => {}
})
}
}
}
if (!window.navigator.onLine) {
setTimer(
[store.state.lang.language === 'en' ? 'Please check your networkand try again later' : '请检查网络,稍后重试!', store.state.lang.language === 'en' ? 'Warning' : '警告', {
type: 'warning',
showCancelButton: false,
callback: action => { }
}], "confirm"
)
if (!window.navigator.onLine && isConfirm) {
MessageBox.confirm(store.state.lang.language === 'en'? 'Please check your networkand try again later' : '请检查网络,稍后重试!', store.state.lang.language === 'en'? 'Warning' : '警告', {
type: 'warning',
showCancelButton: false,
callback: action => {}
})
isConfirm = false
}
return Promise.reject(new Error(message || 'Error'))
}
)
const setTimer = (obj, type) => {
if (timer) {
clearTimeout(timer);
timer = null;
}
timer = setTimeout(() => {
if (type === 'message') {
Message(obj)
}
if (type === 'confirm') {
MessageBox.confirm(...obj)
}
clearTimeout(timer);
timer = null;
}, time)
}
-144
View File
@@ -1,144 +0,0 @@
import JSZip from "jszip";
import axios from "axios";
import { saveAs } from "file-saver";
import Vue from 'vue';
import {
requestPackageAndAnonymizImage,
} from "@/api/load.js";
let flag = {};
export const downloadImage = async (id, id2) => {
if (flag[id2]) return
flag[id2] = true
try {
let params = {
TrialId: id,
SubjectVisitId: id2
}
let res = await requestPackageAndAnonymizImage(params);
flag[id2] = false;
if (res.IsSuccess) {
if (!res.Result) {
Vue.prototype.$message.warning(Vue.prototype.$t("trials:upload:message:not"))
return 1;
}
let a = document.createElement("a");
let href = Vue.prototype.OSSclientConfig.basePath + res.Result;
let fileName =
res.Result.split("/")[res.Result.split("/").length - 1];
a.download = fileName;
a.href = href;
a.click();
URL.revokeObjectURL(href);
let timer = setTimeout(() => {
a = null;
href = null;
timer = null;
}, 500)
return 2;
} else {
return false;
}
} catch (err) {
flag[id2] = false;
console.log(err);
}
};
const setfolder = async (item) => {
const zip = new JSZip(); // 创建实例对象
let patientIds = item.PatientList.map(i => i.PatientIdStr);
let zipName = `${item.SubjectCode}_${patientIds.join(',')}`;
let zipObj = {};
const promises = [];
for (let visit of item.VisitList) {
if (!zipObj[`${visit.VisitName}`]) {
zipObj[`${visit.VisitName}`] = zip.folder(visit.VisitName);
}
for (let study of visit.StudyList) {
let date = study.StudyTime.split(" ")[0];
for (let series of study.SeriesList) {
if (
!zipObj[
`${visit.VisitName}${series.Modality}`
]
) {
zipObj[
`${visit.VisitName}${series.Modality}`
] = zipObj[`${visit.VisitName}`].folder(
`${date}_${series.Modality}`
);
}
for (let instance of series.InstancePathList) {
let obj = {
subjectCode: item.SubjectCode,
visitName: visit.VisitName,
date: study.StudyTime.split(" ")[0],
modality: series.Modality,
instancePath: instance.Path,
dicomName: instance.Path.split("/Dicom/")[1],
};
const promise = handleBatchDown(
obj,
zipObj[
`${visit.VisitName}${series.Modality}`
],
);
promises.push(promise);
}
}
}
}
// 生成 zip 文件
Promise.all(promises)
.then(() => {
// 生成zip 文件
zip
.generateAsync({
type: "blob",
compression: "DEFLATE", // STORE: 默认不压缩, DEFLATE:需要压缩
compressionOptions: {
level: 9, // 压缩等级 1~9 1 压缩速度最快, 9 最优压缩方式
},
})
.then((res) => {
saveAs(res, zipName + ".zip"); // 使用FileSaver.saveAs保存文件,文件名可自定义
flag[id2] = false;
zipObj = null;
});
})
.catch((reason) => { flag[id2] = false; });
};
const handleBatchDown = async (item, zip) => {
return new Promise((resolve) => {
getFileData(
Vue.prototype.OSSclientConfig.basePath + item.instancePath
).then((res) => {
const fileName = item.dicomName + ".dcm";
zip.file(fileName, res.data, { binary: true });
resolve();
});
});
};
const getFileData = (fileUrl) => {
return new Promise((resolve, reject) => {
axios(fileUrl, {
method: "GET",
responseType: "blob", // 返回的数据会被强制转为blob类型 ,转换成arraybuffer 也行
})
.then((res) => {
resolve(res);
})
.catch((error) => {
reject(error);
});
});
};
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);
};
+137 -135
View File
@@ -1,135 +1,137 @@
<template>
<div class="app-container menu">
<el-tree
:props="defaultProps"
:data="treeData"
node-key="Id"
:default-expand-all="true"
:expand-on-click-node="false"
style="width:80%;"
>
<span slot-scope="{ node, data }" class="custom-tree-node">
<span v-if="data.FunctionName">{{ node.label }} --------------------(Function)</span>
<span v-else>{{ node.label }}</span>
<span>
<el-button type="text" icon="el-icon-plus" size="small" @click="() => append(data)">Append</el-button>
<el-button
type="text"
icon="el-icon-edit"
size="small"
@click="() => edit(data)"
>Edit</el-button>
<el-button type="text" icon="el-icon-delete" size="small" @click="() => remove(data)">Delete</el-button>
</span>
</span>
</el-tree>
<menu-form v-if="model_cfg.visible" :form="currenNode" width="500px" @close="closeModel" />
</div>
</template>
<script>
import { getMenuFunction, deleteMenuFunction } from '@/api/admin'
import MenuForm from './components/MenuForm'
import { model_cfg } from './menu'
export default {
name: 'Menu',
components: { MenuForm },
data() {
return {
model_cfg,
treeData: [],
defaultProps: {
label: 'MenuName',
children: 'Children'
},
dialogVisible: false,
title: '',
currenNode: {},
nodeId: '',
parentId: ''
}
},
mounted() {
this.getlist()
},
methods: {
// 获取菜单数据
getlist() {
const loading = this.$loading({
target: document.querySelector('.menu'),
fullscreen: false,
lock: true,
text: 'Loading',
spinner: 'el-icon-loading'
})
getMenuFunction().then(res => {
loading.close()
this.treeData = res.Result
}).catch(() => { loading.close() })
},
// 添加菜单
append(node) {
this.currenNode = {}
this.currenNode.ParentId = node.Id
this.currenNode.Status = 1
// this.currenNode.ShowOrder = 0
this.nodeId = node.Id
this.model_cfg.title = 'Append'
this.model_cfg.visible = true
},
// 编辑菜单
edit(node) {
// eslint-disable-next-line no-unused-vars
const { Children, CreateTime, CreateUserId, UpdateTime, UpdateUserId, ...obj } = JSON.parse(JSON.stringify(node))
obj.MetaBreadcrumb = obj.MetaBreadcrumb ? 1 : 0
obj.Hidden = obj.Hidden ? 1 : 0
this.currenNode = obj
this.nodeId = node.Id
this.model_cfg.title = 'Edit'
this.model_cfg.visible = true
},
// 移除菜单
remove(node) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
type: 'warning',
distinguishCancelAndClose: true
})
.then(() => {
deleteMenuFunction(node.Id)
.then(res => {
if (res.IsSuccess) {
this.getlist()
this.$message.success(this.$t('common:message:deletedSuccessfully'))
}
})
})
},
// 关闭弹窗
closeModel() {
this.model_cfg.visible = false
this.getlist()
}
}
}
</script>
<style lang="scss">
.menu{
.el-tree {
margin-top: 20px;
}
.el-tree-node{
margin-top: 5px;
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.el-dialog__body{
padding: 10px;
}
}
</style>
<template>
<div class="app-container menu">
<el-tree
:props="defaultProps"
:data="treeData"
node-key="Id"
:default-expand-all="true"
:expand-on-click-node="false"
style="width:80%;"
>
<span slot-scope="{ node, data }" class="custom-tree-node">
<span v-if="data.FunctionName">{{ node.label }} --------------------(Function)</span>
<span v-else>{{ node.label }}</span>
<span>
<el-button type="text" icon="el-icon-plus" size="small" @click="() => append(data)">Append</el-button>
<el-button
type="text"
icon="el-icon-edit"
size="small"
@click="() => edit(data)"
>Edit</el-button>
<el-button type="text" icon="el-icon-delete" size="small" @click="() => remove(data)">Delete</el-button>
</span>
</span>
</el-tree>
<menu-form v-if="model_cfg.visible" :form="currenNode" width="500px" @close="closeModel" />
</div>
</template>
<script>
import { getMenuFunction, deleteMenuFunction } from '@/api/admin'
import MenuForm from './components/MenuForm'
import { model_cfg } from './menu'
export default {
name: 'Menu',
components: { MenuForm },
data() {
return {
model_cfg,
treeData: [],
defaultProps: {
label: 'MenuName',
children: 'Children'
},
dialogVisible: false,
title: '',
currenNode: {},
nodeId: '',
parentId: ''
}
},
mounted() {
this.getlist()
},
methods: {
// 获取菜单数据
getlist() {
const loading = this.$loading({
target: document.querySelector('.menu'),
fullscreen: false,
lock: true,
text: 'Loading',
spinner: 'el-icon-loading'
})
getMenuFunction().then(res => {
loading.close()
this.treeData = res.Result
}).catch(() => { loading.close() })
},
// 添加菜单
append(node) {
this.currenNode = {}
this.currenNode.ParentId = node.Id
this.currenNode.Status = 1
// this.currenNode.ShowOrder = 0
this.nodeId = node.Id
this.model_cfg.title = 'Append'
this.model_cfg.visible = true
},
// 编辑菜单
edit(node) {
// eslint-disable-next-line no-unused-vars
const { Children, CreateTime, CreateUserId, UpdateTime, UpdateUserId, ...obj } = JSON.parse(JSON.stringify(node))
obj.MetaBreadcrumb = obj.MetaBreadcrumb ? 1 : 0
obj.Hidden = obj.Hidden ? 1 : 0
this.currenNode = obj
this.nodeId = node.Id
this.model_cfg.title = 'Edit'
this.model_cfg.visible = true
},
// 移除菜单
remove(node) {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
deleteMenuFunction(node.Id)
.then(res => {
if (res.IsSuccess) {
this.getlist()
this.$message.success('Deleted successfully!')
}
})
})
},
// 关闭弹窗
closeModel() {
this.model_cfg.visible = false
this.getlist()
}
}
}
</script>
<style lang="scss">
.menu{
.el-tree {
margin-top: 20px;
}
.el-tree-node{
margin-top: 5px;
}
.custom-tree-node {
flex: 1;
display: flex;
align-items: center;
justify-content: space-between;
font-size: 14px;
padding-right: 8px;
}
.el-dialog__body{
padding: 10px;
}
}
</style>
+4 -3
View File
@@ -89,15 +89,16 @@ export default {
})
},
handleDeleteRole(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
}).then(() => {
deleteUserTypeRole(row.Id).then((res) => {
if (res.IsSuccess) {
this.list.splice(this.list.findIndex((item) => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
})
})
+39 -38
View File
@@ -1,38 +1,39 @@
<template>
<el-card class="box-card" style="width:800px;" size="small">
<!-- <div slot="header" class="clearfix">
<span>Security</span>
</div> -->
<div>
<el-button type="danger" @click="handleReset">Reset Password</el-button>
</div>
</el-card>
</template>
<script>
import { resetPassword } from '@/api/admin'
export default {
name: 'Account',
props: {
userId: { type: String, default: '' }
},
methods: {
handleReset() {
this.$confirm('Sure to reset password?', {
type: 'warning',
distinguishCancelAndClose: true,
})
.then(() => {
resetPassword(this.userId).then(res => {
if (res.IsSuccess) {
this.$message({
message: 'Reset password successfully',
type: 'success'
})
}
})
})
}
}
}
</script>
<template>
<el-card class="box-card" style="width:800px;" size="small">
<!-- <div slot="header" class="clearfix">
<span>Security</span>
</div> -->
<div>
<el-button type="danger" @click="handleReset">Reset Password</el-button>
</div>
</el-card>
</template>
<script>
import { resetPassword } from '@/api/admin'
export default {
name: 'Account',
props: {
userId: { type: String, default: '' }
},
methods: {
handleReset() {
this.$confirm('Sure to reset password?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
resetPassword(this.userId).then(res => {
if (res.IsSuccess) {
this.$message({
message: 'Reset password successfully',
type: 'success'
})
}
})
})
}
}
}
</script>
+4 -3
View File
@@ -113,17 +113,18 @@ export default {
},
// 删除用户
handleDeleteUser(data) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
deleteSysUser(data.Id)
.then(res => {
if (res.IsSuccess) {
this.users.splice(this.users.findIndex(item => item.Id === data.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
})
})
@@ -14,26 +14,27 @@
<span v-else>{{ employment.RankCN }}</span>
</el-form-item>
</el-col>
<!-- <el-col :span="6">-->
<!-- <el-form-item :label="$t('resumeInfo:label:Physician')">-->
<!-- <span v-if="isEnglish">{{ employment.Physician }}</span>-->
<!-- <span v-else>{{ employment.PhysicianCN }}</span>-->
<!-- </el-form-item>-->
<!-- </el-col>-->
<el-col :span="6">
<el-form-item :label="$t('resumeInfo:label:Physician')">
<span v-if="isEnglish">{{ employment.Physician }}</span>
<span v-else>{{ employment.PhysicianCN }}</span>
</el-form-item>
</el-col>
<el-col :span="6">
<el-form-item :label="$t('resumeInfo:label:Position')">
<span v-if="isEnglish">{{ employment.Position }}</span>
<span v-else>{{ employment.PositionCN }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="6">
<el-form-item :label="$t('resumeInfo:label:Hospital')">
<span v-if="isEnglish">{{ employment.HospitalName }}</span>
<span v-else>{{ employment.HospitalNameCN }}</span>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="6">
<el-form-item :label="$t('resumeInfo:label:Affiliated')">
<span v-if="isEnglish">{{ employment.UniversityAffiliated }}</span>
+2 -4
View File
@@ -90,12 +90,11 @@ export default {
this.setLanguage('zh')
this.$updateDictionary()
}
this.title = this.doctorInfo.BasicInfoView?`${this.doctorInfo.BasicInfoView.BlindName}${this.$t('resumeInfo:title:Details')}`:''
this.title = this.doctorInfo.BasicInfoView?`${this.doctorInfo.BasicInfoView.FirstName} ${this.doctorInfo.BasicInfoView.LastName}${this.$t('resumeInfo:title:Details')}`:''
}
},
mounted() {
this.isEnglish = !!((this.$route.query.isEnglish === true || this.$route.query.isEnglish === 'true'))
this.isEnglish = this.$i18n.locale === 'zh' ? false : true
this.doctorId = this.$route.query.doctorId
this.initForm()
},
@@ -136,7 +135,6 @@ export default {
} else {
this.workInfo.Position = this.workInfo.Position
this.workInfo.PositionCN = this.workInfo.PositionCN
//
}
this.workInfo.PositionOther = this.workInfo.PositionOther ? 'Other - ' + this.workInfo.PositionOther : 'Other'
}
@@ -181,7 +179,7 @@ export default {
this.holiday = res.Result.InHoliday ? 'Yes' : 'No'
this.doctorInfo = res.Result
!this.doctorInfo.ResearchPublicationView ? this.doctorInfo.ResearchPublicationView = {} : '';
this.title = this.doctorInfo.BasicInfoView?`${this.doctorInfo.BasicInfoView.BlindName}${this.$t('resumeInfo:title:Details')}`:''
this.title = `${this.doctorInfo.BasicInfoView.BlindName} 's Details`
this.htmlTitle = this.title
this.initStatus()
this.initEmploymentInfo()
+2 -1
View File
@@ -126,7 +126,8 @@ export default {
this.$confirm('Sure to sign out', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.$store.dispatch('user/logout').then(res => {
+3 -7
View File
@@ -63,7 +63,7 @@
import * as dicomParser from 'dicom-parser'
import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
import dicomStore from '@/utils/dicom-store'
import dicomStore from '@/utils/dicom-store.js'
import dicomViewer from '@/components/Dicom/DicomViewer'
import dicomPreview from '@/components/Dicom/DicomPreview'
@@ -86,10 +86,6 @@ export default {
uid: {
type: String,
default: ''
},
studyList: {
type: Array,
default: []
}
},
@@ -106,7 +102,7 @@ export default {
var totalHeight = window.innerHeight || document.body.clientHeight
var wrapper = this.$refs['preview-wrapper']
wrapper.style.height = (totalHeight - 70) + 'px'
if (!this.studyList || !this.uid) return
if (!dicomStore.studyList || !this.uid) return
this.loadStudy()
},
@@ -124,7 +120,7 @@ export default {
return newObj
},
loadStudy() {
var studyList = this.studyList
var studyList = dicomStore.studyList
var studyUid = this.uid
var studyItem = studyList.find(function(item) {
return item.dicomInfo.studyUid === studyUid
+68 -218
View File
@@ -43,83 +43,45 @@
fit="fill"
>
<div class="viewernavitextwrapper">
<div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
<div v-if="item.keySeries" style="color:red">
Key Images
</div>
<div v-else>
#{{ item.seriesNumber }}
</div>
<div v-if="item.isExistMutiFrames && item.instanceCount > 1">
<el-popover
placement="right"
trigger="hover"
popper-class="instance_frame_wrapper"
>
<div
v-for="(instance, idx) in item.instanceInfoList"
:key="instance.Id"
class="frame_content"
:style="{'margin-bottom':idx<item.instanceInfoList.length-1? '5px':'0px'}"
@click="showMultiFrames(item, index, instance)"
>
<!-- <div>
<img
class="image-preview"
:src="series.previewImageUrl"
crossorigin="anonymous"
alt=""
style="width: 40px;height:40px;"
fit="fill"
>
</div> -->
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" />
</el-popover>
</div>
<div v-if="item.keySeries" style="padding: 1px;color:red">
Key Images
</div>
<div v-else style="padding: 1px;">
#{{ item.seriesNumber }}
</div>
<div v-show="item.instanceCount" style="padding: 1px;">
{{ item.modality }}: {{ item.instanceCount }} image
</div>
<div v-show="!item.keySeries && item.sliceThickness" style="padding: 1px;">
T: {{ parseFloat(item.sliceThickness).toFixed(2) }}
T: {{ item.sliceThickness }}
</div>
<div v-show="!item.keySeries &&item.description" style="width: 120px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;padding: 1x;">
{{ item.description }}
</div>
<div v-if="!item.keySeries" style="padding: 1px;">
{{ item.imageloadedArr.length }}/{{ item.instanceCount }}
{{ item.prefetchInstanceCount }}/{{ item.instanceCount }}
</div>
</div>
</div>
<div v-if="showDelete" style="display: flex;flex-direction: row;justify-content: space-between;" @click.stop="">
<div v-if="showDelete" @click.stop="">
<div>
<span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isReading') }}</span>
<el-switch
v-model="item.isReading"
size="mini"
@change="changeReadingStatus($event, item)"
/>
</div>
<div>
<span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isDelete') }}</span>
<el-switch
v-model="item.isDeleted"
size="mini"
@change="changeDeleteStatus($event, item)"
/>
</div>
<span style="font-size: 12px;">{{ $t('trials:audit:table:isReading') }}</span>
<el-switch
v-model="item.isReading"
size="mini"
@change="changeReadingStatus($event, item)"
/>
<span style="font-size: 12px;">{{ $t('trials:audit:table:isDelete') }}</span>
<el-switch
v-model="item.isDeleted"
size="mini"
@change="changeDeleteStatus($event, item)"
/>
</div>
<div v-if="item.prefetchInstanceCount>0 && item.prefetchInstanceCount<item.instanceCount * 100">
<el-progress :percentage="parseInt((item.prefetchInstanceCount/item.instanceCount).toFixed(2))" />
<div v-if="item.prefetchInstanceCount>0 && item.prefetchInstanceCount<item.instanceCount">
<el-progress :percentage="parseInt(((item.prefetchInstanceCount/item.instanceCount)*100).toFixed(2))" />
</div>
</div>
@@ -191,12 +153,10 @@ export default {
showDelete: false,
loading: false,
imageList: [],
showSeriesList: [],
currentLoadIns: []
showSeriesList: []
}
},
created: function() {
requestPoolManager.resetRequestPool()
this.type = this.$router.currentRoute.query.type ? this.$router.currentRoute.query.type : ''
this.visitNum = this.$router.currentRoute.query.visitNum ? parseInt(this.$router.currentRoute.query.visitNum) : 0
@@ -217,18 +177,9 @@ export default {
} else if (this.type === 'Share') {
this.loadStudy()
}
cornerstone.events.addEventListener('cornerstoneimageloadprogress', this.cornerstoneimageloadprogress)
window.addEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache()
requestPoolManager.resetRequestPool()
})
},
beforeDestroy() {
requestPoolManager.stopTaskTimer()
window.removeEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache()
requestPoolManager.resetRequestPool()
})
},
methods: {
loadStudy() {
@@ -250,16 +201,16 @@ export default {
if (data.IsSuccess) {
const { Result } = data
var seriesList = []
Result.forEach((item, index) => {
Result.forEach(function(item) {
const imageIds = []
item.InstanceInfoList.forEach(i => {
if (i.NumberOfFrames && i.NumberOfFrames > 1) {
for (let j = 0; j < i.NumberOfFrames; j++) {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${i.Path}?frame=${j}&instanceId=${i.Id}&seriesIndex=${index}`)
}
} else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${i.Path}?instanceId=${i.Id}&seriesIndex=${index}`)
}
// item.InstanceList.forEach(function(id) {
// imageIds.push(`wadouri:/api/instance/content/${id}`)
// })
// item.InstanceList.forEach((id) => {
// imageIds.push(`wadouri:http://123.56.94.154:7000/instance/content/${id}`)
// })
item.InstancePathList.forEach((path) => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${path}`)
})
var subjectVisitId = scope.$router.currentRoute.query.subjectVisitId
var studyId = scope.$router.currentRoute.query.studyId
@@ -269,7 +220,6 @@ export default {
subjectVisitId,
studyId,
imageIds: imageIds,
instanceInfoList: item.InstanceInfoList,
seriesId: item.Id,
seriesUid: item.SeriesInstanceUid,
seriesNumber: item.SeriesNumber,
@@ -285,8 +235,7 @@ export default {
keySeries: item.KeySeries,
tpCode: scope.tpCode,
loadStatus: false,
imageloadedArr: [],
isExistMutiFrames: item.IsExistMutiFrames
imageloadedArr: []
})
})
scope.seriesList = seriesList
@@ -312,34 +261,29 @@ export default {
getInstanceList(seriesId).then(res => {
if (!res.Result || (res.Result && res.Result.length === 0)) return
var seriesInstanceUid = res.Result[0].SeriesInstanceUid
var sliceThickness = res.Result[0].SliceThickness
var sliceLocation = res.Result[0].SliceLocation
var isReading = res.Result[0].IsReading
var isDeleted = res.Result[0].IsDeleted
var seriesList = []
var imageIds = []
let isExistMutiFrames = false
const instanceInfoList = []
res.Result.forEach(instance => {
if (instance.NumberOfFrames > 1) {
for (let i = 0; i < instance.NumberOfFrames; i++) {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance.Path}?frame=${i}&instanceId=${instance.Id}&seriesIndex=0`)
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance.Path}?frame=${i}`)
}
isExistMutiFrames = true
} else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance.Path}?instanceId=${instance.Id}&seriesIndex=0`)
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instance.Path}`)
}
instanceInfoList.push({ Id: instance.Id, InstanceNumber: instance.InstanceNumber, NumberOfFrames: instance.NumberOfFrames, Path: instance.Path })
})
seriesList.push({
trialId,
subjectVisitId,
studyId,
imageIds: imageIds,
instanceInfoList,
seriesId: seriesId,
seriesUid: seriesInstanceUid,
seriesNumber: seriesNumber,
sliceThickness: sliceThickness,
sliceThickness: sliceLocation,
modality: this.modality,
description: this.description,
isReading,
@@ -348,8 +292,7 @@ export default {
instanceCount: res.Result.length,
prefetchInstanceCount: 0,
loadStatus: false,
imageloadedArr: [],
isExistMutiFrames: isExistMutiFrames
imageloadedArr: []
})
this.seriesList = seriesList
if (this.seriesList.length > 0) {
@@ -373,37 +316,21 @@ export default {
this.$refs.dicomViewer.loadImageStack(this.seriesList[seriesIndex])
if (!series.loadStatus) {
requestPoolManager.changePriority(series.seriesId)
}
},
showMultiFrames(series, seriesIndex, instanceInfo) {
this.currentSeriesIndex = seriesIndex
const imageIds = []
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}&seriesIndex=${seriesIndex}`)
}
} else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?instanceId=${instanceInfo.Id}&seriesIndex=${seriesIndex}`)
}
const seriesInfo = {
trialId: series.trialId,
subjectVisitId: series.subjectVisitId,
studyId: series.studyId,
imageIds: imageIds,
seriesId: series.seriesId,
seriesUid: series.seriesUid,
seriesNumber: series.seriesNumber,
sliceThickness: series.sliceThickness,
modality: series.modality,
description: series.description,
isReading: series.isReading,
isDeleted: series.isDeleted,
previewImageUrl: series.previewImageUrl,
instanceCount: series.instanceCount
}
this.$refs.dicomViewer.loadImageStack(seriesInfo)
if (!series.loadStatus) {
requestPoolManager.changePriority(series.seriesId)
// var isAddToTakPool = false
// if (this.showSeriesList.includes(`${seriesIndex}`)) {
// isAddToTakPool = true
// } else {
// this.showSeriesList.push(`${seriesIndex}`)
// }
// if (!isAddToTakPool) {
// var priority = parseInt(new Date().getTime())
// series.isLoading = true
// series.imageIds.map((imageId) => {
// this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority })
// })
// } else {
// requestPoolManager.changePriority(series.seriesId)
// }
}
},
initStudy() {
@@ -476,7 +403,6 @@ export default {
data.isReading = true
}
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
message = message.replace('yyy', this.$fd('YesOrNo', !data.isReading))
this.$confirm(message, {
distinguishCancelAndClose: true,
type: 'warning'
@@ -504,7 +430,6 @@ export default {
data.isDeleted = true
}
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
message = message.replace('yyy', this.$fd('YesOrNo', !data.isDeleted))
this.$confirm(message, {
distinguishCancelAndClose: true,
type: 'warning'
@@ -526,44 +451,31 @@ export default {
}).catch(() => {})
},
loadAllImages() {
const seriesIndex = this.seriesList.findIndex(i => i.loadStatus === false)
if (seriesIndex === -1) return
const series = this.seriesList[seriesIndex]
var priority = new Date().getTime()
for (let i = 0; i < series.imageIds.length; i++) {
const imageId = series.imageIds[i]
if (series.isExistMutiFrames) {
const params = this.getInstanceInfo(imageId)
if (params.frame && params.frame > 0) {
continue
this.seriesList.forEach((series, index) => {
series.imageIds.forEach(imageId => {
var p = null
if (this.firstInstanceId === imageId) {
p = priority * 100
} else {
p = priority - 1
}
}
var p = null
if (this.firstInstanceId === imageId) {
p = priority * 100
} else {
p = priority - 1
}
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, seriesIndex: seriesIndex, priority: p })
}
// this.load(imageId, series.seriesId, priority)
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, seriesIndex: index, priority: p })
})
})
if (this.imageList.length > 0) {
this.loopLoad()
}
},
getInstanceInfo(imageId) {
const params = {}
const searchParams = new URLSearchParams(imageId.split('?')[1])
for (const [key, value] of searchParams.entries()) {
params[key] = value
}
return params
},
loopLoad() {
if (this.imageList.length > 0) {
requestPoolManager.startTaskTimer()
console.log('loopLoad')
this.imageList.map(image => {
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority)
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority).then(res => {
this.imageLoaded(image, res.data.string('x0020000e'))
})
})
requestPoolManager.sortTaskPool()
this.imageList = []
@@ -646,45 +558,6 @@ export default {
return 0
},
cornerstoneimageloadprogress(e) {
const imageId = e.detail.imageId
const percentComplete = e.detail.percentComplete
const params = {}
const searchParams = new URLSearchParams(imageId.split('?')[1])
for (const [key, value] of searchParams.entries()) {
params[key] = value
}
if (this.visitTaskId === params.visitTaskId) {
const seriesIndex = params.seriesIndex
var prefetchInstanceCount = this.seriesList[seriesIndex].prefetchInstanceCount
var instanceCount = this.seriesList[seriesIndex].instanceCount
if (this.seriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
const i = this.currentLoadIns.findIndex(i => i.imageId === imageId)
if (i > -1) {
prefetchInstanceCount = prefetchInstanceCount - this.currentLoadIns[i].percentComplete + percentComplete
this.currentLoadIns[i].percentComplete = percentComplete
if (percentComplete === 100) {
this.currentLoadIns.splice(i, 1)
}
} else {
if (percentComplete !== 100) {
this.currentLoadIns.push({ imageId, percentComplete })
}
prefetchInstanceCount = prefetchInstanceCount + percentComplete
}
this.seriesList[seriesIndex].prefetchInstanceCount = prefetchInstanceCount
if (percentComplete >= 100) {
this.seriesList[seriesIndex].imageloadedArr.push(imageId)
}
}
if (prefetchInstanceCount >= instanceCount * 100) {
this.seriesList[seriesIndex].prefetchInstanceCount = instanceCount * 100
// 设置当前序列状态为已下载完成
this.seriesList[seriesIndex].loadStatus = true
this.loadAllImages()
}
}
},
cornerstoneImageLoaded(e) {
if (this.firstInstanceId === e.detail.image.imageId && !this.isStartLoad) {
// 初始化图像加载完成时,自动下载
@@ -878,29 +751,6 @@ export default {
color: #D0D0D0;
font-size: 13px;
}
.instance_frame_wrapper{
min-width: 120px;
background-color: #2c2c2c;
border: 1px solid #2c2c2c;
padding: 5px;
}
.frame_content{
height: 50px;
padding: 5px;
display: flex;
justify-content: flex-start;
color: #ddd;
font-size: 12px;
border: 1px solid #404040;
}
.frame_content:hover {
/* font-weight: bold; */
/* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
cursor: pointer;
/* color: #428bca; */
border-color: #213a54 !important;
background-color: #213a54;
}
/* .viewerRightSidePanel {
width: 300px;
height: 100%;
+145 -254
View File
@@ -46,6 +46,13 @@
@click="showSeriesImage($event,index,i,series)"
>
<div class="viewernavigatorwrapper">
<!-- <el-image
class="image-preview"
style="height:72px;width:72px;"
:src="series.previewImageUrl"
fit="fill"
/> -->
<img
class="image-preview"
:src="series.previewImageUrl"
@@ -55,41 +62,8 @@
fit="fill"
>
<div class="viewernavitextwrapper">
<div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
<div>#{{ series.seriesNumber }}</div>
<div v-if="series.isExistMutiFrames && series.instanceCount > 1">
<el-popover
placement="right"
trigger="hover"
popper-class="instance_frame_wrapper"
>
<div
v-for="(instance, idx) in series.instanceInfoList"
:key="instance.Id"
class="frame_content"
:style="{'margin-bottom':idx<series.instanceInfoList.length-1? '5px':'0px'}"
@click="showMultiFrames(index,series, i, instance)"
>
<!-- <div>
<img
class="image-preview"
:src="series.previewImageUrl"
crossorigin="anonymous"
alt=""
style="width: 40px;height:40px;"
fit="fill"
>
</div> -->
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" />
</el-popover>
</div>
<div style="padding: 1px;">
#{{ series.seriesNumber }}
</div>
<div v-show="series.InstanceCount" style="padding: 1px;">
{{ series.modality }}: {{ series.instanceCount }} image
@@ -104,35 +78,32 @@
</div>
</el-tooltip>
<div style="padding: 1px;">
{{ series.imageloadedArr.length }}/{{ series.instanceCount }}
{{ series.prefetchInstanceCount }}/{{ series.instanceCount }}
</div>
<div />
</div>
</div>
<div v-if="showDelete" style="display: flex;flex-direction: row;justify-content: space-between;" @click.stop="">
<div v-if="showDelete" @click.stop="">
<div>
<span style="font-size: 12px;">{{ $t('trials:audit:table:isReading') }}</span>
<el-switch
v-model="series.isReading"
size="mini"
@change="changeReadingStatus($event, series)"
/>
</div>
<div>
<span style="font-size: 12px;">{{ $t('trials:audit:table:isDelete') }}</span>
<el-switch
v-model="series.isDeleted"
size="mini"
@change="changeDeleteStatus($event, series)"
/>
</div>
<span style="font-size: 12px;">{{ $t('trials:audit:table:isReading') }}</span>
<el-switch
v-model="series.isReading"
size="mini"
@change="changeReadingStatus($event, series)"
/>
<span style="font-size: 12px;">{{ $t('trials:audit:table:isDelete') }}</span>
<el-switch
v-model="series.isDeleted"
size="mini"
@change="changeDeleteStatus($event, series)"
/>
</div>
<!-- <div style="position: absolute;bottom: -10px;left: 0;width: 100%;">
<el-progress v-if="series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount" :percentage="Number(series.prefetchInstanceCount/series.instanceCount)*100" />
</div> -->
<div v-if="series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount * 100">
<el-progress :percentage="parseInt((series.prefetchInstanceCount/series.instanceCount).toFixed(2))" />
<div v-if="series.prefetchInstanceCount>0 && series.prefetchInstanceCount<series.instanceCount">
<el-progress :percentage="parseInt(((series.prefetchInstanceCount/series.instanceCount)*100).toFixed(2))" />
</div>
</div>
@@ -146,7 +117,7 @@
<el-tab-pane :label="$t('trials:dicom-show:relatedVisit')" name="relation-study" class="pane-relation-wrapper">
<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}`">
<el-collapse-item v-for="(study) in relationStudyList" :key="`${study.StudyId}`" :name="`${study.StudyId}`">
<template slot="title">
<div class="text-desc">
@@ -189,46 +160,13 @@
>
<div class="viewernavitextwrapper">
<div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
<div v-if="seriesItem.keySeries" style="color:red">
Key Images
</div>
<div v-else>#{{ seriesItem.seriesNumber }}</div>
<div v-if="seriesItem.isExistMutiFrames && seriesItem.instanceCount > 1">
<el-popover
placement="right"
trigger="hover"
popper-class="instance_frame_wrapper"
>
<div
v-for="(instance, idx) in seriesItem.instanceInfoList"
:key="instance.Id"
class="frame_content"
:style="{'margin-bottom':idx<seriesItem.instanceInfoList.length-1? '5px':'0px'}"
@click="showMultiFrames(studyIndex,seriesItem, index, instance)"
>
<!-- <div>
<img
class="image-preview"
:src="series.previewImageUrl"
crossorigin="anonymous"
alt=""
style="width: 40px;height:40px;"
fit="fill"
>
</div> -->
<div>
<div>{{ instance.InstanceNumber }}</div>
<div>{{ `${instance.NumberOfFrames > 0 ? instance.NumberOfFrames : 1} frame` }}</div>
</div>
</div>
<i slot="reference" class="el-icon-connection" style="font-size: 15px;cursor: pointer;" />
</el-popover>
</div>
<div v-if="seriesItem.keySeries" style="padding: 1px;color:red">
Key Images
</div>
<div v-show="seriesItem.instanceCount" style="padding: 1px;">
<div v-else style="padding: 1px;">
#{{ seriesItem.seriesNumber }}
</div>
<div v-show=" seriesItem.instanceCount" style="padding: 1px;">
{{ seriesItem.modality }}: {{ seriesItem.instanceCount }} image
</div>
<div v-show="seriesItem.sliceThickness" style="padding: 1px;">
@@ -239,6 +177,7 @@
{{ seriesItem.description }}
</div>
</el-tooltip>
</div>
<!-- <div style="position: absolute;bottom: -10px;left: 0;width: 100%;">
<el-progress v-if="seriesItem.prefetchInstanceCount>0 && seriesItem.prefetchInstanceCount<seriesItem.instanceCount" :percentage="Number(seriesItem.prefetchInstanceCount/seriesItem.instanceCount)*100" />
@@ -295,13 +234,10 @@ export default {
imageList: [],
activeNames: [],
relationActiveName: [],
showSeriesList: [],
currentLoadIns: []
showSeriesList: []
}
},
mounted() {
requestPoolManager.resetRequestPool()
document.documentElement.style.userSelect = 'none'
if (this.$router.currentRoute.query.TokenKey) {
store.dispatch('user/setToken', this.$router.currentRoute.query.TokenKey)
changeURLStatic('TokenKey', '')
@@ -314,25 +250,16 @@ export default {
this.showDelete = parseInt(this.$router.currentRoute.query.showDelete)
// cornerstone.events.addEventListener('cornerstoneimageloaded', this.cornerstoneImageLoaded)
this.getStudiesInfo()
cornerstone.events.addEventListener('cornerstoneimageloadprogress', this.cornerstoneimageloadprogress)
window.addEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache()
requestPoolManager.resetRequestPool()
})
},
beforeDestroy() {
requestPoolManager.stopTaskTimer()
window.removeEventListener('beforeunload', e => {
cornerstone.imageCache.purgeCache()
requestPoolManager.resetRequestPool()
})
},
methods: {
// 获取某个访视下所有的检查信息
getStudiesInfo() {
this.studyList = []
getVisitStudyList(this.trialId, this.subjectVisitId, this.isReading).then(res => {
res.Result.forEach((study,studyIndex) => {
res.Result.forEach((study) => {
const data = {}
data.StudyId = study.StudyId
data.StudyCode = study.StudyCode
@@ -342,23 +269,23 @@ export default {
data.InstanceCount = study.InstanceCount
data.PreviewImageCount = 0
var seriesList = []
study.SeriesList.forEach((series,seriesIndex) => {
study.SeriesList.forEach((series) => {
const imageIds = []
series.InstanceInfoList.forEach(i => {
if (i.NumberOfFrames && i.NumberOfFrames > 1) {
for (let j = 0; j < i.NumberOfFrames; j++) {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${i.Path}?frame=${j}&instanceId=${i.Id}&idx=${studyIndex}|${seriesIndex}`)
}
} else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${i.Path}?instanceId=${i.Id}&idx=${studyIndex}|${seriesIndex}`)
}
// series.InstanceList.forEach((id) => {
// imageIds.push(`wadouri:/api/instance/content/${id}`)
// })
// series.InstanceList.forEach((id) => {
// imageIds.push(`wadouri:http://123.56.94.154:7000/instance/content/${id}`)
// })
series.InstancePathList.forEach((path) => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${path}`)
})
seriesList.push({
trialId: this.trialId,
subjectVisitId: this.subjectVisitId,
studyId: study.StudyId,
imageIds: imageIds,
instanceInfoList: series.InstanceInfoList,
seriesId: series.Id,
seriesUid: series.SeriesInstanceUid,
seriesNumber: series.SeriesNumber,
@@ -371,8 +298,7 @@ export default {
instanceCount: series.InstanceCount,
prefetchInstanceCount: 0,
loadStatus: false,
imageloadedArr: [],
isExistMutiFrames: series.IsExistMutiFrames
imageloadedArr: []
})
})
data.SeriesList = seriesList
@@ -400,37 +326,21 @@ export default {
this.$refs.dicomViewer.loadImageStack(this.studyList[studyIndex].SeriesList[seriesIndex])
if (!series.loadStatus) {
requestPoolManager.changePriority(series.seriesId)
}
},
showMultiFrames(studyIndex,series, seriesIndex, instanceInfo) {
this.currentSeriesIndex = seriesIndex
const imageIds = []
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}&idx=${studyIndex}|${seriesIndex}`)
}
} else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? this.OSSclientConfig.basePath : this.OSSclientConfig.basePath}${instanceInfo.Path}?instanceId=${instanceInfo.Id}&idx=${studyIndex}|${seriesIndex}`)
}
const seriesInfo = {
trialId: series.trialId,
subjectVisitId: series.subjectVisitId,
studyId: series.studyId,
imageIds: imageIds,
seriesId: series.seriesId,
seriesUid: series.seriesUid,
seriesNumber: series.seriesNumber,
sliceThickness: series.sliceThickness,
modality: series.modality,
description: series.description,
isReading: series.isReading,
isDeleted: series.isDeleted,
previewImageUrl: series.previewImageUrl,
instanceCount: series.instanceCount
}
this.$refs.dicomViewer.loadImageStack(seriesInfo)
if (!series.loadStatus) {
requestPoolManager.changePriority(series.seriesId)
// var isAddToTakPool = false
// if (this.showSeriesList.includes(`${studyIndex}_${seriesIndex}`)) {
// isAddToTakPool = true
// } else {
// this.showSeriesList.push(`${studyIndex}_${seriesIndex}`)
// }
// if (!isAddToTakPool) {
// var priority = parseInt(new Date().getTime())
// series.isLoading = true
// series.imageIds.map((imageId, i) => {
// this.imageList.push({ imageId: imageId, seriesId: series.seriesId, priority })
// })
// } else {
// requestPoolManager.changePriority(series.seriesId)
// }
}
},
changeReadingStatus(callback, data) {
@@ -443,7 +353,6 @@ export default {
data.isReading = true
}
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
message = message.replace('yyy', this.$fd('YesOrNo', !data.isReading))
this.$confirm(message, {
distinguishCancelAndClose: true,
type: 'warning'
@@ -471,7 +380,6 @@ export default {
data.isDeleted = true
}
var message = this.$t('trials:audit:message:changeSeriesStatus').replace('xxx', statusStr)
message = message.replace('yyy', this.$fd('YesOrNo', !data.isDeleted))
this.$confirm(message, {
distinguishCancelAndClose: true,
type: 'warning'
@@ -535,20 +443,19 @@ export default {
if (data.Result != null && data.Result.length > 0) {
var seriesList = []
const res = data.Result
res.forEach((item,seriesIndex)=> {
res.forEach(function(item) {
const imageIds = []
item.InstanceInfoList.forEach(i => {
if (i.NumberOfFrames && i.NumberOfFrames > 1) {
for (let j = 0; j < i.NumberOfFrames; j++) {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${i.Path}?frame=${j}&instanceId=${i.Id}&idx=${index}|${seriesIndex}`)
}
} else {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${i.Path}?instanceId=${i.Id}&idx=${index}|${seriesIndex}`)
}
// item.InstanceList.forEach(function(id) {
// imageIds.push(`wadouri:/api/instance/content/${id}`)
// })
// item.InstanceList.forEach((id) => {
// imageIds.push(`wadouri:http://123.56.94.154:7000/instance/content/${id}`)
// })
item.InstancePathList.forEach((path) => {
imageIds.push(`wadouri:${localStorage.getItem('location') !== 'USA' ? scope.OSSclientConfig.basePath : scope.OSSclientConfig.basePath}${path}`)
})
seriesList.push({
imageIds: imageIds,
instanceInfoList: item.InstanceInfoList,
seriesId: item.Id,
seriesUid: item.SeriesInstanceUid,
seriesNumber: item.SeriesNumber,
@@ -561,8 +468,7 @@ export default {
hasLabel: item.HasLabel,
keySeries: item.KeySeries,
loadStatus: false,
imageloadedArr: [],
isExistMutiFrames: item.IsExistMutiFrames
imageloadedArr: []
})
})
scope.relationStudyList[index].seriesCount = seriesList.length
@@ -591,50 +497,54 @@ export default {
}
},
loadAllImages() {
var seriesList = this.studyList.map(s => s.SeriesList).flat()
const seriesIndex = seriesList.findIndex(i => i.loadStatus === false)
if (seriesIndex === -1) return
const series = seriesList[seriesIndex]
var priority = parseInt(new Date().getTime())
for (let i = 0; i < series.imageIds.length; i++) {
const imageId = series.imageIds[i]
if (series.isExistMutiFrames) {
const params = this.getInstanceInfo(imageId)
if (params.frame && params.frame > 0) {
continue
}
}
var p = null
if (this.firstInstanceId === imageId) {
p = priority * 100
} else {
p = priority - 1
}
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, seriesIndex: seriesIndex, priority: p })
}
this.studyList.map((study, studyIndex) => {
study.SeriesList.map((series, seriesIndex) => {
series.imageIds.map(imageId => {
var p = null
if (this.firstInstanceId === imageId) {
p = priority * 100
} else {
p = priority - 1
}
this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex, seriesIndex, priority: p })
})
// if (!series.loadStatus && series.seriesId !== this.firstSeriesId) {
// series.imageIds.map(imageId => {
// // imageIds.push({ imageId: image, seriesId: series.seriesId, priority })
// this.imageList.push({ imageId: imageId, seriesId: series.seriesId, studyIndex, seriesIndex, priority })
// })
// }
})
})
if (this.imageList.length > 0) {
this.loopLoad()
}
// requestPoolManager.setPendingList(imageIds)
},
getInstanceInfo(imageId) {
const params = {}
const searchParams = new URLSearchParams(imageId.split('?')[1])
for (const [key, value] of searchParams.entries()) {
params[key] = value
}
return params
},
loopLoad() {
if (this.imageList.length > 0) {
requestPoolManager.startTaskTimer()
this.imageList.map(image => {
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority)
requestPoolManager.loadAndCacheImagePlus(image.imageId, image.seriesId, image.priority).then(res => {
this.imageLoaded(image, res.data.string('x0020000e'))
})
})
requestPoolManager.sortTaskPool()
this.imageList = []
}
},
load(imageId, seriesId, priority = 999) {
return new Promise((resolve, reject) => {
requestPoolManager.loadAndCacheImagePlus(imageId, seriesId, priority).then(res => {
if (!res) return
this.imageLoaded(imageId, res.data.string('x0020000e'))
resolve(res)
}).catch(e => {
reject(e)
})
})
},
// load(imageId, priority = 999) {
// return new Promise((resolve, reject) => {
// const imageTask = this.buildImageRequestTask(imageId, { priority })
@@ -677,43 +587,47 @@ export default {
}
}
},
cornerstoneimageloadprogress(e){
const imageId = e.detail.imageId
const percentComplete = e.detail.percentComplete
const params = {}
const searchParams = new URLSearchParams(imageId.split('?')[1])
for (const [key, value] of searchParams.entries()) {
params[key] = value
// instance下载成功回调
cornerstoneImageLoaded(e) {
if (e.detail.image.imageId.includes(this.firstInstanceId) && !this.isStartLoad) {
// 初始化图像加载完成时,自动下载
this.loadAllImages()
this.isStartLoad = true
// requestPoolManager.executeTask()
}
if (this.visitTaskId === params.visitTaskId) {
const studyIndex = params.idx.split('|')[0]
const seriesIndex = params.idx.split('|')[1]
var prefetchInstanceCount = this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount
var instanceCount = this.studyList[studyIndex].SeriesList[seriesIndex].instanceCount
if (this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
const i = this.currentLoadIns.findIndex(i => i.imageId === imageId)
if (i > -1) {
prefetchInstanceCount = prefetchInstanceCount - this.currentLoadIns[i].percentComplete + percentComplete
this.currentLoadIns[i].percentComplete = percentComplete
if (percentComplete === 100) {
this.currentLoadIns.splice(i, 1)
}
} else {
if (percentComplete !== 100) {
this.currentLoadIns.push({ imageId, percentComplete })
}
prefetchInstanceCount = prefetchInstanceCount + percentComplete
}
this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount = prefetchInstanceCount
if (percentComplete >= 100) {
this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr.push(imageId)
const uri = e.detail.image.sharedCacheKey
const index = this.cachedImages.findIndex(item => item.uri === uri)
if (index === -1) {
this.cachedImages.push({ uri: uri, timestamp: new Date().getTime() })
} else {
this.cachedImages[index].timestamp = new Date().getTime()
}
var imageId = e.detail.image.imageId
var seriesUid = e.detail.image.data.string('x0020000e')
var studyIndex = -1
var seriesIndex = -1
for (let i = 0; i < this.studyList.length; ++i) {
for (let j = 0; j < this.studyList[i].SeriesList.length; ++j) {
if (this.studyList[i].SeriesList[j].seriesUid === seriesUid) {
studyIndex = i
seriesIndex = j
break
}
}
if (prefetchInstanceCount >= instanceCount * 100) {
this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount = instanceCount * 100
if (studyIndex > 0) break
}
if (seriesIndex < 0) return
const imageIdIndex = this.studyList[studyIndex].SeriesList[seriesIndex].imageIds.indexOf(imageId)
if (imageIdIndex < 0) return
if (this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr.indexOf(imageId) < 0) {
++this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount
this.studyList[studyIndex].SeriesList[seriesIndex].imageloadedArr.push(imageId)
if (this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount >= this.studyList[studyIndex].SeriesList[seriesIndex].instanceCount) {
this.studyList[studyIndex].SeriesList[seriesIndex].prefetchInstanceCount = this.studyList[studyIndex].SeriesList[seriesIndex].instanceCount
// 设置当前序列状态为已下载完成
this.studyList[studyIndex].SeriesList[seriesIndex].loadStatus = true
this.loadAllImages()
}
}
}
@@ -775,9 +689,9 @@ export default {
padding: 5px;
/* height: 95%; */
height: 99%;
/* overflow: hidden;
text-overflow: clip; */
/* white-space: nowrap; */
overflow: hidden;
text-overflow: clip;
white-space: nowrap;
}
.viewerContainer .viewerContentWrapper>div {
display: inline-block;
@@ -894,29 +808,6 @@ export default {
height: 40px;
line-height: 20px;
}
.instance_frame_wrapper{
min-width: 120px;
background-color: #2c2c2c;
border: 1px solid #2c2c2c;
padding: 5px;
}
.frame_content{
height: 50px;
padding: 5px;
display: flex;
justify-content: flex-start;
color: #ddd;
font-size: 12px;
border: 1px solid #404040;
}
.frame_content:hover {
/* font-weight: bold; */
/* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
cursor: pointer;
/* color: #428bca; */
border-color: #213a54 !important;
background-color: #213a54;
}
/* .viewerRightSidePanel {
width: 300px;
@@ -244,7 +244,8 @@ export default {
this.$confirm('是否确认废除此文件?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
+8 -67
View File
@@ -33,7 +33,7 @@
<el-table-column prop="ModuleTypeValueCN" label="模块" show-overflow-tooltip align="left" min-width="230px" />
<el-table-column prop="Description" label="操作名称" :show-overflow-tooltip="true" min-width="200px">
<template slot-scope="scope">
<span>{{ scope.row.DescriptionCN }}{{scope.row.Description}}</span>
<span>{{ scope.row.Description }}{{scope.row.DescriptionCN}}</span>
</template>
</el-table-column>
<el-table-column prop="DescriptionCN" label="其他" :show-overflow-tooltip="true" min-width="140px">
@@ -513,27 +513,12 @@
</el-col>
<el-col v-show="form.ConfigType === 'C' && title !== '复制' && form.EnumType === 'Dictionary'" :span="12">
<el-form-item label="字典表名">
<!-- <el-input v-model="form.DictionaryCode" placeholder="请输入字典表名" /> -->
<el-autocomplete
clearable
class="inline-input"
v-model="form.DictionaryCode"
:fetch-suggestions="querySearch"
placeholder="请输入字典表名"
></el-autocomplete>
<el-input v-model="form.DictionaryCode" placeholder="请输入字典表名" />
</el-form-item>
</el-col>
<el-col v-show="form.ConfigType === 'C' && title !== '复制' && form.EnumType === 'Dictionary'" :span="12">
<el-form-item label="翻译字段">
<!-- <el-input v-model="form.DictionaryType" placeholder="请输入翻译字段" /> -->
<el-select v-model="form.DictionaryType" clearable placeholder="请选择翻译字段">
<el-option
v-for="item in $d.DictionaryType"
:key="item.id"
:label="item.label"
:value="item.label">
</el-option>
</el-select>
<el-input v-model="form.DictionaryType" placeholder="请输入翻译字段" />
</el-form-item>
</el-col>
<el-col v-show="form.ConfigType === 'C' && title !== '复制' && form.EnumType === 'Date'" :span="24">
@@ -623,11 +608,11 @@
<div style="padding: 0 40px;display: flex;flex-direction: column">
<div style="text-align: right;height: 50px;">
<el-select v-model="copeParams.FromItemId" collapse-tags filterable placeholder="完全拷贝对象" clearable size="small">
<el-option v-for="item of list" v-if="drawer_cfg.drawerChild && item.ConfigType === 'M' && item.ObjectTypeId === selectRow.ObjectTypeId && item.OptTypeId && item.ChildrenTypeId " :value="item.Id" :label="item.DescriptionCN" />
<el-option v-for="item of list" v-if="drawer_cfg.drawerChild && item.ConfigType === 'M' && item.ObjectTypeId === selectRow.ObjectTypeId && item.OptTypeId && item.ChildrenTypeId " :value="item.Id" :label="item.Description" />
</el-select>
<el-button type="primary" size="mini" style="margin-right: 10px" @click="handleOverCope(selectRow)">完全拷贝</el-button>
<el-select v-model="copeParams.DataSourceGuids" multiple collapse-tags filterable placeholder="拷贝对象" clearable size="small">
<el-option v-for="item of list" v-if="drawer_cfg.drawerChild && item.ConfigType === 'M' && item.ObjectTypeId === selectRow.ObjectTypeId && item.OptTypeId && item.ChildrenTypeId " :value="item.Id" :label="item.DescriptionCN" />
<el-option v-for="item of list" v-if="drawer_cfg.drawerChild && item.ConfigType === 'M' && item.ObjectTypeId === selectRow.ObjectTypeId && item.OptTypeId && item.ChildrenTypeId " :value="item.Id" :label="item.Description" />
</el-select>
<el-button type="primary" size="mini" @click="handleCope(selectRow)">拷贝</el-button>
<el-button type="primary" size="mini" @click="handleAdd(selectRow)">新建</el-button>
@@ -683,12 +668,6 @@
<el-table-column prop="TrialConfigRelyFieldName" label="依赖字段" min-width="120px" :show-overflow-tooltip="true" />
<el-table-column label="操作" align="center" min-width="180" class-name="small-padding fixed-width">
<template slot-scope="scope">
<el-button
size="mini"
type="text"
icon="el-icon-edit"
@click="handleCopyData(scope.row)"
>复制</el-button>
<el-button
size="mini"
type="text"
@@ -711,7 +690,7 @@
</template>
<script>
import { fullyReplicated, changeFrontAuditSort, copyFrontAuditConfigItem, getFrontAuditConfigList, addOrUpdateFrontAuditConfig, deleteFrontAuditConfig, copyOtherToThisItem, getAuditConfigChildList, getDictionaryCodeList } from '@/api/dictionary/checkConfig'
import { fullyReplicated, changeFrontAuditSort, copyFrontAuditConfigItem, getFrontAuditConfigList, addOrUpdateFrontAuditConfig, deleteFrontAuditConfig, copyOtherToThisItem, getAuditConfigChildList, setDictionaryValue } from '@/api/dictionary/checkConfig'
import Treeselect from '@riophae/vue-treeselect'
import '@riophae/vue-treeselect/dist/vue-treeselect.css'
import Sortable from 'sortablejs'
@@ -764,41 +743,13 @@ export default {
},
ChildGroup: null,
tableShow: false,
rowDrop2TableIsShow: true,
DictionaryCodeList:[]
rowDrop2TableIsShow: true
}
},
created() {
this.getList();
this.getDictionaryCodeList();
this.getList()
},
methods: {
querySearch(queryString, cb) {
var DictionaryCodeList = this.DictionaryCodeList;
var results = queryString ? DictionaryCodeList.filter(this.createFilter(queryString)) : DictionaryCodeList;
// callback
cb(results);
},
createFilter(queryString) {
return (DictionaryCodeList) => {
return (DictionaryCodeList.value.toLowerCase().indexOf(queryString.toLowerCase()) === 0);
};
},
//
async getDictionaryCodeList(){
try{
let res = await getDictionaryCodeList();
if(res.IsSuccess){
this.DictionaryCodeList = res.Result.map(item=>{
return {
value:item
}
});
}
}catch(err){
console.log(err);
}
},
addParameter() {
this.form.UrlConfig.ParameterList.push({
UrlParameterName: null,
@@ -1195,16 +1146,6 @@ export default {
this.title = '修改'
this.rowDrop2()
},
handleCopyData (row) {
this.$confirm('确定复制该条记录到当前稽查下吗?').then(() => {
let params = {...row}
delete params.Id
addOrUpdateFrontAuditConfig(params).then(() => {
this.$message.success(this.$t('common:message:savedSuccessfully'))
this.getList()
})
})
},
/** 提交按钮 */
submitForm: function() {
this.$refs['form'].validate(valid => {
+4 -3
View File
@@ -125,17 +125,18 @@ export default {
},
//
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
deleteDictionary(row.Id)
.then(res => {
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
this.$store.dispatch('global/setDictionary', {})
}
})
+4 -3
View File
@@ -239,17 +239,18 @@ export default {
},
//
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
deleteEmailNoticeConfig(row.Id)
.then(res => {
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
})
})
@@ -3,34 +3,26 @@
<div class="search">
<el-form :inline="true" size="small" class="base-search-form">
<el-form-item label="CRO Name:">
<el-input v-model="searchData.CROName" style="width: 100px" />
<el-input v-model="searchData.CROName" style="width:100px;" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleSearch"
>Search</el-button
>
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>Reset</el-button
>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">Search</el-button>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">Reset</el-button>
</el-form-item>
</el-form>
<span style="margin-left: auto">
<span style="margin-left:auto;">
<el-button
size="small"
type="primary"
style="margin-left: auto"
style="margin-left:auto;"
icon="el-icon-plus"
@click="handleAddCro"
>New</el-button
>
>New</el-button>
</span>
</div>
<el-table
v-loading="loading"
v-adaptive="{ bottomOffset: 60 }"
v-adaptive="{bottomOffset:60}"
:data="list"
stripe
height="100"
@@ -58,16 +50,6 @@
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="IsTrialLevel"
label="Level"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope">
<span>{{ $fd("IsTrialLevel", String(scope.row.IsTrialLevel)) }}</span>
</template>
</el-table-column>
<el-table-column label="Action" min-width="200">
<template slot-scope="scope">
<el-button
@@ -86,13 +68,7 @@
</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
v-if="editVisible"
@@ -102,32 +78,26 @@
width="600px"
custom-class="base-dialog-wrapper"
>
<CroForm
v-if="editVisible"
:data="rowData"
:IsTrialLevel="rowData.IsTrialLevel"
@close="close"
@getList="getList"
/>
<CroForm v-if="editVisible" :data="rowData" @close="close" @getList="getList" />
</el-dialog>
</box-content>
</template>
<script>
import { getCROPageList, deleteCROCompany } from "@/api/dictionary";
import BoxContent from "@/components/BoxContent";
import Pagination from "@/components/Pagination";
import CroForm from "./CroForm";
import { getCROPageList, deleteCROCompany } from '@/api/dictionary'
import BoxContent from '@/components/BoxContent'
import Pagination from '@/components/Pagination'
import CroForm from './CroForm'
const searchDataDefault = () => {
return {
CROName: "",
CROName: '',
PageIndex: 1,
PageSize: 20,
Asc: true,
SortField: "",
};
};
SortField: ''
}
}
export default {
name: "Cros",
name: 'Cros',
components: { BoxContent, Pagination, CroForm },
data() {
return {
@@ -137,93 +107,88 @@ export default {
loading: false,
rowData: {},
editVisible: false,
title: "",
};
title: ''
}
},
mounted() {
this.getList();
this.getList()
},
methods: {
// CRO
getList() {
this.loading = true;
getCROPageList(this.searchData)
.then((res) => {
this.loading = false;
this.list = res.Result.CurrentPageData;
this.total = res.Result.TotalCount;
})
.catch(() => {
this.loading = false;
});
this.loading = true
getCROPageList(this.searchData).then(res => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}).catch(() => {
this.loading = false
})
},
// CRO
handleAddCro() {
this.rowData = {};
this.title = "Add";
this.editVisible = true;
this.rowData = {}
this.title = 'Add'
this.editVisible = true
},
// CRO
handleEdit(row) {
this.rowData = row;
this.title = "Edit";
this.editVisible = true;
this.rowData = row
this.title = 'Edit'
this.editVisible = true
},
// CRO
handleDelete(row) {
this.$confirm(this.$t("trials:uploadedDicoms:message:deleteMes"), {
type: "warning",
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
}).then(() => {
this.loading = true;
deleteCROCompany(row.Id)
.then((res) => {
this.loading = false;
if (res.IsSuccess) {
this.list.splice(
this.list.findIndex((item) => item.Id === row.Id),
1
);
this.$message.success(
this.$t("common:message:deletedSuccessfully")
);
}
})
.catch(() => {
this.loading = false;
});
});
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
deleteCROCompany(row.Id)
.then(res => {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success('Deleted successfully!')
}
}).catch(() => {
this.loading = false
})
})
},
//
handleReset() {
this.searchData = searchDataDefault();
this.getList();
this.searchData = searchDataDefault()
this.getList()
},
//
handleSearch() {
this.searchData.PageIndex = 1;
this.getList();
this.searchData.PageIndex = 1
this.getList()
},
//
handleSortByColumn(column) {
if (column.order === "ascending") {
this.searchData.Asc = true;
if (column.order === 'ascending') {
this.searchData.Asc = true
} else {
this.searchData.Asc = false;
this.searchData.Asc = false
}
this.searchData.SortField = column.prop;
this.searchData.PageIndex = 1;
this.getList();
this.searchData.SortField = column.prop
this.searchData.PageIndex = 1
this.getList()
},
//
close() {
this.editVisible = false;
},
},
};
this.editVisible = false
}
}
}
</script>
<style lang="scss" scoped>
.cros {
.cros{
height: 100%;
}
</style>
@@ -17,98 +17,70 @@
<el-form-item label="CRO Code: " prop="CROCode">
<el-input v-model="form.CROCode" />
</el-form-item>
<el-form-item label="Level: ">
<el-switch
:disabled="!IsTrialLevel"
v-model="form.IsTrialLevel"
:active-text="$fd('IsTrialLevel', 'true')"
:inactive-text="$fd('IsTrialLevel', 'false')"
>
</el-switch>
</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 :disabled="btnLoading" type="primary" @click="handleCancel"
>Cancel</el-button
>
<el-button type="primary" :loading="btnLoading" @click="handleSave"
>Save</el-button
>
<el-button :disabled="btnLoading" type="primary" @click="handleCancel">Cancel</el-button>
<el-button type="primary" :loading="btnLoading" @click="handleSave">Save</el-button>
</el-form-item>
</div>
</el-form>
</template>
<script>
import { addOrUpdateCro } from "@/api/dictionary";
import { addOrUpdateCro } from '@/api/dictionary'
export default {
name: "CroForm",
name: 'CroForm',
props: {
data: {
type: Object,
default() {
return {};
},
},
IsTrialLevel: {
type: Boolean,
default: true,
},
return {}
}
}
},
data() {
return {
btnLoading: false,
form: {
Id: "",
CROName: "",
CRONameCN: "",
CROCode: "",
IsTrialLevel: true,
Id: '',
CROName: '',
CRONameCN: '',
CROCode: ''
},
rules: {
CROName: [
{ required: true, message: "Please specify", trigger: "blur" },
{ max: 500, message: "The maximum length is 500" },
],
CRONameCN: [
{ required: true, message: "Please specify", trigger: "blur" },
{ max: 500, message: "The maximum length is 500" },
],
CROCode: [
{ required: true, message: "Please specify", trigger: "blur" },
{ max: 50, message: "The maximum length is 50" },
],
},
};
CROName: [{ required: true, message: 'Please specify', trigger: 'blur' }, { max: 50, message: 'The maximum length is 50' }],
CRONameCN: [{ required: true, message: 'Please specify', trigger: 'blur' }, { max: 50, message: 'The maximum length is 50' }],
CROCode: [{ required: true, message: 'Please specify', trigger: 'blur' }, { max: 50, message: 'The maximum length is 50' }]
}
}
},
mounted() {
if (Object.keys(this.data).length && this.data.Id) {
this.form = { ...this.data };
this.form = { ...this.data }
}
},
methods: {
handleSave() {
this.$refs.CROForm.validate((valid) => {
if (!valid) return;
this.btnLoading = true;
addOrUpdateCro(this.form)
.then((res) => {
this.btnLoading = false;
if (res.IsSuccess) {
this.$message.success("Saved successfully");
this.$refs["CROForm"].resetFields();
this.$emit("getList");
this.$emit("close");
}
})
.catch(() => {
this.btnLoading = false;
});
});
this.$refs.CROForm.validate(valid => {
if (!valid) return
this.btnLoading = true
addOrUpdateCro(this.form).then(res => {
this.btnLoading = false
if (res.IsSuccess) {
this.$message.success('Saved successfully')
this.$refs['CROForm'].resetFields()
this.$emit('getList')
this.$emit('close')
}
}).catch(() => {
this.btnLoading = false
})
})
},
handleCancel() {
this.$emit("close");
},
},
};
this.$emit('close')
}
}
}
</script>
@@ -8,15 +8,12 @@
label-width="170px"
>
<div class="base-dialog-body">
<el-form-item label="Site: ">
<el-select v-model="form.SiteId" style="width: 100%" clearable filterable @change="siteChange">
<el-form-item label="Hospital CN: " prop="SiteId">
<el-select v-model="form.SiteId" style="width: 100%" filterable @change="siteChange">
<el-option v-for="item of siteList" :value="item.Id" :key="item.Id" :label="item.SiteName">
</el-option>
</el-select>
</el-form-item>
<el-form-item label="Hospital CN: " prop="HospitalNameCN">
<el-input v-model="form.HospitalNameCN" />
</el-form-item>
<el-form-item label="Hospital EN: " prop="HospitalName">
<el-input v-model="form.HospitalName" />
</el-form-item>
@@ -91,7 +88,9 @@ export default {
},
siteList: [],
rules: {
HospitalNameCN: [{ required: true, message: 'Please specify', trigger: 'blur' }, { max: 50, message: 'The maximum length is 50' }],
SiteId: [{ required: true, message: 'Please specify', trigger: 'blur' },
{ max: 50, message: 'The maximum length is 50' }],
HospitalName: [{ required: true, message: 'Please specify', trigger: 'blur' }, { max: 50, message: 'The maximum length is 50' }],
UniversityAffiliated: [{ max: 100, message: 'The maximum length is 100' }],
UniversityAffiliatedCN: [{ max: 100, message: 'The maximum length is 100' }],
Country: [{ required: true, message: 'Please specify', trigger: 'blur' },
@@ -117,8 +116,7 @@ export default {
this.siteList.forEach(o => {
if (o.Id === v) {
this.form.CityCN = o.City
this.form.HospitalNameCN = o.SiteNameCN
this.form.HospitalName = o.SiteName
this.form.HospitalNameCN = o.SiteName
this.form.ProvinceCN = o.Province
this.form.CountryCN = o.Country
}
@@ -1,255 +1,256 @@
<template>
<box-content>
<div class="search">
<el-form :inline="true" size="small" class="base-search-form">
<el-form-item label="Hospital:">
<el-input v-model="searchData.HospitalName" style="width:100px;" />
</el-form-item>
<el-form-item label="Province:">
<el-input v-model="searchData.Province" style="width:100px;" />
</el-form-item>
<el-form-item label="City:">
<el-input v-model="searchData.City" style="width:100px;" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">Search</el-button>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">Reset</el-button>
</el-form-item>
</el-form>
<span style="margin-left:auto;">
<el-button
size="small"
type="primary"
style="margin-left:auto;"
icon="el-icon-plus"
@click="handleAddHospital"
>New</el-button>
</span>
</div>
<!-- hospital列表 -->
<el-table
v-loading="loading"
v-adaptive="{bottomOffset:60}"
:data="list"
stripe
height="100"
@sort-change="handleSortByColumn"
>
<el-table-column type="index" width="40" />
<el-table-column
prop="HospitalName"
label="Hospital"
min-width="120"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="HospitalNameCN"
label="Hospital CN"
min-width="120"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="UniversityAffiliated"
label="University Affiliated"
min-width="170"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="UniversityAffiliatedCN"
label="University Affiliated CN"
min-width="170"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="Country"
label="Country"
width="120"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="CountryCN"
label="Country CN"
width="140"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="Province"
label="Province"
width="120"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="ProvinceCN"
label="Province CN"
width="140"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="City"
label="City"
width="120"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="CityCN"
label="City CN"
width="120"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column label="Action" width="150">
<template slot-scope="scope">
<el-button
circle
icon="el-icon-edit-outline"
title="编辑"
@click="handleEdit(scope.row)"
/>
<el-button
circle
icon="el-icon-delete"
title="删除"
@click="handleDelete(scope.row)"
/>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
<el-dialog
v-if="editDialog.visible"
:visible.sync="editDialog.visible"
:close-on-click-modal="false"
:title="editDialog.title"
width="600px"
custom-class="base-dialog-wrapper"
>
<hospital-form v-if="editDialog.visible" :data="rowData" @close="close" @getList="getList" />
</el-dialog>
</box-content>
</template>
<script>
import { getHospitalPageList, deleteHospital } from '@/api/dictionary'
import BoxContent from '@/components/BoxContent'
import Pagination from '@/components/Pagination'
import HospitalForm from './HospitalForm'
const searchDataDefault = () => {
return {
HospitalName: '',
Province: '',
City: '',
PageIndex: 1,
PageSize: 20,
Asc: true,
SortField: ''
}
}
export default {
name: 'Hospitals',
components: { BoxContent, Pagination, HospitalForm },
data() {
return {
searchData: searchDataDefault(),
editDialog: { visible: false, title: '' },
list: [],
total: 0,
loading: false,
rowData: {}
}
},
mounted() {
this.getList()
},
methods: {
//
getList() {
this.loading = true
getHospitalPageList(this.searchData).then(res => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}).catch(() => {
this.loading = false
})
},
//
handleAddHospital() {
this.rowData = {}
this.editDialog.title = 'Add'
this.editDialog.visible = true
},
//
handleEdit(row) {
this.rowData = row
this.editDialog.title = 'Edit'
this.editDialog.visible = true
},
//
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
type: 'warning',
distinguishCancelAndClose: true,
})
.then(() => {
this.loading = true
deleteHospital(row.Id)
.then(res => {
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
}
this.loading = false
}).catch(() => {
this.loading = false
})
})
},
//
handleSearch() {
this.searchData.PageIndex = 1
this.getList()
},
//
handleReset() {
this.searchData = searchDataDefault()
this.getList()
},
//
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()
},
//
close() {
this.editDialog.visible = false
}
}
}
</script>
<style lang="scss" scoped>
.hospitals{
height: 100%;
}
</style>
<template>
<box-content>
<div class="search">
<el-form :inline="true" size="small" class="base-search-form">
<el-form-item label="Hospital:">
<el-input v-model="searchData.HospitalName" style="width:100px;" />
</el-form-item>
<el-form-item label="Province:">
<el-input v-model="searchData.Province" style="width:100px;" />
</el-form-item>
<el-form-item label="City:">
<el-input v-model="searchData.City" style="width:100px;" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">Search</el-button>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">Reset</el-button>
</el-form-item>
</el-form>
<span style="margin-left:auto;">
<el-button
size="small"
type="primary"
style="margin-left:auto;"
icon="el-icon-plus"
@click="handleAddHospital"
>New</el-button>
</span>
</div>
<!-- hospital列表 -->
<el-table
v-loading="loading"
v-adaptive="{bottomOffset:60}"
:data="list"
stripe
height="100"
@sort-change="handleSortByColumn"
>
<el-table-column type="index" width="40" />
<el-table-column
prop="HospitalName"
label="Hospital"
min-width="120"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="HospitalNameCN"
label="Hospital CN"
min-width="120"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="UniversityAffiliated"
label="University Affiliated"
min-width="170"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="UniversityAffiliatedCN"
label="University Affiliated CN"
min-width="170"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="Country"
label="Country"
width="120"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="CountryCN"
label="Country CN"
width="140"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="Province"
label="Province"
width="120"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="ProvinceCN"
label="Province CN"
width="140"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="City"
label="City"
width="120"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="CityCN"
label="City CN"
width="120"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column label="Action" width="150">
<template slot-scope="scope">
<el-button
circle
icon="el-icon-edit-outline"
title="编辑"
@click="handleEdit(scope.row)"
/>
<el-button
circle
icon="el-icon-delete"
title="删除"
@click="handleDelete(scope.row)"
/>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
<el-dialog
v-if="editDialog.visible"
:visible.sync="editDialog.visible"
:close-on-click-modal="false"
:title="editDialog.title"
width="600px"
custom-class="base-dialog-wrapper"
>
<hospital-form v-if="editDialog.visible" :data="rowData" @close="close" @getList="getList" />
</el-dialog>
</box-content>
</template>
<script>
import { getHospitalPageList, deleteHospital } from '@/api/dictionary'
import BoxContent from '@/components/BoxContent'
import Pagination from '@/components/Pagination'
import HospitalForm from './HospitalForm'
const searchDataDefault = () => {
return {
HospitalName: '',
Province: '',
City: '',
PageIndex: 1,
PageSize: 20,
Asc: true,
SortField: ''
}
}
export default {
name: 'Hospitals',
components: { BoxContent, Pagination, HospitalForm },
data() {
return {
searchData: searchDataDefault(),
editDialog: { visible: false, title: '' },
list: [],
total: 0,
loading: false,
rowData: {}
}
},
mounted() {
this.getList()
},
methods: {
//
getList() {
this.loading = true
getHospitalPageList(this.searchData).then(res => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}).catch(() => {
this.loading = false
})
},
//
handleAddHospital() {
this.rowData = {}
this.editDialog.title = 'Add'
this.editDialog.visible = true
},
//
handleEdit(row) {
this.rowData = row
this.editDialog.title = 'Edit'
this.editDialog.visible = true
},
//
handleDelete(row) {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
deleteHospital(row.Id)
.then(res => {
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success('Deleted successfully!')
}
this.loading = false
}).catch(() => {
this.loading = false
})
})
},
//
handleSearch() {
this.searchData.PageIndex = 1
this.getList()
},
//
handleReset() {
this.searchData = searchDataDefault()
this.getList()
},
//
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()
},
//
close() {
this.editDialog.visible = false
}
}
}
</script>
<style lang="scss" scoped>
.hospitals{
height: 100%;
}
</style>
@@ -3,50 +3,33 @@
<div class="search">
<el-form :inline="true" size="small" class="base-search-form">
<el-form-item label="Site Name:">
<el-input v-model="searchData.SiteName" style="width: 120px" />
<el-input v-model="searchData.SiteName" style="width:120px;" />
</el-form-item>
<el-form-item label="Alias Name:">
<el-input v-model="searchData.AliasName" style="width: 120px" />
<el-input v-model="searchData.AliasName" style="width:120px;" />
</el-form-item>
<el-form-item label="Country:">
<el-input v-model="searchData.Country" style="width: 120px" />
<el-input v-model="searchData.Country" style="width:120px;" />
</el-form-item>
<el-form-item label="City:">
<el-input v-model="searchData.City" style="width: 120px" />
<el-input v-model="searchData.City" style="width:120px;" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleSearch"
>Search</el-button
>
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>Reset</el-button
>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">Search</el-button>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">Reset</el-button>
</el-form-item>
</el-form>
<div style="margin-left: auto">
<el-button
type="primary"
size="small"
icon="el-icon-plus"
@click="handleAddSystemSite"
>{{ $t("trial:dictionary:institutions:site:addSystemSite") }}
</el-button>
<el-button
type="primary"
size="small"
style="margin-left: 10px"
icon="el-icon-plus"
@click="handleAddSite"
>New
</el-button>
</div>
<el-button
type="primary"
size="small"
style="margin-left:auto;"
icon="el-icon-plus"
@click="handleAddSite"
>New</el-button>
</div>
<el-table
v-loading="loading"
v-adaptive="{ bottomOffset: 60 }"
v-adaptive="{bottomOffset:60}"
:data="list"
stripe
height="100"
@@ -137,13 +120,6 @@
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="CreateTime"
label="CreateTime"
min-width="160"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column label="Action" fixed="right" width="150">
<template slot-scope="scope">
<el-button
@@ -162,362 +138,132 @@
</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
v-if="editVisible"
:visible.sync="editVisible"
:close-on-click-modal="false"
:title="title"
width="800px"
width="600px"
custom-class="base-dialog-wrapper"
>
<site-form
v-if="editVisible"
:data="rowData"
@close="close"
@getList="getList"
/>
<site-form v-if="editVisible" :data="rowData" @close="close" @getList="getList" />
</el-dialog>
<base-model
v-if="addSystemSite_model.visible"
:config="addSystemSite_model"
>
<template slot="dialog-body">
<div class="search">
<el-form :inline="true" size="small" class="base-search-form">
<el-form-item
:label="
$t(
'trial:dictionary:institutions:site:table:addSystemSite:TrialCode'
)
"
>
<el-input
v-model="addSystemSiteSearchData.TrialCode"
style="width: 100px"
/>
</el-form-item>
<el-form-item
:label="
$t(
'trial:dictionary:institutions:site:table:addSystemSite:TrialSiteName'
)
"
>
<el-input
v-model="addSystemSiteSearchData.TrialSiteName"
style="width: 100px"
/>
</el-form-item>
<el-form-item
:label="
$t(
'trial:dictionary:institutions:site:table:addSystemSite:TrialSiteAliasName'
)
"
>
<el-input
v-model="addSystemSiteSearchData.TrialSiteAliasName"
style="width: 100px"
/>
</el-form-item>
<el-form-item>
<el-button
type="primary"
icon="el-icon-search"
@click="getTrialSiteList"
>{{ $t("trial:dictionary:institutions:site:button:sreach") }}
</el-button>
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleResetAddSite"
>{{ $t("trial:dictionary:institutions:site:button:reset") }}
</el-button>
</el-form-item>
</el-form>
</div>
<el-table
v-loading="addSystemSiteLoading"
:data="addSystemSiteList"
stripe
height="300"
@sort-change="handleSortByColumnAddSite"
>
<el-table-column type="index" width="40" />
<el-table-column
prop="TrialCode"
:label="
$t(
'trial:dictionary:institutions:site:table:addSystemSite:TrialCode'
)
"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="TrialSiteName"
:label="
$t(
'trial:dictionary:institutions:site:table:addSystemSite:TrialSiteName'
)
"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="TrialSiteAliasName"
:label="
$t(
'trial:dictionary:institutions:site:table:addSystemSite:TrialSiteAliasName'
)
"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
:label="
$t(
'trial:dictionary:institutions:site:table:addSystemSite:Action'
)
"
fixed="right"
width="80"
>
<template slot-scope="scope">
<el-button
circle
type="text"
:title="$t('trial:dictionary:institutions:site:button:add')"
@click="addSystemSite(scope.row)"
>{{
$t("trial:dictionary:institutions:site:button:add")
}}</el-button
>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination
class="page"
style="float: right"
:total="addSystemSiteSearchDataTotal"
:page.sync="addSystemSiteSearchData.PageIndex"
:limit.sync="addSystemSiteSearchData.PageSize"
@pagination="getTrialSiteList"
/>
</template>
</base-model>
</box-content>
</template>
<script>
import {
getSiteList,
deleteSite,
addOrUpdateSite,
getTrialSiteList,
} from "@/api/dictionary";
import BaseModel from "@/components/BaseModel";
import BoxContent from "@/components/BoxContent";
import Pagination from "@/components/Pagination";
import SiteForm from "./SiteForm";
import { getSiteList, deleteSite } from '@/api/dictionary'
import BoxContent from '@/components/BoxContent'
import Pagination from '@/components/Pagination'
import SiteForm from './SiteForm'
const searchDataDefault = () => {
return {
SiteName: "",
PageIndex: 1,
PageSize: 20,
Asc: false,
SortField: "CreateTime",
AliasName: "",
Country: null,
City: null,
};
};
const searchSiteDataDefault = () => {
return {
// SiteName: "",
SiteName: '',
PageIndex: 1,
PageSize: 20,
Asc: true,
SortField: "",
TrialCode: null,
TrialSiteName: null,
TrialSiteAliasName: null,
};
};
SortField: '',
AliasName: '',
Country: null,
City: null
}
}
export default {
name: "Sites",
components: { BoxContent, Pagination, SiteForm, BaseModel },
name: 'Sites',
components: { BoxContent, Pagination, SiteForm },
data() {
return {
editVisible: false,
title: "Add",
title: 'Add',
searchData: searchDataDefault(),
list: [],
total: 0,
loading: false,
rowData: {},
addSystemSite_model: {
visible: false,
title: this.$t("trial:dictionary:institutions:site:addSystemSite"),
width: "800px",
appendToBody: true,
},
addSystemSiteLoading: false,
addSystemSiteList: [],
addSystemSiteSearchData: searchSiteDataDefault(),
addSystemSiteSearchDataTotal: 0,
};
rowData: {}
}
},
mounted() {
this.getList();
this.getTrialSiteList();
this.getList()
},
methods: {
//
async getTrialSiteList() {
try {
this.addSystemSiteLoading = true;
let res = await getTrialSiteList(this.addSystemSiteSearchData);
if (res.IsSuccess) {
this.addSystemSiteLoading = false;
this.addSystemSiteList = res.Result.CurrentPageData;
this.addSystemSiteSearchDataTotal = res.Result.TotalCount;
}
} catch (err) {
this.addSystemSiteLoading = false;
console.log(err);
}
},
//
async addSystemSite(item) {
try {
let data = {
SiteName: item.TrialSiteName,
SiteNameCN: item.TrialSiteName,
AliasName: item.TrialSiteAliasName,
SiteCode: item.TrialCode,
TrialSiteId: item.TrialSiteId,
};
this.addSystemSiteLoading = true;
let res = await addOrUpdateSite(data);
if (res.IsSuccess) {
this.getTrialSiteList();
this.getList();
}
} catch (err) {
this.addSystemSiteLoading = false;
console.log(err);
}
},
handleAddSystemSite() {
this.addSystemSite_model.visible = true;
this.addSystemSiteSearchData = searchSiteDataDefault();
this.addSystemSiteList = [];
this.addSystemSiteSearchDataTotal = 0;
this.getTrialSiteList();
},
// Site
getList() {
this.loading = true;
getSiteList(this.searchData)
.then((res) => {
this.loading = false;
this.list = res.Result.CurrentPageData;
this.total = res.Result.TotalCount;
})
.catch(() => {
this.loading = false;
});
this.loading = true
getSiteList(this.searchData).then(res => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}).catch(() => {
this.loading = false
})
},
// Site
handleAddSite() {
this.rowData = {};
this.title = "Add";
this.editVisible = true;
this.rowData = {}
this.title = 'Add'
this.editVisible = true
},
// Site
handleEdit(row) {
this.rowData = row;
this.title = "Edit";
this.editVisible = true;
this.rowData = row
this.title = 'Edit'
this.editVisible = true
},
// Site
handleDelete(row) {
this.$confirm(this.$t("trials:uploadedDicoms:message:deleteMes"), {
type: "warning",
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
}).then(() => {
this.loading = true;
deleteSite(row.Id)
.then((res) => {
this.loading = false;
if (res.IsSuccess) {
this.list.splice(
this.list.findIndex((item) => item.Id === row.Id),
1
);
this.$store.dispatch("global/setSite", {});
this.$message.success(
this.$t("common:message:deletedSuccessfully")
);
}
})
.catch(() => {
this.loading = false;
});
});
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
deleteSite(row.Id)
.then(res => {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$store.dispatch('global/setSite', {})
this.$message.success('Deleted successfully!')
}
}).catch(() => {
this.loading = false
})
})
},
//
handleReset() {
this.searchData = searchDataDefault();
this.getList();
},
handleResetAddSite() {
this.addSystemSiteSearchData = searchSiteDataDefault();
this.getTrialSiteList();
this.searchData = searchDataDefault()
this.getList()
},
//
handleSearch() {
this.searchData.PageIndex = 1;
this.getList();
this.searchData.PageIndex = 1
this.getList()
},
//
handleSortByColumn(column) {
if (column.order === "ascending") {
this.searchData.Asc = true;
if (column.order === 'ascending') {
this.searchData.Asc = true
} else {
this.searchData.Asc = false;
this.searchData.Asc = false
}
this.searchData.SortField = column.prop;
this.searchData.PageIndex = 1;
this.getList();
},
handleSortByColumnAddSite(column) {
if (column.order === "ascending") {
this.addSystemSiteSearchData.Asc = true;
} else {
this.addSystemSiteSearchData.Asc = false;
}
this.addSystemSiteSearchData.SortField = column.prop;
this.addSystemSiteSearchData.PageIndex = 1;
this.getTrialSiteList();
this.searchData.SortField = column.prop
this.searchData.PageIndex = 1
this.getList()
},
//
close() {
this.editVisible = false;
},
},
};
this.editVisible = false
}
}
}
</script>
<style lang="scss" scoped>
.Sites {
.Sites{
height: 100%;
}
</style>
@@ -1,4 +1,5 @@
<template>
<el-form
ref="sponsorForm"
:model="form"
@@ -14,109 +15,73 @@
<el-form-item label="Sponsor NameCN: " prop="SponsorName">
<el-input v-model="form.SponsorNameCN" />
</el-form-item>
<el-form-item label="Sponsor Code: " prop="SponsorCode">
<el-form-item label="Sponsor Code: " prop="SponsorName">
<el-input v-model="form.SponsorCode" />
</el-form-item>
<el-form-item label="Level: ">
<el-switch
:disabled="!IsTrialLevel"
v-model="form.IsTrialLevel"
:active-text="$fd('IsTrialLevel', 'true')"
:inactive-text="$fd('IsTrialLevel', 'false')"
>
</el-switch>
</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
:disabled="btnLoading"
size="small"
type="primary"
@click="handleCancel"
>Cancel</el-button
>
<el-button
size="small"
type="primary"
:loading="btnLoading"
@click="handleSave"
>Save</el-button
>
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancel">Cancel</el-button>
<el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">Save</el-button>
</el-form-item>
</div>
</el-form>
</template>
<script>
import { addOrUpdateSponsor } from "@/api/dictionary";
import { addOrUpdateSponsor } from '@/api/dictionary'
export default {
name: "SponsorForm",
name: 'SponsorForm',
props: {
data: {
type: Object,
default() {
return {};
},
},
IsTrialLevel: {
type: Boolean,
default: true,
},
return {}
}
}
},
data() {
return {
btnLoading: false,
form: {
Id: "",
SponsorName: "",
SponsorNameCN: "",
SponsorCode: "",
IsTrialLevel: true,
Id: '',
SponsorName: '',
SponsorNameCN: '',
SponsorCode: '',
},
rules: {
SponsorName: [
{ required: true, message: "Please specify", trigger: "blur" },
{ max: 500, message: "The maximum length is 500" },
],
SponsorNameCN: [
{ required: true, message: "Please specify", trigger: "blur" },
{ max: 500, message: "The maximum length is 500" },
],
SponsorCode: [
{ required: true, message: "Please specify", trigger: "blur" },
{ max: 50, message: "The maximum length is 50" },
],
},
};
SponsorName: [{ required: true, message: 'Please specify', trigger: 'blur' }, { max: 50, message: 'The maximum length is 50' }],
SponsorNameCN: [{ required: true, message: 'Please specify', trigger: 'blur' }, { max: 50, message: 'The maximum length is 50' }],
SponsorCode: [{ required: true, message: 'Please specify', trigger: 'blur' }, { max: 50, message: 'The maximum length is 50' }]
}
}
},
mounted() {
if (Object.keys(this.data).length && this.data.Id) {
this.form = { ...this.data };
this.form = { ...this.data }
}
},
methods: {
handleSave() {
this.$refs.sponsorForm.validate((valid) => {
if (!valid) return;
this.btnLoading = true;
addOrUpdateSponsor(this.form)
.then((res) => {
this.btnLoading = false;
if (res.IsSuccess) {
this.$message.success("Saved successfully");
this.$refs["sponsorForm"].resetFields();
this.$emit("getList");
this.$emit("close");
}
})
.catch(() => {
this.btnLoading = false;
});
});
this.$refs.sponsorForm.validate(valid => {
if (!valid) return
this.btnLoading = true
addOrUpdateSponsor(this.form).then(res => {
this.btnLoading = false
if (res.IsSuccess) {
this.$message.success('Saved successfully')
this.$refs['sponsorForm'].resetFields()
this.$emit('getList')
this.$emit('close')
}
}).catch(() => {
this.btnLoading = false
})
})
},
handleCancel() {
this.$emit("close");
},
},
};
this.$emit('close')
}
}
}
</script>
@@ -3,34 +3,26 @@
<div class="search">
<el-form :inline="true" size="small" class="base-search-form">
<el-form-item label="Sponsor Name:">
<el-input v-model="searchData.SponsorName" style="width: 100px" />
<el-input v-model="searchData.SponsorName" style="width:100px;" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleSearch"
>Search</el-button
>
<el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>Reset</el-button
>
<el-button type="primary" icon="el-icon-search" @click="handleSearch">Search</el-button>
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">Reset</el-button>
</el-form-item>
</el-form>
<span style="margin-left: auto">
<span style="margin-left:auto;">
<el-button
size="small"
type="primary"
style="margin-left: auto"
style="margin-left:auto;"
icon="el-icon-plus"
@click="handleAddSponsor"
>New</el-button
>
>New</el-button>
</span>
</div>
<el-table
v-loading="loading"
v-adaptive="{ bottomOffset: 60 }"
v-adaptive="{bottomOffset:60}"
:data="list"
stripe
height="100"
@@ -58,16 +50,6 @@
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="IsTrialLevel"
label="Level"
show-overflow-tooltip
sortable="custom"
>
<template slot-scope="scope">
<span>{{ $fd("IsTrialLevel", String(scope.row.IsTrialLevel)) }}</span>
</template>
</el-table-column>
<el-table-column label="Action" min-width="150">
<template slot-scope="scope">
<el-button
@@ -86,13 +68,7 @@
</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
v-if="editVisible"
@@ -102,32 +78,26 @@
width="600px"
custom-class="base-dialog-wrapper"
>
<sponsor-form
v-if="editVisible"
:IsTrialLevel="rowData.IsTrialLevel"
:data="rowData"
@close="close"
@getList="getList"
/>
<sponsor-form v-if="editVisible" :data="rowData" @close="close" @getList="getList" />
</el-dialog>
</box-content>
</template>
<script>
import { getSponsorPageList, deleteSponsor } from "@/api/dictionary";
import BoxContent from "@/components/BoxContent";
import Pagination from "@/components/Pagination";
import SponsorForm from "./SponsorForm";
import { getSponsorPageList, deleteSponsor } from '@/api/dictionary'
import BoxContent from '@/components/BoxContent'
import Pagination from '@/components/Pagination'
import SponsorForm from './SponsorForm'
const searchDataDefault = () => {
return {
SponsorName: "",
SponsorName: '',
PageIndex: 1,
PageSize: 20,
Asc: true,
SortField: "",
};
};
SortField: ''
}
}
export default {
name: "Sponsors",
name: 'Sponsors',
components: { BoxContent, Pagination, SponsorForm },
data() {
return {
@@ -137,93 +107,88 @@ export default {
loading: false,
rowData: {},
editVisible: false,
title: "",
};
title: ''
}
},
mounted() {
this.getList();
this.getList()
},
methods: {
// Sponsors
getList() {
this.loading = true;
getSponsorPageList(this.searchData)
.then((res) => {
this.loading = false;
this.list = res.Result.CurrentPageData;
this.total = res.Result.TotalCount;
})
.catch(() => {
this.loading = false;
});
this.loading = true
getSponsorPageList(this.searchData).then(res => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}).catch(() => {
this.loading = false
})
},
// Sponsor
handleAddSponsor() {
this.rowData = {};
this.title = "Add";
this.editVisible = true;
this.rowData = {}
this.title = 'Add'
this.editVisible = true
},
// Sponsor
handleEdit(row) {
this.rowData = row;
this.title = "Edit";
this.editVisible = true;
this.rowData = row
this.title = 'Edit'
this.editVisible = true
},
// Sponsor
handleDelete(row) {
this.$confirm(this.$t("trials:uploadedDicoms:message:deleteMes"), {
type: "warning",
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
}).then(() => {
this.loading = true;
deleteSponsor(row.Id)
.then((res) => {
this.loading = false;
if (res.IsSuccess) {
this.list.splice(
this.list.findIndex((item) => item.Id === row.Id),
1
);
this.$message.success(
this.$t("common:message:deletedSuccessfully")
);
}
})
.catch(() => {
this.loading = false;
});
});
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
deleteSponsor(row.Id)
.then(res => {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success('Deleted successfully!')
}
}).catch(() => {
this.loading = false
})
})
},
//
handleReset() {
this.searchData = searchDataDefault();
this.getList();
this.searchData = searchDataDefault()
this.getList()
},
//
handleSearch() {
this.searchData.PageIndex = 1;
this.getList();
this.searchData.PageIndex = 1
this.getList()
},
//
handleSortByColumn(column) {
if (column.order === "ascending") {
this.searchData.Asc = true;
if (column.order === 'ascending') {
this.searchData.Asc = true
} else {
this.searchData.Asc = false;
this.searchData.Asc = false
}
this.searchData.SortField = column.prop;
this.searchData.PageIndex = 1;
this.getList();
this.searchData.SortField = column.prop
this.searchData.PageIndex = 1
this.getList()
},
//
close() {
this.editVisible = false;
},
},
};
this.editVisible = false
}
}
}
</script>
<style lang="scss" scoped>
.sponsors {
.sponsors{
height: 100%;
}
</style>
@@ -182,10 +182,11 @@ export default {
})
},
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
@@ -194,7 +195,7 @@ export default {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
}).catch(() => { this.loading = false })
})
@@ -154,10 +154,11 @@ export default {
})
},
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
@@ -166,7 +167,7 @@ export default {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
}).catch(() => { this.loading = false })
})
@@ -183,10 +183,11 @@ export default {
})
},
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
@@ -195,7 +196,7 @@ export default {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
}).catch(() => { this.loading = false })
})
@@ -182,10 +182,11 @@ export default {
})
},
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
@@ -194,7 +195,7 @@ export default {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
}).catch(() => { this.loading = false })
})
@@ -153,10 +153,11 @@ export default {
})
},
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
@@ -165,7 +166,7 @@ export default {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
}).catch(() => { this.loading = false })
})
@@ -206,10 +206,11 @@ export default {
})
},
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
@@ -218,7 +219,7 @@ export default {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
}).catch(() => { this.loading = false })
})
@@ -183,10 +183,11 @@ export default {
})
},
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
@@ -195,7 +196,7 @@ export default {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
}).catch(() => { this.loading = false })
})
@@ -122,10 +122,11 @@ export default {
})
},
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
@@ -134,7 +135,7 @@ export default {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
}).catch(() => { this.loading = false })
})
+162 -161
View File
@@ -1,161 +1,162 @@
<template>
<box-content>
<!-- 搜索框 -->
<div class="search">
<span style="margin-left:auto;">
<el-button
type="primary"
size="mini"
@click="handleAdd"
>
Add
</el-button>
</span>
</div>
<!-- 受试者列表 -->
<el-table
v-loading="loading"
v-adaptive="{bottomOffset:45}"
:data="list"
stripe
height="100"
style="width:100%"
>
<el-table-column type="index" width="40" />
<el-table-column
prop="Code"
label="编号"
sortable="custom"
show-overflow-tooltip
/>
<el-table-column
prop="Name"
label="场景类型"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="Value"
label="签名内容(EN)"
show-overflow-tooltip
/>
<el-table-column
prop="ValueCN"
label="签名内容(CN)"
show-overflow-tooltip
/>
<el-table-column
prop="UpdateTime"
label="更新时间"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="CreateTime"
label="创建时间"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column label="Action" width="200" fixed="right">
<template slot-scope="scope">
<el-button
type="text"
@click="handleEdit(scope.row)"
>
Edit
</el-button>
<el-button type="text" @click="handleDelete(scope.row)">Delete</el-button>
</template>
</el-table-column>
</el-table>
<!-- 场景配置 -->
<el-dialog
v-if="editVisible"
:visible.sync="editVisible"
:close-on-click-modal="false"
:title="title"
width="700px"
append-to-body
custom-class="base-dialog-wrapper"
>
<SceneConfigForm :parent-id="parentId" :data="rowData" @closeDialog="closeDialog" @getList="getList" />
</el-dialog>
</box-content>
</template>
<script>
import { getChildList, deleteSystemBasicData } from '@/api/dictionary'
import BoxContent from '@/components/BoxContent'
import SceneConfigForm from './SceneConfigForm'
export default {
name: 'SignTemplate',
components: { BoxContent, SceneConfigForm },
props: {
parentId: {
type: String,
required: true
}
},
data() {
return {
loading: false,
list: [],
rowData: {},
title: '',
editVisible: false
}
},
mounted() {
this.getList()
},
methods: {
//
getList() {
this.loading = true
getChildList(this.parentId).then(res => {
this.loading = false
this.list = res.Result
}).catch(() => { this.loading = false })
},
//
handleAdd() {
this.rowData = {}
this.title = 'Add'
this.editVisible = true
},
//
handleEdit(row) {
this.rowData = { ...row }
this.title = 'Edit'
this.editVisible = true
},
//
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
type: 'warning',
distinguishCancelAndClose: true,
})
.then(() => {
deleteSystemBasicData(row.Id)
.then(res => {
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
}
})
})
},
//
closeDialog() {
this.editVisible = false
}
}
}
</script>
<template>
<box-content>
<!-- 搜索框 -->
<div class="search">
<span style="margin-left:auto;">
<el-button
type="primary"
size="mini"
@click="handleAdd"
>
Add
</el-button>
</span>
</div>
<!-- 受试者列表 -->
<el-table
v-loading="loading"
v-adaptive="{bottomOffset:45}"
:data="list"
stripe
height="100"
style="width:100%"
>
<el-table-column type="index" width="40" />
<el-table-column
prop="Code"
label="编号"
sortable="custom"
show-overflow-tooltip
/>
<el-table-column
prop="Name"
label="场景类型"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="Value"
label="签名内容(EN)"
show-overflow-tooltip
/>
<el-table-column
prop="ValueCN"
label="签名内容(CN)"
show-overflow-tooltip
/>
<el-table-column
prop="UpdateTime"
label="更新时间"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="CreateTime"
label="创建时间"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column label="Action" width="200" fixed="right">
<template slot-scope="scope">
<el-button
type="text"
@click="handleEdit(scope.row)"
>
Edit
</el-button>
<el-button type="text" @click="handleDelete(scope.row)">Delete</el-button>
</template>
</el-table-column>
</el-table>
<!-- 场景配置 -->
<el-dialog
v-if="editVisible"
:visible.sync="editVisible"
:close-on-click-modal="false"
:title="title"
width="700px"
append-to-body
custom-class="base-dialog-wrapper"
>
<SceneConfigForm :parent-id="parentId" :data="rowData" @closeDialog="closeDialog" @getList="getList" />
</el-dialog>
</box-content>
</template>
<script>
import { getChildList, deleteSystemBasicData } from '@/api/dictionary'
import BoxContent from '@/components/BoxContent'
import SceneConfigForm from './SceneConfigForm'
export default {
name: 'SignTemplate',
components: { BoxContent, SceneConfigForm },
props: {
parentId: {
type: String,
required: true
}
},
data() {
return {
loading: false,
list: [],
rowData: {},
title: '',
editVisible: false
}
},
mounted() {
this.getList()
},
methods: {
//
getList() {
this.loading = true
getChildList(this.parentId).then(res => {
this.loading = false
this.list = res.Result
}).catch(() => { this.loading = false })
},
//
handleAdd() {
this.rowData = {}
this.title = 'Add'
this.editVisible = true
},
//
handleEdit(row) {
this.rowData = { ...row }
this.title = 'Edit'
this.editVisible = true
},
//
handleDelete(row) {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
deleteSystemBasicData(row.Id)
.then(res => {
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success('Deleted successfully!')
}
})
})
},
//
closeDialog() {
this.editVisible = false
}
}
}
</script>
+229 -228
View File
@@ -1,228 +1,229 @@
<template>
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form-item label="编号:">
<el-input v-model="searchData.Code" style="width:100px;" />
</el-form-item>
<el-form-item label="模板:">
<el-input v-model="searchData.Name" style="width:100px;" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleReset">Reset</el-button>
<el-button type="primary" @click="handleSearch">Search</el-button>
</el-form-item>
</el-form>
<span style="margin-left:auto;">
<el-button
type="primary"
size="mini"
@click="handleAdd"
>
New
</el-button>
</span>
</div>
<!-- 受试者列表 -->
<el-table
v-loading="loading"
v-adaptive="{bottomOffset:45}"
:data="list"
stripe
height="100"
style="width:100%"
@sort-change="handleSortByColumn"
>
<el-table-column type="index" width="40" />
<el-table-column
prop="Code"
label="Code"
sortable="custom"
show-overflow-tooltip
/>
<el-table-column
prop="Name"
label="模板"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="Value"
label="签名内容(EN)"
show-overflow-tooltip
/>
<el-table-column
prop="ValueCN"
label="签名内容(CN)"
show-overflow-tooltip
/>
<el-table-column
prop="UpdateTime"
label="更新时间"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="CreateTime"
label="创建时间"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column label="Action" width="200" fixed="right">
<template slot-scope="scope">
<el-button
type="text"
@click="handleEdit(scope.row)"
>
Edit
</el-button>
<el-button
type="text"
@click="handleConfig(scope.row)"
>
场景配置
</el-button>
<el-button type="text" @click="handleDelete(scope.row)">Delete</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
<!-- 新增编辑 -->
<el-dialog
v-if="editVisible"
:visible.sync="editVisible"
:close-on-click-modal="false"
:title="title"
width="700px"
custom-class="base-dialog-wrapper"
>
<SignTemplateForm :data="rowData" @closeDialog="closeDialog" @getList="getList" />
</el-dialog>
<!-- 场景配置 -->
<el-dialog
v-if="configVisible"
:visible.sync="configVisible"
title="场景配置"
:fullscreen="true"
append-to-body
custom-class="base-dialog-wrapper"
>
<SceneList :parent-id="rowData.Id" @closeDialog="closeDialog" />
</el-dialog>
</box-content>
</template>
<script>
import { getSystemBasicDataList, deleteSystemBasicData } from '@/api/dictionary'
import BoxContent from '@/components/BoxContent'
import SignTemplateForm from './components/SignTemplateForm'
import SceneList from './components/SceneList'
import Pagination from '@/components/Pagination'
const searchDataDefault = () => {
return {
Code: '',
Name: '',
PageIndex: 1,
PageSize: 20
}
}
export default {
name: 'SignTemplate',
components: { BoxContent, SignTemplateForm, Pagination, SceneList },
data() {
return {
searchData: searchDataDefault(),
loading: false,
list: [],
total: 0,
rowData: {},
title: '',
editVisible: false,
configVisible: false
}
},
mounted() {
this.getList()
},
methods: {
//
getList() {
this.loading = true
getSystemBasicDataList(this.searchData).then(res => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}).catch(() => { this.loading = false })
},
//
handleAdd() {
this.rowData = {}
this.title = 'Add'
this.editVisible = true
},
//
handleEdit(row) {
this.rowData = { ...row }
this.title = 'Edit'
this.editVisible = true
},
//
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
type: 'warning',
distinguishCancelAndClose: true,
})
.then(() => {
deleteSystemBasicData(row.Id)
.then(res => {
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
}
})
})
},
//
handleConfig(row) {
this.rowData = { ...row }
this.configVisible = true
},
//
handleSearch() {
this.searchData.PageIndex = 1
this.getList()
},
//
handleReset() {
this.searchData = searchDataDefault()
this.getList()
},
//
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()
},
//
closeDialog() {
this.editVisible = false
}
}
}
</script>
<template>
<box-content>
<!-- 搜索框 -->
<div class="search">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form-item label="编号:">
<el-input v-model="searchData.Code" style="width:100px;" />
</el-form-item>
<el-form-item label="模板:">
<el-input v-model="searchData.Name" style="width:100px;" />
</el-form-item>
<el-form-item>
<el-button type="primary" @click="handleReset">Reset</el-button>
<el-button type="primary" @click="handleSearch">Search</el-button>
</el-form-item>
</el-form>
<span style="margin-left:auto;">
<el-button
type="primary"
size="mini"
@click="handleAdd"
>
New
</el-button>
</span>
</div>
<!-- 受试者列表 -->
<el-table
v-loading="loading"
v-adaptive="{bottomOffset:45}"
:data="list"
stripe
height="100"
style="width:100%"
@sort-change="handleSortByColumn"
>
<el-table-column type="index" width="40" />
<el-table-column
prop="Code"
label="Code"
sortable="custom"
show-overflow-tooltip
/>
<el-table-column
prop="Name"
label="模板"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="Value"
label="签名内容(EN)"
show-overflow-tooltip
/>
<el-table-column
prop="ValueCN"
label="签名内容(CN)"
show-overflow-tooltip
/>
<el-table-column
prop="UpdateTime"
label="更新时间"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column
prop="CreateTime"
label="创建时间"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column label="Action" width="200" fixed="right">
<template slot-scope="scope">
<el-button
type="text"
@click="handleEdit(scope.row)"
>
Edit
</el-button>
<el-button
type="text"
@click="handleConfig(scope.row)"
>
场景配置
</el-button>
<el-button type="text" @click="handleDelete(scope.row)">Delete</el-button>
</template>
</el-table-column>
</el-table>
<!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" @pagination="getList" />
<!-- 新增编辑 -->
<el-dialog
v-if="editVisible"
:visible.sync="editVisible"
:close-on-click-modal="false"
:title="title"
width="700px"
custom-class="base-dialog-wrapper"
>
<SignTemplateForm :data="rowData" @closeDialog="closeDialog" @getList="getList" />
</el-dialog>
<!-- 场景配置 -->
<el-dialog
v-if="configVisible"
:visible.sync="configVisible"
title="场景配置"
:fullscreen="true"
append-to-body
custom-class="base-dialog-wrapper"
>
<SceneList :parent-id="rowData.Id" @closeDialog="closeDialog" />
</el-dialog>
</box-content>
</template>
<script>
import { getSystemBasicDataList, deleteSystemBasicData } from '@/api/dictionary'
import BoxContent from '@/components/BoxContent'
import SignTemplateForm from './components/SignTemplateForm'
import SceneList from './components/SceneList'
import Pagination from '@/components/Pagination'
const searchDataDefault = () => {
return {
Code: '',
Name: '',
PageIndex: 1,
PageSize: 20
}
}
export default {
name: 'SignTemplate',
components: { BoxContent, SignTemplateForm, Pagination, SceneList },
data() {
return {
searchData: searchDataDefault(),
loading: false,
list: [],
total: 0,
rowData: {},
title: '',
editVisible: false,
configVisible: false
}
},
mounted() {
this.getList()
},
methods: {
//
getList() {
this.loading = true
getSystemBasicDataList(this.searchData).then(res => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}).catch(() => { this.loading = false })
},
//
handleAdd() {
this.rowData = {}
this.title = 'Add'
this.editVisible = true
},
//
handleEdit(row) {
this.rowData = { ...row }
this.title = 'Edit'
this.editVisible = true
},
//
handleDelete(row) {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
deleteSystemBasicData(row.Id)
.then(res => {
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success('Deleted successfully!')
}
})
})
},
//
handleConfig(row) {
this.rowData = { ...row }
this.configVisible = true
},
//
handleSearch() {
this.searchData.PageIndex = 1
this.getList()
},
//
handleReset() {
this.searchData = searchDataDefault()
this.getList()
},
//
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()
},
//
closeDialog() {
this.editVisible = false
}
}
}
</script>
@@ -162,10 +162,11 @@ export default {
})
},
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
@@ -174,7 +175,7 @@ export default {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
}).catch(() => { this.loading = false })
})
@@ -7,7 +7,6 @@
<el-button
size="mini"
type="primary"
:disabled="isCompleteConfig"
@click="handleAdd"
style="margin-right: 10px;"
>
@@ -60,13 +59,12 @@
show-overflow-tooltip
>
<template slot-scope="scope">
<el-button size="small" :disabled="isCompleteConfig" type="primary" @click="openChildren(scope.row)">
<el-button size="small" type="primary" @click="openChildren(scope.row)">
配置
</el-button>
<el-button
type="danger"
size="small"
:disabled="isCompleteConfig"
@click="handleDelete(scope.row)"
>
删除
@@ -153,10 +151,6 @@ export default {
criterionId: {
type: String,
required: true
},
isCompleteConfig: {
type: Boolean,
required: true
}
},
components: {
@@ -19,52 +19,6 @@
/>
</el-select>
</el-form-item>
<el-form-item
v-if="form.Type === 'group'"
label="分组名称"
prop="GroupName"
>
<el-input v-model="form.GroupName" />
</el-form-item>
<el-form-item
label="分组标识"
v-if="form.Type === 'group'"
prop="GroupClassify"
>
<el-select
v-model="form.GroupClassify"
clearable
>
<el-option
v-for="item of groupClassifyList"
:key="item.Id"
:value="parseInt(item.Code)"
:label="item.ValueCN"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="form.Type === 'group'"
label="分组名称(EN"
prop="GroupEnName"
>
<el-input v-model="form.GroupEnName" />
</el-form-item>
<el-form-item
v-if="form.Type !== 'group'"
label="问题名称"
prop="QuestionName"
>
<el-input v-model="form.QuestionName" />
</el-form-item>
<el-form-item
v-if="form.Type !== 'group'"
label="问题名称(EN"
prop="QuestionEnName"
>
<el-input v-model="form.QuestionEnName" />
</el-form-item>
<!-- 数值类型 -->
<el-form-item
v-if="form.Type === 'number' || form.Type === 'calculation'"
@@ -121,6 +75,52 @@
/>
</el-select>
</el-form-item>
<el-form-item
v-if="form.Type === 'group'"
label="分组名称"
prop="GroupName"
>
<el-input v-model="form.GroupName" />
</el-form-item>
<el-form-item
label="分组标识"
prop="GroupClassify"
>
<el-select
v-model="form.GroupClassify"
clearable
>
<el-option
v-for="item of groupClassifyList"
:key="item.Id"
:value="parseInt(item.Code)"
:label="item.ValueCN"
/>
</el-select>
</el-form-item>
<el-form-item
v-if="form.Type === 'group'"
label="分组名称(EN"
prop="GroupEnName"
>
<el-input v-model="form.GroupEnName" />
</el-form-item>
<el-form-item
v-if="form.Type !== 'group'"
label="问题名称"
prop="QuestionName"
>
<el-input v-model="form.QuestionName" />
</el-form-item>
<el-form-item
v-if="form.Type !== 'group'"
label="问题名称(EN"
prop="QuestionEnName"
>
<el-input v-model="form.QuestionEnName" />
</el-form-item>
<!-- <el-form-item
v-if="form.Type === 'select' || form.Type === 'radio'"
label="选项"
@@ -170,7 +170,7 @@
placeholder="选项请用‘|’分割多个选项"
/>
</el-form-item>
<el-form-item label="问题分类" v-if="form.Type !== 'group'">
<el-form-item label="问题分类">
<!-- <el-radio-group v-model="form.QuestionClassify">
<el-radio v-for="item of $d.QuestionClassify" :key="item.id" :label="item.value">{{ item.label }}</el-radio>
</el-radio-group> -->
@@ -406,7 +406,6 @@
</el-form-item>
<el-form-item
label="问题标识"
v-if="form.Type !== 'group'"
prop="QuestionType"
>
<el-select
@@ -1,7 +1,7 @@
<template>
<div class="criterion-config">
<el-tabs v-model="activeName">
<el-tab-pane :label="'访视阅片'" name="0">
<el-tab-pane label="访视阅片" name="0">
<div class="search-form" style="display:flex;justify-content: space-between;">
<el-form :inline="true" size="mini" class="base-search-form">
<el-form-item label="名称">
@@ -18,7 +18,7 @@
:disabled="list.length === 0"
size="mini"
type="primary"
@click="handlePreview"
@click="preview.visible = true"
>
预览
</el-button>
@@ -200,7 +200,7 @@
v-if="addOrEdit.visible"
:visible.sync="addOrEdit.visible"
:close-on-click-modal="false"
:title="`${addOrEdit.title}`"
:title="addOrEdit.title"
width="600px"
append-to-body
custom-class="base-dialog-wrapper"
@@ -303,9 +303,6 @@ export default {
this.getList()
},
methods: {
handlePreview() {
window.open(`/ecrfPreview?SystemReadingCriterionId=${this.criterionId}&lang=${this.$i18n.locale}`)
},
getList() {
this.loading = true
this.searchData.ReadingQuestionCriterionSystemId = this.criterionId
@@ -104,7 +104,6 @@
<el-button
type="danger"
size="mini"
:disabled="scope.row.IsCompleteConfig"
@click="handleDelete(scope.row)"
>
删除
@@ -134,7 +133,7 @@
<el-dialog
v-if="configVisible"
:title="'eCRF' + `(${rowData.CriterionName})`"
title="eCRF"
:visible.sync="configVisible"
:close-on-click-modal="false"
:fullscreen="true"
@@ -146,7 +145,7 @@
<el-dialog
v-if="configBaseDataVisible"
:title="'基础数据配置' + `(${rowData.CriterionName})`"
title="基础数据配置"
:visible.sync="configBaseDataVisible"
:close-on-click-modal="false"
:fullscreen="true"
@@ -191,7 +190,6 @@ export default {
addDialog: { title: '', visible: false }
}
},
mounted() {
this.getList()
},
@@ -137,10 +137,11 @@ export default {
})
},
handleDelete(row) {
this.$confirm(this.$t('trials:uploadedDicoms:message:deleteMes'), {
this.$confirm('Sure to delete?', {
type: 'warning',
distinguishCancelAndClose: true,
confirmButtonText: 'Ok',
cancelButtonText: 'Cancel'
})
.then(() => {
this.loading = true
@@ -149,7 +150,7 @@ export default {
this.loading = false
if (res.IsSuccess) {
this.list.splice(this.list.findIndex(item => item.Id === row.Id), 1)
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.$message.success('Deleted successfully!')
}
}).catch(() => { this.loading = false })
})
+109 -109
View File
@@ -1,109 +1,109 @@
<template>
<div v-loading="loading" style="min-height:400px;">
<el-form
v-if="isRender"
ref="questions"
size="small"
:model="questionForm"
>
<CriterionFormItem
v-for="question of questions"
:key="question.Id"
:question="question"
:question-form="questionForm"
:reading-task-state="readingTaskState"
:criterion-id="criterionId"
@resetFormItemData="resetFormItemData"
@setFormItemData="setFormItemData"
/>
</el-form>
</div>
</template>
<script>
import { getSystemReadingQuestion } from '@/api/dictionary'
import CriterionFormItem from './CriterionFormItem'
import {mapMutations} from "vuex";
export default {
name: 'EcrfPreview',
components: {
CriterionFormItem
},
data() {
return {
loading: false,
questions: [],
questionForm: {},
publicQuestions: [],
isRender: false,
readingTaskState: 0,
activeName: 0
}
},
mounted() {
this.$i18n.locale = this.$route.query.lang
this.setLanguage(this.$route.query.lang)
this.$updateDictionary()
this.criterionId = this.$route.query.SystemReadingCriterionId
this.getQuestions()
},
methods: {
...mapMutations({ setLanguage: 'lang/setLanguage' }),
getQuestions() {
this.loading = true
var param = {
id: this.criterionId
}
getSystemReadingQuestion(param).then(res => {
res.Result.SinglePage.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0) return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') {
this.$set(this.questionForm, v.Id, v.DefaultValue)
}
if (v.Childrens && v.Childrens.length > 0) {
this.setChild(v.Childrens)
}
})
this.questions = res.Result.SinglePage
this.isRender = true
this.loading = false
}).catch(() => { this.loading = false })
},
setChild(obj) {
obj.forEach(i => {
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id) {
this.$set(this.questionForm, i.Id, '')
}
if (i.Childrens && i.Childrens.length > 0) {
this.setChild(i.Childrens)
}
})
},
resetFormItemData(v) {
this.questionForm[v] = ''
},
setFormItemData(obj) {
this.$set(this.questionForm, obj.key, obj.val)
}
}
}
</script>
<style lang="scss" scoped>
::-webkit-scrollbar {
width: 7px;
height: 7px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
.tabContent{
height:300px;
overflow-y: auto;
}
</style>
<template>
<div v-loading="loading" style="min-height:400px;">
<el-form
v-if="isRender"
ref="questions"
size="small"
:model="questionForm"
>
<CriterionFormItem
v-for="question of questions"
:key="question.Id"
:question="question"
:question-form="questionForm"
:reading-task-state="readingTaskState"
:criterion-id="criterionId"
@resetFormItemData="resetFormItemData"
@setFormItemData="setFormItemData"
/>
</el-form>
</div>
</template>
<script>
import { getSystemReadingQuestion } from '@/api/dictionary'
import CriterionFormItem from './CriterionFormItem'
export default {
name: 'EcrfPreview',
components: {
CriterionFormItem
},
props: {
criterionId: {
type: String,
required: true
}
},
data() {
return {
loading: false,
questions: [],
questionForm: {},
publicQuestions: [],
isRender: false,
readingTaskState: 0,
activeName: 0
}
},
mounted() {
this.getQuestions()
},
methods: {
getQuestions() {
this.loading = true
var param = {
id: this.criterionId
}
getSystemReadingQuestion(param).then(res => {
res.Result.SinglePage.map((v) => {
if (v.Type === 'group' && v.Childrens.length === 0) return
if (!v.IsPage && v.Type !== 'group' && v.Type !== 'summary') {
this.$set(this.questionForm, v.Id, v.DefaultValue)
}
if (v.Childrens && v.Childrens.length > 0) {
this.setChild(v.Childrens)
}
})
this.questions = res.Result.SinglePage
this.isRender = true
this.loading = false
}).catch(() => { this.loading = false })
},
setChild(obj) {
obj.forEach(i => {
if (i.Type !== 'group' && i.Type !== 'summary' && i.Id) {
this.$set(this.questionForm, i.Id, '')
}
if (i.Childrens && i.Childrens.length > 0) {
this.setChild(i.Childrens)
}
})
},
resetFormItemData(v) {
this.questionForm[v] = ''
},
setFormItemData(obj) {
this.$set(this.questionForm, obj.key, obj.val)
}
}
}
</script>
<style lang="scss" scoped>
::-webkit-scrollbar {
width: 7px;
height: 7px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
.tabContent{
height:300px;
overflow-y: auto;
}
</style>
@@ -104,7 +104,7 @@
v-if="config.configType === 2"
v-loading="loading"
ref="multipleTable"
:data="GlobalAssessType"
:data="$d && $d.GlobalAssessType"
stripe
@selection-change="handleSelectionChange"
>
@@ -165,7 +165,7 @@
<script>
import BaseModel from '@/components/BaseModel'
import { getCriterionDictionary, getAssessType, setAssessType, setDictionaryBaseLineUse, setDictionaryFollowVisitUse, setSystemGlobalInfo, getSystemGlobalInfo } from '@/api/dictionary'
import { getAssessType, setAssessType, setDictionaryBaseLineUse, setDictionaryFollowVisitUse, setSystemGlobalInfo, getSystemGlobalInfo } from '@/api/dictionary'
export default {
props: {
data: {
@@ -192,8 +192,7 @@ export default {
IsMustGlobalReading: false,
form: {
IsMustGlobalReading: false
},
GlobalAssessType: []
}
}
},
beforecreate() {
@@ -205,17 +204,8 @@ export default {
mounted() {
this.getList()
this.getSystemGlobalInfo()
this.getCriterionDictionary()
},
methods: {
getCriterionDictionary() {
getCriterionDictionary({
ReadingCriterionId: this.criterionId,
DictionaryCode: 'GlobalAssessType'
}).then(res => {
this.GlobalAssessType = res.Result.GlobalAssessType
})
},
getSystemGlobalInfo() {
getSystemGlobalInfo({
SystemCriterionId: this.criterionId

Some files were not shown because too many files have changed in this diff Show More