Compare commits

..

No commits in common. "main" and "v1.12.2" have entirely different histories.

211 changed files with 12473 additions and 23700 deletions

View File

@ -20,7 +20,6 @@
"@cornerstonejs/core": "^2.19.7", "@cornerstonejs/core": "^2.19.7",
"@cornerstonejs/dicom-image-loader": "^2.19.7", "@cornerstonejs/dicom-image-loader": "^2.19.7",
"@cornerstonejs/tools": "^2.19.7", "@cornerstonejs/tools": "^2.19.7",
"@fingerprintjs/fingerprintjs": "^4.6.2",
"@icr/polyseg-wasm": "^0.4.0", "@icr/polyseg-wasm": "^0.4.0",
"@microsoft/signalr": "^8.0.7", "@microsoft/signalr": "^8.0.7",
"@riophae/vue-treeselect": "^0.4.0", "@riophae/vue-treeselect": "^0.4.0",

View File

@ -10,7 +10,7 @@
<meta http-equiv="Pragma" content="no-cache"> <meta http-equiv="Pragma" content="no-cache">
<meta http-equiv="Cache-control" content="no-store,no-cache,must-revalidate"> <meta http-equiv="Cache-control" content="no-store,no-cache,must-revalidate">
<meta http-equiv="Cache" content="no-cache"> <meta http-equiv="Cache" content="no-cache">
<title>EIC lmaging Trial Management System</title> <title>IRC Imaging System</title>
</head> </head>
<body> <body>

View File

@ -31,7 +31,7 @@
<div class="title-container" style="display: flex;padding-top:180px;justify-content: flex-start;height: 100%;box-sizing: border-box"> <div class="title-container" style="display: flex;padding-top:180px;justify-content: flex-start;height: 100%;box-sizing: border-box">
<!-- IRC Management System --> <!-- IRC Management System -->
<!-- <div class="title" style="text-align: center;font-size: 28px;margin-top: 100px;padding-right: 120px"></div>--> <!-- <div class="title" style="text-align: center;font-size: 28px;margin-top: 100px;padding-right: 120px"></div>-->
<!-- <div class="title" v-show="false">EIC lmaging Trial Management System</div>--> <!-- <div class="title" v-show="false">IRC Imaging System</div>-->
<div style="color: #0a84ff;text-align: left;font-size: 28px"> <div style="color: #0a84ff;text-align: left;font-size: 28px">
{{message}} {{message}}
</div> </div>
@ -63,7 +63,7 @@
<div style="margin: 0 auto;width: 600px;line-height: 28px;text-align: center" > <div style="margin: 0 auto;width: 600px;line-height: 28px;text-align: center" >
<h1 style="text-align: center;margin-bottom: 20px">关于</h1> <h1 style="text-align: center;margin-bottom: 20px">关于</h1>
<p style="margin-bottom: 20px"> <p style="margin-bottom: 20px">
EIC lmaging Trial Management System IRC Imaging System
</p> </p>
<p style="margin-bottom: 20px"> <p style="margin-bottom: 20px">
V1.3.0.001 V1.3.0.001

View File

@ -31,7 +31,7 @@
<div class="title-container" style="display: flex;padding-top:180px;justify-content: flex-start;height: 100%;box-sizing: border-box"> <div class="title-container" style="display: flex;padding-top:180px;justify-content: flex-start;height: 100%;box-sizing: border-box">
<!-- IRC Management System --> <!-- IRC Management System -->
<!-- <div class="title" style="text-align: center;font-size: 28px;margin-top: 100px;padding-right: 120px"></div>--> <!-- <div class="title" style="text-align: center;font-size: 28px;margin-top: 100px;padding-right: 120px"></div>-->
<!-- <div class="title" v-show="false">EIC lmaging Trial Management System</div>--> <!-- <div class="title" v-show="false">IRC Imaging System</div>-->
<div style="color: #0a84ff;text-align: left;font-size: 28px"> <div style="color: #0a84ff;text-align: left;font-size: 28px">
{{message}} {{message}}
</div> </div>

Binary file not shown.

View File

@ -1,7 +1,12 @@
<template> <template>
<div id="app" style="position: relative"> <div id="app" style="position: relative">
<router-view /> <router-view />
<div v-show="show" v-if="$route.matched.length > 0" v-adaptive @click="openI18n" style=" <div
v-show="show"
v-if="$route.matched.length > 0"
v-adaptive
@click="openI18n"
style="
position: fixed; position: fixed;
bottom: 50px; bottom: 50px;
left: 50px; left: 50px;
@ -14,27 +19,58 @@
color: #fff; color: #fff;
border-radius: 50%; border-radius: 50%;
cursor: pointer; cursor: pointer;
"> "
>
i18n i18n
</div> </div>
<el-drawer :title="$t('il8n:title')" :visible.sync="drawer" direction="rtl" size="80%"> <el-drawer
:title="$t('il8n:title')"
:visible.sync="drawer"
direction="rtl"
size="80%"
>
<div style="width: 800px"> <div style="width: 800px">
<el-form label-width="100px" @submit.native.prevent size="small" :inline="true" class="demo-form-inline"> <el-form
label-width="100px"
@submit.native.prevent
size="small"
:inline="true"
class="demo-form-inline"
>
<el-form-item :label="$t('il8n:search:keyword')"> <el-form-item :label="$t('il8n:search:keyword')">
<el-input v-model="key" @input="keyChange" /> <el-input v-model="key" @input="keyChange" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('il8n:search:state')"> <el-form-item :label="$t('il8n:search:state')">
<el-select v-model="State" clearable filterable @change="handleStateChange"> <el-select
<el-option v-for="item of $d.InternationalizationKeyState" v-model="State"
:key="'InternationalizationKeyState' + item.value" :label="item.label" :value="item.value" /> clearable
filterable
@change="handleStateChange"
>
<el-option
v-for="item of $d.InternationalizationKeyState"
:key="'InternationalizationKeyState' + item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-form> </el-form>
</div> </div>
<el-table :data="tableData" v-adaptive="{ bottomOffset: 50 }" height="100" style="width: 100%" <el-table
@sort-change="handleSortByColumn"> :data="tableData"
<el-table-column prop="Code" :label="$t('il8n:table:label')" width="300" show-overflow-tooltip v-adaptive="{ bottomOffset: 50 }"
sortable="custom"> height="100"
style="width: 100%"
@sort-change="handleSortByColumn"
>
<el-table-column
prop="Code"
:label="$t('il8n:table:label')"
width="300"
show-overflow-tooltip
sortable="custom"
>
</el-table-column> </el-table-column>
<!-- <el-table-column--> <!-- <el-table-column-->
<!-- prop="Description"--> <!-- prop="Description"-->
@ -45,37 +81,71 @@
<!-- {{scope.row.Description}}--> <!-- {{scope.row.Description}}-->
<!-- </template>--> <!-- </template>-->
<!-- </el-table-column>--> <!-- </el-table-column>-->
<el-table-column prop="Value" :label="$t('il8n:table:en')" sortable="custom"> <el-table-column
prop="Value"
:label="$t('il8n:table:en')"
sortable="custom"
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-input v-model="scope.row.Value" @input=" <el-input
v-model="scope.row.Value"
@input="
(e) => { (e) => {
$set(scope.row, 'Value', e) $set(scope.row, 'Value', e)
} }
" size="mini"></el-input> "
size="mini"
></el-input>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="ValueCN" :label="$t('il8n:table:cn')" sortable="custom"> <el-table-column
prop="ValueCN"
:label="$t('il8n:table:cn')"
sortable="custom"
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-input v-model="scope.row.ValueCN" @input=" <el-input
v-model="scope.row.ValueCN"
@input="
(e) => { (e) => {
$set(scope.row, 'ValueCN', e) $set(scope.row, 'ValueCN', e)
} }
" size="mini"></el-input> "
size="mini"
></el-input>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="ValueCN" :label="$t('il8n:table:state')" sortable="custom"> <el-table-column
prop="ValueCN"
:label="$t('il8n:table:state')"
sortable="custom"
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-select v-model="scope.row.State" clearable filterable size="mini"> <el-select
<el-option v-for="item of $d.InternationalizationKeyState" v-model="scope.row.State"
:key="'InternationalizationKeyState' + item.value" :label="item.label" :value="item.value" /> clearable
filterable
size="mini"
>
<el-option
v-for="item of $d.InternationalizationKeyState"
:key="'InternationalizationKeyState' + item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column prop="Version" :label="$t('il8n:table:Version')" sortable="custom"> <el-table-column
prop="Version"
:label="$t('il8n:table:Version')"
sortable="custom"
>
</el-table-column> </el-table-column>
</el-table> </el-table>
<div style="text-align: right; padding-top: 10px; padding-right: 10px"> <div style="text-align: right; padding-top: 10px; padding-right: 10px">
<el-button size="mini" @click="drawer = false">{{ $t('common:button:cancel') }} <el-button size="mini" @click="drawer = false"
>{{ $t('common:button:cancel') }}
</el-button> </el-button>
<el-button size="mini" type="primary" @click="handleSave">{{ <el-button size="mini" type="primary" @click="handleSave">{{
$t('common:button:save') $t('common:button:save')
@ -83,7 +153,6 @@
</div> </div>
</el-drawer> </el-drawer>
<feedBack v-if="$route.matched.length > 0" /> <feedBack v-if="$route.matched.length > 0" />
<timeTag />
</div> </div>
</template> </template>
@ -94,12 +163,11 @@ import {
} from '@/api/dictionary/dictionary' } from '@/api/dictionary/dictionary'
import { getTrialExtralConfig } from '@/api/trials' import { getTrialExtralConfig } from '@/api/trials'
import feedBack from '@/views/trials/trials-layout/components/feedBack' import feedBack from '@/views/trials/trials-layout/components/feedBack'
import timeTag from '@/components/timeTag'
import Vue from 'vue' import Vue from 'vue'
import i18n from './lang' import i18n from './lang'
export default { export default {
name: 'App', name: 'App',
components: { feedBack, timeTag }, components: { feedBack },
data() { data() {
return { return {
drawer: false, drawer: false,
@ -112,8 +180,7 @@ export default {
} }
}, },
mounted() { mounted() {
// this.show = process.env.VUE_APP_OSS_PATH === '/test/dist' this.show = process.env.VUE_APP_OSS_PATH === '/test/dist'
this.show = false
Vue.prototype.$openI18n = this.openI18n Vue.prototype.$openI18n = this.openI18n
}, },
// watch: { // watch: {
@ -299,16 +366,13 @@ export default {
<style lang="scss"> <style lang="scss">
$light_gray: #606266; $light_gray: #606266;
.el-tooltip__popper { .el-tooltip__popper {
max-width: 400px; max-width: 400px;
} }
.my_multiple { .my_multiple {
.el-input--medium .el-input__inner { .el-input--medium .el-input__inner {
height: 36px !important; height: 36px !important;
} }
.el-select__tags { .el-select__tags {
flex-wrap: nowrap; flex-wrap: nowrap;
overflow: hidden; overflow: hidden;
@ -317,7 +381,6 @@ $light_gray: #606266;
display: block; display: block;
} }
} }
input::-webkit-outer-spin-button, input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button { input::-webkit-inner-spin-button {
-webkit-appearance: none !important; -webkit-appearance: none !important;
@ -330,7 +393,6 @@ input[type='number'] {
.viewer-fixed.viewer-container { .viewer-fixed.viewer-container {
z-index: 10000; z-index: 10000;
} }
textarea { textarea {
white-space: break-spaces; white-space: break-spaces;
word-break: normal; word-break: normal;
@ -339,15 +401,12 @@ textarea {
* { * {
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; 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; color: #fff;
} }
.system-title { .system-title {
font-size: 35px; font-size: 35px;
color: $light_gray; color: $light_gray;
@ -356,11 +415,9 @@ textarea {
font-family: 'Times New Roman'; font-family: 'Times New Roman';
text-shadow: 1px 0.5px 1.5px #666; text-shadow: 1px 0.5px 1.5px #666;
} }
.title-logo { .title-logo {
height: 40px; height: 40px;
} }
.title-logo { .title-logo {
height: 40px; height: 40px;
} }

View File

@ -350,43 +350,3 @@ export function getUserJoinedTrialList(data) {
data data
}) })
} }
// 邮件日志-日志列表
export function getEmailLogList(data) {
return request({
url: `/EmailLog/getEmailLogList`,
method: 'post',
data
})
}
// 邮件日志-日志详情
export function getEmailInfo(data) {
return request({
url: `/EmailLog/getEmailInfo`,
method: 'post',
data
})
}
// 邮件日志-重发邮件
export function resendEmail(data) {
return request({
url: `/EmailLog/resendEmail`,
method: 'post',
data
})
}
// 邮件日志-同步邮件
export function synchronizationEmail(data) {
return request({
url: `/EmailLog/synchronizationEmail`,
method: 'post',
data
})
}
// 邮件日志-重发列表
export function getReSendEmail(data) {
return request({
url: `/EmailLog/getReSendEmail`,
method: 'post',
data
})
}

View File

@ -1403,74 +1403,3 @@ export function batchUpdateEmail(data) {
data data
}) })
} }
// 隐私政策和用户协议-获取列表
export function getUserAgreementList(data) {
return request({
url: `/UserAgreement/getUserAgreementList`,
method: 'post',
data
})
}
// 隐私政策和用户协议-设置当前版本
export function setCurrentVersion(data) {
return request({
url: `/UserAgreement/setCurrentVersion`,
method: 'post',
data
})
}
// 隐私政策和用户协议-新增或修改
export function addOrUpdateUserAgreement(data) {
return request({
url: `/UserAgreement/addOrUpdateUserAgreement`,
method: 'post',
data
})
}
// 隐私政策和用户协议-删除
export function deleteUserAgreement(id) {
return request({
url: `/UserAgreement/deleteUserAgreement/${id}`,
method: 'delete',
})
}
// 隐私政策和用户协议-详情
export function getUserAgreementById(data) {
return request({
url: `/UserAgreement/getUserAgreementById`,
method: 'post',
data
})
}
// 隐私政策和用户协议-当前版本
export function getCurrentVersionUserAgreements(data) {
return request({
url: `/UserAgreement/getCurrentVersionUserAgreements`,
method: 'post',
data
})
}
// 获取系统阅片关键点文件列表
export function getSystemCriterionKeyFileList(data) {
return request({
url: `/SystemCriterionKeyFile/getSystemCriterionKeyFileList`,
method: 'post',
data
})
}
// 新增/修改系统阅片关键点文件
export function addOrUpdateSystemCriterionKeyFile(data) {
return request({
url: `/SystemCriterionKeyFile/addOrUpdateSystemCriterionKeyFile`,
method: 'post',
data
})
}
// 删除系统阅片关键点文件
export function deleteSystemCriterionKeyFile(systemCriterionKeyFileId) {
return request({
url: `/SystemCriterionKeyFile/deleteSystemCriterionKeyFile/${systemCriterionKeyFileId}`,
method: 'delete'
})
}

View File

@ -239,7 +239,7 @@ export function getPatientList_Export(data) {
data data
}) })
} }
export function getTumor_CDISC_IVUSOCT_Export(data) { export function getTumor_CDISC_Export(data) {
return requestDownload({ return requestDownload({
url: `/IVUS_OCTExport/getTumor_CDISC_Export`, url: `/IVUS_OCTExport/getTumor_CDISC_Export`,
responseType: 'blob', responseType: 'blob',
@ -263,14 +263,6 @@ export function getCommonJudgeRatioList_Export(data) {
data data
}) })
} }
export function getTumor_CDISC_Export(data) {
return requestDownload({
url: `/Tumor_CDISC_Export/getTumor_CDISC_Export`,
responseType: 'blob',
method: 'post',
data
})
}
// 导出国际化列表 // 导出国际化列表
export function GetInternationalizationList_Export(data) { export function GetInternationalizationList_Export(data) {
return requestDownload({ return requestDownload({

View File

@ -295,22 +295,6 @@ export function readingImport(param) {
}) })
} }
// 非dicom阅片保存标记
export function saveAnswerAndBindingNoneDicomMark(param) {
return request({
url: `/ReadingImageTask/saveAnswerAndBindingNoneDicomMark`,
method: 'post',
data: param
})
}
// 非dicom按比例修改答案
export function changePlottingScaleChangeAnswer(param) {
return request({
url: `/ReadingImageTask/changePlottingScaleChangeAnswer`,
method: 'post',
data: param
})
}
// 阅片获取图表数据 // 阅片获取图表数据
export function getReportsChartData(param) { export function getReportsChartData(param) {
return request({ return request({

View File

@ -26,11 +26,8 @@ export function getTrialSurveyInitInfo(trialId) {
export function getSiteSurveyInfo(trialId, id) { export function getSiteSurveyInfo(trialId, id) {
return request({ return request({
url: `/TrialSiteSurvey/getSiteSurveyInfo/${trialId}`, url: `/TrialSiteSurvey/getSiteSurveyInfo/${trialId}/${id}`,
method: 'get', method: 'get'
params: {
TrialsiteSurveyId: id
}
}) })
} }

View File

@ -1203,13 +1203,7 @@ export function getConsistencyVerificationList(param) {
data: param data: param
}) })
} }
export function getConsistencyCheckFileList(param) {
return request({
url: `/QCList/getConsistencyCheckFileList`,
method: 'post',
data: param
})
}
export function getCheckChallengeDialogList(subjectVisitId) { export function getCheckChallengeDialogList(subjectVisitId) {
return request({ return request({
url: `/QCList/getCheckChallengeDialogList/${subjectVisitId}`, url: `/QCList/getCheckChallengeDialogList/${subjectVisitId}`,
@ -1262,11 +1256,11 @@ export function getCRCVisitChallengeAndDialog(subjectVisitId, trialQCProcess) {
}) })
} }
export function uploadVisitCheckExcel(trialId, file, isFullCheck = false) { export function uploadVisitCheckExcel(trialId, file) {
const formData = new FormData() const formData = new FormData()
formData.append('file', file) formData.append('file', file)
return request({ return request({
url: `/QCOperation/UploadVisitCheckExcel/${trialId}?isFullCheck=${isFullCheck}`, url: `/QCOperation/UploadVisitCheckExcel/${trialId}`,
method: 'post', method: 'post',
data: formData data: formData
}) })
@ -2839,13 +2833,7 @@ export function getSplitPPdSum(param) {
data: param data: param
}) })
} }
export function getSplitPPdSumNoPet(param) {
return request({
url: `/LuganoWithoutPETCalculate/getSplitPPdSum`,
method: 'post',
data: param
})
}
export function submitDicomVisitTask(param) { export function submitDicomVisitTask(param) {
return request({ return request({
url: `/Inspection/ReadingImageTask/SubmitDicomVisitTask`, url: `/Inspection/ReadingImageTask/SubmitDicomVisitTask`,
@ -2884,13 +2872,7 @@ export function getIsSuvMaxLesion(param) {
data: param data: param
}) })
} }
export function getIsSuvMaxLesionNoPet(param) {
return request({
url: `/LuganoWithoutPETCalculate/getIsSuvMaxLesion`,
method: 'post',
data: param
})
}
export function getCanChooseNotMerge(param) { export function getCanChooseNotMerge(param) {
return request({ return request({
url: `/LuganoCalculate/getCanChooseNotMerge`, url: `/LuganoCalculate/getCanChooseNotMerge`,
@ -2898,13 +2880,6 @@ export function getCanChooseNotMerge(param) {
data: param data: param
}) })
} }
export function getCanChooseNotMergeNoPet(param) {
return request({
url: `/LuganoWithoutPETCalculate/getCanChooseNotMerge`,
method: 'post',
data: param
})
}
export function saveTaskQuestion(saveQuestionType, param) { export function saveTaskQuestion(saveQuestionType, param) {
return request({ return request({
url: `/SaveTaskQuestion/${saveQuestionType}`, url: `/SaveTaskQuestion/${saveQuestionType}`,
@ -3628,24 +3603,13 @@ export function getSplenicState(visitTaskId, spleenLength) {
method: 'post' method: 'post'
}) })
} }
export function getSplenicStateNoPet(visitTaskId, spleenLength) {
return request({
url: `/LuganoWithoutPETCalculate/getSplenicState?visitTaskId=${visitTaskId}&spleenLength=${spleenLength}`,
method: 'post'
})
}
export function getSplenicVerify(visitTaskId) { export function getSplenicVerify(visitTaskId) {
return request({ return request({
url: `/LuganoCalculate/getSplenicVerify?visitTaskId=${visitTaskId}`, url: `/LuganoCalculate/getSplenicVerify?visitTaskId=${visitTaskId}`,
method: 'post' method: 'post'
}) })
} }
export function getSplenicVerifyNoPet(visitTaskId) {
return request({
url: `/LuganoWithoutPETCalculate/getSplenicVerify?visitTaskId=${visitTaskId}`,
method: 'post'
})
}
export function uploadTrialSiteSurveyUser(trialId, baseUrl, routeUrl, param) { export function uploadTrialSiteSurveyUser(trialId, baseUrl, routeUrl, param) {
return request({ return request({
url: `/TrialSiteSurvey/UploadTrialSiteSurveyUser?trialId=${trialId}&baseUrl=${baseUrl}&routeUrl=${routeUrl}`, url: `/TrialSiteSurvey/UploadTrialSiteSurveyUser?trialId=${trialId}&baseUrl=${baseUrl}&routeUrl=${routeUrl}`,
@ -4318,103 +4282,7 @@ export function deleteAuditRecord(auditRecordId) {
method: 'delete' method: 'delete'
}) })
} }
// 核对中心人员发送邮件
export function sendCheckSiteSurveyUserEmail(data) {
return request({
url: `/TrialSiteSurvey/sendCheckSiteSurveyUserEmail`,
method: 'post',
data
})
}
// 更新中心人员发送邮件
export function sendUpdateSiteSurveyUserEmail(data) {
return request({
url: `/TrialSiteSurvey/sendUpdateSiteSurveyUserEmail`,
method: 'post',
data
})
}
// 更新中心人员发送邮件
export function getTrialSiteLatestSurvey(params) {
return request({
url: `/TrialSiteSurvey/getTrialSiteLatestSurvey`,
method: 'get',
params
})
}
// 阅片期计划列表
export function getReadModulePageList(data) {
return request({
url: `/ReadModule/getReadModulePageList`,
method: 'post',
data
})
}
// 移除阅片期
export function setBatchRemoveReadingPlan(data) {
return request({
url: `/ReadingPeriodSet/setBatchRemoveReadingPlan`,
method: 'post',
data
})
}
// 更新项目额外json配置
export function updateTrialExtralConfig(params, data) {
return request({
url: `/TrialConfig/updateTrialExtralConfig`,
method: 'put',
params,
data
})
}
// 获取项目标准阅片关键点列表
export function getTrialCriterionKeyFileList(data) {
return request({
url: `/TrialCriterionKeyFile/getTrialCriterionKeyFileList`,
method: 'post',
data
})
}
// 设置已阅读关键文件
export function setReadKeyFile(data) {
return request({
url: `/ReadingImageTask/setReadKeyFile`,
method: 'post',
data
})
}
// 项目报表-访视完成度
export function getTrialVisitFinishedStatList(data) {
return request({
url: `/TrialStat/getTrialVisitFinishedStatList`,
method: 'post',
data
})
}
// 项目报表-质疑统计表
export function getTrialQuestionStatList(data) {
return request({
url: `/TrialStat/getTrialQuestionStatList`,
method: 'post',
data
})
}
// 项目报表-疗效统计表
export function getTrialEfficacyEvaluationStatList(data) {
return request({
url: `/TrialStat/getTrialEfficacyEvaluationStatList`,
method: 'post',
data
})
}
// 受试者图表
export function getReportsChartSummary(data) {
return request({
url: `/ReadingImageTask/getReportsChartSummary`,
method: 'post',
data
})
}
// 靶段标注列表 // 靶段标注列表
export function getTrialSubjectVisitMarkList(data) { export function getTrialSubjectVisitMarkList(data) {
return request({ return request({
@ -4423,11 +4291,3 @@ export function getTrialSubjectVisitMarkList(data) {
data data
}) })
} }
// 更新缩略图
export function updateImageResizePath(data) {
return request({
url: `/Series/updateImageResizePath`,
method: 'post',
data
})
}

View File

@ -1,37 +0,0 @@
import Vue from "vue";
import AGRCOMP from "./index.vue";
const MFAConstructor = Vue.extend(AGRCOMP);
let MFAINSTANCELIST = [];
const AGR = options => {
const { Id, IsEn_Us, callBack, cancelBack } = options;
if (!Id) throw `Id is requred.but ${Id}`
const id = `AGR${new Date().getTime()}`;
const instance = new MFAConstructor();
MFAINSTANCELIST.push(instance)
instance.id = id;
instance.vm = instance.$mount();
if (instance.vm.visible) return;
document.body.appendChild(instance.vm.$el);
instance.vm.open({ Id, IsEn_Us });
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();
let index = MFAINSTANCELIST.findIndex(item => item.id === id);
MFAINSTANCELIST.splice(index, 1)
});
return instance.vm;
}
AGR.close = () => {
if (MFAINSTANCELIST.length <= 0) return;
MFAINSTANCELIST.forEach(item => {
document.body.removeChild(item.vm.$el);
item.vm.$destroy();
})
MFAINSTANCELIST = [];
}
export default AGR;

View File

@ -1,7 +0,0 @@
import AGRCOMP from "./index.vue";
import AGR from "./fun";
export default Vue => {
Vue.component(AGRCOMP.name, AGRCOMP);
Vue.prototype.$AGR = AGR;
};

View File

@ -1,65 +0,0 @@
<template>
<!--AGR-->
<el-dialog v-if="visible" :visible.sync="visible" width="60%" :close-on-click-modal="false" append-to-body center
:show-close="true" @close="cancel">
<!-- <div slot="title">
{{ agreement.FileName }}
</div> -->
<div v-html="agreement.FileEnContent" class="content" v-if="IsEn_Us"></div>
<div v-html="agreement.FileContent" class="content" v-else></div>
</el-dialog>
</template>
<script>
import {
getUserAgreementById
} from '@/api/dictionary'
export default {
name: "AGR",
data() {
return {
visible: false,
agreement: {},
IsEn_Us: false
}
},
mounted() {
},
methods: {
async getAgreement(Id) {
try {
let data = {
Id
}
let res = await getUserAgreementById(data)
if (res.IsSuccess) {
this.agreement = res.Result
}
} catch (err) {
console.log(err)
}
},
open(data) {
let { Id, IsEn_Us } = data;
this.IsEn_Us = IsEn_Us
this.getAgreement(Id)
this.visible = true
},
cancel() {
this.visible = false;
this.$emit("closed");
},
},
};
</script>
<style lang="scss" scoped>
::v-deep .el-dialog__body {
height: 500px;
}
.content {
height: 100%;
overflow-y: auto;
}
</style>

View File

@ -2,17 +2,9 @@
<el-breadcrumb class="app-breadcrumb" separator-class="el-icon-arrow-right"> <el-breadcrumb class="app-breadcrumb" separator-class="el-icon-arrow-right">
<transition-group name="breadcrumb"> <transition-group name="breadcrumb">
<el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path"> <el-breadcrumb-item v-for="(item,index) in levelList" :key="item.path">
<span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect"> <span v-if="item.redirect==='noRedirect'||index==levelList.length-1" class="no-redirect">{{ item.meta.title }}</span>
<!-- {{ item.meta.title }} --> <span v-else-if="item.name === 'TrialsPanel'" class="no-redirect">{{ item.meta.title }}</span>
{{ item.meta.i18n ? $t(item.meta.i18n) : item.meta.title }} <a v-else @click.prevent="handleLink(item)">{{ item.meta.title }}</a>
</span>
<span v-else-if="item.name === 'TrialsPanel'" class="no-redirect">
<!-- {{ item.meta.title }} -->
{{ item.meta.i18n ? $t(item.meta.i18n) : item.meta.title }}
</span>
<a v-else @click.prevent="handleLink(item)">
{{ item.meta.i18n ? $t(item.meta.i18n) : item.meta.title }}
</a>
</el-breadcrumb-item> </el-breadcrumb-item>
</transition-group> </transition-group>
</el-breadcrumb> </el-breadcrumb>
@ -43,7 +35,6 @@ export default {
item.meta.title = this.$route.query.trialCode // item.meta.title = this.$route.query.trialCode //
} }
}) })
this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false) this.levelList = matched.filter(item => item.meta && item.meta.title && item.meta.breadcrumb !== false)
}, },
isDashboard(route) { isDashboard(route) {

View File

@ -1,11 +1,25 @@
<template> <template>
<!--MFA--> <!--MFA-->
<el-dialog v-if="visible" :visible.sync="visible" width="540px" :close-on-click-modal="false" append-to-body center <el-dialog
:show-close="status === 'login'" @close="cancel"> 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"> <div slot="title">
{{ status === "login" ? $t("mfa:title") : $t("mfa:lock:title") }} {{ status === "login" ? $t("mfa:title") : $t("mfa:lock:title") }}
</div> </div>
<el-form ref="mfaForm" label-position="right" :model="form" :rules="rules" label-width="100px"> <el-form
ref="mfaForm"
label-position="right"
:model="form"
:rules="rules"
label-width="100px"
>
<!-- 邮箱 --> <!-- 邮箱 -->
<p class="tip_mfa"> <p class="tip_mfa">
<i class="el-icon-warning" style="color: #409eff"></i> <i class="el-icon-warning" style="color: #409eff"></i>
@ -17,13 +31,18 @@
</el-form-item> </el-form-item>
<!-- 验证码 --> <!-- 验证码 -->
<el-form-item :label="$t('mfa:form:MFACode')" prop="Code"> <el-form-item :label="$t('mfa:form:MFACode')" prop="Code">
<div style="display: flex;justify-content: space-between;width: 90%;"> <el-input
<el-input :placeholder="$t('mfa:form:input:placeholder:Codes')" v-model="form.Code" /> :placeholder="$t('mfa:form:input:placeholder:Codes')"
<el-button size="small" @click.stop="sendMFACode" :disabled="flag || sendFlag" style="margin-left: 10px;" v-model="form.Code"
class="codeBtn">{{ style="width: 240px; margin-right: 10px"
flag ? />
`${$t("mfa:form:sendMFACodeCountDown")} (${second}s)` : $t("mfa:form:sendMFACode") }}</el-button> <el-button
</div> type="primary"
size="small"
@click.stop="sendMFACode"
:disabled="flag || sendFlag"
>{{ flag ? `${second}s` : $t("mfa:form:sendMFACode") }}</el-button
>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div slot="footer"> <div slot="footer">
@ -32,16 +51,19 @@
{{ $t("mfa:button:cancel") }} {{ $t("mfa:button:cancel") }}
</el-button> --> </el-button> -->
<!-- 保存 --> <!-- 保存 -->
<el-button type="primary" size="small" @click="save" :loading="loading" style="width: 80%"> <el-button
type="primary"
size="small"
@click="save"
:loading="loading"
style="width: 80%"
>
{{ {{
status === "login" status === "login"
? $t("mfa:button:save") ? $t("mfa:button:save")
: $t("mfa:lock:button:save") : $t("mfa:lock:button:save")
}} }}
</el-button> </el-button>
<p style="text-align: left;font-size: 14px;margin:10px auto;width: 80%;">
<el-checkbox v-model="form.isRemember" /><span style="margin-left: 10px;">{{ $t("mfa:tip:noLogin") }}</span>
</p>
</div> </div>
</el-dialog> </el-dialog>
</template> </template>
@ -64,7 +86,6 @@ export default {
IdentityUserId: null, IdentityUserId: null,
EMail: null, EMail: null,
username: null, username: null,
isRemember: true
}, },
rules: { rules: {
Code: [ Code: [
@ -91,18 +112,6 @@ export default {
}, },
}; };
}, },
mounted() {
this.flag = true;
this.second = 60;
this.timer = setInterval(() => {
this.second--;
if (this.second <= 0) {
this.flag = false;
clearInterval(this.timer);
this.timer = null;
}
}, 1000);
},
methods: { methods: {
open(data) { open(data) {
let { UserId, status, username, EMail } = data; let { UserId, status, username, EMail } = data;
@ -180,21 +189,6 @@ export default {
}; };
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.codeBtn {
color: #409EFF;
border-color: #409EFF;
}
.codeBtn.is-disabled,
.codeBtn.is-disabled:focus,
.codeBtn.is-disabled:hover {
color: #c0c4cc;
cursor: not-allowed;
background-image: none;
background-color: #fff;
border-color: #ebeef5;
}
.tip_mfa { .tip_mfa {
width: 86%; width: 86%;
margin: auto; margin: auto;
@ -204,12 +198,10 @@ export default {
line-height: 30px; line-height: 30px;
border-radius: 5px; border-radius: 5px;
background-color: #eee; background-color: #eee;
i { i {
margin-right: 5px; margin-right: 5px;
} }
} }
::v-deep .el-dialog__header { ::v-deep .el-dialog__header {
font-weight: bold; font-weight: bold;
} }

View File

@ -54,7 +54,7 @@ export default {
currentUser: zzSessionStorage.getItem('userName'), currentUser: zzSessionStorage.getItem('userName'),
COMPANY: process.env.VUE_APP_COMPANY_NAME, COMPANY: process.env.VUE_APP_COMPANY_NAME,
onlyOffice_url: process.env.VUE_APP_ONLYOFFICE_URL, onlyOffice_url: process.env.VUE_APP_ONLYOFFICE_URL,
window, window
} }
}, },
computed: { computed: {

View File

@ -22,7 +22,7 @@ export default {
}, },
methods: { methods: {
click() { click() {
if (!screenfull.isEnabled) { if (!screenfull.enabled) {
this.$message({ this.$message({
message: 'you browser can not work', message: 'you browser can not work',
type: 'warning' type: 'warning'
@ -35,12 +35,12 @@ export default {
this.isFullscreen = screenfull.isFullscreen this.isFullscreen = screenfull.isFullscreen
}, },
init() { init() {
if (screenfull.isEnabled) { if (screenfull.enabled) {
screenfull.on('change', this.change) screenfull.on('change', this.change)
} }
}, },
destroy() { destroy() {
if (screenfull.isEnabled) { if (screenfull.enabled) {
screenfull.off('change', this.change) screenfull.off('change', this.change)
} }
} }

View File

@ -2,21 +2,19 @@
<template> <template>
<div class="trialsTab"> <div class="trialsTab">
<el-tabs v-model="trialsTab" @tab-click="clickTab"> <el-tabs v-model="trialsTab" @tab-click="clickTab">
<template v-for="item of trialsRouter.children.find(v => { return v.name == 'TrialsPanel' }).children"> <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 :key="`tab${item.path}`" <el-tabs v-if="!item.tabHiddn" v-model="trialsTabChild" @tab-click="clickTab" style="background-color: #f5f7fa;">
:disabled="TotalNeedSignTrialDocCount !== 0 && item.path !== '/trials/trials-panel/attachments'"
:label="$t(item.LanguageMark)" :name="item.path" v-if="isShowNode(item)">
<el-tabs v-if="!item.tabHiddn" v-model="trialsTabChild" @tab-click="clickTab"
style="background-color: #f5f7fa;">
<template v-for="item1 of item.children"> <template v-for="item1 of item.children">
<el-tab-pane v-if="TrialConfig && isShow(item1.path)" :key="`tab1${item1.path}`" <el-tab-pane
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 && 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'))"
:label="$t(item1.LanguageMark)" :name="item1.path" /> :label="$t(item1.LanguageMark)"
:name="item1.path"
/>
</template> </template>
</el-tabs> </el-tabs>
</el-tab-pane> </el-tab-pane>
</template>
</el-tabs> </el-tabs>
<div style="position: absolute;top: 0;right: 0;display: flex;justify-content: space-between;align-items: center"> <div style="position: absolute;top: 0;right: 0;display: flex;justify-content: space-between;align-items: center">
<trials-select /> <trials-select />
@ -119,17 +117,8 @@ export default {
} }
}, },
methods: { methods: {
isShowNode(item) {
if (item.path === '/trials/trials-panel/trial-summary' && item.children.length === 1 && item.children[0].path === '/trials/trials-panel/trial-summary/report-forms' && !this.$store.state.trials.config.IsExternalViewTrialChart && this.hasPermi(['role:cmm', 'role:cpm', 'role:ea', 'role:mc', 'role:smm', 'role:spm'])) {
return false
}
return true
},
isShow: function(path) { isShow: function(path) {
var isShow = true var isShow = true
let chartList = [
'/trials/trials-panel/trial-summary/report-forms'
]
var qualityList = [ var qualityList = [
'/trials/trials-panel/visit/crc-question', '/trials/trials-panel/visit/crc-question',
'/trials/trials-panel/visit/qc-check', '/trials/trials-panel/visit/qc-check',
@ -145,9 +134,6 @@ export default {
'/trials/trials-panel/trial-summary/image-inspect', '/trials/trials-panel/trial-summary/image-inspect',
'/trials/trials-panel/trial-summary/push-record', '/trials/trials-panel/trial-summary/push-record',
] ]
if (!this.$store.state.trials.config.IsExternalViewTrialChart && ~chartList.indexOf(path) && this.hasPermi(['role:cmm', 'role:cpm', 'role:ea', 'role:mc', 'role:smm', 'role:spm'])) {
isShow = false
}
if (this.TrialConfig.QCProcessEnum === 0 && ~qualityList.indexOf(path)) { if (this.TrialConfig.QCProcessEnum === 0 && ~qualityList.indexOf(path)) {
isShow = false isShow = false
} }
@ -228,49 +214,37 @@ export default {
display: flex; display: flex;
justify-content: center; justify-content: center;
align-items: center; align-items: center;
&:hover{ &:hover{
color: #428bca; color: #428bca;
} }
span{ span{
margin-left: 3px; margin-left: 3px;
font-size: 14px; font-size: 14px;
} }
} }
.el-tabs__header{ .el-tabs__header{
margin-bottom: 3px; margin-bottom: 3px;
} }
.el-tabs__item.is-active{ .el-tabs__item.is-active{
font-weight: bold; font-weight: bold;
} }
position: relative; position: relative;
.el-input--medium .el-input__inner{ .el-input--medium .el-input__inner{
height: 44px; height: 44px;line-height: 44px;width: 280px;
line-height: 44px;
width: 280px;
border: none; border: none;
text-align: right; text-align: right;
} }
} }
.base-model-wrapper{ .base-model-wrapper{
.el-dialog__header{ .el-dialog__header{
padding: 10px; padding: 10px;
.el-dialog__headerbtn{ .el-dialog__headerbtn{
top: 10px; top: 10px;
right: 10px; right: 10px;
} }
} }
.el-dialog__body{ .el-dialog__body{
padding:10px 10px 10px 10px; padding:10px 10px 10px 10px;
.base-modal-body{ .base-modal-body{
min-height: 100px; min-height: 100px;
max-height:650px; max-height:650px;
@ -279,7 +253,6 @@ export default {
border: 1px solid #e0e0e0; border: 1px solid #e0e0e0;
} }
} }
.el-dialog__footer{ .el-dialog__footer{
padding: 10px; padding: 10px;
} }

View File

@ -8,6 +8,7 @@
<script> <script>
import { getReportsChartData } from "@/api/reading" import { getReportsChartData } from "@/api/reading"
import moment from "moment"
let echarts = require('echarts/lib/echarts'); let echarts = require('echarts/lib/echarts');
// //

View File

@ -1,116 +0,0 @@
<template>
<div id="timeTag" :style="`color:${suggestionTextColor};background-color: inherit;`">{{ time }}</div>
</template>
<script>
import moment from 'moment'
export default {
name: "timeTag",
data() {
return {
time: '',
timer: null,
suggestionTextColor: '#909399'
}
},
created() {
this.getTime()
},
async mounted() {
this.dragDoc()
this.setColor()
},
methods: {
getTime() {
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
this.timer = setInterval(async () => {
this.time = moment(new Date()).format('YYYY-MM-DD HH:mm:ss Z z')
}, 1000)
},
dragDoc() {
const box = document.querySelector('#timeTag')
const body = document.getElementsByTagName('body')[0]
let maxLeft = body.offsetWidth - box.offsetWidth
let maxTop = body.offsetHeight - box.offsetHeight - 30
box.style.cssText += `left:${maxLeft}px;top:7px;`
const sty = (function () {
if (window.document.currentStyle) {
return (dom, attr) => dom.currentStyle[attr]
} else {
return (dom, attr) => getComputedStyle(dom, false)[attr]
}
})()
box.onmousedown = (e) => {
//
const disX = e.clientX - box.offsetLeft
const disY = e.clientY - box.offsetTop
// px
let styL = sty(box, 'left')
let styT = sty(box, 'top')
// ie 50% px
if (styL.includes('%')) {
styL = +document.body.clientWidth * (+styL.replace(/\%/g, '') / 100)
styT = +document.body.clientHeight * (+styT.replace(/\%/g, '') / 100)
} else {
styL = +styL.replace(/\px/g, '')
styT = +styT.replace(/\px/g, '')
}
const oldMousemove = document.onmousemove
document.onmousemove = function (e) {
oldMousemove(e)
//
let left = e.clientX - disX
let top = e.clientY - disY
if (left < 0) {
left = 0
}
if (left > maxLeft) {
left = maxLeft
}
if (top < 0) {
top = 0
}
if (top > maxTop) {
top = maxTop
}
//
box.style.cssText += `;left:${left}px;top:${top}px;`
}
document.onmouseup = function (e) {
document.onmousemove = oldMousemove
document.onmouseup = null
}
}
},
setColor() {
this.suggestionTextColor = "#909399"
let pathList = ['/showvisitdicoms', '/showdicom', '/readingDicoms', '/petct', '/noneDicomReading']
if (pathList.includes(window.location.pathname)) {
this.suggestionTextColor = "#fff"
}
}
},
destroyed() {
if (this.timer) {
clearInterval(this.timer)
this.timer = null
}
}
}
</script>
<style lang="scss" scoped>
#timeTag {
position: fixed;
z-index: 99999;
cursor: move;
width: 195px;
font-size: 14px;
}
</style>

View File

@ -753,13 +753,6 @@ export default {
fileList: [], fileList: [],
dicomInfo: { dicomInfo: {
studyId: data.string('x00200010'), studyId: data.string('x00200010'),
Manufacturer: data.string('x00080070') || '',
ManufacturerModelName: data.string('x000801090') || '',
DeviceSerialNumber: data.string('x00181000') || '',
DeviceUID: data.string('x00181002') || '',
SoftwareVersions: data.string('x00181020') || '',
PatientWeight: data.string('x00101030') || '',
DicomStudyDate: data.string('x00080020'), DicomStudyDate: data.string('x00080020'),
DicomStudyTime: data.string('x00080030'), DicomStudyTime: data.string('x00080030'),
studyUid: studyUid, studyUid: studyUid,
@ -872,9 +865,6 @@ export default {
) )
seriesItem = { seriesItem = {
seriesUid: seriesUid, seriesUid: seriesUid,
RadiopharmaceuticalInformationSequence: data.string('x00540016') || "",
AcquisitionDate: data.string('x00080022') || "",
DicomSeriesDate: data.string('x00080021'), DicomSeriesDate: data.string('x00080021'),
DicomSeriesTime: data.string('x00080031'), DicomSeriesTime: data.string('x00080031'),
seriesNumber: data.intString('x00200011') || 1, seriesNumber: data.intString('x00200011') || 1,
@ -915,20 +905,6 @@ export default {
instanceTime = time ? `${date} ${time}` : `${date} 00:00:00` instanceTime = time ? `${date} ${time}` : `${date} 00:00:00`
} }
instanceItem = { instanceItem = {
PhotometricInterpretation: data.string('x00280004') || '',
BitsAllocated: data.uint16('x00280100') || '',
PixelRepresentation: data.uint16('x00280103') || '',
RescaleIntercept: data.string('x00281052') || '',
RescaleSlope: data.string('x00281053') || '',
ImagePositionPatient: data.string('x00200032') || '',
ImageOrientationPatient: data.string('x00200037') || '',
SequenceOfUltrasoundRegions: data.string('x00186011') || '',
FrameTime: data.string('x00181063') || '',
CorrectedImage: data.string('x00280051') || '',
Units: data.string('x00541001') || '',
DecayCorrection: data.string('x00541102') || '',
EncapsulatedDocument: data.string('x00420011') || '',
instanceUid: instanceUid, instanceUid: instanceUid,
SOPClassUID: data.string('x00080016'), SOPClassUID: data.string('x00080016'),
TransferSytaxUID: data.string('x00020010'), TransferSytaxUID: data.string('x00020010'),
@ -1160,13 +1136,6 @@ export default {
DicomStudyDate: dicomInfo.DicomStudyDate, DicomStudyDate: dicomInfo.DicomStudyDate,
DicomStudyTime: dicomInfo.DicomStudyTime, DicomStudyTime: dicomInfo.DicomStudyTime,
seriesList: [], seriesList: [],
Manufacturer: dicomInfo.Manufacturer,
ManufacturerModelName: dicomInfo.ManufacturerModelName,
DeviceSerialNumber: dicomInfo.DeviceSerialNumber,
DeviceUID: dicomInfo.DeviceUID,
SoftwareVersions: dicomInfo.SoftwareVersions,
PatientWeight: dicomInfo.PatientWeight,
}, },
} }
let arr = [] let arr = []
@ -1209,20 +1178,6 @@ export default {
windowWidth: o.windowWidth, windowWidth: o.windowWidth,
path: o.myPath, path: o.myPath,
FileSize: o.FileSize, FileSize: o.FileSize,
PhotometricInterpretation: o.PhotometricInterpretation,
BitsAllocated: o.BitsAllocated,
PixelRepresentation: o.PixelRepresentation,
RescaleIntercept: o.RescaleIntercept,
RescaleSlope: o.RescaleSlope,
ImagePositionPatient: o.ImagePositionPatient,
ImageOrientationPatient: o.ImageOrientationPatient,
SequenceOfUltrasoundRegions: o.SequenceOfUltrasoundRegions,
FrameTime: o.FrameTime,
CorrectedImage: o.CorrectedImage,
Units: o.Units,
DecayCorrection: o.DecayCorrection,
EncapsulatedDocument: o.EncapsulatedDocument,
}) })
Record.Uploaded.push(name) Record.Uploaded.push(name)
dicomInfo.failedFileCount++ dicomInfo.failedFileCount++
@ -1320,20 +1275,6 @@ export default {
windowWidth: o.windowWidth, windowWidth: o.windowWidth,
path: scope.$getObjectName(res.url), path: scope.$getObjectName(res.url),
FileSize: o.FileSize, FileSize: o.FileSize,
PhotometricInterpretation: o.PhotometricInterpretation,
BitsAllocated: o.BitsAllocated,
PixelRepresentation: o.PixelRepresentation,
RescaleIntercept: o.RescaleIntercept,
RescaleSlope: o.RescaleSlope,
ImagePositionPatient: o.ImagePositionPatient,
ImageOrientationPatient: o.ImageOrientationPatient,
SequenceOfUltrasoundRegions: o.SequenceOfUltrasoundRegions,
FrameTime: o.FrameTime,
CorrectedImage: o.CorrectedImage,
Units: o.Units,
DecayCorrection: o.DecayCorrection,
EncapsulatedDocument: o.EncapsulatedDocument,
}) })
o.myPath = scope.$getObjectName(res.url) o.myPath = scope.$getObjectName(res.url)
Record.Uploaded.push(name) Record.Uploaded.push(name)
@ -1382,9 +1323,6 @@ export default {
bodyPartExamined: dicomInfo.bodyPart, bodyPartExamined: dicomInfo.bodyPart,
instanceList: instanceList, instanceList: instanceList,
ImageResizePath: ImageResizePath, ImageResizePath: ImageResizePath,
RadiopharmaceuticalInformationSequence: v.RadiopharmaceuticalInformationSequence,
AcquisitionDate: v.AcquisitionDate,
}) })
} }
let text = JSON.stringify(Record) let text = JSON.stringify(Record)

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="1762494352859" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="22987" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M896 832a128 128 0 0 1-128 128H256a128 128 0 0 1-128-128V192a128 128 0 0 1 128-128h512a128 128 0 0 1 128 128v640zM192 768v64a64 64 0 0 0 56.512 63.552L256 896h512a64 64 0 0 0 63.552-56.512L832 832v-64H192z m448-640H512v206.912l64-38.4 64 38.464V128z m-448 576h640V192a64 64 0 0 0-56.512-63.552L768 128h-64v263.488a32 32 0 0 1-48.448 27.456L576 371.2l-79.552 47.744A32 32 0 0 1 448 391.424V128H256a64 64 0 0 0-63.552 56.512L192 192v512z" fill="#e6e6e6" p-id="22988"></path></svg>

Before

Width:  |  Height:  |  Size: 812 B

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="1766048712120" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="6026" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M924.520311 484.074997c7.439436 0 13.884218 2.726088 19.336394 8.16496 5.437849 5.452175 8.16496 11.897981 8.16496 19.336394 0 7.452739-2.726088 13.898545-8.16496 19.336394-5.452175 5.452175-11.897981 8.16496-19.336394 8.16496l-83.363639 0c-3.437286 40.110533-13.617136 77.777411-30.508851 113.012913-16.906042 35.236526-38.673811 66.175165-65.315588 92.816942s-57.58144 48.422849-92.816942 65.315588c-35.236526 16.906042-72.915683 26.790156-113.012913 29.650297l0 84.223217c0 7.439436-2.726088 13.884218-8.16496 19.336394-5.451152 5.437849-11.896958 8.16496-19.336394 8.16496-7.452739 0-13.898545-2.726088-19.336394-8.16496-5.452175-5.452175-8.16496-11.897981-8.16496-19.336394l0-84.223217c-40.110533-2.860141-77.777411-12.743232-113.012913-29.650297-35.236526-16.892739-66.175165-38.673811-92.816942-65.315588s-48.422849-57.58144-65.315588-92.816942c-16.906042-35.236526-27.071565-72.90238-30.508851-113.012913L99.479689 539.077705c-7.452739 0-13.898545-2.711761-19.336394-8.16496-5.452175-5.437849-8.16496-11.883655-8.16496-19.336394 0-7.439436 2.712785-13.884218 8.16496-19.336394 5.437849-5.437849 11.883655-8.16496 19.336394-8.16496l83.363639 0c3.437286-40.09723 13.602809-77.777411 30.508851-113.012913 16.892739-35.236526 38.673811-66.175165 65.315588-92.816942s57.58144-48.409546 92.816942-65.315588c35.236526-16.892739 72.90238-26.77583 113.012913-29.650297L484.497623 99.05604c0-7.439436 2.712785-13.885242 8.16496-19.336394 5.437849-5.437849 11.883655-8.16496 19.336394-8.16496 7.440459 0 13.885242 2.726088 19.336394 8.16496 5.437849 5.452175 8.16496 11.896958 8.16496 19.336394l0 84.223217c40.098253 2.874467 77.777411 12.757558 113.012913 29.650297 35.236526 16.906042 66.175165 38.673811 92.816942 65.315588s48.409546 57.58144 65.315588 92.816942c16.892739 35.236526 27.071565 72.916706 30.508851 113.012913L924.520311 484.074997zM484.498646 238.281965c-32.657794 2.874467-63.167668 11.320836-91.527576 25.352411-28.360931 14.046924-53.431933 31.946596-75.198679 53.713342-21.781072 21.781072-39.680744 46.837748-53.713342 75.198679-14.045901 28.360931-22.49227 58.869782-25.352411 91.527576L484.498646 484.073974 484.498646 238.281965zM238.70459 539.077705c2.860141 32.657794 11.30651 63.166645 25.352411 91.527576 14.032598 28.360931 31.933293 53.431933 53.713342 75.198679 21.766746 21.781072 46.837748 39.680744 75.198679 53.713342 28.360931 14.046924 58.869782 22.49227 91.527576 25.352411L484.496599 539.077705 238.70459 539.077705zM539.501354 484.074997l245.793032 0c-2.874467-32.657794-11.320836-63.167668-25.352411-91.527576-14.046924-28.360931-31.946596-53.417607-53.713342-75.198679-21.780049-21.766746-46.837748-39.667441-75.198679-53.713342-28.360931-14.032598-58.869782-22.478967-91.527576-25.352411L539.502377 484.074997zM539.501354 784.870738c32.657794-2.860141 63.167668-11.30651 91.527576-25.352411 28.360931-14.032598 53.41863-31.93227 75.198679-53.713342 21.766746-21.766746 39.667441-46.837748 53.713342-75.198679 14.032598-28.360931 22.478967-58.869782 25.352411-91.527576L539.501354 539.078729 539.501354 784.870738z" p-id="6027" fill="#ffffff"></path></svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 418 B

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="1762485648235" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="10985" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M543.378286 515.949714V104.521143a31.451429 31.451429 0 0 0-62.976 0v411.501714a125.44 125.44 0 0 0 0.292571 242.834286 31.670857 31.670857 0 0 0-0.292571 3.949714v156.745143a31.451429 31.451429 0 0 0 62.902857 0v-156.745143a31.597714 31.597714 0 0 0-0.219429-3.876571 125.513143 125.513143 0 0 0 0.292572-242.980572z m12.946285 165.814857a62.683429 62.683429 0 1 1-88.649142-88.722285 62.683429 62.683429 0 0 1 88.649142 88.722285zM229.522286 202.459429a31.597714 31.597714 0 0 0 0.292571-3.949715V104.594286a31.305143 31.305143 0 1 0-62.610286 0v93.988571c0 1.389714 0 2.706286 0.146286 4.022857a125.44 125.44 0 0 0 0 242.907429 31.670857 31.670857 0 0 0-0.146286 3.876571v470.235429a31.305143 31.305143 0 1 0 62.610286 0V449.316571a31.597714 31.597714 0 0 0-0.292571-3.803428 125.44 125.44 0 0 0 0-243.053714z m13.312 165.888a62.683429 62.683429 0 1 1-88.649143-88.722286 62.683429 62.683429 0 0 1 88.649143 88.722286zM950.857143 324.022857c0-58.587429-40.228571-107.739429-94.500572-121.563428a31.670857 31.670857 0 0 0 0.146286-3.949715V104.594286a31.305143 31.305143 0 0 0-62.610286 0v93.988571c0 1.389714 0.146286 2.706286 0.292572 4.022857a125.44 125.44 0 0 0 0 242.907429 31.670857 31.670857 0 0 0-0.292572 3.949714v470.162286a31.305143 31.305143 0 1 0 62.610286 0V449.389714c0-1.316571 0-2.56-0.146286-3.876571A125.513143 125.513143 0 0 0 950.857143 324.022857z m-81.042286 44.324572a62.683429 62.683429 0 1 1-88.649143-88.722286 62.683429 62.683429 0 0 1 88.649143 88.722286z" p-id="10986" fill="#e6e6e6"></path></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

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="1764830990216" class="icon" viewBox="0 0 1024 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5566" xmlns:xlink="http://www.w3.org/1999/xlink" width="200" height="200"><path d="M192 170.666667a21.333333 21.333333 0 0 0-21.333333 21.333333v640a21.333333 21.333333 0 0 0 21.333333 21.333333h640a21.333333 21.333333 0 0 0 21.333333-21.333333v-640a21.333333 21.333333 0 0 0-21.333333-21.333333h-640zM85.333333 192A106.666667 106.666667 0 0 1 192 85.333333h640A106.666667 106.666667 0 0 1 938.666667 192v640a106.666667 106.666667 0 0 1-106.666667 106.666667h-640A106.666667 106.666667 0 0 1 85.333333 832v-640z" fill="#ffffff" p-id="5567"></path><path d="M173.653333 170.666667c-1.621333 5.034667-2.986667 12.373333-2.986666 21.333333v640c0 8.96 1.365333 16.298667 2.986666 21.333333h292.693334c1.621333-5.034667 2.986667-12.373333 2.986666-21.333333v-640c0-8.96-1.365333-16.298667-2.986666-21.333333H173.653333zM99.157333 127.658667C107.306667 111.530667 126.293333 85.333333 160 85.333333h320c33.706667 0 52.736 26.197333 60.8 42.325334 9.301333 18.688 13.866667 41.472 13.866667 64.341333v640c0 22.869333-4.565333 45.653333-13.866667 64.341333-8.106667 16.128-27.093333 42.325333-60.8 42.325334h-320c-33.706667 0-52.736-26.197333-60.8-42.325334C89.856 877.653333 85.333333 854.869333 85.333333 832v-640c0-22.869333 4.522667-45.653333 13.866667-64.341333z" fill="#ffffff" p-id="5568"></path><path d="M170.666667 170.666667v298.666666h298.666666V170.666667H170.666667z m-85.333334-10.666667C85.333333 118.784 118.784 85.333333 160 85.333333h320c41.216 0 74.666667 33.450667 74.666667 74.666667v320A74.666667 74.666667 0 0 1 480 554.666667h-320A74.666667 74.666667 0 0 1 85.333333 480v-320z" fill="#ffffff" p-id="5569"></path></svg>

Before

Width:  |  Height:  |  Size: 1.8 KiB

View File

@ -1608,7 +1608,7 @@ Enroll: Enrolled Confirmation`,
'trials:notice:table:appendix': `Attachment`, 'trials:notice:table:appendix': `Attachment`,
'trials:notice:table:isRead': `Readed`, 'trials:notice:table:isRead': `Readed`,
'trials:notice:action:detail': `Details`, 'trials:notice:action:detail': `Details`,
'login:title:system': `EIC lmaging Trial Management System`, 'login:title:system': `IRC Imaging System`,
'login:form:userName': `User ID`, 'login:form:userName': `User ID`,
'login:form:password': `Password`, 'login:form:password': `Password`,
'login:button:login': `Login`, 'login:button:login': `Login`,
@ -1672,7 +1672,7 @@ Enroll: Enrolled Confirmation`,
'trials:tab:trials': `My Trials`, 'trials:tab:trials': `My Trials`,
'trials:trials:title:back': `Return`, 'trials:trials:title:back': `Return`,
'trials:trials:title:backTrialList': `Return to trial list`, 'trials:trials:title:backTrialList': `Return to trial list`,
'trials:trials:title:eics': `EIC lmaging Trial Management System`, 'trials:trials:title:eics': `IRC Imaging System`,
'trials:tab:reading': `Reads`, 'trials:tab:reading': `Reads`,
'trials:tab:pendingReadingTasks': `Pending`, 'trials:tab:pendingReadingTasks': `Pending`,
'trials:pendingReadingTasks:table:subjectCode': `Subject ID`, 'trials:pendingReadingTasks:table:subjectCode': `Subject ID`,

View File

@ -218,7 +218,7 @@ export default {
.right-menu { .right-menu {
// float: right; // float: right;
height: 100%; height: 100%;
line-height: 65px; line-height: 50px;
// position: relative; // position: relative;
&:focus { &:focus {
outline: none; outline: none;

View File

@ -3,16 +3,14 @@
<template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow"> <template v-if="hasOneShowingChild(item.children,item) && (!onlyOneChild.children||onlyOneChild.noShowingChildren)&&!item.alwaysShow">
<app-link v-if="!onlyOneChild.hidden" :to="resolvePath(onlyOneChild.path)"> <app-link v-if="!onlyOneChild.hidden" :to="resolvePath(onlyOneChild.path)">
<el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}" @click="handleClick(onlyOneChild.meta.title)"> <el-menu-item :index="resolvePath(onlyOneChild.path)" :class="{'submenu-title-noDropdown':!isNest}" @click="handleClick(onlyOneChild.meta.title)">
<!-- :title="onlyOneChild.meta ? onlyOneChild.meta.title : null" --> <item :icon="onlyOneChild.meta ? (onlyOneChild.meta.icon||(item.meta&&item.meta.icon)) : null" :title="onlyOneChild.meta ? onlyOneChild.meta.title : null" />
<item :icon="onlyOneChild.meta ? (onlyOneChild.meta.icon||(item.meta&&item.meta.icon)) : null" :title="onlyOneChild.meta.i18n ? $t(onlyOneChild.meta.i18n) : null" />
</el-menu-item> </el-menu-item>
</app-link> </app-link>
</template> </template>
<el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body> <el-submenu v-else ref="subMenu" :index="resolvePath(item.path)" popper-append-to-body>
<template slot="title"> <template slot="title">
<!-- :title="item.meta.title" --> <item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.title" />
<item v-if="item.meta" :icon="item.meta && item.meta.icon" :title="item.meta.i18n ? $t(item.meta.i18n) : null" />
</template> </template>
<sidebar-item <sidebar-item
v-for="child in item.children" v-for="child in item.children"

View File

@ -1,11 +1,11 @@
<template> <template>
<el-dropdown <el-dropdown
style="height:50px;line-height: 65px;" style="height:50px;line-height: 60px;"
@command="handleSetLanguage" @command="handleSetLanguage"
> >
<span class="el-dropdown-link"> <span class="el-dropdown-link">
<svg-icon icon-class="language" style="font-size:20px;margin:0 10px;" /> <svg-icon icon-class="language" style="font-size:25px;margin:0 10px;" />
<!-- {{ language==='zh'?'语言:中文':'Language: English' }} --> <!-- {{ language==='zh'?'语言:中文':'Language: English' }} -->
<!-- <i class="el-icon-arrow-down el-icon--right" /> --> <!-- <i class="el-icon-arrow-down el-icon--right" /> -->
</span> </span>

View File

@ -26,9 +26,8 @@ Vue.use(VueClipboard)
import permission from './utils/permission' import permission from './utils/permission'
Vue.use(permission) Vue.use(permission)
import { formatSize, guidToColor } from "./utils" import { formatSize } from "./utils"
Vue.prototype.$FormatSize = formatSize Vue.prototype.$FormatSize = formatSize
Vue.prototype.$GuidToColor = guidToColor
import Viewer from 'v-viewer' import Viewer from 'v-viewer'
import './assets/css/viewer.css' import './assets/css/viewer.css'
@ -62,8 +61,6 @@ import Onlyoffice from '@/components/Preview_onlyoffice/index'
Vue.use(Onlyoffice) Vue.use(Onlyoffice)
import Video from '@/components/Preview_video/index' import Video from '@/components/Preview_video/index'
Vue.use(Video) Vue.use(Video)
import AGR from '@/components/AGR/index'
Vue.use(AGR)
import MFA from '@/components/MFA/index' import MFA from '@/components/MFA/index'
Vue.use(MFA) Vue.use(MFA)
import FB from '@/components/feedBack/index' import FB from '@/components/feedBack/index'

View File

@ -1,7 +1,7 @@
// eslint-disable-next-line no-undef // eslint-disable-next-line no-undef
module.exports = { module.exports = {
title: 'EIC lmaging Trial Management System', title: 'IRC Imaging System',
/** /**
* @type {boolean} true | false * @type {boolean} true | false

View File

@ -39,7 +39,6 @@ function filterAsyncRouter(asyncRouterMap = [], lastRouter = false, type = false
// eslint-disable-next-line // eslint-disable-next-line
route.meta = eval('(' + route.Meta + ')') route.meta = eval('(' + route.Meta + ')')
route.meta.icon = route.MenuIcon route.meta.icon = route.MenuIcon
route.meta.i18n = route.LanguageMark
delete route.Meta delete route.Meta
} }
delete route.MenuIcon delete route.MenuIcon

View File

@ -1,32 +0,0 @@
import FingerprintJS from '@fingerprintjs/fingerprintjs';
export const customAgent = () => {
return new Promise(async resolve => {
const fpPromise = await FingerprintJS.load({
monitoring: false
});
const result = await fpPromise.get({
products: ['fonts', 'screen', 'canvas'],
extendedData: true,
debug: false
})
// const filteredComponents = Object.fromEntries(
// Object.entries(result.components)
// .filter(([key, value]) => value.confidence > 0.5)
// );
resolve({
...result,
});
// fpPromise
// .then(fp => fp.get({
// products: ['fonts', 'screen', 'canvas'],
// extendedData: true,
// debug: true
// }))
// .then(result => {
// // 自定义数据转换
// });
});
}

View File

@ -1,6 +1,6 @@
import defaultSettings from '@/settings' import defaultSettings from '@/settings'
const title = defaultSettings.title || 'EIC lmaging Trial Management System' const title = defaultSettings.title || 'IRC Imaging System'
export default function getPageTitle(pageTitle) { export default function getPageTitle(pageTitle) {
if (pageTitle) { if (pageTitle) {

View File

@ -197,109 +197,3 @@ export function workSpeedclose(isForce = false) {
imageId = null; imageId = null;
percentageById = {}; percentageById = {};
} }
function readDirectoryEntries(directoryReader) {
return new Promise((resolve, reject) => {
let entries = [];
function readBatch() {
directoryReader.readEntries(
(results) => {
if (results.length) {
entries = entries.concat(results);
readBatch();
} else {
resolve(entries);
}
},
(error) => reject(error)
);
}
readBatch();
});
}
export async function readEntry(entry) {
const files = [];
// 如果是文件夹,创建读取器并递归读取其内容
if (entry.isDirectory) {
const directoryReader = entry.createReader();
const entries = await readDirectoryEntries(directoryReader)
// 递归读取文件夹内的每一项
for (const subEntry of entries) {
const subFiles = await readEntry(subEntry);
files.push(...subFiles);
}
}
// 如果是文件则将其转换为File对象
else if (entry.isFile) {
const file = await new Promise((resolve, reject) => {
entry.file(resolve, reject); // entry.file()是异步的
});
files.push(file);
}
return files;
}
// 使用FNV-1a哈希算法确保相同GUID产生相同结果
function fnv1aHash(str) {
const FNV_OFFSET_BASIS = 2166136261;
const FNV_PRIME = 16777619;
let hash = FNV_OFFSET_BASIS;
for (let i = 0; i < str.length; i++) {
hash ^= str.charCodeAt(i);
hash = (hash * FNV_PRIME) >>> 0; // 使用无符号右移确保结果为无符号32位整数
}
return hash;
}
// RGB转十六进制
function rgbToHex(r, g, b) {
return "#" + ((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase();
}
// HSL转RGB函数
function hslToRgb(h, s, l) {
let r, g, b;
if (s === 0) {
r = g = b = l; // 灰色
} else {
const hue2rgb = (p, q, t) => {
if (t < 0) t += 1;
if (t > 1) t -= 1;
if (t < 1 / 6) return p + (q - p) * 6 * t;
if (t < 1 / 2) return q;
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
return p;
};
const q = l < 0.5 ? l * (1 + s) : l + s - l * s;
const p = 2 * l - q;
r = hue2rgb(p, q, h + 1 / 3);
g = hue2rgb(p, q, h);
b = hue2rgb(p, q, h - 1 / 3);
}
return { r, g, b };
}
export function guidToColor(guid) {
// 移除GUID中的连字符和花括号如果有
let cleanGuid = guid.replace(/[{}()-]/g, '');
// 计算GUID的哈希值
const hash = fnv1aHash(cleanGuid);
// 使用哈希值生成HLS颜色确保高区分度
// 将哈希值映射到0-1之间
const h = (hash & 0xFFFF) / 0xFFFF; // 使用前16位作为色相
const s = ((hash >> 16) & 0xFF) / 0xFF * 0.6 + 0.4; // 饱和度在0.4-1.0之间
const l = ((hash >> 24) & 0xFF) / 0xFF * 0.4 + 0.4; // 亮度在0.3-0.7之间,避免太暗或太亮
// 返回RGB对象
let rgb = hslToRgb(h, s, l);
let obj = {
r: Math.round(rgb.r * 255),
g: Math.round(rgb.g * 255),
b: Math.round(rgb.b * 255)
}
let str = rgbToHex(obj.r, obj.g, obj.b)
return str;
}

View File

@ -5,10 +5,8 @@ import router from '@/router'
import WHITELIST from "./whiteList" import WHITELIST from "./whiteList"
import moment from 'moment-timezone'; import moment from 'moment-timezone';
import { encryptConfig } from "@/utils/encrypt" import { encryptConfig } from "@/utils/encrypt"
import SystemInfo from "@/utils/systemInfo";
const ROUTER = require('@/router'); const ROUTER = require('@/router');
axios.defaults.withCredentials = false axios.defaults.withCredentials = false
const systemInfo = new SystemInfo();
const service = axios.create({ const service = axios.create({
baseURL: '/api', baseURL: '/api',
// baseURL: process.env.NODE_ENV === 'prod' ? "https://api.irc.extimaging.com" : '/api', // baseURL: process.env.NODE_ENV === 'prod' ? "https://api.irc.extimaging.com" : '/api',
@ -28,40 +26,6 @@ service.interceptors.request.use(
var language = zzSessionStorage.getItem('lang') 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['Accept-Language'] = language === 'en' ? 'en-US,en;q=0.5' : 'zh-CN,zh;q=0.9'
config.headers['TimeZoneId'] = moment.tz.guess() config.headers['TimeZoneId'] = moment.tz.guess()
const allInfo = systemInfo.getAllInfo();
let obj = {
browser: {
name: allInfo.browser.name,
version: allInfo.browser.version,
},
platform: allInfo.platform,
os: {
name: allInfo.os.name,
version: allInfo.os.version
},
hardware: {
logicalCores: allInfo.hardware.logicalCores,
deviceMemory: allInfo.hardware.deviceMemory
},
webgl: {
version: allInfo.webgl.version,
renderer: allInfo.webgl.renderer,
vendor: allInfo.webgl.vendor,
shadingLanguage: allInfo.webgl.shadingLanguage,
gpuType: {
type: allInfo.webgl.gpuType.type,
discrete: allInfo.webgl.gpuType.discrete,
},
performance: {
tier: allInfo.webgl.performance.tier,
},
extensions: {
length: allInfo.webgl.extensions.length,
}
}
}
let guid = await systemInfo.generateGuid(obj)
config.headers['BrowserFingerprint'] = guid
if (config.ENCRYPT) { if (config.ENCRYPT) {
try { try {
config = await encryptConfig(config) config = await encryptConfig(config)

View File

@ -1,88 +0,0 @@
async function queryWindowManagement() {
return await navigator.permissions.query({ name: 'window-management' });;
}
async function getPermission() {
const permission = await queryWindowManagement();
console.log(permission.state, 'permission.state')
if (permission.state === "granted") { // 已经授权
return true
} else if (permission.state === "prompt") { // 询问是否授权
// 请求授权
if (navigator.permissions.request) {
navigator.permissions.request({ name: 'window-management' })
}
return false
} else if (permission.state === "denied") {
// 权限被拒绝
return false
}
}
function getScreen() {
return new Promise((resolve, reject) => {
let multiScreen = []
if (window.getScreenDetails) {
let getScreensProsime1 = window.getScreenDetails();
getScreensProsime1.then((c) => {
if (c instanceof Array) {
multiScreen = c
} else if (c instanceof Object) {
multiScreen = c.screens
} else {
multiScreen = []
}
resolve(multiScreen)
}).catch((err) => {
reject(err)
});
} else if (window.getScreens) {
let getScreensProsime = window.getScreens();
getScreensProsime.then((c) => {
if (c instanceof Array) {
multiScreen = c
} else if (c instanceof Object) {
multiScreen = c.screens
} else {
multiScreen = []
}
resolve(multiScreen)
}).catch((err) => {
reject(err)
})
}
})
}
export async function openWindow(url, name, Skip = false) {
// 判断浏览器是否兼容
// 高版本的谷歌edge不支持跨屏需要降低浏览器版本86.0版
if (!window.getScreens && !window.getScreenDetails) {
console.log('你的浏览器版本不支持多屏展示功能!');
return window.open(url, name);
}
let permission = await getPermission()
if (!permission) {
// alert('使用多屏功能请先进行授权')
if (Skip) {
return window.open(url, name);
}
return false
}
let multiScreen = await getScreen()
console.log(multiScreen, 'multiScreen')
// 判断是否2个屏幕
if (multiScreen.length < 2) {
console.log('请接入多个显示屏!');
return window.open(url, name);
}
console.log(screen, 'screen')
// 获取当前屏幕availLeft信息和所有信息比对取另一个屏幕数据
let currentAvailLeft = screen.availLeft ? screen.availLeft : '0'
let newCurr = multiScreen.find((t) => t.availLeft != currentAvailLeft)
console.log(newCurr, 'newCurr')
let fulls = ''
for (let key in newCurr) {
fulls += `${key}=${(newCurr[key] || newCurr[key] === 0) ? newCurr[key] : 0},`
}
console.log(fulls, 'fulls')
return window.open(url, name, fulls);
}

View File

@ -1,5 +1,5 @@
import streamSaver from "streamsaver"; import streamSaver from "streamsaver";
import "./zip-stream.js"; import "streamsaver/examples/zip-stream.js";
import store from '@/store' import store from '@/store'
import dcmjs from './dcmUpload/dcmjs' import dcmjs from './dcmUpload/dcmjs'
streamSaver.mitm = `${window.location.origin}/mitm.html?version=2.0.0` streamSaver.mitm = `${window.location.origin}/mitm.html?version=2.0.0`

View File

@ -1,686 +0,0 @@
// 浏览器信息检测
class SystemInfo {
constructor() {
this.info = {
browser: this.getBrowserInfo(),
os: this.getOSInfo(),
hardware: this.getHardwareInfo(),
webgl: this.getWebGLInfo()
};
}
// 获取浏览器信息
getBrowserInfo() {
const ua = navigator.userAgent;
let browser = {
name: 'Unknown',
version: 'Unknown',
fullVersion: navigator.appVersion
};
// 检测浏览器类型
if (ua.includes('Firefox')) {
browser.name = 'Firefox';
browser.version = this.extractVersion(ua, 'Firefox');
} else if (ua.includes('Chrome') && !ua.includes('Edg') && !ua.includes('OPR')) {
browser.name = 'Chrome';
browser.version = this.extractVersion(ua, 'Chrome');
} else if (ua.includes('Safari') && !ua.includes('Chrome')) {
browser.name = 'Safari';
browser.version = this.extractVersion(ua, 'Version');
} else if (ua.includes('Edg')) {
browser.name = 'Edge';
browser.version = this.extractVersion(ua, 'Edg');
} else if (ua.includes('OPR') || ua.includes('Opera')) {
browser.name = 'Opera';
browser.version = this.extractVersion(ua, 'OPR') || this.extractVersion(ua, 'Opera');
} else if (ua.includes('Trident') || ua.includes('MSIE')) {
browser.name = 'Internet Explorer';
browser.version = this.extractVersion(ua, 'MSIE') || this.extractVersion(ua, 'rv:');
}
return browser;
}
// 提取版本号
extractVersion(userAgent, browserName) {
const match = userAgent.match(new RegExp(`${browserName}/([0-9]+(\\.[0-9]+)?)`));
return match ? match[1] : 'Unknown';
}
// 获取操作系统信息
getOSInfo() {
const ua = navigator.userAgent;
let os = {
name: 'Unknown',
version: 'Unknown',
architecture: this.getArchitecture()
};
if (ua.includes('Windows')) {
os.name = 'Windows';
if (ua.includes('Windows NT 10.0')) os.version = '10';
else if (ua.includes('Windows NT 6.3')) os.version = '8.1';
else if (ua.includes('Windows NT 6.2')) os.version = '8';
else if (ua.includes('Windows NT 6.1')) os.version = '7';
else if (ua.includes('Windows NT 6.0')) os.version = 'Vista';
else if (ua.includes('Windows NT 5.1')) os.version = 'XP';
} else if (ua.includes('Mac OS X')) {
os.name = 'macOS';
const match = ua.match(/Mac OS X (\d+[._]\d+)/);
if (match) os.version = match[1].replace('_', '.');
} else if (ua.includes('Linux')) {
os.name = 'Linux';
} else if (ua.includes('Android')) {
os.name = 'Android';
const match = ua.match(/Android ([0-9.]+)/);
if (match) os.version = match[1];
} else if (ua.includes('like Mac')) {
os.name = 'iOS';
const match = ua.match(/OS (\d+[_]\d+)/);
if (match) os.version = match[1].replace('_', '.');
}
return os;
}
// 获取系统架构
getArchitecture() {
if (navigator.userAgent.includes('x64') || navigator.userAgent.includes('x86_64')) {
return '64-bit';
} else if (navigator.userAgent.includes('x86') || navigator.userAgent.includes('i686')) {
return '32-bit';
} else if (navigator.userAgent.includes('ARM')) {
return 'ARM';
} else if (navigator.userAgent.includes('Win64')) {
return '64-bit';
}
return 'Unknown';
}
// 获取硬件信息
getHardwareInfo() {
return {
logicalCores: navigator.hardwareConcurrency || 'Unknown',
deviceMemory: navigator.deviceMemory ? `${navigator.deviceMemory} GB` : 'Unknown',
maxTouchPoints: navigator.maxTouchPoints || 0
};
}
// 获取WebGL和显卡信息
getWebGLInfo() {
const webglInfo = {
webgl1: this.getWebGLContextInfo('webgl'),
webgl2: this.getWebGLContextInfo('webgl2'),
supported: false,
renderer: 'Unknown',
vendor: 'Unknown',
version: 'Unknown',
shadingLanguage: 'Unknown',
extensions: []
};
const canvas = document.createElement('canvas');
let gl = null;
// 尝试获取WebGL2上下文
try {
gl = canvas.getContext('webgl2') || canvas.getContext('experimental-webgl2');
} catch (e) {
console.log('WebGL2 not supported:', e.message);
}
// 如果WebGL2不可用尝试WebGL1
if (!gl) {
try {
gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
} catch (e) {
console.log('WebGL not supported:', e.message);
}
}
if (gl) {
webglInfo.supported = true;
// 获取显卡信息
const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
if (debugInfo) {
webglInfo.renderer = gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL) || 'Unknown';
webglInfo.vendor = gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL) || 'Unknown';
}
// 获取WebGL版本信息
webglInfo.version = gl.getParameter(gl.VERSION) || 'Unknown';
webglInfo.shadingLanguage = gl.getParameter(gl.SHADING_LANGUAGE_VERSION) || 'Unknown';
// 获取支持的扩展
try {
webglInfo.extensions = gl.getSupportedExtensions() || [];
} catch (e) {
console.log('无法获取WebGL扩展:', e.message);
}
// 检查GPU性能级别
webglInfo.performance = this.getGPUPerformanceInfo(gl);
// 检查内存信息(如果支持)
webglInfo.memoryInfo = this.getGPUMemoryInfo(gl);
// 检查是否使用集成显卡
if (webglInfo.renderer) {
webglInfo.gpuType = this.detectGPUType(webglInfo.renderer);
}
}
return webglInfo;
}
// 获取WebGL上下文的具体信息
getWebGLContextInfo(contextType) {
const canvas = document.createElement('canvas');
let gl = null;
try {
gl = canvas.getContext(contextType) ||
canvas.getContext(`experimental-${contextType}`);
} catch (e) {
return { supported: false, error: e.message };
}
if (!gl) {
return { supported: false };
}
return {
supported: true,
context: gl
};
}
// 获取GPU性能信息
getGPUPerformanceInfo(gl) {
const info = { tier: 'unknown', features: [] };
// 检查是否支持高性能特性
try {
// 检查帧缓冲
if (gl.checkFramebufferStatus) {
info.features.push('framebuffer');
}
// 检查浮点纹理
const floatExt = gl.getExtension('OES_texture_float') ||
gl.getExtension('EXT_color_buffer_float');
if (floatExt) info.features.push('float_textures');
// 检查多重采样
const msaaExt = gl.getExtension('WEBGL_multisampled_render_to_texture');
if (msaaExt) info.features.push('msaa');
// 检查实例化渲染
const instancingExt = gl.getExtension('ANGLE_instanced_arrays') ||
gl.getExtension('WEBGL_draw_buffers');
if (instancingExt) info.features.push('instancing');
// 尝试检测性能级别(基于支持的扩展)
if (info.features.includes('float_textures') &&
info.features.includes('msaa') &&
info.features.includes('instancing')) {
info.tier = 'high';
} else if (info.features.length >= 2) {
info.tier = 'medium';
} else {
info.tier = 'low';
}
} catch (e) {
console.log('获取GPU性能信息失败:', e);
}
return info;
}
// 获取GPU内存信息
getGPUMemoryInfo(gl) {
const memoryInfo = { estimatedMemory: 'Unknown' };
// 尝试通过扩展获取内存信息
try {
// 检查是否支持内存信息扩展
const memoryExt = gl.getExtension('WEBGL_debug_renderer_info');
if (memoryExt) {
// 一些浏览器会通过UNMASKED_RENDERER_WEBGL暴露内存信息
const renderer = gl.getParameter(memoryExt.UNMASKED_RENDERER_WEBGL);
if (renderer) {
// 尝试从渲染器字符串中提取内存信息
const match = renderer.match(/(\d+)\s*MB|(\d+)\s*GB|VRAM\s*:\s*(\d+)/i);
if (match) {
memoryInfo.estimatedMemory = match[0];
}
}
}
// 通过创建大纹理测试内存
memoryInfo.maxTextureSize = gl.getParameter(gl.MAX_TEXTURE_SIZE);
memoryInfo.maxRenderbufferSize = gl.getParameter(gl.MAX_RENDERBUFFER_SIZE);
} catch (e) {
// 静默失败
}
return memoryInfo;
}
// 检测GPU类型
detectGPUType(renderer) {
const r = renderer.toLowerCase();
if (r.includes('nvidia') || r.includes('geforce') || r.includes('gtx') || r.includes('rtx')) {
return { type: 'NVIDIA', discrete: true };
} else if (r.includes('amd') || r.includes('radeon') || r.includes('rx')) {
return { type: 'AMD', discrete: true };
} else if (r.includes('intel') || r.includes('hd graphics') || r.includes('iris') || r.includes('uhd')) {
return { type: 'Intel', discrete: false };
} else if (r.includes('apple') || r.includes('apple gpu') || r.includes('apple m')) {
return { type: 'Apple Silicon', discrete: false };
} else if (r.includes('mali') || r.includes('adreno') || r.includes('powervr')) {
return { type: 'Mobile GPU', discrete: false };
} else if (r.includes('microsoft') || r.includes('basic')) {
return { type: 'Software Renderer', discrete: false };
}
return { type: 'Unknown', discrete: false };
}
// 获取屏幕信息
getScreenInfo() {
return {
width: window.screen.width,
height: window.screen.height,
colorDepth: window.screen.colorDepth,
pixelDepth: window.screen.pixelDepth,
devicePixelRatio: window.devicePixelRatio || 1,
orientation: window.screen.orientation ? window.screen.orientation.type : 'unknown'
};
}
// 获取所有系统信息
getAllInfo() {
return {
...this.info,
screen: this.getScreenInfo(),
userAgent: navigator.userAgent,
platform: navigator.platform,
language: navigator.language,
languages: navigator.languages,
cookiesEnabled: navigator.cookieEnabled,
online: navigator.onLine,
javaEnabled: navigator.javaEnabled ? navigator.javaEnabled() : false,
pdfViewerEnabled: navigator.pdfViewerEnabled || false,
doNotTrack: navigator.doNotTrack || 'unknown',
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
dateTimeFormat: new Date().toString()
};
}
// 格式化输出
formatAsText() {
const info = this.getAllInfo();
let output = '========== 系统信息 ==========\n\n';
// 浏览器信息
output += '=== 浏览器信息 ===\n';
output += `浏览器: ${info.browser.name} ${info.browser.version}\n`;
output += `完整版本: ${info.browser.fullVersion}\n`;
output += `用户代理: ${info.userAgent}\n\n`;
// 操作系统信息
output += '=== 操作系统信息 ===\n';
output += `系统: ${info.os.name} ${info.os.version}\n`;
output += `架构: ${info.os.architecture}\n`;
output += `平台: ${info.platform}\n\n`;
// 硬件信息
output += '=== 硬件信息 ===\n';
output += `逻辑核心数: ${info.hardware.logicalCores}\n`;
output += `设备内存: ${info.hardware.deviceMemory}\n`;
output += `最大触摸点数: ${info.hardware.maxTouchPoints}\n\n`;
// 屏幕信息
output += '=== 屏幕信息 ===\n';
output += `分辨率: ${info.screen.width} × ${info.screen.height}\n`;
output += `设备像素比: ${info.screen.devicePixelRatio}\n`;
output += `颜色深度: ${info.screen.colorDepth}\n`;
output += `像素深度: ${info.screen.pixelDepth}\n`;
output += `方向: ${info.screen.orientation}\n\n`;
// WebGL信息
output += '=== WebGL 信息 ===\n';
output += `WebGL 支持: ${info.webgl.supported ? '是' : '否'}\n`;
if (info.webgl.supported) {
output += `WebGL 版本: ${info.webgl.version}\n`;
output += `显卡型号: ${info.webgl.renderer}\n`;
output += `显卡厂商: ${info.webgl.vendor}\n`;
output += `着色语言: ${info.webgl.shadingLanguage}\n`;
if (info.webgl.gpuType) {
output += `GPU 类型: ${info.webgl.gpuType.type}\n`;
output += `独立显卡: ${info.webgl.gpuType.discrete ? '是' : '否'}\n`;
}
output += `性能等级: ${info.webgl.performance.tier}\n`;
output += `支持特性: ${info.webgl.performance.features.join(', ')}\n`;
if (info.webgl.memoryInfo.estimatedMemory !== 'Unknown') {
output += `显存估计: ${info.webgl.memoryInfo.estimatedMemory}\n`;
}
if (info.webgl.memoryInfo.maxTextureSize) {
output += `最大纹理尺寸: ${info.webgl.memoryInfo.maxTextureSize}\n`;
}
output += `WebGL 扩展数: ${info.webgl.extensions.length}\n`;
}
// 其他信息
output += '\n=== 其他信息 ===\n';
output += `语言: ${info.language}\n`;
output += `支持语言: ${info.languages.join(', ')}\n`;
output += `时区: ${info.timezone}\n`;
output += `Cookie 支持: ${info.cookiesEnabled ? '是' : '否'}\n`;
output += `在线状态: ${info.online ? '在线' : '离线'}\n`;
output += `Java 支持: ${info.javaEnabled ? '是' : '否'}\n`;
output += `PDF 查看器: ${info.pdfViewerEnabled ? '支持' : '不支持'}\n`;
output += `Do Not Track: ${info.doNotTrack}\n`;
output += `当前时间: ${info.dateTimeFormat}\n`;
return output;
}
// 创建HTML显示
createInfoHTML() {
const info = this.getAllInfo();
let html = `
<div class="system-info">
<h2>系统信息</h2>
<div class="info-section">
<h3>🌐 浏览器信息</h3>
<table>
<tr><td>浏览器</td><td>${info.browser.name} ${info.browser.version}</td></tr>
<tr><td>用户代理</td><td><code>${info.userAgent}</code></td></tr>
<tr><td>平台</td><td>${info.platform}</td></tr>
</table>
</div>
<div class="info-section">
<h3>💻 操作系统</h3>
<table>
<tr><td>系统</td><td>${info.os.name} ${info.os.version}</td></tr>
<tr><td>架构</td><td>${info.os.architecture}</td></tr>
<tr><td>语言</td><td>${info.language}</td></tr>
<tr><td>时区</td><td>${info.timezone}</td></tr>
</table>
</div>
<div class="info-section">
<h3>🖥 硬件信息</h3>
<table>
<tr><td>CPU 核心数</td><td>${info.hardware.logicalCores}</td></tr>
<tr><td>设备内存</td><td>${info.hardware.deviceMemory}</td></tr>
<tr><td>屏幕分辨率</td><td>${info.screen.width} × ${info.screen.height}</td></tr>
<tr><td>设备像素比</td><td>${info.screen.devicePixelRatio}</td></tr>
</table>
</div>
`;
if (info.webgl.supported) {
html += `
<div class="info-section">
<h3>🎮 WebGL & 显卡信息</h3>
<table>
<tr><td>WebGL 支持</td><td> </td></tr>
<tr><td>WebGL 版本</td><td>${info.webgl.version}</td></tr>
<tr><td>显卡型号</td><td><strong>${info.webgl.renderer}</strong></td></tr>
<tr><td>显卡厂商</td><td>${info.webgl.vendor}</td></tr>
<tr><td>GPU 类型</td><td>${info.webgl.gpuType.type} ${info.webgl.gpuType.discrete ? '' : ''}</td></tr>
<tr><td>着色语言</td><td>${info.webgl.shadingLanguage}</td></tr>
<tr><td>性能等级</td><td><span class="perf-${info.webgl.performance.tier}">${info.webgl.performance.tier}</span></td></tr>
<tr><td>WebGL 扩展数</td><td>${info.webgl.extensions.length} </td></tr>
`;
if (info.webgl.memoryInfo.estimatedMemory !== 'Unknown') {
html += `<tr><td>显存估计</td><td>${info.webgl.memoryInfo.estimatedMemory}</td></tr>`;
}
html += `</table></div>`;
} else {
html += `
<div class="info-section">
<h3>🎮 WebGL & 显卡信息</h3>
<p style="color: red;"> WebGL 不支持</p>
</div>
`;
}
html += `</div>`;
return html;
}
deepSortObject(obj) {
if (obj === null || typeof obj !== 'object') {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(deepSortObject);
}
const sorted = {};
Object.keys(obj).sort().forEach(key => {
sorted[key] = this.deepSortObject(obj[key]);
});
return sorted;
}
getCanonicalString(obj) {
if (typeof obj !== 'object' || obj === null) {
return JSON.stringify(obj);
}
const sorted = this.deepSortObject(obj);
return JSON.stringify(sorted);
}
// 简单哈希函数
simpleHash(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash;
}
return hash;
}
// 简单SHA-256模拟
simpleSHA256(str) {
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash;
}
const hashArray = [];
for (let i = 0; i < 8; i++) {
hashArray[i] = (hash + i * 2654435761) >>> 0;
}
return hashArray;
}
// 格式化哈希为GUID
formatHashAsGuid(hashArray) {
const hexParts = hashArray.map(h => h.toString(16).padStart(8, '0'));
return `${hexParts[0]}${hexParts[1].substring(0, 4)}-${hexParts[1].substring(4)}-${hexParts[2].substring(0, 4)}-${hexParts[3].substring(0, 4)}-${hexParts[3].substring(4)}${hexParts[4]}${hexParts[5]}`;
}
// 1. 确定性哈希算法
objectToGuidDeterministic(obj) {
const canonicalString = this.getCanonicalString(obj);
const hash = this.simpleSHA256(canonicalString);
return this.formatHashAsGuid(hash).toUpperCase();
}
// 2. 伪随机算法
getSeedFromObject(obj) {
const str = JSON.stringify(obj);
return this.simpleHash(str);
}
createSeededRandom(seed) {
let state = seed;
return function () {
state = (state * 1664525 + 1013904223) >>> 0;
return (state & 0x3FFFFFFF) / 0x3FFFFFFF;
};
}
generateVersion4Guid(randomFn) {
let guid = '';
for (let i = 0; i < 32; i++) {
if (i === 8 || i === 12 || i === 16 || i === 20) {
guid += '-';
}
if (i === 12) {
guid += '4';
} else if (i === 16) {
const variant = Math.floor(randomFn() * 4);
guid += (8 + variant).toString(16).toUpperCase();
} else {
const randomHex = Math.floor(randomFn() * 16).toString(16);
guid += randomHex;
}
}
return guid.toUpperCase();
}
objectToGuidPseudorandom(obj) {
const seed = this.getSeedFromObject(obj);
const prng = this.createSeededRandom(seed);
return this.generateVersion4Guid(prng);
}
// 3. Crypto API算法同步版本
objectToGuidCryptoSync(obj) {
try {
const str = this.getCanonicalString(obj);
let hash = 0;
for (let i = 0; i < str.length; i++) {
const char = str.charCodeAt(i);
hash = ((hash << 5) - hash) + char;
hash = hash & hash;
}
const bytes = new Array(16);
for (let i = 0; i < 16; i++) {
bytes[i] = (hash + i * 2654435761) & 0xFF;
}
bytes[6] = (bytes[6] & 0x0F) | 0x40;
bytes[8] = (bytes[8] & 0x3F) | 0x80;
return bytes.map(b => b.toString(16).padStart(2, '0'))
.join('')
.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5')
.toUpperCase();
} catch (error) {
return this.objectToGuidDeterministic(obj);
}
}
// 4. 组合算法
combineComponents(deterministicHash, namespaceHash, timestamp, randomComponent) {
const hashDigits = deterministicHash.replace(/-/g, '');
const bytes = new Array(16);
for (let i = 0; i < 16; i++) {
const hashByte = parseInt(hashDigits.substr(i * 2, 2), 16) || 0;
const nsByte = (namespaceHash >> (i * 2)) & 0xFF;
const timeByte = (timestamp >> (i * 2)) & 0xFF;
const randomByte = parseInt(randomComponent.substr(i % 8, 1), 16) || 0;
bytes[i] = (hashByte ^ nsByte ^ timeByte ^ randomByte) & 0xFF;
}
bytes[6] = (bytes[6] & 0x0F) | 0x40;
bytes[8] = (bytes[8] & 0x3F) | 0x80;
return bytes.map(b => b.toString(16).padStart(2, '0'))
.join('')
.replace(/(.{8})(.{4})(.{4})(.{4})(.{12})/, '$1-$2-$3-$4-$5')
.toUpperCase();
}
objectToGuidCombined(obj, namespace = '') {
const deterministicHash = this.objectToGuidDeterministic(obj);
const namespaceHash = namespace ? this.simpleHash(namespace) : 0;
const timestamp = Date.now();
const randomComponent = Math.random().toString(16).substr(2, 8);
return this.combineComponents(deterministicHash, namespaceHash, timestamp, randomComponent);
}
// 主生成函数
async generateGuid(inputText, inputType, algorithmType = 'deterministic') {
let obj;
try {
if (inputType === 'json') {
obj = JSON.parse(inputText);
} else {
obj = inputText
}
} catch (error) {
return error;
}
let guid;
let algorithmName;
try {
switch (algorithmType) {
case 'deterministic':
guid = this.objectToGuidDeterministic(obj);
algorithmName = '确定性哈希算法';
break;
case 'pseudorandom':
guid = this.objectToGuidPseudorandom(obj);
algorithmName = '伪随机算法';
break;
case 'crypto':
guid = this.objectToGuidCryptoSync(obj);
algorithmName = 'Crypto API算法';
break;
case 'combined':
guid = this.objectToGuidCombined(obj, 'example-namespace');
algorithmName = '组合算法';
break;
default:
guid = '未知算法';
algorithmName = '未知';
}
return guid;
} catch (error) {
return error
}
}
}
if (typeof module !== 'undefined' && module.exports) {
module.exports = SystemInfo;
} else if (typeof window !== 'undefined') {
window.SystemInfo = SystemInfo;
}

View File

@ -1,382 +0,0 @@
class Crc32 {
constructor() {
this.crc = -1
}
append(data) {
var crc = this.crc | 0; var table = this.table
for (var offset = 0, len = data.length | 0; offset < len; offset++) {
crc = (crc >>> 8) ^ table[(crc ^ data[offset]) & 0xFF]
}
this.crc = crc
}
get() {
return ~this.crc
}
}
Crc32.prototype.table = (() => {
var i; var j; var t; var table = []
for (i = 0; i < 256; i++) {
t = i
for (j = 0; j < 8; j++) {
t = (t & 1)
? (t >>> 1) ^ 0xEDB88320
: t >>> 1
}
table[i] = t
}
return table
})()
const getDataHelper = byteLength => {
var uint8 = new Uint8Array(byteLength)
return {
array: uint8,
view: new DataView(uint8.buffer)
}
}
const ZIP_SIGNATURE_LOCAL = 0x04034b50
const ZIP_SIGNATURE_CENTRAL = 0x02014b50
const ZIP_SIGNATURE_EOCD = 0x06054b50
const ZIP_SIGNATURE_ZIP64_EOCD = 0x06064b50
const ZIP_SIGNATURE_ZIP64_LOCATOR = 0x07064b50
const ZIP64_MAGIC = 0xFFFFFFFF
function u16(view, offset, value) { view.setUint16(offset, value, true) }
function u32(view, offset, value) { view.setUint32(offset, value >>> 0, true) }
function concatUint8(chunks, total) {
const out = new Uint8Array(total)
let off = 0
for (const c of chunks) {
out.set(c, off)
off += c.length
}
return out
}
function createWriter(underlyingSource) {
const files = Object.create(null)
const filenames = []
const encoder = new TextEncoder() // 保持UTF-8编码
let offset = 0 // bytes written to output so far
let activeZipIndex = 0
let ctrl
let activeZipObject
let closed = false
function processNextChunk() {
if (!activeZipObject) return
// directory entry: just local header + immediate footer
if (activeZipObject.directory) {
if (!activeZipObject.headerWritten) {
activeZipObject.writeLocalHeader()
activeZipObject.headerWritten = true
}
if (!activeZipObject.footerWritten) {
activeZipObject.writeDataDescriptor() // will be zeros
activeZipObject.footerWritten = true
next()
}
return
}
if (!activeZipObject.reader) {
if (!activeZipObject.fileLike || !activeZipObject.fileLike.stream) {
next()
return
}
activeZipObject.crc = new Crc32()
activeZipObject.reader = activeZipObject.fileLike.stream().getReader()
activeZipObject.writeLocalHeader()
activeZipObject.headerWritten = true
return
}
return activeZipObject.reader.read().then(({ done, value }) => {
if (done) {
activeZipObject.writeDataDescriptor()
activeZipObject.footerWritten = true
next()
return
}
const chunk = value instanceof Uint8Array ? value : new Uint8Array(value)
activeZipObject.crc.append(chunk)
activeZipObject.uncompressedLength += chunk.length
activeZipObject.compressedLength += chunk.length
ctrl.enqueue(chunk)
offset += chunk.length
})
}
function next() {
activeZipIndex++
activeZipObject = files[filenames[activeZipIndex]]
if (activeZipObject) {
processNextChunk()
} else if (closed) {
closeZip()
}
}
function dosDateTime(date) {
const dt = new Date(date)
const time = ((dt.getHours() << 11) | (dt.getMinutes() << 5) | (dt.getSeconds() / 2)) & 0xFFFF
const d = (((dt.getFullYear() - 1980) << 9) | ((dt.getMonth() + 1) << 5) | dt.getDate()) & 0xFFFF
return { time, date: d }
}
const zipWriter = {
enqueue(fileLike) {
if (closed) throw new TypeError('Cannot enqueue after close()')
let name = String(fileLike.name || '').trim()
if (!name) throw new Error('Missing file name')
if (fileLike.directory && !name.endsWith('/')) name += '/'
if (files[name]) throw new Error('File already exists.')
const nameBuf = encoder.encode(name) // 保持UTF-8编码
const commentBuf = encoder.encode(fileLike.comment || '')
const { time, date } = dosDateTime(typeof fileLike.lastModified === 'undefined' ? Date.now() : fileLike.lastModified)
const zipObject = (files[name] = {
fileLike,
directory: !!fileLike.directory,
nameBuf,
comment: commentBuf,
time,
date,
// tracked
offset: 0,
crc: null,
compressedLength: 0,
uncompressedLength: 0,
headerWritten: false,
footerWritten: false,
reader: null,
// whether sizes/offset require ZIP64
needsZip64() {
return (
this.uncompressedLength > ZIP64_MAGIC ||
this.compressedLength > ZIP64_MAGIC ||
this.offset > ZIP64_MAGIC
)
},
writeLocalHeader() {
this.offset = offset
// 关键修改设置通用位标记第11位0x0800表示文件名使用UTF-8编码
// 保留原0x0008数据描述符存在新增0x0800UTF-8编码
const generalPurposeBitFlag = 0x0808
const compressionMethod = 0 // store
const versionNeeded = this.needsZip64() ? 45 : 20 // 适配ZIP64
// We always use data descriptor; write zeros for crc/sizes in local header
const local = getDataHelper(30 + this.nameBuf.length)
u32(local.view, 0, ZIP_SIGNATURE_LOCAL)
u16(local.view, 4, versionNeeded)
u16(local.view, 6, generalPurposeBitFlag) // 应用UTF-8标记
u16(local.view, 8, compressionMethod)
u16(local.view, 10, this.time)
u16(local.view, 12, this.date)
u32(local.view, 14, 0)
u32(local.view, 18, 0)
u32(local.view, 22, 0)
u16(local.view, 26, this.nameBuf.length)
u16(local.view, 28, 0) // extra length
local.array.set(this.nameBuf, 30)
ctrl.enqueue(local.array)
offset += local.array.length
},
writeDataDescriptor() {
// data descriptor: optional signature + crc32 + sizes (32-bit or 64-bit)
const crc = this.crc ? this.crc.get() >>> 0 : 0
const useZip64 = this.needsZip64()
if (!useZip64) {
const dd = getDataHelper(16)
u32(dd.view, 0, 0x08074b50)
u32(dd.view, 4, crc)
u32(dd.view, 8, this.compressedLength)
u32(dd.view, 12, this.uncompressedLength)
ctrl.enqueue(dd.array)
offset += dd.array.length
} else {
// 24 bytes: sig + crc32 + compSize(8) + uncompSize(8)
const dd = getDataHelper(24)
u32(dd.view, 0, 0x08074b50)
u32(dd.view, 4, crc)
// BigInt writes
dd.view.setBigUint64(8, BigInt(this.compressedLength), true)
dd.view.setBigUint64(16, BigInt(this.uncompressedLength), true)
ctrl.enqueue(dd.array)
offset += dd.array.length
}
}
})
filenames.push(name)
if (!activeZipObject) {
activeZipObject = zipObject
processNextChunk()
}
},
close() {
if (closed) throw new TypeError('Cannot close twice')
closed = true
if (!activeZipObject) closeZip()
}
}
function closeZip() {
// Build central directory in memory then enqueue once.
const cdChunks = []
let cdSize = 0
for (const name of filenames) {
const file = files[name]
const useZip64 = file.needsZip64()
const versionMadeBy = useZip64 ? 45 : 20
const versionNeeded = useZip64 ? 45 : 20
// 关键修改中央目录也需要设置UTF-8标记
const generalPurposeBitFlag = 0x0808
const compressionMethod = 0
const crc = file.crc ? file.crc.get() >>> 0 : 0
const compressed32 = useZip64 ? ZIP64_MAGIC : file.compressedLength
const uncompressed32 = useZip64 ? ZIP64_MAGIC : file.uncompressedLength
const offset32 = useZip64 ? ZIP64_MAGIC : file.offset
// ZIP64 extra field if needed
let extra = new Uint8Array(0)
if (useZip64) {
// headerId(2)=0x0001, dataSize(2)=24, uncompressed(8), compressed(8), offset(8)
extra = new Uint8Array(4 + 24)
const ev = new DataView(extra.buffer)
u16(ev, 0, 0x0001)
u16(ev, 2, 24)
ev.setBigUint64(4, BigInt(file.uncompressedLength), true)
ev.setBigUint64(12, BigInt(file.compressedLength), true)
ev.setBigUint64(20, BigInt(file.offset), true)
}
const headerLen = 46 + file.nameBuf.length + extra.length + file.comment.length
const cd = getDataHelper(headerLen)
u32(cd.view, 0, ZIP_SIGNATURE_CENTRAL)
u16(cd.view, 4, versionMadeBy)
u16(cd.view, 6, versionNeeded)
u16(cd.view, 8, generalPurposeBitFlag) // 中央目录应用UTF-8标记
u16(cd.view, 10, compressionMethod)
u16(cd.view, 12, file.time)
u16(cd.view, 14, file.date)
u32(cd.view, 16, crc)
u32(cd.view, 20, compressed32)
u32(cd.view, 24, uncompressed32)
u16(cd.view, 28, file.nameBuf.length)
u16(cd.view, 30, extra.length)
u16(cd.view, 32, file.comment.length)
u16(cd.view, 34, 0) // disk number start
u16(cd.view, 36, 0) // internal attrs
// external file attrs: mark directory
u32(cd.view, 38, file.directory ? 0x10 : 0)
u32(cd.view, 42, offset32)
cd.array.set(file.nameBuf, 46)
if (extra.length) cd.array.set(extra, 46 + file.nameBuf.length)
if (file.comment.length) cd.array.set(file.comment, 46 + file.nameBuf.length + extra.length)
cdChunks.push(cd.array)
cdSize += cd.array.length
}
const centralDirectoryOffset = offset
const centralDirectory = concatUint8(cdChunks, cdSize)
ctrl.enqueue(centralDirectory)
offset += centralDirectory.length
const entries = filenames.length
const needsZip64ForArchive =
entries > 0xFFFF ||
centralDirectoryOffset > ZIP64_MAGIC ||
cdSize > ZIP64_MAGIC ||
offset > ZIP64_MAGIC
const tailChunks = []
let tailSize = 0
if (needsZip64ForArchive) {
// ZIP64 EOCD
const zip64eocd = getDataHelper(56)
u32(zip64eocd.view, 0, ZIP_SIGNATURE_ZIP64_EOCD)
zip64eocd.view.setBigUint64(4, BigInt(44), true) // remaining size
u16(zip64eocd.view, 12, 45)
u16(zip64eocd.view, 14, 45)
u32(zip64eocd.view, 16, 0)
u32(zip64eocd.view, 20, 0)
zip64eocd.view.setBigUint64(24, BigInt(entries), true)
zip64eocd.view.setBigUint64(32, BigInt(entries), true)
zip64eocd.view.setBigUint64(40, BigInt(cdSize), true)
zip64eocd.view.setBigUint64(48, BigInt(centralDirectoryOffset), true)
// ZIP64 locator
const locator = getDataHelper(20)
u32(locator.view, 0, ZIP_SIGNATURE_ZIP64_LOCATOR)
u32(locator.view, 4, 0)
locator.view.setBigUint64(8, BigInt(centralDirectoryOffset + cdSize), true) // offset of zip64eocd
u32(locator.view, 16, 1)
tailChunks.push(zip64eocd.array, locator.array)
tailSize += zip64eocd.array.length + locator.array.length
}
// EOCD
const eocd = getDataHelper(22)
u32(eocd.view, 0, ZIP_SIGNATURE_EOCD)
u16(eocd.view, 4, 0)
u16(eocd.view, 6, 0)
u16(eocd.view, 8, Math.min(entries, 0xFFFF))
u16(eocd.view, 10, Math.min(entries, 0xFFFF))
u32(eocd.view, 12, needsZip64ForArchive ? ZIP64_MAGIC : cdSize)
u32(eocd.view, 16, needsZip64ForArchive ? ZIP64_MAGIC : centralDirectoryOffset)
u16(eocd.view, 20, 0) // comment length
tailChunks.push(eocd.array)
tailSize += eocd.array.length
ctrl.enqueue(concatUint8(tailChunks, tailSize))
ctrl.close()
}
return new ReadableStream({
start: c => {
ctrl = c
underlyingSource.start && Promise.resolve(underlyingSource.start(zipWriter))
},
pull() {
return processNextChunk() || (
underlyingSource.pull &&
Promise.resolve(underlyingSource.pull(zipWriter))
)
}
})
}
window.ZIP = createWriter

View File

@ -112,7 +112,7 @@ export default {
this.currentTime = moment().format('YYYY-MM-DD HH:mm:ss') this.currentTime = moment().format('YYYY-MM-DD HH:mm:ss')
}, },
handleTitleClick() { handleTitleClick() {
if (!screenfull.isEnabled) { if (!screenfull.enabled) {
this.$message({ this.$message({
message: 'Your browser can not work', message: 'Your browser can not work',
type: 'warning' type: 'warning'

View File

@ -29,12 +29,8 @@
:src="item.previewImageUrl" :src="item.previewImageUrl"
fit="fill" fit="fill"
/> --> /> -->
<div class="imageBox" style="width: 72px;height:72px;">
<img class="image-preview" :src="item.previewImageUrl" crossorigin="anonymous" alt="" <img class="image-preview" :src="item.previewImageUrl" crossorigin="anonymous" alt=""
style="width: 72px;height:72px;" fit="fill" /> style="width: 72px;height:72px;" fit="fill">
<i class="el-icon-refresh" :title="$t('tip:refreshImage')"
@click.stop="refreshImage(item)"></i>
</div>
<div class="viewernavitextwrapper"> <div class="viewernavitextwrapper">
<div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;"> <div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
<div v-if="item.keySeries" style="color:red"> <div v-if="item.keySeries" style="color:red">
@ -87,8 +83,8 @@
{{ item.description }} {{ item.description }}
</div> </div>
<div v-if="!item.keySeries" style="padding: 1px;"> <div v-if="!item.keySeries" style="padding: 1px;">
{{ item.imageloadedArr.length <= item.instanceCount ? item.imageloadedArr.length : {{ item.imageloadedArr.length }}/{{ item.instanceCount }}
item.instanceCount }}/{{ item.instanceCount }} </div> </div>
</div> </div>
</div> </div>
@ -98,14 +94,11 @@
<div> <div>
<span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isReading') <span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isReading')
}}</span> }}</span>
<el-switch v-model="item.isReading" size="mini" <el-switch v-model="item.isReading" size="mini" @change="changeReadingStatus($event, item)" />
@change="changeReadingStatus($event, item)" />
</div> </div>
<div> <div>
<span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isDelete') <span style="font-size: 12px;margin-right: 5px">{{ $t('trials:audit:table:isDelete') }}</span>
}}</span> <el-switch v-model="item.isDeleted" size="mini" @change="changeDeleteStatus($event, item)" />
<el-switch v-model="item.isDeleted" size="mini"
@change="changeDeleteStatus($event, item)" />
</div> </div>
</div> </div>
<div <div
@ -140,7 +133,7 @@ import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader' import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
import dicomViewer from '@/components/Dicom/DicomViewer' import dicomViewer from '@/components/Dicom/DicomViewer'
import { getStudyInfo, getSeriesList } from '@/api/reading' import { getStudyInfo, getSeriesList } from '@/api/reading'
import { getInstanceList, getPatientSeriesList, setSeriesStatus, setInstanceStatus, updateImageResizePath } from '@/api/trials' import { getInstanceList, getPatientSeriesList, setSeriesStatus, setInstanceStatus } from '@/api/trials'
import requestPoolManager from '@/utils/request-pool' import requestPoolManager from '@/utils/request-pool'
import store from '@/store' import store from '@/store'
@ -251,62 +244,6 @@ export default {
workSpeedclose(true) workSpeedclose(true)
}, },
methods: { methods: {
async updateImageResizePath(data) {
try {
let res = await updateImageResizePath(data)
if (res.IsSuccess) {
this.$message.success(this.$t("message:tip:updateImageResizePath:success"))
}
} catch (err) {
console.log(err)
}
},
async refreshImage(item) {
let thumbnailPath = item.previewImageUrl.split(this.OSSclientConfig.basePath)[1]
let blob = await this.dicomToPng(item.imageIds[0])
let OSSclient = this.OSSclient
try {
let seriesRes = await OSSclient.put(thumbnailPath, blob)
if (seriesRes && seriesRes.url) {
let path = this.$getObjectName(seriesRes.url)
item.previewImageUrl = seriesRes.url
let data = {
seriesId: item.seriesId,
ImageResizePath: path
}
this.updateImageResizePath(data)
}
} catch (e) {
}
},
dicomToPng(imageId) {
return new Promise((resolve) => {
cornerstone.loadImage(imageId).then(async (image) => {
let width = image.columns, height = image.rows;
let canvas = document.createElement('canvas')
canvas.width = (width * 60) / height
canvas.height = 60
if (image) {
cornerstone.renderToCanvas(canvas, image)
// Canvas PNG
let blob = await this.canvasToBlob(canvas)
resolve(blob)
} else {
resolve()
}
})
}).catch((reason) => {
reason()
})
},
canvasToBlob(canvas) {
return new Promise((resolve) => {
canvas.toBlob((blob) => {
resolve(blob)
})
})
},
async loadStudy() { async loadStudy() {
let params = {} let params = {}
if (this.isPacs) { if (this.isPacs) {
@ -954,7 +891,6 @@ export default {
// //
this.seriesList[seriesIndex].loadStatus = true this.seriesList[seriesIndex].loadStatus = true
workSpeedclose() workSpeedclose()
localStorage.setItem("QCRiskControl", 1)
if (!this.isFromCRCUpload) { if (!this.isFromCRCUpload) {
this.loadAllImages() this.loadAllImages()
} }
@ -965,18 +901,7 @@ export default {
} }
</script> </script>
<style lang="scss" scoped> <style>
.imageBox {
position: relative;
i {
position: absolute;
top: 0;
left: 0;
cursor: pointer;
}
}
.viewerContainer .el-tabs--border-card { .viewerContainer .el-tabs--border-card {
background: none; background: none;
border: none; border: none;

View File

@ -45,12 +45,8 @@
style="position: relative;margin-bottom:5px;border-radius: 2px;border: 1px solid #404040;" style="position: relative;margin-bottom:5px;border-radius: 2px;border: 1px solid #404040;"
series-type="current" @click="showSeriesImage($event, index, i, series)"> series-type="current" @click="showSeriesImage($event, index, i, series)">
<div class="viewernavigatorwrapper"> <div class="viewernavigatorwrapper">
<div class="imageBox" style="width: 72px;height:72px;">
<img class="image-preview" :src="series.previewImageUrl" crossorigin="anonymous" alt="" <img class="image-preview" :src="series.previewImageUrl" crossorigin="anonymous" alt=""
style="width: 72px;height:72px;" fit="fill" /> style="width: 85px;height:85px;" fit="fill">
<i class="el-icon-refresh" :title="$t('tip:refreshImage')"
@click.stop="refreshImage(series)"></i>
</div>
<div class="viewernavitextwrapper"> <div class="viewernavitextwrapper">
<div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;"> <div style="padding: 1px 5px 1px 1px;display: flex;justify-content: space-between;">
<div>#{{ series.seriesNumber }}</div> <div>#{{ series.seriesNumber }}</div>
@ -117,8 +113,8 @@
</div> </div>
</el-tooltip> </el-tooltip>
<div style="padding: 1px;"> <div style="padding: 1px;">
{{ series.imageloadedArr.length <= series.instanceCount ? series.imageloadedArr.length : {{ series.imageloadedArr.length }}/{{ series.instanceCount }}
series.instanceCount }}/{{ series.instanceCount }} </div> </div>
<div /> <div />
</div> </div>
</div> </div>
@ -188,12 +184,8 @@
<div class="viewernavigatorwrapper" <div class="viewernavigatorwrapper"
style="position: relative;border:1px solid #434343;" series-type="relation" style="position: relative;border:1px solid #434343;" series-type="relation"
@click="showRelationSeriesImage($event, seriesItem, studyIndex, index)"> @click="showRelationSeriesImage($event, seriesItem, studyIndex, index)">
<div class="imageBox" style="width: 72px;height:72px;"> <img class="image-preview" :src="seriesItem.previewImageUrl" crossorigin="anonymous"
<img class="image-preview" :src="seriesItem.previewImageUrl" alt="" style="width: 85px;height:85px;" fit="fill">
crossorigin="anonymous" alt="" style="width: 72px;height:72px;" fit="fill" />
<i class="el-icon-refresh" :title="$t('tip:refreshImage')"
@click.stop="refreshImage(item)"></i>
</div>
<div class="viewernavitextwrapper"> <div class="viewernavitextwrapper">
<div <div
@ -281,7 +273,7 @@ import * as cornerstone from 'cornerstone-core'
import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader' import * as cornerstoneWADOImageLoader from 'cornerstone-wado-image-loader'
import dicomViewer from '@/components/Dicom/DicomViewer' import dicomViewer from '@/components/Dicom/DicomViewer'
import { getVisitStudyList, getAllRelationStudyList, getSeriesList } from '@/api/reading' import { getVisitStudyList, getAllRelationStudyList, getSeriesList } from '@/api/reading'
import { setSeriesStatus, setInstanceStatus, updateImageResizePath } from '@/api/trials' import { setSeriesStatus, setInstanceStatus } from '@/api/trials'
import { getTaskUploadedDicomStudyList } from '@/api/reading' import { getTaskUploadedDicomStudyList } from '@/api/reading'
import requestPoolManager from '@/utils/request-pool' import requestPoolManager from '@/utils/request-pool'
import store from '@/store' import store from '@/store'
@ -366,62 +358,6 @@ export default {
workSpeedclose(true) workSpeedclose(true)
}, },
methods: { methods: {
async updateImageResizePath(data) {
try {
let res = await updateImageResizePath(data)
if (res.IsSuccess) {
this.$message.success(this.$t("message:tip:updateImageResizePath:success"))
}
} catch (err) {
console.log(err)
}
},
async refreshImage(item) {
let thumbnailPath = item.previewImageUrl.split(this.OSSclientConfig.basePath)[1]
let blob = await this.dicomToPng(item.imageIds[0])
let OSSclient = this.OSSclient
try {
let seriesRes = await OSSclient.put(thumbnailPath, blob)
if (seriesRes && seriesRes.url) {
let path = this.$getObjectName(seriesRes.url)
item.previewImageUrl = seriesRes.url
let data = {
seriesId: item.seriesId,
ImageResizePath: path
}
this.updateImageResizePath(data)
}
} catch (e) {
}
},
dicomToPng(imageId) {
return new Promise((resolve) => {
cornerstone.loadImage(imageId).then(async (image) => {
let width = image.columns, height = image.rows;
let canvas = document.createElement('canvas')
canvas.width = (width * 60) / height
canvas.height = 60
if (image) {
cornerstone.renderToCanvas(canvas, image)
// Canvas PNG
let blob = await this.canvasToBlob(canvas)
resolve(blob)
} else {
resolve()
}
})
}).catch((reason) => {
reason()
})
},
canvasToBlob(canvas) {
return new Promise((resolve) => {
canvas.toBlob((blob) => {
resolve(blob)
})
})
},
// 访 // 访
async getStudiesInfo() { async getStudiesInfo() {
this.studyList = [] this.studyList = []
@ -1004,25 +940,13 @@ export default {
this.loadAllImages() this.loadAllImages()
} }
workSpeedclose() workSpeedclose()
localStorage.setItem("QCRiskControl", 1)
} }
} }
} }
} }
</script> </script>
<style lang="scss"> <style>
.imageBox {
position: relative;
i {
position: absolute;
top: 0;
left: 0;
cursor: pointer;
}
}
.viewerContainer .el-tabs--border-card { .viewerContainer .el-tabs--border-card {
background: none; background: none;
border: none; border: none;

View File

@ -106,16 +106,6 @@ export default {
isTrial: { isTrial: {
type: Boolean, type: Boolean,
default: false default: false
},
isExternal: {
type: Boolean,
default: false
},
ExternalList: {
type: Array,
default: () => {
return []
}
} }
}, },
data() { data() {
@ -132,8 +122,7 @@ export default {
rowData: {}, rowData: {},
list: [], list: [],
searchData: defaultSearchData(), searchData: defaultSearchData(),
title: this.$t('dictionary:signature:fileList'), title: this.$t('dictionary:signature:fileList')
loading: false
} }
}, },
watch: { watch: {
@ -142,16 +131,6 @@ export default {
this.getList() this.getList()
}, },
immediate: true, immediate: true,
},
isExternal: {
handler() {
if (this.isExternal) {
this.list = this.ExternalList
this.rowData = this.list[0] || {}
this.title = this.$t('dictionary:signature:view')
}
},
immediate: true
} }
}, },
methods: { methods: {
@ -166,7 +145,6 @@ export default {
}, },
async getList() { async getList() {
try { try {
if (this.isExternal) return
if (!this.SystemDocumentId) return false if (!this.SystemDocumentId) return false
this.loading = true this.loading = true
if (!this.isTrial) { if (!this.isTrial) {

View File

@ -1,118 +1,75 @@
<template> <template>
<div class="app-container my_menu"> <div class="app-container my_menu">
<el-form :inline="true"> <el-form :inline="true">
<!-- 模块 --> <el-form-item label="模块">
<el-form-item :label="$t('audit:label:moduleType')"> <el-select v-model="queryParams.ModuleTypeId" placeholder="模块" clearable>
<el-select v-model="queryParams.ModuleTypeId" clearable>
<el-option v-for="item of dict.type.ModuleType" :key="`ModuleTypeId${item.value}`" :value="item.value" <el-option v-for="item of dict.type.ModuleType" :key="`ModuleTypeId${item.value}`" :value="item.value"
:label="item.raw.ValueCN" /> :label="item.raw.ValueCN" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<el-button type="primary" icon="el-icon-search" @click="handleQuery"> <el-button type="primary" icon="el-icon-search" @click="handleQuery"></el-button>
{{ $t('common:button:search') }} <el-button type="primary" icon="el-icon-plus" @click="handleAdd"></el-button>
</el-button>
<el-button type="primary" icon="el-icon-plus" @click="handleAdd">
{{ $t('common:button:new') }}
</el-button>
</el-form-item> </el-form-item>
</el-form> </el-form>
<div> <div>
<!-- 展开/折叠 --> <el-button type="info" plain icon="el-icon-sort" size="mini" @click="toggleExpandAll">/</el-button>
<el-button type="info" plain icon="el-icon-sort" size="mini" @click="toggleExpandAll">
{{ $t('audit:button:fold') }}
</el-button>
</div> </div>
<el-table v-if="refreshTable" v-adaptive="{ bottomOffset: 45 }" v-loading="loading" height="100" :data="menuList" <el-table v-if="refreshTable" v-adaptive="{ bottomOffset: 45 }" v-loading="loading" height="100" :data="menuList"
:default-expand-all="isExpandAll" row-key="Id" :tree-props="{ children: 'Children', hasChildren: 'hasChildren' }"> :default-expand-all="isExpandAll" row-key="Id" :tree-props="{ children: 'Children', hasChildren: 'hasChildren' }">
<!-- 模块 --> <el-table-column prop="ModuleTypeValueCN" label="模块" show-overflow-tooltip align="left" min-width="230px" />
<el-table-column prop="ModuleTypeValueCN" :label="$t('audit:label:moduleType')" show-overflow-tooltip align="left" min-width="230px" /> <el-table-column prop="Description" label="操作名称" :show-overflow-tooltip="true" min-width="200px">
<!-- 操作名称 -->
<el-table-column prop="Description" :label="$t('audit:label:desc')" :show-overflow-tooltip="true" min-width="200px">
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ scope.row.DescriptionCN }}{{ scope.row.Description }}</span> <span>{{ scope.row.DescriptionCN }}{{ scope.row.Description }}</span>
</template> </template>
</el-table-column> </el-table-column>
<!-- 其他 --> <el-table-column prop="DescriptionCN" label="其他" :show-overflow-tooltip="true" min-width="140px">
<el-table-column prop="DescriptionCN" :label="$t('audit:label:descCN')" :show-overflow-tooltip="true" min-width="140px">
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 被禁用 -->
<!-- -->
<span v-if="!scope.row.IsEnable" <span v-if="!scope.row.IsEnable"
style="cursor:pointer;line-height:20px;text-align:center;font-size: 12px;display: inline-block;width: 20px;height: 20px;border-radius: 50%;background: #DC143C;color: #fff;" style="cursor:pointer;line-height:20px;text-align:center;font-size: 12px;display: inline-block;width: 20px;height: 20px;border-radius: 50%;background: #DC143C;color: #fff;"
:title="$t('audit:label:disable')">{{ $t('audit:label:disable1') }}</span> title="被禁用"></span>
<!-- 需要电签 -->
<span v-if="scope.row.IsHaveSign" <span v-if="scope.row.IsHaveSign"
style="cursor:pointer;line-height:20px;text-align:center;font-size: 12px;display: inline-block;width: 20px;height: 20px;border-radius: 50%;background: #428bca;color: #fff;" style="cursor:pointer;line-height:20px;text-align:center;font-size: 12px;display: inline-block;width: 20px;height: 20px;border-radius: 50%;background: #428bca;color: #fff;"
:title="$t('audit:label:needSign')">{{ $t('audit:label:needSign1') }}</span> title="需要电签"></span>
<!-- 需要原因 -->
<span v-if="scope.row.IsHaveReason" <span v-if="scope.row.IsHaveReason"
style="cursor:pointer;line-height:20px;text-align:center;font-size: 12px;display: inline-block;width: 20px;height: 20px;border-radius: 50%;background: #fab6b6;color: #fff;" style="cursor:pointer;line-height:20px;text-align:center;font-size: 12px;display: inline-block;width: 20px;height: 20px;border-radius: 50%;background: #fab6b6;color: #fff;"
:title="$t('audit:label:needReason')">{{ $t('audit:label:needReason1') }}</span> title="需要原因"></span>
<!-- 已经记录 -->
<span v-if="scope.row.IsFinish" <span v-if="scope.row.IsFinish"
style="cursor:pointer;line-height:20px;text-align:center;font-size: 12px;display: inline-block;width: 20px;height: 20px;border-radius: 50%;background:#3CB371;color: #fff;" style="cursor:pointer;line-height:20px;text-align:center;font-size: 12px;display: inline-block;width: 20px;height: 20px;border-radius: 50%;background:#3CB371;color: #fff;"
:title="$t('audit:label:isFinish')">{{ $t('audit:label:isFinish1') }}</span> title="已经记录"></span>
<!-- 核对完 -->
<span v-if="scope.row.IsJoinPlan" <span v-if="scope.row.IsJoinPlan"
style="cursor:pointer;line-height:20px;text-align:center;font-size: 12px;display: inline-block;width: 20px;height: 20px;border-radius: 50%;background: #FFA500;color: #fff;" style="cursor:pointer;line-height:20px;text-align:center;font-size: 12px;display: inline-block;width: 20px;height: 20px;border-radius: 50%;background: #FFA500;color: #fff;"
:title="$t('audit:label:isJoinPlan')">{{ $t('audit:label:isJoinPlan1') }}</span> title="核对完"></span>
</template> </template>
</el-table-column> </el-table-column>
<!-- 标识 --> <el-table-column prop="Identification" label="标识" :show-overflow-tooltip="true" min-width="200px" />
<el-table-column prop="Identification" :label="$t('audit:label:identification')" :show-overflow-tooltip="true" min-width="200px" /> <el-table-column prop="OptTypeValueCN" label="操作类型" show-overflow-tooltip width="100px" />
<!-- 操作类型 --> <el-table-column prop="ObjectTypeValueCN" label="对象类型" show-overflow-tooltip min-width="100px" />
<el-table-column prop="OptTypeValueCN" :label="$t('audit:label:optType')" show-overflow-tooltip width="100px" /> <el-table-column prop="ChildrenTypeValueCN" label="数据类型" show-overflow-tooltip min-width="100px" />
<!-- 对象类型 --> <el-table-column prop="Sort" label="显示顺序" min-width="80" show-overflow-tooltip />
<el-table-column prop="ObjectTypeValueCN" :label="$t('audit:label:objectType')" show-overflow-tooltip min-width="100px" /> <el-table-column label="启用" align="center" prop="CreateTime" min-width="80">
<!-- 数据类型 -->
<el-table-column prop="ChildrenTypeValueCN" :label="$t('audit:label:dataType')" show-overflow-tooltip min-width="100px" />
<!-- 显示顺序 -->
<el-table-column prop="Sort" :label="$t('audit:label:sort')" min-width="80" show-overflow-tooltip />
<!-- 启用 -->
<el-table-column :label="$t('audit:label:isEnable')" align="center" prop="CreateTime" min-width="80">
<!-- 启用/禁用 -->
<template slot-scope="scope"> <template slot-scope="scope">
<!-- <el-tag v-if="scope.row.IsEnable" size="success"></el-tag> <el-tag v-if="scope.row.IsEnable" size="success"></el-tag>
<el-tag v-else size="danger">禁用</el-tag> --> <el-tag v-else size="danger">禁用</el-tag>
<el-tag :type="!scope.row.IsEnable ? 'info' : ''">
{{ $fd('IsEnable', scope.row.IsEnable) }}
</el-tag>
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('common:action:action')" align="center" fixed="right" min-width="340" class-name="small-padding fixed-width"> <el-table-column label="操作" align="center" fixed="right" min-width="340" class-name="small-padding fixed-width">
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 上移 -->
<el-button <el-button
v-if="scope.row.ModuleTypeValueCN && scope.row.ObjectTypeValueCN && scope.row.OptTypeValueCN && scope.row.ChildrenTypeValueCN" v-if="scope.row.ModuleTypeValueCN && scope.row.ObjectTypeValueCN && scope.row.OptTypeValueCN && scope.row.ChildrenTypeValueCN"
type="text" @click="handleUpMove(scope.row)" type="text" @click="handleUpMove(scope.row)">上移</el-button>
> <el-button type="text" @click="handleUpdate(scope.row)"></el-button>
{{ $t('audit:button:upward') }}
</el-button>
<!-- 修改 -->
<el-button type="text" @click="handleUpdate(scope.row)">
{{ $t('audit:button:modify') }}
</el-button>
<!-- 新增 -->
<el-button <el-button
v-if="!(scope.row.ModuleTypeValueCN && scope.row.ObjectTypeValueCN && scope.row.OptTypeValueCN && scope.row.ChildrenTypeValueCN)" v-if="!(scope.row.ModuleTypeValueCN && scope.row.ObjectTypeValueCN && scope.row.OptTypeValueCN && scope.row.ChildrenTypeValueCN)"
type="text" @click="handleAdd(scope.row)">{{ $t('common:button:new') }}</el-button> type="text" @click="handleAdd(scope.row)">新增</el-button>
<!-- Children -->
<el-button <el-button
v-if="scope.row.ModuleTypeValueCN && scope.row.ObjectTypeValueCN && scope.row.OptTypeValueCN && scope.row.ChildrenTypeValueCN" v-if="scope.row.ModuleTypeValueCN && scope.row.ObjectTypeValueCN && scope.row.OptTypeValueCN && scope.row.ChildrenTypeValueCN"
type="text" @click="handleChildren(scope.row)" type="text" @click="handleChildren(scope.row)">Children</el-button>
>
{{ $t('audit:button:children') }}
</el-button>
<!-- 复制到 -->
<el-button <el-button
v-if="scope.row.ModuleTypeValueCN && scope.row.ObjectTypeValueCN && scope.row.OptTypeValueCN && scope.row.ChildrenTypeValueCN" v-if="scope.row.ModuleTypeValueCN && scope.row.ObjectTypeValueCN && scope.row.OptTypeValueCN && scope.row.ChildrenTypeValueCN"
type="text" @click="handleCopy(scope.row)"> type="text" @click="handleCopy(scope.row)">复制到</el-button>
{{ $t('audit:button:copyTo') }} <el-button type="text" @click="handleDelete(scope.row)"></el-button>
</el-button>
<!-- 删除 -->
<el-button type="text" @click="handleDelete(scope.row)">{{ $t('common:button:delete') }}</el-button>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
@ -234,17 +191,6 @@
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col :span="24">
<el-form-item>
<span slot="label">
适用的标准
</span>
<el-select v-model="form.ApplyCriterionList" placeholder="" clearable multiple>
<el-option v-for="item in $d.CriterionType" :key="item.id" :label="item.label" :value="item.value">
</el-option>
</el-select>
</el-form-item>
</el-col>
<el-col v-show="form.ConfigType === 'C' && title !== '复制'" :span="12"> <el-col v-show="form.ConfigType === 'C' && title !== '复制'" :span="12">
<el-form-item> <el-form-item>
<span slot="label"> <span slot="label">
@ -1062,7 +1008,6 @@ export default {
ValueCN: null, ValueCN: null,
EnumType: '', EnumType: '',
IsShowByTrialConfig: false, IsShowByTrialConfig: false,
ApplyCriterionList: [],
TrialConfigRelyFieldName: null, TrialConfigRelyFieldName: null,
Identification: null, Identification: null,
IsForwardPosition: false, IsForwardPosition: false,

View File

@ -3,11 +3,11 @@
<!-- 搜索框 --> <!-- 搜索框 -->
<div class="search"> <div class="search">
<el-form :inline="true" class="base-search-form"> <el-form :inline="true" class="base-search-form">
<el-form-item :label="$t('dic:all:label:code')"> <el-form-item label="字典表名称:">
<el-input v-model="searchData.Code" clearable style="width:120px;" /> <el-input v-model="searchData.Code" clearable style="width:120px;" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('dic:all:label:group')"> <el-form-item label="字典分组:">
<el-select v-model="searchData.ConfigTypeId" clearable size="small"> <el-select v-model="searchData.ConfigTypeId" placeholder="字典分组" clearable size="small">
<el-option v-for="item of basicDicList" :key="item.Id" :value="item.Id" :label="item.Code" /> <el-option v-for="item of basicDicList" :key="item.Id" :value="item.Id" :label="item.Code" />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -29,9 +29,7 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<span style="margin-left:auto"> <span style="margin-left:auto">
<el-button type="primary" @click="handleAdd"> <el-button type="primary" @click="handleAdd"></el-button>
{{ $t('common:button:new') }}
</el-button>
</span> </span>
</div> </div>
<el-table <el-table
@ -46,33 +44,33 @@
<el-table-column type="index" width="60" /> <el-table-column type="index" width="60" />
<el-table-column <el-table-column
prop="Code" prop="Code"
:label="$t('dic:all:label:code')" label="字典表名称"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column <el-table-column
prop="ConfigType" prop="ConfigType"
:label="$t('dic:all:label:group')" label="字典分组"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column <el-table-column
prop="Description" prop="Description"
:label="$t('dic:all:label:desc')" label="描述"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column <el-table-column
prop="ShowOrder" prop="ShowOrder"
:label="$t('dic:all:label:showOrder')" label="显示顺序"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column :label="$t('dic:all:label:isEnable')" width="100" fixed="right"> <el-table-column label="是否可用" width="100" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch <el-switch
v-model="scope.row.IsEnable" v-model="scope.row.IsEnable"
@ -82,25 +80,25 @@
/> />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('common:action:action')" width="200" fixed="right"> <el-table-column label="操作" width="200" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
type="text" type="text"
@click="handleEdit(scope.row)" @click="handleEdit(scope.row)"
> >
{{ $t('common:action:edit') }} 编辑
</el-button> </el-button>
<el-button <el-button
type="text" type="text"
@click="handleChild(scope.row)" @click="handleChild(scope.row)"
> >
{{ $t('dic:all:label:childItem') }} 子项
</el-button> </el-button>
<el-button <el-button
type="text" type="text"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
> >
{{ $t('common:button:delete') }} 删除
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
@ -176,7 +174,7 @@ export default {
switchChange(event, item) { switchChange(event, item) {
this.loading = true this.loading = true
addOrUpdateBasicDic(item).then(res => { addOrUpdateBasicDic(item).then(res => {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success('Saved successfully!')
this.loading = false this.loading = false
}).catch(() => { }).catch(() => {
this.loading = false this.loading = false
@ -184,12 +182,12 @@ export default {
}, },
handleEdit(row) { handleEdit(row) {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['DictionaryTypeConfigForm'].openDialog(this.$t('common:action:edit'), row) this.$refs['DictionaryTypeConfigForm'].openDialog('DictionaryTypeConfig', row)
}) })
}, },
handleAdd() { handleAdd() {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['DictionaryTypeConfigForm'].openDialog(this.$t('common:button:new'), { DataTypeEnum: 3 }) this.$refs['DictionaryTypeConfigForm'].openDialog('DictionaryTypeConfig', { DataTypeEnum: 3 })
}) })
}, },
handleDelete(row) { handleDelete(row) {

View File

@ -4,39 +4,32 @@
<div class="search"> <div class="search">
<el-form :inline="true" size="mini" class="base-search-form" /> <el-form :inline="true" size="mini" class="base-search-form" />
<span style="margin-left:auto"> <span style="margin-left:auto">
<el-button type="primary" size="mini" @click="handleAdd">{{ $t('common:button:new') }}</el-button> <el-button type="primary" size="mini" @click="handleAdd"></el-button>
</span> </span>
</div> </div>
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 45 }" :data="list" stripe size="small" height="100" <el-table v-loading="loading" v-adaptive="{ bottomOffset: 45 }" :data="list" stripe size="small" height="100"
@sort-change="handleSortByColumn"> @sort-change="handleSortByColumn">
<el-table-column type="index" width="60" /> <el-table-column type="index" width="60" />
<!-- 字典键值 --> <el-table-column v-if="!~$route.path.indexOf('select')" prop="Code" label="字典键值" min-width="180"
<el-table-column v-if="!~$route.path.indexOf('select')" prop="Code" :label="$t('dic:all:label:keyCode')" min-width="180"
show-overflow-tooltip sortable='custom' /> show-overflow-tooltip sortable='custom' />
<!-- 中文值 --> <el-table-column prop="ValueCN" label="中文值" min-width="180" show-overflow-tooltip sortable='custom' />
<el-table-column prop="ValueCN" :label="$t('dic:all:label:valueCN')" min-width="180" show-overflow-tooltip sortable='custom' /> <el-table-column prop="Value" label="英文值" min-width="180" show-overflow-tooltip sortable='custom' />
<!-- 英文值 --> <el-table-column prop="ChildGroup" label="分组" min-width="180" show-overflow-tooltip sortable='custom' />
<el-table-column prop="Value" :label="$t('dic:all:label:valueEN')" min-width="180" show-overflow-tooltip sortable='custom' /> <el-table-column prop="ShowOrder" label="显示顺序" min-width="180" show-overflow-tooltip sortable='custom' />
<!-- 分组 --> <el-table-column prop="Description" label="描述" min-width="180" show-overflow-tooltip sortable='custom' />
<el-table-column prop="ChildGroup" :label="$t('dic:all:label:childGroup')" min-width="180" show-overflow-tooltip sortable='custom' /> <el-table-column label="是否可用" width="100" fixed="right">
<!-- 显示顺序 -->
<el-table-column prop="ShowOrder" :label="$t('dic:all:label:showOrder')" min-width="180" show-overflow-tooltip sortable='custom' />
<!-- 描述 -->
<el-table-column prop="Description" :label="$t('dic:all:label:desc')" min-width="180" show-overflow-tooltip sortable='custom' />
<!-- 是否可用 -->
<el-table-column :label="$t('dic:all:label:isEnable')" width="100" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch v-model="scope.row.IsEnable" :active-value="true" :inactive-value="false" <el-switch v-model="scope.row.IsEnable" :active-value="true" :inactive-value="false"
@change="(event) => { return switchChange(event, scope.row) }" /> @change="(event) => { return switchChange(event, scope.row) }" />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('common:action:action')" width="150" fixed="right"> <el-table-column label="操作" width="150" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" @click="handleEdit(scope.row)"> <el-button type="text" @click="handleEdit(scope.row)">
{{ $t('common:action:edit') }} 编辑
</el-button> </el-button>
<el-button type="text" @click="handleDelete(scope.row)"> <el-button type="text" @click="handleDelete(scope.row)">
{{ $t('common:button:delete') }} 删除
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
@ -108,7 +101,7 @@ export default {
switchChange(event, item) { switchChange(event, item) {
this.loading = true this.loading = true
addOrUpdateBasicDic(item).then(res => { addOrUpdateBasicDic(item).then(res => {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success('Saved successfully!')
this.loading = false this.loading = false
}).catch(() => { }).catch(() => {
this.loading = false this.loading = false
@ -116,12 +109,12 @@ export default {
}, },
handleEdit(row) { handleEdit(row) {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['DictionaryChildAddOrUpdateForm'].openDialog(this.$t('common:action:edit'), row, { DataTypeEnum: this.parent.DataTypeEnum }) this.$refs['DictionaryChildAddOrUpdateForm'].openDialog('DictionaryChild Edit', row, { DataTypeEnum: this.parent.DataTypeEnum })
}) })
}, },
handleAdd() { handleAdd() {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['DictionaryChildAddOrUpdateForm'].openDialog(this.$t('common:button:new'), {}, { ConfigTypeId: this.parent.ConfigTypeId, parentId: this.parent.Id, DataTypeEnum: this.parent.DataTypeEnum }) this.$refs['DictionaryChildAddOrUpdateForm'].openDialog('DictionaryChild Add', {}, { ConfigTypeId: this.parent.ConfigTypeId, parentId: this.parent.Id, DataTypeEnum: this.parent.DataTypeEnum })
}) })
}, },
handleDelete(row) { handleDelete(row) {

View File

@ -8,25 +8,25 @@
label-width="120px" label-width="120px"
size="small" size="small"
> >
<el-form-item :label="$t('dic:all:label:keyCode')" prop="Code"> <el-form-item label="Enum Value: " prop="Code">
<el-input v-model="form.Code" /> <el-input v-model="form.Code" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('dic:all:label:valueCN')" prop="Code"> <el-form-item label="Value: " prop="Code">
<el-input v-model="form.ValueCN" /> <el-input v-model="form.ValueCN" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('dic:all:label:valueEN')" prop="Code"> <el-form-item label="Value EN: " prop="Code">
<el-input v-model="form.Value" /> <el-input v-model="form.Value" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('dic:all:label:childGroup')" prop="Code"> <el-form-item label="ChildGroup: " prop="Code">
<el-input v-model="form.ChildGroup" /> <el-input v-model="form.ChildGroup" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('dic:all:label:showOrder')" prop="Code"> <el-form-item label="ShowOrder: " prop="Code">
<el-input-number v-model="form.ShowOrder" :min="0" /> <el-input-number v-model="form.ShowOrder" :min="0" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('dic:all:label:desc')" prop="Code"> <el-form-item label="Description: " prop="Code">
<el-input v-model="form.Description" /> <el-input v-model="form.Description" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('dic:all:label:isEnable')"> <el-form-item label="Is Enable: ">
<el-switch <el-switch
v-model="form.IsEnable" v-model="form.IsEnable"
:active-value="true" :active-value="true"
@ -36,12 +36,8 @@
</el-form> </el-form>
</template> </template>
<template slot="dialog-footer"> <template slot="dialog-footer">
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancle"> <el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancle">Cancel</el-button>
{{ $t('common:button:cancel') }} <el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">Save</el-button>
</el-button>
<el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">
{{ $t('common:button:save') }}
</el-button>
</template> </template>
</base-model> </base-model>
</template> </template>
@ -94,7 +90,7 @@ export default {
this.btnLoading = true this.btnLoading = true
addOrUpdateBasicDic(this.form).then(res => { addOrUpdateBasicDic(this.form).then(res => {
this.btnLoading = false this.btnLoading = false
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success('Saved successfully!')
this.model_cfg.visible = false this.model_cfg.visible = false
this.$emit('getList') this.$emit('getList')
}).catch(() => { }).catch(() => {

View File

@ -8,8 +8,7 @@
label-width="120px" label-width="120px"
size="small" size="small"
> >
<!-- 字典分组 --> <el-form-item label="ConfigTypeId: " prop="Code">
<el-form-item :label="$t('dic:all:label:group')" prop="Code">
<el-select v-model="form.ConfigTypeId" filterable style="width:100%;"> <el-select v-model="form.ConfigTypeId" filterable style="width:100%;">
<el-option <el-option
v-for="(item,index) of basicDicList" v-for="(item,index) of basicDicList"
@ -19,8 +18,7 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 类型 --> <el-form-item label="TypeEnum: " prop="DataTypeEnum">
<el-form-item :label="$t('dic:all:label:dataType')" prop="DataTypeEnum">
<el-select v-model="form.DataTypeEnum" filterable style="width:100%;"> <el-select v-model="form.DataTypeEnum" filterable style="width:100%;">
<el-option <el-option
:label="`config`" :label="`config`"
@ -40,19 +38,16 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 字典表名称 --> <el-form-item label="Code: " prop="Code">
<el-form-item :label="$t('dic:all:label:code')" prop="Code">
<el-input v-model="form.Code" /> <el-input v-model="form.Code" />
</el-form-item> </el-form-item>
<!--<el-form-item label="KeyName: " prop="Code">--> <!--<el-form-item label="KeyName: " prop="Code">-->
<!--<el-input v-model="form.KeyName" />--> <!--<el-input v-model="form.KeyName" />-->
<!--</el-form-item>--> <!--</el-form-item>-->
<!-- 显示顺序 --> <el-form-item label="ShowOrder: " prop="Code">
<el-form-item :label="$t('dic:all:label:showOrder')" prop="Code">
<el-input-number v-model="form.ShowOrder" :min="0" /> <el-input-number v-model="form.ShowOrder" :min="0" />
</el-form-item> </el-form-item>
<!-- 描述 --> <el-form-item label="Description: " prop="Code">
<el-form-item :label="$t('dic:all:label:desc')" prop="Code">
<el-input v-model="form.Description" /> <el-input v-model="form.Description" />
</el-form-item> </el-form-item>
<!-- <el-form-item label="Value: " prop="Code"> <!-- <el-form-item label="Value: " prop="Code">
@ -61,8 +56,7 @@
<el-form-item label="ValueCN: " prop="Code"> <el-form-item label="ValueCN: " prop="Code">
<el-input v-model="form.ValueCN" /> <el-input v-model="form.ValueCN" />
</el-form-item> --> </el-form-item> -->
<!-- 是否启用 --> <el-form-item label="Is Enable: ">
<el-form-item :label="$t('dic:all:label:isEnable')">
<el-switch <el-switch
v-model="form.IsEnable" v-model="form.IsEnable"
:active-value="true" :active-value="true"
@ -72,12 +66,8 @@
</el-form> </el-form>
</template> </template>
<template slot="dialog-footer"> <template slot="dialog-footer">
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancle"> <el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancle">Cancel</el-button>
{{ $t('common:button:cancel') }} <el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">Save</el-button>
</el-button>
<el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">
{{ $t('common:button:save') }}
</el-button>
</template> </template>
</base-model> </base-model>
</template> </template>
@ -113,8 +103,8 @@ export default {
btnLoading: false, btnLoading: false,
form: formDataDefault(), form: formDataDefault(),
rules: { rules: {
Code: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }], Code: [{ required: true, message: 'Please specify', trigger: 'blur' }],
DataTypeEnum: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }] DataTypeEnum: [{ required: true, message: 'Please specify', trigger: 'blur' }]
}, },
model_cfg: { visible: false, showClose: true, width: '600px', title: '', appendToBody: true } model_cfg: { visible: false, showClose: true, width: '600px', title: '', appendToBody: true }
} }
@ -142,7 +132,7 @@ export default {
this.btnLoading = true this.btnLoading = true
addOrUpdateBasicDic(this.form).then(res => { addOrUpdateBasicDic(this.form).then(res => {
this.btnLoading = false this.btnLoading = false
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success('Saved successfully!')
this.model_cfg.visible = false this.model_cfg.visible = false
this.$emit('getList') this.$emit('getList')
}).catch(() => { }).catch(() => {

View File

@ -3,11 +3,11 @@
<!-- 搜索框 --> <!-- 搜索框 -->
<div class="search"> <div class="search">
<el-form :inline="true" class="base-search-form"> <el-form :inline="true" class="base-search-form">
<el-form-item :label="$t('dic:all:label:code')"> <el-form-item label="字典表名称:">
<el-input v-model="searchData.Code" clearable style="width:120px;" /> <el-input v-model="searchData.Code" clearable style="width:120px;" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('dic:all:label:group')"> <el-form-item label="字典分组:">
<el-select v-model="searchData.ConfigTypeId" clearable size="small"> <el-select v-model="searchData.ConfigTypeId" placeholder="字典分组" clearable size="small">
<el-option v-for="item of basicDicList" :key="item.Id" :value="item.Id" :label="item.Code" /> <el-option v-for="item of basicDicList" :key="item.Id" :value="item.Id" :label="item.Code" />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -29,9 +29,7 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<span style="margin-left:auto"> <span style="margin-left:auto">
<el-button type="primary" @click="handleAdd"> <el-button type="primary" @click="handleAdd"></el-button>
{{ $t('common:button:new') }}
</el-button>
</span> </span>
</div> </div>
<el-table <el-table
@ -46,33 +44,33 @@
<el-table-column type="index" width="60" /> <el-table-column type="index" width="60" />
<el-table-column <el-table-column
prop="Code" prop="Code"
:label="$t('dic:all:label:code')" label="字典表名称"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column <el-table-column
prop="ConfigType" prop="ConfigType"
:label="$t('dic:all:label:group')" label="字典分组"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column <el-table-column
prop="Description" prop="Description"
:label="$t('dic:all:label:desc')" label="描述"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column <el-table-column
prop="ShowOrder" prop="ShowOrder"
:label="$t('dic:all:label:showOrder')" label="显示顺序"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column :label="$t('dic:all:label:isEnable')" width="100" fixed="right"> <el-table-column label="是否可用" width="100" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch <el-switch
v-model="scope.row.IsEnable" v-model="scope.row.IsEnable"
@ -82,25 +80,25 @@
/> />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('common:action:action')" width="200" fixed="right"> <el-table-column label="操作" width="200" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
type="text" type="text"
@click="handleEdit(scope.row)" @click="handleEdit(scope.row)"
> >
{{ $t('common:action:edit') }} 编辑
</el-button> </el-button>
<el-button <el-button
type="text" type="text"
@click="handleChild(scope.row)" @click="handleChild(scope.row)"
> >
{{ $t('dic:all:label:childItem') }} 子项
</el-button> </el-button>
<el-button <el-button
type="text" type="text"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
> >
{{ $t('common:button:delete') }} 删除
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
@ -176,7 +174,7 @@ export default {
switchChange(event, item) { switchChange(event, item) {
this.loading = true this.loading = true
addOrUpdateBasicDic(item).then(res => { addOrUpdateBasicDic(item).then(res => {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success('Saved successfully!')
this.loading = false this.loading = false
}).catch(() => { }).catch(() => {
this.loading = false this.loading = false
@ -184,12 +182,12 @@ export default {
}, },
handleEdit(row) { handleEdit(row) {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['DictionaryTypeConfigForm'].openDialog(this.$t('common:action:edit'), row) this.$refs['DictionaryTypeConfigForm'].openDialog('DictionaryTypeConfig', row)
}) })
}, },
handleAdd() { handleAdd() {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['DictionaryTypeConfigForm'].openDialog(this.$t('common:button:new'), { DataTypeEnum: 2 }) this.$refs['DictionaryTypeConfigForm'].openDialog('DictionaryTypeConfig', { DataTypeEnum: 2 })
}) })
}, },
handleDelete(row) { handleDelete(row) {

View File

@ -1,24 +1,19 @@
<template> <template>
<div> <div>
<el-tabs v-model="activeTab" @tab-click="handleClick"> <el-tabs v-model="activeTab" @tab-click="handleClick">
<!-- 全部 --> <el-tab-pane label="全部" name="/dictionary/newDictionary/list">
<el-tab-pane :label="$t('dic:label:all')" name="/dictionary/newDictionary/list">
<dictList v-if="activeTab == '/dictionary/newDictionary/list'" /> <dictList v-if="activeTab == '/dictionary/newDictionary/list'" />
</el-tab-pane> </el-tab-pane>
<!-- 下拉框字典 --> <el-tab-pane label="下拉框字典" name="/dictionary/newDictionary/select">
<el-tab-pane :label="$t('dic:label:select')" name="/dictionary/newDictionary/select">
<dictSelect v-if="activeTab == '/dictionary/newDictionary/select'" /> <dictSelect v-if="activeTab == '/dictionary/newDictionary/select'" />
</el-tab-pane> </el-tab-pane>
<!-- 枚举字典 --> <el-tab-pane label="枚举字典" name="/dictionary/newDictionary/enum">
<el-tab-pane :label="$t('dic:label:enum')" name="/dictionary/newDictionary/enum">
<dictEnum v-if="activeTab == '/dictionary/newDictionary/enum'" /> <dictEnum v-if="activeTab == '/dictionary/newDictionary/enum'" />
</el-tab-pane> </el-tab-pane>
<!-- 布尔字典 --> <el-tab-pane label="布尔字典" name="/dictionary/newDictionary/bool">
<el-tab-pane :label="$t('dic:label:bool')" name="/dictionary/newDictionary/bool">
<dictBool v-if="activeTab == '/dictionary/newDictionary/bool'" /> <dictBool v-if="activeTab == '/dictionary/newDictionary/bool'" />
</el-tab-pane> </el-tab-pane>
<!-- 字典类型配置 --> <el-tab-pane label="字典类型配置" name="/dictionary/newDictionary/config">
<el-tab-pane :label="$t('dic:label:config')" name="/dictionary/newDictionary/config">
<dictConfig v-if="activeTab == '/dictionary/newDictionary/config'" /> <dictConfig v-if="activeTab == '/dictionary/newDictionary/config'" />
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>

View File

@ -8,8 +8,7 @@
label-width="120px" label-width="120px"
size="small" size="small"
> >
<!-- 字典分组 --> <el-form-item label="ConfigTypeId: " prop="Code">
<el-form-item :label="$t('dic:all:label:group')" prop="Code">
<el-select v-model="form.ConfigTypeId" filterable style="width:100%;"> <el-select v-model="form.ConfigTypeId" filterable style="width:100%;">
<el-option <el-option
v-for="(item,index) of basicDicList" v-for="(item,index) of basicDicList"
@ -19,8 +18,7 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 类型 --> <el-form-item label="DataTypeEnum: " prop="DataTypeEnum">
<el-form-item :label="$t('dic:all:label:dataType')" prop="DataTypeEnum">
<el-select v-model="form.DataTypeEnum" filterable style="width:100%;"> <el-select v-model="form.DataTypeEnum" filterable style="width:100%;">
<el-option <el-option
:label="`config`" :label="`config`"
@ -40,19 +38,16 @@
/> />
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 字典表名称 --> <el-form-item label="Code: " prop="Code">
<el-form-item :label="$t('dic:all:label:code')" prop="Code">
<el-input v-model="form.Code" /> <el-input v-model="form.Code" />
</el-form-item> </el-form-item>
<!--<el-form-item label="KeyName: " prop="Code">--> <!--<el-form-item label="KeyName: " prop="Code">-->
<!--<el-input v-model="form.KeyName" />--> <!--<el-input v-model="form.KeyName" />-->
<!--</el-form-item>--> <!--</el-form-item>-->
<!-- 显示顺序 --> <el-form-item label="ShowOrder: " prop="Code">
<el-form-item :label="$t('dic:all:label:showOrder')" prop="Code">
<el-input-number v-model="form.ShowOrder" :min="0" /> <el-input-number v-model="form.ShowOrder" :min="0" />
</el-form-item> </el-form-item>
<!-- 描述 --> <el-form-item label="Description: " prop="Code">
<el-form-item :label="$t('dic:all:label:desc')" prop="Code">
<el-input v-model="form.Description" /> <el-input v-model="form.Description" />
</el-form-item> </el-form-item>
<!-- <el-form-item label="Value: " prop="Code"> <!-- <el-form-item label="Value: " prop="Code">
@ -61,8 +56,7 @@
<el-form-item label="ValueCN: " prop="Code"> <el-form-item label="ValueCN: " prop="Code">
<el-input v-model="form.ValueCN" /> <el-input v-model="form.ValueCN" />
</el-form-item> --> </el-form-item> -->
<!-- 是否启用 --> <el-form-item label="Is Enable: ">
<el-form-item :label="$t('dic:all:label:isEnable')">
<el-switch <el-switch
v-model="form.IsEnable" v-model="form.IsEnable"
:active-value="true" :active-value="true"
@ -72,12 +66,8 @@
</el-form> </el-form>
</template> </template>
<template slot="dialog-footer"> <template slot="dialog-footer">
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancle"> <el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancle">Cancel</el-button>
{{ $t('common:button:cancel') }} <el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">Save</el-button>
</el-button>
<el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">
{{ $t('common:button:save') }}
</el-button>
</template> </template>
</base-model> </base-model>
</template> </template>
@ -113,8 +103,8 @@ export default {
btnLoading: false, btnLoading: false,
form: formDataDefault(), form: formDataDefault(),
rules: { rules: {
Code: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }], Code: [{ required: true, message: 'Please specify', trigger: 'blur' }],
DataTypeEnum: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }] DataTypeEnum: [{ required: true, message: 'Please specify', trigger: 'blur' }]
}, },
model_cfg: { visible: false, showClose: true, width: '600px', title: '', appendToBody: true } model_cfg: { visible: false, showClose: true, width: '600px', title: '', appendToBody: true }
} }
@ -140,7 +130,7 @@ export default {
this.btnLoading = true this.btnLoading = true
addOrUpdateBasicDic(this.form).then(res => { addOrUpdateBasicDic(this.form).then(res => {
this.btnLoading = false this.btnLoading = false
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success('Saved successfully!')
this.model_cfg.visible = false this.model_cfg.visible = false
this.$emit('getList') this.$emit('getList')
}).catch(() => { }).catch(() => {

View File

@ -3,18 +3,15 @@
<!-- 搜索框 --> <!-- 搜索框 -->
<div class="search"> <div class="search">
<el-form :inline="true" class="base-search-form"> <el-form :inline="true" class="base-search-form">
<!-- 字典表名称 --> <el-form-item label="字典表名称:">
<el-form-item :label="$t('dic:all:label:code')">
<el-input v-model="searchData.Code" clearable style="width:120px;" /> <el-input v-model="searchData.Code" clearable style="width:120px;" />
</el-form-item> </el-form-item>
<!-- 字典分组 --> <el-form-item label="字典分组:">
<el-form-item :label="$t('dic:all:label:group')"> <el-select v-model="searchData.ConfigTypeId" placeholder="字典分组" clearable size="small">
<el-select v-model="searchData.ConfigTypeId" clearable size="small">
<el-option v-for="item of basicDicList" :key="item.Id" :value="item.Id" :label="item.Code" /> <el-option v-for="item of basicDicList" :key="item.Id" :value="item.Id" :label="item.Code" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 关键字 --> <el-form-item label="关键字:">
<el-form-item :label="$t('dic:all:label:keyWord')">
<el-input v-model="searchData.KeyInfo" clearable style="width:120px;" /> <el-input v-model="searchData.KeyInfo" clearable style="width:120px;" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
@ -35,14 +32,8 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<span style="margin-left:auto"> <span style="margin-left:auto">
<!-- 新建 --> <el-button type="primary" @click="handleAdd"></el-button>
<el-button type="primary" @click="handleAdd"> <el-button type="primary" @click="handleBatchAdd"></el-button>
{{ $t('common:button:new') }}
</el-button>
<!-- 批量新建 -->
<el-button type="primary" @click="handleBatchAdd">
{{ $t('common:button:batchNew') }}
</el-button>
</span> </span>
</div> </div>
<el-table <el-table
@ -55,18 +46,16 @@
@sort-change="handleSortByColumn" @sort-change="handleSortByColumn"
> >
<el-table-column type="index" width="60" /> <el-table-column type="index" width="60" />
<!-- 字典表名称 -->
<el-table-column <el-table-column
prop="Code" prop="Code"
:label="$t('dic:all:label:code')" label="字典表名称"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<!-- 类型 -->
<el-table-column <el-table-column
prop="DataTypeEnum" prop="DataTypeEnum"
:label="$t('dic:all:label:dataType')" label="类型"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
@ -75,32 +64,28 @@
{{ DataTypeEnumList[scope.row.DataTypeEnum] }} {{ DataTypeEnumList[scope.row.DataTypeEnum] }}
</template> </template>
</el-table-column> </el-table-column>
<!-- 字典分组 -->
<el-table-column <el-table-column
prop="ConfigType" prop="ConfigType"
:label="$t('dic:all:label:group')" label="字典分组"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<!-- 描述 -->
<el-table-column <el-table-column
prop="Description" prop="Description"
:label="$t('dic:all:label:desc')" label="描述"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<!-- 显示顺序 -->
<el-table-column <el-table-column
prop="ShowOrder" prop="ShowOrder"
:label="$t('dic:all:label:showOrder')" label="显示顺序"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<!-- 是否可用 --> <el-table-column label="是否可用" width="100" fixed="right">
<el-table-column :label="$t('dic:all:label:isEnable')" width="100" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch <el-switch
v-model="scope.row.IsEnable" v-model="scope.row.IsEnable"
@ -110,28 +95,25 @@
/> />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('common:action:action')" width="300" fixed="right"> <el-table-column label="操作" width="300" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 编辑 -->
<el-button <el-button
type="text" type="text"
@click="handleEdit(scope.row)" @click="handleEdit(scope.row)"
> >
{{ $t('common:action:edit') }} 编辑
</el-button> </el-button>
<!-- 子项 -->
<el-button <el-button
type="text" type="text"
@click="handleChild(scope.row)" @click="handleChild(scope.row)"
> >
{{ $t('dic:all:label:childItem') }} 子项
</el-button> </el-button>
<!-- 删除 -->
<el-button <el-button
type="text" type="text"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
> >
{{ $t('common:button:delete') }} 删除
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
@ -219,17 +201,17 @@ export default {
}, },
handleEdit(row) { handleEdit(row) {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['DictionaryTypeConfigForm'].openDialog(this.$t('common:action:edit'), row) this.$refs['DictionaryTypeConfigForm'].openDialog('DictionaryTypeConfig', row)
}) })
}, },
handleAdd() { handleAdd() {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['DictionaryTypeConfigForm'].openDialog(this.$t('common:button:new'), {}) this.$refs['DictionaryTypeConfigForm'].openDialog('DictionaryTypeConfig', {})
}) })
}, },
handleBatchAdd() { handleBatchAdd() {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['batchAddForm'].openDialog(this.$t('common:button:batchNew'), {}) this.$refs['batchAddForm'].openDialog('批量新建', {})
}) })
}, },
handleDelete(row) { handleDelete(row) {

View File

@ -3,11 +3,11 @@
<!-- 搜索框 --> <!-- 搜索框 -->
<div class="search"> <div class="search">
<el-form :inline="true" class="base-search-form"> <el-form :inline="true" class="base-search-form">
<el-form-item :label="$t('dic:all:label:code')"> <el-form-item label="字典表名称:">
<el-input v-model="searchData.Code" clearable style="width:120px;" /> <el-input v-model="searchData.Code" clearable style="width:120px;" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('dic:all:label:group')"> <el-form-item label="字典分组:">
<el-select v-model="searchData.ConfigTypeId" clearable size="small"> <el-select v-model="searchData.ConfigTypeId" placeholder="字典分组" clearable size="small">
<el-option v-for="item of basicDicList" :key="item.Id" :value="item.Id" :label="item.Code" /> <el-option v-for="item of basicDicList" :key="item.Id" :value="item.Id" :label="item.Code" />
</el-select> </el-select>
</el-form-item> </el-form-item>
@ -29,13 +29,8 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<span style="margin-left:auto"> <span style="margin-left:auto">
<!-- 配置字典分组 --> <el-button type="primary" @click="handleSetting"></el-button>
<el-button type="primary" @click="handleSetting"> <el-button type="primary" @click="handleAdd"></el-button>
{{ $t('dic:select:button:setting') }}
</el-button>
<el-button type="primary" @click="handleAdd">
{{ $t('common:button:new') }}
</el-button>
</span> </span>
</div> </div>
<el-table <el-table
@ -50,33 +45,33 @@
<el-table-column type="index" width="60" /> <el-table-column type="index" width="60" />
<el-table-column <el-table-column
prop="Code" prop="Code"
:label="$t('dic:all:label:code')" label="字典表名称"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column <el-table-column
prop="ConfigType" prop="ConfigType"
:label="$t('dic:all:label:group')" label="字典分组"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column <el-table-column
prop="Description" prop="Description"
:label="$t('dic:all:label:desc')" label="描述"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column <el-table-column
prop="ShowOrder" prop="ShowOrder"
:label="$t('dic:all:label:showOrder')" label="显示顺序"
sortable="custom" sortable="custom"
min-width="180" min-width="180"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column :label="$t('dic:all:label:isEnable')" width="100" fixed="right"> <el-table-column label="是否可用" width="100" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch <el-switch
v-model="scope.row.IsEnable" v-model="scope.row.IsEnable"
@ -86,25 +81,25 @@
/> />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('common:action:action')" width="300" fixed="right"> <el-table-column label="操作" width="300" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
type="text" type="text"
@click="handleEdit(scope.row)" @click="handleEdit(scope.row)"
> >
{{ $t('common:action:edit') }} 编辑
</el-button> </el-button>
<el-button <el-button
type="text" type="text"
@click="handleChild(scope.row)" @click="handleChild(scope.row)"
> >
{{ $t('dic:all:label:childItem') }} 子项
</el-button> </el-button>
<el-button <el-button
type="text" type="text"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
> >
{{ $t('common:button:delete') }} 删除
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
@ -180,7 +175,7 @@ export default {
switchChange(event, item) { switchChange(event, item) {
this.loading = true this.loading = true
addOrUpdateBasicDic(item).then(res => { addOrUpdateBasicDic(item).then(res => {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success('Saved successfully!')
this.loading = false this.loading = false
}).catch(() => { }).catch(() => {
this.loading = false this.loading = false
@ -188,12 +183,12 @@ export default {
}, },
handleEdit(row) { handleEdit(row) {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['DictionaryTypeConfigForm'].openDialog(this.$t('common:action:edit'), row) this.$refs['DictionaryTypeConfigForm'].openDialog('DictionaryTypeConfig', row)
}) })
}, },
handleAdd() { handleAdd() {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['DictionaryTypeConfigForm'].openDialog(this.$t('common:button:new'), { DataTypeEnum: 1 }) this.$refs['DictionaryTypeConfigForm'].openDialog('DictionaryTypeConfig', { DataTypeEnum: 1 })
}) })
}, },
handleDelete(row) { handleDelete(row) {

View File

@ -8,13 +8,13 @@
label-width="150px" label-width="150px"
size="small" size="small"
> >
<el-form-item :label="$t('dic:all:label:group')"" prop="Code"> <el-form-item label="Dictionary Type: " prop="Code">
<el-input v-model="form.Code" /> <el-input v-model="form.Code" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('dic:all:label:desc')"> <el-form-item label="Description: " prop="Code">
<el-input v-model="form.Description" /> <el-input v-model="form.Description" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('dic:all:label:isEnable')"> <el-form-item label="Is Enable: ">
<el-switch <el-switch
v-model="form.IsEnable" v-model="form.IsEnable"
:active-value="true" :active-value="true"
@ -24,12 +24,8 @@
</el-form> </el-form>
</template> </template>
<template slot="dialog-footer"> <template slot="dialog-footer">
<el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancle"> <el-button :disabled="btnLoading" size="small" type="primary" @click="handleCancle">Cancel</el-button>
{{ $t('common:button:cancel') }} <el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">Save</el-button>
</el-button>
<el-button size="small" type="primary" :loading="btnLoading" @click="handleSave">
{{ $t('common:button:save') }}
</el-button>
</template> </template>
</base-model> </base-model>
</template> </template>
@ -56,7 +52,7 @@ export default {
btnLoading: false, btnLoading: false,
form: formDataDefault(), form: formDataDefault(),
rules: { rules: {
Code: [{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: 'blur' }] Code: [{ required: true, message: 'Please specify', trigger: 'blur' }]
}, },
model_cfg: { visible: false, showClose: true, width: '600px', title: '' } model_cfg: { visible: false, showClose: true, width: '600px', title: '' }
} }

View File

@ -3,10 +3,10 @@
<!-- 搜索框 --> <!-- 搜索框 -->
<div class="search"> <div class="search">
<el-form :inline="true" class="base-search-form"> <el-form :inline="true" class="base-search-form">
<el-form-item :label="$t('dic:all:label:group')"> <el-form-item label="Code:">
<el-input v-model="searchData.Code" clearable style="width:120px;" /> <el-input v-model="searchData.Code" clearable style="width:120px;" />
</el-form-item> </el-form-item>
<el-form-item :label="$t('dic:all:label:keyWord')"> <el-form-item label="KeyName:">
<el-input v-model="searchData.KeyName" clearable style="width:120px;" /> <el-input v-model="searchData.KeyName" clearable style="width:120px;" />
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
@ -27,9 +27,7 @@
</el-form-item> </el-form-item>
</el-form> </el-form>
<span style="margin-left:auto"> <span style="margin-left:auto">
<el-button type="primary" @click="handleAdd"> <el-button type="primary" @click="handleAdd">New</el-button>
{{ $t('common:button:new') }}
</el-button>
</span> </span>
</div> </div>
<el-table <el-table
@ -43,15 +41,15 @@
<el-table-column type="index" width="60" /> <el-table-column type="index" width="60" />
<el-table-column <el-table-column
prop="Code" prop="Code"
:label="$t('dic:all:label:group')" label="Dictionary Type"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column <el-table-column
prop="Description" prop="Description"
:label="$t('dic:all:label:desc')" label="Description"
show-overflow-tooltip show-overflow-tooltip
/> />
<el-table-column :label="$t('dic:all:label:isEnable')" width="100" fixed="right"> <el-table-column label="Is Enable" width="100" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch <el-switch
v-model="scope.row.IsEnable" v-model="scope.row.IsEnable"
@ -61,19 +59,19 @@
/> />
</template> </template>
</el-table-column> </el-table-column>
<el-table-column :label="$t('common:action:action')" width="200" fixed="right"> <el-table-column label="Action" width="200" fixed="right">
<template slot-scope="scope"> <template slot-scope="scope">
<el-button <el-button
type="text" type="text"
@click="handleEdit(scope.row)" @click="handleEdit(scope.row)"
> >
{{ $t('common:action:edit') }} 编辑
</el-button> </el-button>
<el-button <el-button
type="text" type="text"
@click="handleDelete(scope.row)" @click="handleDelete(scope.row)"
> >
{{ $t('common:button:delete') }} 删除
</el-button> </el-button>
</template> </template>
</el-table-column> </el-table-column>
@ -117,7 +115,7 @@ export default {
switchChange(event, item) { switchChange(event, item) {
this.loading = true this.loading = true
addOrUpdateBasicDic(item).then(res => { addOrUpdateBasicDic(item).then(res => {
this.$message.success(this.$t('common:message:savedSuccessfully')) this.$message.success('Saved successfully!')
this.loading = false this.loading = false
}).catch(() => { }).catch(() => {
this.loading = false this.loading = false
@ -125,12 +123,12 @@ export default {
}, },
handleEdit(row) { handleEdit(row) {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['DictionaryTypeConfigForm'].openDialog(this.$t('common:action:edit'), row) this.$refs['DictionaryTypeConfigForm'].openDialog('DictionaryTypeConfig', row)
}) })
}, },
handleAdd() { handleAdd() {
this.$nextTick(() => { this.$nextTick(() => {
this.$refs['DictionaryTypeConfigForm'].openDialog(this.$t('common:button:new'), {}) this.$refs['DictionaryTypeConfigForm'].openDialog('DictionaryTypeConfig', {})
}) })
}, },
handleDelete(row) { handleDelete(row) {

View File

@ -1,194 +0,0 @@
<template>
<el-form ref="sysAgreementFrom" v-loading="loading" :model="form" label-width="140px" size="small" :rules="rules"
class="upload-temporary-file">
<div class="base-dialog-body">
<el-row>
<el-col :span="12">
<el-form-item :label="$t('dictionary:agreement:table:UserAgreementTypeEnum')" prop="UserAgreementTypeEnum"
style="width: 48%">
<el-select v-model="form.UserAgreementTypeEnum" style="width: 100%" size="small" filterable>
<el-option v-for="item of $d.UserAgreementType" :key="item.id" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('dictionary:agreement:table:FileName')" prop="FileName" style="width: 48%">
<el-input v-model="form.FileName" clearable style="width: 100%" />
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item :label="$t('dictionary:agreement:table:FileVersion')" prop="FileVersion" style="width: 48%">
<el-input v-model="form.FileVersion" clearable style="width: 100%" />
</el-form-item>
</el-col>
<el-col :span="12">
<el-form-item :label="$t('dictionary:agreement:table:UpdateDate')" prop="UpdateDate" style="width: 48%">
<el-date-picker v-model="form.UpdateDate" type="date"
:placeholder="$t('trials:seletctedReviews:table:selectionTime')" value-format="yyyy-MM-dd"
format="yyyy-MM-dd" clearable style="width: 100%;">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="12">
<el-form-item :label="$t('dictionary:agreement:table:EffectiveDate')" prop="EffectiveDate" style="width: 48%">
<el-date-picker v-model="form.EffectiveDate" type="date"
:placeholder="$t('trials:seletctedReviews:table:selectionTime')" value-format="yyyy-MM-dd"
format="yyyy-MM-dd" clearable style="width: 100%;">
</el-date-picker>
</el-form-item>
</el-col>
</el-row>
<el-form-item :label="$t('dictionary:agreement:table:FileContent')" prop="FileContent">
<div class="html_temp">
<prism-editor class="my-editor" v-model="form.FileContent" :highlight="highlighter" :line-numbers="true"
style="width: 50%;max-height: 350px;"></prism-editor>
<div v-html="form.FileContent" style="width: 45%;" class="content"></div>
</div>
</el-form-item>
<el-form-item :label="$t('dictionary:agreement:table:FileContentEn')" prop="FileEnContent">
<div class="html_temp">
<prism-editor class="my-editor" v-model="form.FileEnContent" :highlight="highlighter" :line-numbers="true"
style="width: 50%;max-height: 350px;"></prism-editor>
<div v-html="form.FileEnContent" style="width: 45%;" class="content"></div>
</div>
</el-form-item>
</div>
<div class="base-dialog-footer" style="text-align: right; margin-top: 10px">
<el-form-item style="text-align: right">
<el-button size="small" type="primary" :loading="saveBtnLoading" @click="handleSave">{{ $t('common:button:save')
}}</el-button>
</el-form-item>
</div>
</el-form>
</template>
<script>
import {
addOrUpdateUserAgreement,
} from '@/api/dictionary'
import { PrismEditor } from 'vue-prism-editor';
import 'vue-prism-editor/dist/prismeditor.min.css';
import { highlight, languages } from 'prismjs/components/prism-core';
import 'prismjs/components/prism-clike';
import 'prismjs/components/prism-javascript';
import 'prismjs/themes/prism.css';
export default {
name: 'TemplateForm',
props: {
data: {
type: Object,
default() {
return {}
},
},
},
components: { PrismEditor },
data() {
return {
form: {
Id: '',
UserAgreementTypeEnum: '',
FileName: '',
FileVersion: null,
FileContent: '\n\n\n\n',
FileEnContent: `\n\n\n\n`,
UpdateDate: '',
EffectiveDate: '',
IsCurrentVersion: false
},
rules: {
UserAgreementTypeEnum: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
],
FileName: [
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
],
FileVersion: [
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
],
FileContent: [
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
],
FileEnContent: [
{ required: true, message: this.$t('common:ruleMessage:specify'), trigger: ['blur'] },
],
UpdateDate: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
],
EffectiveDate: [
{ required: true, message: this.$t('common:ruleMessage:select'), trigger: ['blur'] },
],
},
saveBtnLoading: false,
loading: false,
dictionaryList: {},
}
},
mounted() {
this.initForm()
},
methods: {
highlighter(code) {
return highlight(code, languages.js);
},
async initForm() {
if (Object.keys(this.data).length > 0) {
for (const k in this.form) {
if (this.data.hasOwnProperty(k)) {
this.form[k] = this.data[k]
}
}
}
},
handleSave() {
this.$refs.sysAgreementFrom.validate((valid) => {
if (!valid) return
this.saveBtnLoading = true
addOrUpdateUserAgreement(this.form)
.then((res) => {
this.saveBtnLoading = false
this.$emit('closeDialog')
this.$emit('getList')
this.$message.success(this.$t('common:message:savedSuccessfully'))
})
.catch(() => {
this.saveBtnLoading = false
})
})
},
},
}
</script>
<style lang="scss" scoped>
.html_temp {
display: flex;
justify-content: space-between;
width: 100%;
.my-editor {
border: 1px solid #333;
}
}
.base-dialog-body {
max-height: calc(100% - 60px);
}
.upload-temporary-file {
overflow-y: auto;
height: 100%;
}
.content {
max-height: 350px;
overflow-y: auto;
}
</style>

View File

@ -1,313 +0,0 @@
<template>
<BaseContainer>
<template slot="search-container">
<el-form :inline="true" size="small">
<!-- 文件类型 -->
<el-form-item :label="$t('dictionary:agreement:table:UserAgreementTypeEnum')">
<el-select v-model="searchData.UserAgreementTypeEnum" style="width: 150px">
<el-option v-for="item of $d.UserAgreementType" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<!-- 文件名称 -->
<el-form-item :label="$t('dictionary:agreement:table:FileName')">
<el-input v-model="searchData.FileName" style="width: 130px" clearable />
</el-form-item>
<!-- 版本 -->
<el-form-item :label="$t('dictionary:agreement:table:FileVersion')">
<el-input v-model="searchData.FileVersion" style="width: 130px" clearable />
</el-form-item>
<!--更新日期-->
<el-form-item :label="$t('dictionary:agreement:table:UpdateDate')">
<el-date-picker v-model="UpdateDate" @change="changeTimeList('UpdateDate')" value-format="yyyy-MM-dd"
type="daterange">
</el-date-picker>
</el-form-item>
<!--生效日期-->
<el-form-item :label="$t('dictionary:agreement:table:EffectiveDate')">
<el-date-picker v-model="EffectiveDate" @change="changeTimeList('EffectiveDate')" value-format="yyyy-MM-dd"
type="daterange">
</el-date-picker>
</el-form-item>
<!-- 当前版本 -->
<el-form-item :label="$t('dictionary:agreement:table:IsCurrentVersion')">
<el-select v-model="searchData.IsCurrentVersion" style="width: 150px">
<el-option v-for="item of $d.YesOrNo" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</el-form-item>
<el-form-item>
<!-- 查询 -->
<el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t('common:button:search') }}
</el-button>
<!-- 重置 -->
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
<el-button type="primary" style="float: right" size="small" @click="handleAdd">
{{ $t('common:button:new') }}
</el-button>
</el-form>
</template>
<template slot="main-container">
<el-table v-adaptive="{ bottomOffset: 60 }" v-loading="loading" :data="list" stripe height="100"
@sort-change="handleSortChange">
<el-table-column type="index" width="40" />
<!-- 文件类型 -->
<el-table-column prop="UserAgreementTypeEnum" :label="$t('dictionary:agreement:table:UserAgreementTypeEnum')"
show-overflow-tooltip sortable="custom">
<template slot-scope="scope">
{{
$fd(
'UserAgreementType',
scope.row.UserAgreementTypeEnum
)
}}
</template>
</el-table-column>
<!-- 文件名称 -->
<el-table-column prop="FileName" :label="$t('dictionary:agreement:table:FileName')" show-overflow-tooltip
sortable="custom" />
<!-- 版本 -->
<el-table-column prop="FileVersion" :label="$t('dictionary:agreement:table:FileVersion')" show-overflow-tooltip
sortable="custom" />
<!--内容-->
<el-table-column prop="FileContent" :label="$t('dictionary:agreement:table:FileContent')">
<template slot-scope="scope">
<el-button type="text" size="small" @click.stop="view(scope.row)">{{ $t('dictionary:agreement:button:view')
}}</el-button>
</template>
</el-table-column>
<!-- 更新日期 -->
<el-table-column prop="UpdateDate" :label="$t('dictionary:agreement:table:UpdateDate')" show-overflow-tooltip
sortable="custom">
<template slot-scope="scope">
<span>{{ scope.row.UpdateDate ? scope.row.UpdateDate.split(' ')[0] : '' }}</span>
</template>
</el-table-column>
<!-- 生效日期 -->
<el-table-column prop="EffectiveDate" :label="$t('dictionary:agreement:table:EffectiveDate')"
show-overflow-tooltip sortable="custom">
<template slot-scope="scope">
<span>{{ scope.row.EffectiveDate ? scope.row.EffectiveDate.split(' ')[0] : '' }}</span>
</template>
</el-table-column>
<!-- 当前版本 -->
<el-table-column prop="IsCurrentVersion" :label="$t('dictionary:agreement:table:IsCurrentVersion')"
show-overflow-tooltip sortable="custom">
<template slot-scope="scope">
{{
$fd(
'YesOrNo',
scope.row.IsCurrentVersion
)
}}
</template>
</el-table-column>
<!-- 创建日期 -->
<el-table-column prop="CreateTime" :label="$t('dictionary:agreement:table:CreateTime')" show-overflow-tooltip
sortable="custom" />
<!-- 修改日期 -->
<el-table-column prop="UpdateTime" :label="$t('dictionary:agreement:table:UpdateTime')" show-overflow-tooltip
sortable="custom" />
<el-table-column :label="$t('common:action:action')" width="300">
<template slot-scope="scope">
<el-button type="text" :disabled="scope.row.IsCurrentVersion" @click="setCurrentVersion(scope.row)">
{{ $t('dictionary:agreement:button:setCurrentVersion') }}
</el-button>
<el-button type="text" @click="handleEdit(scope.row)">
{{ $t('common:button:edit') }}
</el-button>
<!-- <el-button type="text" @click="handleDelete(scope.row)">
{{ $t('common:button: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="editDialog.visible" :visible.sync="editDialog.visible" :close-on-click-modal="false"
:title="editDialog.title" custom-class="base-dialog-wrapper" :fullscreen="true">
<TemplateForm :data="currentRow" @closeDialog="closeDialog" @getList="getList" />
</el-dialog>
</template>
</BaseContainer>
</template>
<script>
import {
getUserAgreementList,
deleteUserAgreement,
setCurrentVersion
} from '@/api/dictionary'
import BaseContainer from '@/components/BaseContainer'
import Pagination from '@/components/Pagination'
import TemplateForm from './TemplateForm'
const searchDataDefault = () => {
return {
StartEffectiveDate: null,
EndEffectiveDate: null,
FileName: null,
FileVersion: null,
IsCurrentVersion: null,
StartUpdateDate: null,
EndUpdateDate: null,
UserAgreementTypeEnum: null,
Asc: false,
SortField: "",
PageIndex: 1,
PageSize: 20,
}
}
export default {
name: 'Agreement',
components: { BaseContainer, Pagination, TemplateForm },
data() {
return {
searchData: searchDataDefault(),
list: [],
total: 0,
currentRow: {},
editDialog: { title: '', visible: false },
loading: false,
UpdateDate: [],
EffectiveDate: []
}
},
mounted() {
this.getList()
},
computed: {
isEN() {
return this.$i18n.locale !== 'zh'
},
},
methods: {
async setCurrentVersion(row) {
try {
let data = {
Id: row.Id
}
this.loading = true
let res = await setCurrentVersion(data)
this.loading = false
if (res.IsSuccess) {
this.getList()
}
} catch (err) {
this.loading = false
console.log(err)
}
},
view(row) {
this.$AGR({
Id: row.Id,
IsEn_Us: this.isEN
})
},
changeTimeList(key) {
if (this[key]) {
this.searchData[`Start${key}`] = this[key][0]
this.searchData[`End${key}`] = this[key][1]
} else {
this.searchData.BeginCreateTime = null
this.searchData.EndCreateTime = null
}
},
handleDelete(row) {
//
this.$confirm(this.$t('dictionary:agreement:message:msg1')).then(() => {
deleteUserAgreement(row.Id).then(() => {
this.$message.success(this.$t('common:message:deletedSuccessfully'))
this.getList()
})
}).catch(() => { })
},
PreviewFile(row) {
let basePath = window.location.origin
if (window.location.protocol !== 'https:') {
basePath = 'https://irc.test.extimaging.com'
}
let data = {
name: row.NameCN,
path: basePath + row.Path,
}
this.$emit('PreviewFile', data)
},
getList() {
this.loading = true
getUserAgreementList(this.searchData)
.then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
})
.catch(() => {
this.loading = false
})
},
//
handleAdd() {
this.editDialog.title = this.$t('common:button:new')
this.currentRow = {}
this.editDialog.visible = true
},
//
async handleDownload(row) {
try {
this.loading = true
let fileName = this.isEN ? row.Name : row.NameCN;
let type = fileName
.substring(fileName.lastIndexOf('.'))
.toLocaleLowerCase()
if (!type) {
let extendName = row.Path
.substring(row.Path.lastIndexOf('.'))
.toLocaleLowerCase()
fileName += extendName
}
let res = await downLoadFile(this.OSSclientConfig.basePath + row.Path, fileName)
this.loading = false
} catch (err) {
this.loading = false
}
},
//
handleEdit(row) {
this.editDialog.title = this.$t('common:button:edit')
this.currentRow = { ...row }
this.editDialog.visible = true
},
handleSearch() {
this.searchData.PageIndex = 1
this.getList()
},
handleReset() {
this.searchData = searchDataDefault()
this.getList()
},
closeDialog() {
this.editDialog.visible = false
},
//
handleSortChange(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()
},
},
}
</script>
<style lang="scss" scoped>
::v-deep .search {
display: block;
}
</style>

View File

@ -6,13 +6,12 @@
</template> </template>
<script> <script>
import { getExploreRecommentInfo } from "@/api/dictionary"; import { getExploreRecommentInfo } from "@/api/dictionary";
import SystemInfo from "@/utils/systemInfo";
export default { export default {
name: "browserTip", name: "browserTip",
data() { data() {
return { return {
form: {}, form: {},
tip: '', tip: this.$t("browser:tip:changeBorwser"),
visible: false, visible: false,
}; };
}, },
@ -37,7 +36,6 @@ export default {
// console.log(type, No); // console.log(type, No);
if (type !== "Chrome" && type !== "Edge") { if (type !== "Chrome" && type !== "Edge") {
this.tip = this.$t("browser:tip:changeBorwser"); this.tip = this.$t("browser:tip:changeBorwser");
this.getSystemInfo()
return (this.visible = true); return (this.visible = true);
} }
let res = await this.getInfo(); let res = await this.getInfo();
@ -53,30 +51,12 @@ export default {
this.tip += "、"; this.tip += "、";
} }
}); });
this.getSystemInfo()
return (this.visible = true); return (this.visible = true);
} }
this.getSystemInfo()
} catch (err) { } catch (err) {
console.log(err); console.log(err);
} }
}, },
getSystemInfo() {
const systemInfo = new SystemInfo();
const allInfo = systemInfo.getAllInfo();
let deviceMemory = allInfo.hardware.deviceMemory; //
let { width, height } = allInfo.screen; //
// let discrete = allInfo.webgl.gpuType.discrete; //
// let estimatedMemory = allInfo.webgl.memoryInfo.estimatedMemory; //
// parseFloat(deviceMemory) < 16 ||
if (width < 1920 || height < 1080) {
if (this.tip) {
this.tip += `<br/>`
}
this.tip += `<span>${this.$t("browser:tip:Configuration")}</span>`
this.visible = true
}
},
getExplore() { getExplore() {
var Sys = {}; var Sys = {};
var ua = navigator.userAgent.toLowerCase(); var ua = navigator.userAgent.toLowerCase();
@ -120,7 +100,6 @@ export default {
align-items: center; align-items: center;
padding: 0 20px; padding: 0 20px;
color: #555; color: #555;
i { i {
color: red; color: red;
font-size: 24px; font-size: 24px;

View File

@ -300,7 +300,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 高亮标记值 --> <!-- 高亮标记值 -->
<el-form-item v-if="form.Type === 'select' || form.Type === 'radio' || form.Type === 'calculation'" <el-form-item v-if="form.Type === 'select' || form.Type === 'radio'"
:label="$t('trials:readingUnit:qsList:title:highlightAnswers')" prop="HighlightAnswerList"> :label="$t('trials:readingUnit:qsList:title:highlightAnswers')" prop="HighlightAnswerList">
<el-select v-model="form.HighlightAnswerList" clearable multiple> <el-select v-model="form.HighlightAnswerList" clearable multiple>
<template v-if="form.TypeValue"> <template v-if="form.TypeValue">

View File

@ -3,22 +3,27 @@
<!-- 器官 --> <!-- 器官 -->
<el-tab-pane :label="$t('dictionary:template:basicData:organs')" name="organs"> <el-tab-pane :label="$t('dictionary:template:basicData:organs')" name="organs">
<OrgansTbl :criterion-id="criterionId" :is-complete-config="isCompleteConfig" /> <OrgansTbl
:criterion-id="criterionId"
:is-complete-config="isCompleteConfig"
/>
</el-tab-pane> </el-tab-pane>
<!-- 疗效评估 --> <!-- 疗效评估 -->
<el-tab-pane :label="$t('dictionary:template:basicData:efficacyAssessment')" name="efficacyAssessment"> <el-tab-pane :label="$t('dictionary:template:basicData:efficacyAssessment')" name="efficacyAssessment">
<EfficacyAssessment v-if="tabs.includes('efficacyAssessment')" :criterion-id="criterionId" <EfficacyAssessment
:criterion-type="criterionType" :is-complete-config="isCompleteConfig" /> v-if="tabs.includes('efficacyAssessment')"
:criterion-id="criterionId"
:criterion-type="criterionType"
:is-complete-config="isCompleteConfig"
/>
</el-tab-pane> </el-tab-pane>
<!-- 标准字典 --> <!-- 标准字典 -->
<el-tab-pane :label="$t('dictionary:template:basicData:criterionDictionary')" name="criterionDictionary"> <el-tab-pane :label="$t('dictionary:template:basicData:criterionDictionary')" name="criterionDictionary">
<CriterionDictionary v-if="tabs.includes('criterionDictionary')" :criterion-id="criterionId" <CriterionDictionary
:is-complete-config="isCompleteConfig" /> v-if="tabs.includes('criterionDictionary')"
</el-tab-pane> :criterion-id="criterionId"
<!-- 关键文件 --> :is-complete-config="isCompleteConfig"
<el-tab-pane :label="$t('dictionary:template:basicData:keyDocument')" name="keyDocument"> />
<KeyDocument v-if="tabs.includes('keyDocument')" :criterion-id="criterionId"
:is-complete-config="isCompleteConfig" />
</el-tab-pane> </el-tab-pane>
</el-tabs> </el-tabs>
</template> </template>
@ -26,10 +31,9 @@
import OrgansTbl from './OrgansTbl' import OrgansTbl from './OrgansTbl'
import EfficacyAssessment from './EfficacyAssessment' import EfficacyAssessment from './EfficacyAssessment'
import CriterionDictionary from './CriterionDictionary' import CriterionDictionary from './CriterionDictionary'
import KeyDocument from './KeyDocument'
export default { export default {
name: 'CriterionsBaseData', name: 'CriterionsBaseData',
components: { OrgansTbl, EfficacyAssessment, CriterionDictionary, KeyDocument }, components: { OrgansTbl, EfficacyAssessment, CriterionDictionary },
props: { props: {
criterionId: { criterionId: {
type: String, type: String,

View File

@ -8,8 +8,13 @@
{{ $fd('YesOrNo', IsMustGlobalReading) }} {{ $fd('YesOrNo', IsMustGlobalReading) }}
</el-form-item> </el-form-item>
<!-- 配置 --> <!-- 配置 -->
<el-button size="mini" type="primary" style="position: absolute;right: 10px;top: 15px" <el-button
v-if="Object.keys(data).length > 0 && !(data.IsCompleteConfig || data.IsBeUsed)" @click="handleAdd(1)"> size="mini"
type="primary"
style="position: absolute;right: 10px;top: 15px"
v-if="Object.keys(data).length > 0 && !(data.IsCompleteConfig || data.IsBeUsed)"
@click="handleAdd(1)"
>
{{ $t('dictionary:template:globalConfig:config') }} {{ $t('dictionary:template:globalConfig:config') }}
</el-button> </el-button>
</el-form> </el-form>
@ -17,29 +22,54 @@
<!-- 名称 --> <!-- 名称 -->
<el-divider content-position="left">{{ $t('dictionary:template:globalConfig:name') }}</el-divider> <el-divider content-position="left">{{ $t('dictionary:template:globalConfig:name') }}</el-divider>
<!-- 配置 --> <!-- 配置 -->
<el-button size="mini" type="primary" style="position: absolute;right: 10px;top: 15px" <el-button
v-if="Object.keys(data).length > 0 && !(data.IsCompleteConfig || data.IsBeUsed)" @click="handleAdd(2)"> size="mini"
type="primary"
style="position: absolute;right: 10px;top: 15px"
v-if="Object.keys(data).length > 0 && !(data.IsCompleteConfig || data.IsBeUsed)"
@click="handleAdd(2)"
>
{{ $t('dictionary:template:globalConfig:config') }} {{ $t('dictionary:template:globalConfig:config') }}
</el-button> </el-button>
<!-- 评估更新类型 --> <!-- 评估更新类型 -->
<el-form-item :label="$t('dictionary:template:globalConfig:updateType')" style="width: 100%"> <el-form-item :label="$t('dictionary:template:globalConfig:updateType')" style="width: 100%">
</el-form-item> </el-form-item>
<el-table v-loading="loading" style="width: 100%" :data="list" stripe> <el-table
v-loading="loading"
style="width: 100%"
:data="list"
stripe
>
<!-- 序号 --> <!-- 序号 -->
<el-table-column prop="" :label="$t('dictionary:template:globalConfig:order')" width="80"> <el-table-column
prop=""
:label="$t('dictionary:template:globalConfig:order')"
width="80"
>
<template slot-scope="scope"> <template slot-scope="scope">
{{scope.$index + 1}} {{scope.$index + 1}}
</template> </template>
</el-table-column> </el-table-column>
<!-- 中文值 --> <!-- 中文值 -->
<el-table-column prop="ValueCN" :label="$t('dictionary:template:globalConfig:valueCN')" show-overflow-tooltip> <el-table-column
prop="ValueCN"
:label="$t('dictionary:template:globalConfig:valueCN')"
show-overflow-tooltip
>
</el-table-column> </el-table-column>
<!-- 英文值 --> <!-- 英文值 -->
<el-table-column prop="Value" :label="$t('dictionary:template:globalConfig:value')" show-overflow-tooltip> <el-table-column
prop="Value"
:label="$t('dictionary:template:globalConfig:value')"
show-overflow-tooltip
>
</el-table-column> </el-table-column>
<!-- 是否基线评估 --> <!-- 是否基线评估 -->
<el-table-column prop="IsBaseLineUse" :label="$t('dictionary:template:globalConfig:isBaseLineUse')" <el-table-column
show-overflow-tooltip> prop="IsBaseLineUse"
:label="$t('dictionary:template:globalConfig:isBaseLineUse')"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
<!-- <el-switch--> <!-- <el-switch-->
<!-- @change="(v) => {BaseLineUseChange(v, scope.row)}"--> <!-- @change="(v) => {BaseLineUseChange(v, scope.row)}"-->
@ -51,62 +81,90 @@
</template> </template>
</el-table-column> </el-table-column>
<!-- 是否随访评估 --> <!-- 是否随访评估 -->
<el-table-column prop="IsFollowVisitUse" :label="$t('dictionary:template:globalConfig:isFollowVisitUse')" <el-table-column
show-overflow-tooltip> prop="IsFollowVisitUse"
:label="$t('dictionary:template:globalConfig:isFollowVisitUse')"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
<!-- <el-switch--> <!-- <el-switch-->
<!-- @change="(v) => {FollowVisitUseChange(v, scope.row)}"--> <!-- @change="(v) => {FollowVisitUseChange(v, scope.row)}"-->
<!-- v-model="scope.row.IsFollowVisitUse"--> <!-- v-model="scope.row.IsFollowVisitUse"-->
<!-- >--> <!-- >-->
<!-- </el-switch>--> <!-- </el-switch>-->
<el-tag v-if="scope.row.IsFollowVisitUse" type="primary">{{ $fd('YesOrNo', scope.row.IsFollowVisitUse) <el-tag v-if="scope.row.IsFollowVisitUse" type="primary">{{ $fd('YesOrNo', scope.row.IsFollowVisitUse) }}</el-tag>
}}</el-tag>
<el-tag v-else type="danger">{{ $fd('YesOrNo', scope.row.IsFollowVisitUse) }}</el-tag> <el-tag v-else type="danger">{{ $fd('YesOrNo', scope.row.IsFollowVisitUse) }}</el-tag>
<!-- <span>{{$fd('YesOrNo', scope.row.IsFollowVisitUse)}}</span>--> <!-- <span>{{$fd('YesOrNo', scope.row.IsFollowVisitUse)}}</span>-->
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
</el-form> </el-form>
<base-model :config="config"> <base-model
:config="config"
>
<template slot="dialog-body"> <template slot="dialog-body">
<el-form size="small" :inline="true" label-width="130px"> <el-form size="small" :inline="true" label-width="130px">
<!-- 是否必须全局阅片 --> <!-- 是否必须全局阅片 -->
<el-form-item :label="$t('dictionary:template:globalConfig:isMustGlobalReading')" <el-form-item :label="$t('dictionary:template:globalConfig:isMustGlobalReading')" v-if="config.configType === 1">
v-if="config.configType === 1">
<el-radio-group v-model="form.IsMustGlobalReading"> <el-radio-group v-model="form.IsMustGlobalReading">
<el-radio v-for="item of $d.YesOrNo" :key="'form.IsMustGlobalReading' + item.value" :label="item.value">{{ <el-radio v-for="item of $d.YesOrNo" :key="'form.IsMustGlobalReading' + item.value" :label="item.value">{{ item.label }}</el-radio>
item.label }}</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<!-- 评估更新类型 @selection-change="handleSelectionChange"--> <!-- 评估更新类型 -->
<el-form-item v-if="config.configType === 2" :label="$t('dictionary:template:globalConfig:updateType')" <el-form-item v-if="config.configType === 2" :label="$t('dictionary:template:globalConfig:updateType')" style="width: 100%">
style="width: 100%">
</el-form-item> </el-form-item>
<el-table v-if="config.configType === 2" v-loading="loading" ref="multipleTable" :data="GlobalAssessType" <el-table
stripe> v-if="config.configType === 2"
<!-- <el-table-column type="selection" width="55"> v-loading="loading"
</el-table-column> --> ref="multipleTable"
:data="GlobalAssessType"
stripe
@selection-change="handleSelectionChange"
>
<el-table-column
type="selection"
width="55">
</el-table-column>
<!-- 中文值 --> <!-- 中文值 -->
<el-table-column prop="ValueCN" :label="$t('dictionary:template:globalConfig:valueCN')" <el-table-column
show-overflow-tooltip> prop="ValueCN"
:label="$t('dictionary:template:globalConfig:valueCN')"
show-overflow-tooltip
>
</el-table-column> </el-table-column>
<!-- 英文值 --> <!-- 英文值 -->
<el-table-column prop="Value" :label="$t('dictionary:template:globalConfig:value')" show-overflow-tooltip> <el-table-column
prop="Value"
:label="$t('dictionary:template:globalConfig:value')"
show-overflow-tooltip
>
</el-table-column> </el-table-column>
<!-- 是否基线评估 --> <!-- 是否基线评估 -->
<el-table-column prop="IsBaseLineUse" :label="$t('dictionary:template:globalConfig:isBaseLineUse')" <el-table-column
show-overflow-tooltip> prop="IsBaseLineUse"
:label="$t('dictionary:template:globalConfig:isBaseLineUse')"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch v-model="scope.row.IsBaseLineUse" @change="() => $forceUpdate()"> <el-switch
v-model="scope.row.IsBaseLineUse"
@change="() => $forceUpdate()"
>
</el-switch> </el-switch>
<span>{{$fd('YesOrNo', scope.row.IsBaseLineUse)}}</span> <span>{{$fd('YesOrNo', scope.row.IsBaseLineUse)}}</span>
</template> </template>
</el-table-column> </el-table-column>
<!-- 是否随访评估 --> <!-- 是否随访评估 -->
<el-table-column prop="IsFollowVisitUse" :label="$t('dictionary:template:globalConfig:isFollowVisitUse')" <el-table-column
show-overflow-tooltip> prop="IsFollowVisitUse"
:label="$t('dictionary:template:globalConfig:isFollowVisitUse')"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-switch v-model="scope.row.IsFollowVisitUse" @change="() => $forceUpdate()"> <el-switch
v-model="scope.row.IsFollowVisitUse"
@change="() => $forceUpdate()"
>
</el-switch> </el-switch>
<span>{{$fd('YesOrNo', scope.row.IsFollowVisitUse)}}</span> <span>{{$fd('YesOrNo', scope.row.IsFollowVisitUse)}}</span>
</template> </template>
@ -168,7 +226,7 @@ export default {
mounted() { mounted() {
this.getList() this.getList()
this.getSystemGlobalInfo() this.getSystemGlobalInfo()
// this.getCriterionDictionary() this.getCriterionDictionary()
}, },
methods: { methods: {
getCriterionDictionary() { getCriterionDictionary() {
@ -183,7 +241,7 @@ export default {
getSystemGlobalInfo({ getSystemGlobalInfo({
SystemCriterionId: this.criterionId SystemCriterionId: this.criterionId
}).then(res => { }).then(res => {
this.GlobalAssessType = res.Result.DictionaryList
}) })
}, },
FollowVisitUseChange(v, row) { FollowVisitUseChange(v, row) {
@ -215,7 +273,6 @@ export default {
} }
}, },
handleSelectionChange(val) { handleSelectionChange(val) {
console.log(this.selectedList, 'this.selectedList')
this.selectedList = val this.selectedList = val
}, },
getList() { getList() {
@ -238,6 +295,18 @@ export default {
} else { } else {
this.config.title = this.$t('dictionary:template:globalConfig:updateType') this.config.title = this.$t('dictionary:template:globalConfig:updateType')
this.config.visible = true this.config.visible = true
this.$nextTick(() => {
var a = this.$d.GlobalAssessType.filter(v => {
return !!this.list.find(v1 => {
if (v.id === v1.DictionaryId) {
v.IsBaseLineUse = v1.IsBaseLineUse
v.IsFollowVisitUse = v1.IsFollowVisitUse
}
return v1.DictionaryId === v.id
})
})
this.toggleSelection(a)
})
} }
}, },
handleSave() { handleSave() {
@ -250,11 +319,11 @@ export default {
var params = { var params = {
SystemCriterionId: this.criterionId, SystemCriterionId: this.criterionId,
IsMustGlobalReading: this.form.IsMustGlobalReading, IsMustGlobalReading: this.form.IsMustGlobalReading,
DictionaryList: this.config.configType === 1 ? this.list : this.GlobalAssessType.map(v => { DictionaryList: this.config.configType === 1 ? this.list : this.selectedList.map(v => {
return { return {
DictionaryId: v.DictionaryId, DictionaryId: v.id,
IsBaseLineUse: v.IsBaseLineUse ? v.IsBaseLineUse : false, IsBaseLineUse: v.IsBaseLineUse,
IsFollowVisitUse: v.IsFollowVisitUse ? v.IsFollowVisitUse : false, IsFollowVisitUse: v.IsFollowVisitUse,
} }
}), }),
} }
@ -273,3 +342,5 @@ export default {
} }
} }
</script> </script>

View File

@ -1,286 +0,0 @@
<template>
<BaseContainer>
<!-- 搜索框 -->
<template slot="search-container">
<el-form :inline="true" size="mini">
<el-form-item :label="$t('dictionary:template:keyDocList:FileName')">
<el-input clearable v-model="searchData.FileName"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="mini" @click="handleSearch">
{{ $t('common:button:search') }}
</el-button>
<el-button type="primary" icon="el-icon-refresh-left" size="mini" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
</el-form-item>
<el-form-item>
<div class="upload">
<input directory accept=".pdf" type="file" name="uploadFolder" class="select-file" title=""
@change="beginScanFiles($event)" />
<div class="btn-select">
{{ $t('dictionary:template:basicData:button:selectFile') }}
</div>
</div>
</el-form-item>
</el-form>
</template>
<template slot="main-container">
<div class="drag" ref="drag" @dragover="handleDragover" @drop="handleDrop">
<el-table ref="keyDocList" v-loading="loading" v-adaptive="{ bottomOffset: 80 }" :data="list"
width="100%" style="width: 100%;min-width: 300px" stripe height="100"
@sort-change="handleSortByColumn">
<el-table-column type="index" min-width="90" />
<el-table-column prop="FileName" :label="$t('dictionary:template:keyDocList:FileName')"
show-overflow-tooltip />
<el-table-column prop="CreateTime" :label="$t('dictionary:template:keyDocList:CreateTime')"
show-overflow-tooltip />
<el-table-column :label="$t('common:action:action')" align="left" fixed="right">
<template slot-scope="scope">
<el-button circle icon="el-icon-view"
:title="$t('dictionary:template:keyDocList:button:view')"
@click.stop="view(scope.row)" />
<el-button circle icon="el-icon-delete"
:title="$t('dictionary:template:keyDocList:button:del')" @click.stop="del(scope.row)" />
</template>
</el-table-column>
</el-table>
</div>
<!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
</template>
</BaseContainer>
</template>
<script>
import { Upload } from '@/api/dictionary'
import BaseContainer from '@/components/BaseContainer'
import Pagination from '@/components/Pagination'
import { getSystemCriterionKeyFileList, addOrUpdateSystemCriterionKeyFile, deleteSystemCriterionKeyFile } from '@/api/dictionary'
import { readEntry } from '@/utils/index'
const searchDataDefault = () => {
return {
FileName: '',
PageIndex: 1,
PageSize: 20,
Asc: false,
SortField: ''
}
}
export default {
name: "KeyDocument",
components: { BaseContainer, Pagination },
props: {
criterionId: {
type: String,
required: true
},
isCompleteConfig: {
type: Boolean,
required: true
},
},
data() {
return {
searchData: searchDataDefault(),
loading: false,
list: [],
total: 0,
}
},
mounted() {
this.getList()
},
methods: {
handleDragover(e) {
e.stopPropagation();
e.preventDefault();
},
handleDrop(e) {
e.stopPropagation();
e.preventDefault();
this.beginScanFiles(e, true)
},
beforeUpload(file) {
//
if (this.checkFileSuffix(file.name)) {
this.fileList = [];
return true;
} else {
// this.$alert("word/excel");
this.$alert(this.$t("dictionary:attachment:export:alert:formatFile"));
return false;
}
},
async beginScanFiles(e, isDrop = false) {
try {
this.loading = true;
let files = []
if (isDrop) {
const items = e.dataTransfer.items;
const allFiles = []; //
//
for (const item of items) {
const entry = item.webkitGetAsEntry(); //
if (entry) {
const files = await readEntry(entry); //
allFiles.push(...files);
}
}
files = allFiles
} else {
files = [...e.target.files]
}
for (let i = 0; i < files.length; i++) {
let file = files[i]
if (!this.checkFileSuffix(file.name)) continue
const formData = new FormData();
formData.append("file", file);
let res = await Upload(formData, 5)
let data = {
FilePath: res.Result.FilePath,
FileName: file.name
}
await this.addKeyDoc(data)
}
} catch (err) {
console.log(err)
this.loading = false;
}
},
checkFileSuffix(fileName) {
var index = fileName.lastIndexOf('.')
var suffix = fileName.substring(index + 1, fileName.length)
if ('.pdf'.toLocaleLowerCase().search(suffix.toLocaleLowerCase()) === -1) {
return false
} else {
return true
}
},
async getList() {
try {
this.searchData.SystemCriterionId = this.criterionId
this.loading = true
let res = await getSystemCriterionKeyFileList(this.searchData)
this.loading = false
if (res.IsSuccess) {
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
}
} catch (err) {
this.loading = false
console.log(err)
}
},
async addKeyDoc(row) {
try {
let { FileName, FilePath } = row
let data = {
FileName,
FilePath,
SystemCriterionId: this.criterionId
}
this.loading = true
let res = await addOrUpdateSystemCriterionKeyFile(data)
this.loading = false
if (res.IsSuccess) {
this.getList()
}
} catch (err) {
this.loading = false
console.log(err)
}
},
async del(row) {
try {
this.loading = true
let res = await deleteSystemCriterionKeyFile(row.Id)
this.loading = false
if (res.IsSuccess) {
this.getList()
}
} catch (err) {
console.log(err)
this.loading = false
}
},
view(row) {
this.$preview({
path: row.FilePath,
type: 'pdf',
isLocal: true,
title: row.FileName,
})
},
//
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()
}
}
}
</script>
<style lang="scss" scoped>
.upload {
display: inline-block;
height: 30px;
width: 90px;
padding: 2px 10px;
line-height: 23px;
position: relative;
text-decoration: none;
border-radius: 3px;
overflow: hidden;
text-align: center;
background: #428bca;
border-color: #428bca;
color: #fff;
.select-file {
height: 30px;
width: 90px;
position: absolute;
overflow: hidden;
left: 0;
top: 0;
opacity: 0;
font-size: 0;
}
.btn-select {
//
width: 90px;
height: 30px;
line-height: 30px;
text-align: center;
cursor: pointer;
border-radius: 24px;
overflow: hidden;
position: absolute;
top: 0;
left: 0;
pointer-events: none; //pointer-events:none穿
}
}
</style>

View File

@ -228,7 +228,7 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 高亮标记值 --> <!-- 高亮标记值 -->
<el-form-item v-if="form.Type === 'select' || form.Type === 'radio' || form.Type === 'calculation'" <el-form-item v-if="form.Type === 'select' || form.Type === 'radio'"
:label="$t('trials:readingUnit:qsList:title:highlightAnswers')" prop="HighlightAnswerList"> :label="$t('trials:readingUnit:qsList:title:highlightAnswers')" prop="HighlightAnswerList">
<el-select v-model="form.HighlightAnswerList" clearable multiple> <el-select v-model="form.HighlightAnswerList" clearable multiple>
<template v-if="form.TypeValue"> <template v-if="form.TypeValue">

View File

@ -41,7 +41,6 @@
<el-option v-for="item of UserTypeList" :value="item.value" :label="item.label" :key="item.id" /> <el-option v-for="item of UserTypeList" :value="item.value" :label="item.label" :key="item.id" />
</el-select> </el-select>
</el-form-item> </el-form-item>
<!--v-if="systemLevel === 1"-->
<el-form-item :label="$t('trials:emailManageCfg:form:EmailUrgent')"> <el-form-item :label="$t('trials:emailManageCfg:form:EmailUrgent')">
<el-select v-model="searchData.EmailUrgentEnum" clearable style="width: 100px"> <el-select v-model="searchData.EmailUrgentEnum" clearable style="width: 100px">
<el-option v-for="item of $d.EmailUrgent" :value="item.value" :label="item.label" :key="item.id" /> <el-option v-for="item of $d.EmailUrgent" :value="item.value" :label="item.label" :key="item.id" />

View File

@ -6,45 +6,68 @@
<qc-questions v-if="activeTab == 'qc'" /> <qc-questions v-if="activeTab == 'qc'" />
</el-tab-pane> </el-tab-pane>
<!-- 阅片标准配置 --> <!-- 阅片标准配置 -->
<el-tab-pane :label="$t('dictionary:template:tab:criterionsConfig')" name="criterions"> <el-tab-pane
:label="$t('dictionary:template:tab:criterionsConfig')"
name="criterions"
>
<criterions-tmp v-if="activeTab == 'criterions'" /> <criterions-tmp v-if="activeTab == 'criterions'" />
</el-tab-pane> </el-tab-pane>
<!-- 临床数据配置 --> <!-- 临床数据配置 -->
<el-tab-pane :label="$t('dictionary:template:tab:clinicalDataConfig')" name="clinicalData"> <el-tab-pane
:label="$t('dictionary:template:tab:clinicalDataConfig')"
name="clinicalData"
>
<clinical-data v-if="activeTab == 'clinicalData'" /> <clinical-data v-if="activeTab == 'clinicalData'" />
</el-tab-pane> </el-tab-pane>
<!-- 医学审核问题配置 --> <!-- 医学审核问题配置 -->
<el-tab-pane :label="$t('dictionary:template:tab:medicalConfig')" name="medicalAudit"> <el-tab-pane
:label="$t('dictionary:template:tab:medicalConfig')"
name="medicalAudit"
>
<medical-audit v-if="activeTab == 'medicalAudit'" /> <medical-audit v-if="activeTab == 'medicalAudit'" />
</el-tab-pane> </el-tab-pane>
<!-- DICOM字段匿名化配置 --> <!-- DICOM字段匿名化配置 -->
<el-tab-pane :label="$t('dictionary:template:tab:dicomTagConfig')" name="anonymization"> <el-tab-pane
:label="$t('dictionary:template:tab:dicomTagConfig')"
name="anonymization"
>
<Anonymization v-if="activeTab == 'anonymization'" /> <Anonymization v-if="activeTab == 'anonymization'" />
</el-tab-pane> </el-tab-pane>
<!-- DICOM字段新增配置 --> <!-- DICOM字段新增配置 -->
<el-tab-pane :label="$t('dictionary:template:tab:dicomTagAddConfig')" name="increasefields"> <el-tab-pane
:label="$t('dictionary:template:tab:dicomTagAddConfig')"
name="increasefields"
>
<IncreaseFields v-if="activeTab == 'increasefields'" /> <IncreaseFields v-if="activeTab == 'increasefields'" />
</el-tab-pane> </el-tab-pane>
<!-- 邮件管理 --> <!-- 邮件管理 -->
<el-tab-pane :label="$t('dictionary:template:tab:emailConfig')" name="email"> <el-tab-pane
:label="$t('dictionary:template:tab:emailConfig')"
name="email"
>
<Email v-if="activeTab == 'email'" /> <Email v-if="activeTab == 'email'" />
</el-tab-pane> </el-tab-pane>
<!-- 签名管理 --> <!-- 签名管理 -->
<el-tab-pane :label="$t('dictionary:template:tab:signConfig')" name="sign"> <el-tab-pane
:label="$t('dictionary:template:tab:signConfig')"
name="sign"
>
<Sign v-if="activeTab == 'sign'" /> <Sign v-if="activeTab == 'sign'" />
</el-tab-pane> </el-tab-pane>
<!-- 浏览器推荐 --> <!-- 浏览器推荐 -->
<el-tab-pane :label="$t('dictionary:template:tab:browserConfig')" name="browser"> <el-tab-pane
:label="$t('dictionary:template:tab:browserConfig')"
name="browser"
>
<Browser v-if="activeTab == 'browser'" /> <Browser v-if="activeTab == 'browser'" />
</el-tab-pane> </el-tab-pane>
<!-- 文件记录 --> <!-- 文件记录 -->
<el-tab-pane :label="$t('dictionary:template:tab:fileConfig')" name="file"> <el-tab-pane
:label="$t('dictionary:template:tab:fileConfig')"
name="file"
>
<File v-if="activeTab == 'file'" /> <File v-if="activeTab == 'file'" />
</el-tab-pane> </el-tab-pane>
<!-- 用户协议 -->
<el-tab-pane :label="$t('dictionary:template:tab:agreement')" name="agreement">
<Agreement v-if="activeTab == 'agreement'" />
</el-tab-pane>
</el-tabs> </el-tabs>
</div> </div>
</template> </template>
@ -59,7 +82,6 @@ import Email from './email/index.vue'
import Sign from './sign/index.vue' import Sign from './sign/index.vue'
import Browser from './browser/index.vue' import Browser from './browser/index.vue'
import File from './file/index.vue' import File from './file/index.vue'
import Agreement from './agreement/index.vue'
export default { export default {
name: 'Questions', name: 'Questions',
components: { components: {
@ -73,7 +95,6 @@ export default {
MedicalAudit, MedicalAudit,
Browser, Browser,
File, File,
Agreement
}, },
data() { data() {
return { return {
@ -101,18 +122,16 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
} }
.el-tabs__header { .el-tabs__header {
height: 40px; height: 40px;
margin-bottom: 5px; margin-bottom: 5px;
} }
.el-tabs__content { .el-tabs__content {
flex: 1; flex: 1;
.el-tab-pane { .el-tab-pane {
height: 100%; height: 100%;
} }
} }
} }
</style> </style>

View File

@ -21,19 +21,13 @@
<el-form-item :label="$t('trials:researchForm:form:verifyCode')" required> <el-form-item :label="$t('trials:researchForm:form:verifyCode')" required>
<el-col :span="18"> <el-col :span="18">
<el-form-item prop="VerificationCode"> <el-form-item prop="VerificationCode">
<div style="display: flex;justify-content: space-between;">
<el-input v-model="form.VerificationCode" autocomplete="off" /> <el-input v-model="form.VerificationCode" autocomplete="off" />
<el-button size="small" class="codeBtn" :disabled="sendDisabled" @click="handleSendCode"
style="width: 30%;margin-left: 10px;">
{{ sendTitle }}
</el-button>
</div>
</el-form-item> </el-form-item>
</el-col> </el-col>
<!-- <el-col :span="6" style="text-align: right"> <el-col :span="6" style="text-align: right">
<el-button size="small" type="primary" style="width: 80%" :disabled="sendDisabled"
</el-col> --> @click="handleSendCode">{{ sendTitle }}</el-button>
</el-col>
</el-form-item> </el-form-item>
</el-form> </el-form>
<!-- 校验 --> <!-- 校验 -->
@ -387,21 +381,6 @@ export default {
/*::v-deep .is-error{*/ /*::v-deep .is-error{*/
/* margin-bottom: 40px;*/ /* margin-bottom: 40px;*/
/*}*/ /*}*/
.codeBtn {
color: #409EFF;
border-color: #409EFF;
}
.codeBtn.is-disabled,
.codeBtn.is-disabled:focus,
.codeBtn.is-disabled:hover {
color: #c0c4cc;
cursor: not-allowed;
background-image: none;
background-color: #fff;
border-color: #ebeef5;
}
.is-error.my_new_pwd { .is-error.my_new_pwd {
margin-bottom: 45px; margin-bottom: 45px;
} }

View File

@ -77,22 +77,13 @@
</span> --> </span> -->
</el-form-item> </el-form-item>
<!-- Login --> <!-- Login -->
<el-button :loading="loading" type="primary" :disabled="!checked" style=" <el-button :loading="loading" type="primary" style="
width: 100%; width: 100%;
margin-bottom: 10px; margin-bottom: 10px;
background-color: rgb(0, 147, 221); background-color: rgb(0, 147, 221);
" size="medium" @click.native.prevent="handleLogin"> " size="medium" @click.native.prevent="handleLogin">
{{ $t('login:button:login') }} {{ $t('login:button:login') }}
</el-button> </el-button>
<div class="PrivacyPolicy" style="font-size: 14px;">
<el-checkbox v-model="checked" style="margin-right: 5px;" />
<span>{{ $t('login:message:PrivacyPolicy') }}</span>
<span style="cursor: pointer;color:#428bca" @click="viewAgreement(0)">{{ $t('login:message:UserAgreement')
}}</span>
<span>{{ $t('login:message:and') }}</span>
<span style="cursor: pointer;color:#428bca" @click="viewAgreement(1)">{{
$t('login:message:PrivacyPolicyName') }}</span>
</div>
<div style="text-align: right"> <div style="text-align: right">
<TopLang v-if=" <TopLang v-if="
VUE_APP_OSS_CONFIG_REGION !== 'oss-us-west-1' && VUE_APP_OSS_CONFIG_REGION !== 'oss-us-west-1' &&
@ -190,9 +181,6 @@ import Vcode from 'vue-puzzle-vcode'
import browserTip from '@/views/dictionary/template/browser/tip.vue' import browserTip from '@/views/dictionary/template/browser/tip.vue'
import Img1 from '@/assets/pic-2.png' import Img1 from '@/assets/pic-2.png'
import toggleRole from '@/components/toggleRole' import toggleRole from '@/components/toggleRole'
import {
getCurrentVersionUserAgreements,
} from '@/api/dictionary'
export default { export default {
name: 'Login', name: 'Login',
components: { TopLang, Vcode, browserTip, toggleRole }, components: { TopLang, Vcode, browserTip, toggleRole },
@ -240,8 +228,6 @@ export default {
Img1, Img1,
toggleRoleVisible: false, toggleRoleVisible: false,
toggleRoleLoading: false, toggleRoleLoading: false,
Agreement: [],
checked: true
} }
}, },
computed: { computed: {
@ -270,6 +256,7 @@ export default {
zzSessionStorage.setItem('loginType', this.loginType) zzSessionStorage.setItem('loginType', this.loginType)
localStorage.setItem('location', this.location) localStorage.setItem('location', this.location)
// zh-CN navigator.language // zh-CN navigator.language
console.log(navigator.language, 'navigator.language')
if (navigator.language !== 'zh-CN' && navigator.language !== 'zh-TW') { if (navigator.language !== 'zh-CN' && navigator.language !== 'zh-TW') {
this.$i18n.locale = 'en' this.$i18n.locale = 'en'
this.setLanguage('en') this.setLanguage('en')
@ -291,30 +278,9 @@ export default {
} }
} }
this.$refs.browserTip.open() this.$refs.browserTip.open()
this.getAgreementList()
}, },
methods: { methods: {
...mapMutations({ setLanguage: 'lang/setLanguage' }), ...mapMutations({ setLanguage: 'lang/setLanguage' }),
viewAgreement(type) {
let find = this.Agreement.find(item => item.IsCurrentVersion && item.UserAgreementTypeEnum === type)
if (!find) return this.$confirm(this.$t('login:message:noAgreement').replace('xxx', this.$fd('UserAgreementType', type)))
this.$AGR({
Id: find.Id,
IsEn_Us: this.$i18n.locale !== 'zh'
})
},
getAgreementList() {
getCurrentVersionUserAgreements({
PageIndex: 1,
PageSize: 20,
IsCurrentVersion: true
})
.then((res) => {
this.Agreement = res.Result
})
.catch(() => {
})
},
openAbout() { openAbout() {
this.aboutVisible = true this.aboutVisible = true
}, },
@ -710,7 +676,7 @@ $light_gray: #606266;
.title-container { .title-container {
// margin-bottom: 50px; // margin-bottom: 50px;
text-align: center; text-align: center;
margin-top: 17%; margin-top: 20%;
.title { .title {
font-size: 35px; font-size: 35px;

View File

@ -1,6 +1,5 @@
<template> <template>
<el-form v-if="isShow" ref="researchBSForm" size="small" :model="form" :rules="rules" style="width:80%" <el-form v-if="isShow" ref="researchBSForm" size="small" :model="form" :rules="rules" style="width:80%">
label-position="left">
<!-- 项目编号 --> <!-- 项目编号 -->
<el-form-item :label="$t('trials:researchForm:form:trialId')"> <el-form-item :label="$t('trials:researchForm:form:trialId')">
<el-input v-model="form.TrialCode" disabled /> <el-input v-model="form.TrialCode" disabled />
@ -19,10 +18,19 @@
</el-form-item> </el-form-item>
<!-- 中心名称 --> <!-- 中心名称 -->
<el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId"> <el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId">
<el-select v-model="form.TrialSiteId" filterable style="width:100%;" <el-select
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" @change="handleSiteChange"> v-model="form.TrialSiteId"
<el-option v-for="(item, index) of siteOptions" :key="index" :label="item.TrialSiteAliasName" filterable
:value="item.TrialSiteId" /> style="width:100%;"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory"
@change="handleSiteChange"
>
<el-option
v-for="(item,index) of siteOptions"
:key="index"
:label="item.TrialSiteAliasName"
:value="item.TrialSiteId"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 中心编号 --> <!-- 中心编号 -->
@ -34,7 +42,10 @@
<el-input v-model="form.UserName" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" /> <el-input v-model="form.UserName" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
</el-form-item> </el-form-item>
<!-- 联系电话 --> <!-- 联系电话 -->
<el-form-item :label="$t('trials:researchForm:form:contactorPhone')" prop="Phone"> <el-form-item
:label="$t('trials:researchForm:form:contactorPhone')"
prop="Phone"
>
<el-input v-model="form.Phone" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" /> <el-input v-model="form.Phone" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" />
</el-form-item> </el-form-item>
<!-- 联系邮箱 --> <!-- 联系邮箱 -->
@ -44,71 +55,75 @@
<!-- <el-divider /> --> <!-- <el-divider /> -->
<!-- 平均刻盘周期 --> <!-- 平均刻盘周期 -->
<el-form-item v-if="!notShowFieldList.includes('AverageEngravingCycle')" <el-form-item v-if="!notShowFieldList.includes('AverageEngravingCycle')" :label="$t('trials:researchForm:form:engravingCycle')">
:label="$t('trials:researchForm:form:engravingCycle')"> <el-input-number v-model="form.AverageEngravingCycle" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" controls-position="right" :min="0" />
<el-input-number v-model="form.AverageEngravingCycle"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" controls-position="right" :min="0" />
</el-form-item> </el-form-item>
<!-- 请确认参与本项目影像采集的影像技师具备对应的资质技师证对应设备的大型设备上岗证 --> <!-- 请确认参与本项目影像采集的影像技师具备对应的资质技师证对应设备的大型设备上岗证 -->
<el-form-item v-if="!notShowFieldList.includes('IsConfirmImagingTechnologist')" <el-form-item v-if="!notShowFieldList.includes('IsConfirmImagingTechnologist')" :label="$t('trials:researchForm:form:isQualified')">
:label="$t('trials:researchForm:form:isQualified')"> <el-radio-group v-model="form.IsConfirmImagingTechnologist" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
<el-radio-group v-model="form.IsConfirmImagingTechnologist" <el-radio
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory"> v-for="item of $d.YesOrNo"
<el-radio v-for="item of $d.YesOrNo" :key="`IsConfirmImagingTechnologist${item.value}`" :label="item.value">{{ :key="`IsConfirmImagingTechnologist${item.value}`"
item.label }}</el-radio> :label="item.value"
>{{ item.label }}</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<!-- 原因 --> <!-- 原因 -->
<el-form-item v-if="!notShowFieldList.includes('NotConfirmReson') && form.IsConfirmImagingTechnologist === false" <el-form-item
:label="$t('trials:researchForm:form:notQualifiedReason')"> v-if="!notShowFieldList.includes('NotConfirmReson') && form.IsConfirmImagingTechnologist === false"
<el-input v-model="form.NotConfirmReson" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" :label="$t('trials:researchForm:form:notQualifiedReason')"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" /> >
<el-input
v-model="form.NotConfirmReson"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory"
/>
</el-form-item> </el-form-item>
<!-- 研究单位疗效评估人员类型 --> <!-- 研究单位疗效评估人员类型 -->
<el-form-item v-if="!notShowFieldList.includes('EfficacyEvaluatorType')" <el-form-item v-if="!notShowFieldList.includes('EfficacyEvaluatorType')" :label="$t('trials:researchForm:form:staffType')">
:label="$t('trials:researchForm:form:staffType')"> <el-radio-group v-model="form.EfficacyEvaluatorType" :disabled="!(state === 0 && userTypeEnumInt === 0)|| isHistory">
<el-radio-group v-model="form.EfficacyEvaluatorType" <el-radio v-for="item of $d.EfficacyEvaluatorType" :key="`EfficacyEvaluatorType${item.value}`" :label="item.value">{{ item.label }}</el-radio>
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
<el-radio v-for="item of $d.EfficacyEvaluatorType" :key="`EfficacyEvaluatorType${item.value}`"
:label="item.value">{{ item.label }}</el-radio>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
<!-- 是否严格按照研究单位影像手册参数完成图像采集 --> <!-- 是否严格按照研究单位影像手册参数完成图像采集 -->
<el-form-item v-if="!notShowFieldList.includes('IsFollowStudyParameters')"> <el-form-item v-if="!notShowFieldList.includes('IsFollowStudyParameters')">
<span slot="label" v-html="$t('trials:researchForm:form:isFollowStudyParam')" /> <span slot="label" v-html="$t('trials:researchForm:form:isFollowStudyParam')" />
<el-radio-group v-model="form.IsFollowStudyParameters" <el-radio-group v-model="form.IsFollowStudyParameters" :disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory">
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" style="margin-right: 10px;"> <el-radio v-for="item of $d.YesOrNo" :key="`IsFollowStudyParameters${item.value}`" :label="item.value">{{ item.label }}</el-radio>
<el-radio v-for="item of $d.YesOrNo" :key="`IsFollowStudyParameters${item.value}`" :label="item.value">{{
item.label }}</el-radio>
</el-radio-group> </el-radio-group>
<el-button type="primary" size="small" @click="viewManual">
{{ $t('trials:researchForm:button:viewManual') }}
</el-button>
</el-form-item> </el-form-item>
<!-- 不能严格按照研究单位影像手册参数采集图像原因 --> <!-- 不能严格按照研究单位影像手册参数采集图像原因 -->
<el-form-item v-if="!notShowFieldList.includes('NotFollowReson') && !form.IsFollowStudyParameters"> <el-form-item
v-if="!notShowFieldList.includes('NotFollowReson') && !form.IsFollowStudyParameters"
>
<span slot="label" v-html="$t('trials:researchForm:form:notFollowStudyParam')" /> <span slot="label" v-html="$t('trials:researchForm:form:notFollowStudyParam')" />
<el-input v-model="form.NotFollowReson" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" <el-input
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory" /> v-model="form.NotFollowReson"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
:disabled="!(state === 0 && userTypeEnumInt === 0) || isHistory"
/>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<!-- 保存 --> <!-- 保存 -->
<el-button v-if="state === 0 && userTypeEnumInt === 0 && !isHistory" type="primary" :loading="btnLoading" <el-button
size="small" @click="handleSave(false)"> v-if="state === 0 && userTypeEnumInt === 0 && !isHistory"
type="primary"
:loading="btnLoading"
size="small"
@click="handleSave(false)"
>
{{ $t('common:button:save') }} {{ $t('common:button:save') }}
</el-button> </el-button>
</el-form-item> </el-form-item>
<attachmentPreview :visible.sync="perview_visible" :isView="true" :isExternal="true" :ExternalList="ExternalList"
v-if="perview_visible" />
</el-form> </el-form>
</template> </template>
<script> <script>
import { getTrialSiteSelect, getTrialDocumentList } from '@/api/trials' import { getTrialSiteSelect } from '@/api/trials'
import { addOrUpdateTrialSiteSurvey } from '@/api/research' import { addOrUpdateTrialSiteSurvey } from '@/api/research'
import attachmentPreview from '@/views/dictionary/attachment/components/SignatureTemplate/attachmentPreview'
export default { export default {
name: 'QuestionForm', name: 'QuestionForm',
components: { attachmentPreview },
props: { props: {
isHistory: { isHistory: {
type: Boolean, type: Boolean,
@ -182,41 +197,10 @@ export default {
state: null, state: null,
userTypeEnumInt: zzSessionStorage.getItem('userTypeEnumInt') * 1, userTypeEnumInt: zzSessionStorage.getItem('userTypeEnumInt') * 1,
isShow: false, isShow: false,
notShowFieldList: [], notShowFieldList: []
perview_visible: false,
ExternalList: []
} }
}, },
methods: { methods: {
async viewManual() {
try {
let data = {
PageIndex: 1,
PageSize: 20,
TrialId: this.$route.query.trialId,
IsPublish: true,
FileTypeCode: 4,
IsDeleted: false
}
let res = await getTrialDocumentList(data)
if (res.IsSuccess) {
const { CurrentPageData } = res.Result
if (CurrentPageData.length <= 0) return this.$message.warning(this.$t("trials:researchRecord:ImageManual:message:noImageManual"))
this.ExternalList = []
CurrentPageData.forEach(item => {
let obj = {
FilePath: item.Path,
FileFormat: 'pdf',
Name: item.Name
}
this.ExternalList.push(obj)
});
this.perview_visible = true
}
} catch (err) {
console.log(err)
}
},
// //
handleSave(isAutoCommit) { handleSave(isAutoCommit) {
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {

View File

@ -21,15 +21,14 @@
<!-- <h4>{{ $t('trials:staffResearch:title:staff') }}</h4>--> <!-- <h4>{{ $t('trials:staffResearch:title:staff') }}</h4>-->
<!-- 历史人员 --> <!-- 历史人员 -->
<h4>{{ $t('trials:staffResearch:title:historicalStaff') }}</h4> <h4>{{ $t('trials:staffResearch:title:historicalStaff') }}</h4>
<HistoricalParticipant ref="historicalParticipant" :is-history="true" @refreshPage="refreshPage" <HistoricalParticipant ref="historicalParticipant" :is-history="true" @refreshPage="refreshPage" @getList="initPage" />
@getList="initPage" />
<!-- 新增人员 --> <!-- 新增人员 -->
<h4>{{ $t('trials:staffResearch:title:newStaff') }}</h4> <h4>{{ $t('trials:staffResearch:title:newStaff') }}</h4>
<ParticipantList ref="researchParticipants" :is-history="true" @refreshPage="refreshPage" @getList="initPage" /> <ParticipantList ref="researchParticipants" :is-history="true" @refreshPage="refreshPage" @getList="initPage" />
</el-card> </el-card>
<!-- 设备调研 --> <!-- 设备调研 -->
<el-card shadow="hover" class="mt10" v-if="!siteSurveyNoteInfo.IsCloseEquipmentSurvey"> <el-card shadow="hover" class="mt10">
<h4>{{ $t('trials:equiptResearch:title:equiptResearch') }}</h4> <h4>{{ $t('trials:equiptResearch:title:equiptResearch') }}</h4>
<EquipmentList ref="researchEquipments" :is-history="true" /> <EquipmentList ref="researchEquipments" :is-history="true" />
</el-card> </el-card>
@ -54,17 +53,31 @@
</el-card> </el-card>
</div> </div>
<el-dialog v-if="rejectVisible" :visible.sync="rejectVisible" :close-on-click-modal="false" <el-dialog
:title="$t('trials:researchForm:dialogTitle:reject')" width="600px" custom-class="base-dialog-wrapper" v-if="rejectVisible"
:append-to-body="userTypeEnumInt !== 0"> :visible.sync="rejectVisible"
:close-on-click-modal="false"
:title="$t('trials:researchForm:dialogTitle:reject')"
width="600px"
custom-class="base-dialog-wrapper"
:append-to-body="userTypeEnumInt !== 0"
>
<el-form ref="rejectForm" :model="rejectForm" label-width="100px"> <el-form ref="rejectForm" :model="rejectForm" label-width="100px">
<div class="base-dialog-body"> <div class="base-dialog-body">
<!-- 驳回原因 --> <!-- 驳回原因 -->
<el-form-item :label="$t('trials:researchForm:form:rejectReson')" prop="reason" :rules="[ <el-form-item
:label="$t('trials:researchForm:form:rejectReson')"
prop="reason"
:rules="[
{ required: true, message: $t('trials:researchForm:formRule:specify')} { required: true, message: $t('trials:researchForm:formRule:specify')}
]"> ]"
<el-input v-model="rejectForm.reason" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" >
style="width:100%;" /> <el-input
v-model="rejectForm.reason"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
style="width:100%;"
/>
</el-form-item> </el-form-item>
</div> </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;">
@ -123,7 +136,7 @@ export default {
props: { props: {
trialSiteSurveyId: { trialSiteSurveyId: {
type: String, type: String,
default: '' required: true
} }
}, },
data() { data() {
@ -139,7 +152,7 @@ export default {
btnLoading: false, btnLoading: false,
isFullscreen: false, isFullscreen: false,
historyVisible: false, historyVisible: false,
siteSurveyNoteInfo: {} siteSurveyNoteInfo: null
} }
}, },
mounted() { mounted() {
@ -159,7 +172,6 @@ export default {
if (res.Result.SiteSurveyFiledConfig && res.Result.SiteSurveyFiledConfig.ModifyFiledList.length > 0) { if (res.Result.SiteSurveyFiledConfig && res.Result.SiteSurveyFiledConfig.ModifyFiledList.length > 0) {
this.siteSurveyNoteInfo = res.Result.SiteSurveyFiledConfig.ModifyFiledList.find(i => i.NeedModifyFiled === 'SiteSurveyNote') this.siteSurveyNoteInfo = res.Result.SiteSurveyFiledConfig.ModifyFiledList.find(i => i.NeedModifyFiled === 'SiteSurveyNote')
} }
this.siteSurveyNoteInfo.IsCloseEquipmentSurvey = res.Result.SiteSurveyFiledConfig.IsCloseEquipmentSurvey
var historicalArr = [] var historicalArr = []
var newArr = [] var newArr = []
res.Result.TrialSiteUserSurveyList.map(i => { res.Result.TrialSiteUserSurveyList.map(i => {
@ -312,16 +324,13 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
.mt10{ .mt10{
margin-top: 10px; margin-top: 10px;
} }
.header-wrapper{ .header-wrapper{
width: 70%; width: 70%;
margin: 20px auto; margin: 20px auto;
} }
.center-wrapper{ .center-wrapper{
flex: 1; flex: 1;
width: 70%; width: 70%;
@ -329,11 +338,9 @@ export default {
padding-bottom: 20px; padding-bottom: 20px;
overflow-y: auto; overflow-y: auto;
} }
::v-deep .el-card__body{ ::v-deep .el-card__body{
padding: 10px; padding: 10px;
} }
// >>>.el-dialog__body{ // >>>.el-dialog__body{
// padding: 10px 20px 20px 20px; // padding: 10px 20px 20px 20px;
// } // }
@ -343,12 +350,10 @@ export default {
height: calc(100% - 80px); height: calc(100% - 80px);
} }
} }
::v-deep .dialog-container{ ::v-deep .dialog-container{
// margin-top: 50px !important; // margin-top: 50px !important;
width:75%; width:75%;
height:80%; height:80%;
.el-dialog__body{ .el-dialog__body{
padding: 10px; padding: 10px;
height: calc(100% - 80px); height: calc(100% - 80px);

View File

@ -6,37 +6,61 @@
{{ $t('trials:researchForm:title:question') }} {{ $t('trials:researchForm:title:question') }}
</h2> </h2>
<!-- <TopLang style="position: fixed;top: 40px;right: 40px" /> --> <!-- <TopLang style="position: fixed;top: 40px;right: 40px" /> -->
<div style="display: flex;justify-content: space-between;" v-if="!isPreview"> <div style="display: flex;justify-content: space-between;">
<div>{{ $t('trials:researchForm:title:researchSurveyStatus') }} <el-tag>{{ $fd('ResearchRecord', state) <div>{{ $t('trials:researchForm:title:researchSurveyStatus') }} <el-tag>{{ $fd('ResearchRecord', state) }}</el-tag></div>
}}</el-tag></div>
<div> <div>
<!-- 提交 --> <!-- 提交 -->
<el-button v-if="(state === 0 && userTypeEnumInt === 0)" type="primary" size="small" <el-button
@click="handleSubmit('submit')"> v-if="(state === 0 && userTypeEnumInt === 0)"
type="primary"
size="small"
@click="handleSubmit('submit')"
>
{{ $t('trials:researchForm:button:submit') }} {{ $t('trials:researchForm:button:submit') }}
</el-button> </el-button>
<!-- 审核通过 --> <!-- 审核通过 -->
<el-button v-if="(state === 1 && hasPermi(['role:spm', 'role:cpm']))" type="primary" size="small" <el-button
@click="handleSubmit('approve')"> v-if="(state === 1 && hasPermi(['role:spm','role:cpm']))"
type="primary"
size="small"
@click="handleSubmit('approve')"
>
{{ $t('trials:researchForm:button:auditPasses') }} {{ $t('trials:researchForm:button:auditPasses') }}
</el-button> </el-button>
<!-- 审核通过 --> <!-- 审核通过 -->
<el-button v-if="(state === 2 && hasPermi(['role:pm', 'role:apm']))" type="primary" size="small" <el-button
@click="generateAccount"> v-if="(state === 2 && hasPermi(['role:pm','role:apm']))"
type="primary"
size="small"
@click="generateAccount"
>
{{ $t('trials:researchForm:button:auditPasses') }} {{ $t('trials:researchForm:button:auditPasses') }}
</el-button> </el-button>
<!-- 驳回 --> <!-- 驳回 -->
<el-button <el-button
v-if="((state === 1 && hasPermi(['role:spm','role:cpm'])) || (state === 2 && hasPermi(['role:pm','role:apm'])))" v-if="((state === 1 && hasPermi(['role:spm','role:cpm'])) || (state === 2 && hasPermi(['role:pm','role:apm'])))"
type="primary" size="small" @click="handleReject"> type="primary"
size="small"
@click="handleReject"
>
{{ $t('trials:researchForm:button:auditRejected') }} {{ $t('trials:researchForm:button:auditRejected') }}
</el-button> </el-button>
<!-- 历史记录 --> <!-- 历史记录 -->
<el-button v-if="userTypeEnumInt === 0" type="primary" size="small" @click="handleHistory"> <el-button
v-if="userTypeEnumInt === 0"
type="primary"
size="small"
@click="handleHistory"
>
{{ $t('trials:researchForm:button:historicalRecord') }} {{ $t('trials:researchForm:button:historicalRecord') }}
</el-button> </el-button>
<!-- 退出 --> <!-- 退出 -->
<el-button v-if="userTypeEnumInt === 0" type="primary" size="small" @click="handleBack"> <el-button
v-if="userTypeEnumInt === 0"
type="primary"
size="small"
@click="handleBack"
>
{{ $t('trials:researchForm:button:loginOut') }} {{ $t('trials:researchForm:button:loginOut') }}
</el-button> </el-button>
</div> </div>
@ -45,26 +69,24 @@
<div class="center-wrapper"> <div class="center-wrapper">
<!-- 基本信息 --> <!-- 基本信息 -->
<el-card shadow="hover"> <el-card shadow="hover">
<BaseInfo ref="baseResearchInfo" :isPreview="isPreview" /> <BaseInfo ref="baseResearchInfo" />
</el-card> </el-card>
<!-- 人员调查 --> <!-- 人员调查 -->
<el-card shadow="hover" class="mt10"> <el-card shadow="hover" class="mt10">
<!-- 历史人员 --> <!-- 历史人员 -->
<h4>{{ $t('trials:staffResearch:title:historicalStaff') }}</h4> <h4>{{ $t('trials:staffResearch:title:historicalStaff') }}</h4>
<HistoricalParticipant ref="historicalParticipant" :isPreview="isPreview" @refreshPage="refreshPage" <HistoricalParticipant ref="historicalParticipant" @refreshPage="refreshPage" @getList="initPage" />
@getList="initPage" />
<!-- <h4>{{ $t('trials:staffResearch:title:staff') }}</h4> --> <!-- <h4>{{ $t('trials:staffResearch:title:staff') }}</h4> -->
<!-- 新增人员 --> <!-- 新增人员 -->
<h4>{{ $t('trials:staffResearch:title:newStaff') }}</h4> <h4>{{ $t('trials:staffResearch:title:newStaff') }}</h4>
<ParticipantList ref="researchParticipants" :isPreview="isPreview" @refreshPage="refreshPage" <ParticipantList ref="researchParticipants" @refreshPage="refreshPage" @getList="initPage" />
@getList="initPage" />
</el-card> </el-card>
<!-- 设备调研 --> <!-- 设备调研 -->
<el-card shadow="hover" class="mt10" v-if="!siteSurveyNoteInfo.IsCloseEquipmentSurvey"> <el-card shadow="hover" class="mt10">
<h4>{{ $t('trials:equiptResearch:title:equiptResearch') }}</h4> <h4>{{ $t('trials:equiptResearch:title:equiptResearch') }}</h4>
<EquipmentList ref="researchEquipments" :isPreview="isPreview" /> <EquipmentList ref="researchEquipments" />
</el-card> </el-card>
<!-- 其他信息调研 --> <!-- 其他信息调研 -->
@ -88,17 +110,31 @@
</el-card> </el-card>
</div> </div>
<el-dialog v-if="rejectVisible" :visible.sync="rejectVisible" :close-on-click-modal="false" <el-dialog
:title="$t('trials:researchForm:dialogTitle:reject')" width="600px" custom-class="base-dialog-wrapper" v-if="rejectVisible"
append-to-body> :visible.sync="rejectVisible"
:close-on-click-modal="false"
:title="$t('trials:researchForm:dialogTitle:reject')"
width="600px"
custom-class="base-dialog-wrapper"
append-to-body
>
<el-form ref="rejectForm" :model="rejectForm" label-width="100px"> <el-form ref="rejectForm" :model="rejectForm" label-width="100px">
<div class="base-dialog-body"> <div class="base-dialog-body">
<!-- 驳回原因 --> <!-- 驳回原因 -->
<el-form-item :label="$t('trials:researchForm:form:rejectReson')" prop="reason" :rules="[ <el-form-item
:label="$t('trials:researchForm:form:rejectReson')"
prop="reason"
:rules="[
{ required: true, message: $t('trials:researchForm:formRule:specify')} { required: true, message: $t('trials:researchForm:formRule:specify')}
]"> ]"
<el-input v-model="rejectForm.reason" type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" >
style="width:100%;" /> <el-input
v-model="rejectForm.reason"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
style="width:100%;"
/>
</el-form-item> </el-form-item>
</div> </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;">
@ -116,24 +152,30 @@
</el-form> </el-form>
</el-dialog> </el-dialog>
<el-dialog :visible.sync="historyVisible" <el-dialog
:custom-class="isFullscreen ? 'full-dialog-container' : 'dialog-container'" :close-on-click-modal="false" :visible.sync="historyVisible"
:fullscreen="isFullscreen" :show-close="false"> :custom-class="isFullscreen?'full-dialog-container':'dialog-container'"
:close-on-click-modal="false"
:fullscreen="isFullscreen"
:show-close="false"
>
<span slot="title" class="dialog-footer"> <span slot="title" class="dialog-footer">
<div style="display: flex;flex-direction: row;justify-content: space-between;"> <div style="display: flex;flex-direction: row;justify-content: space-between;">
<div> <div>
{{ $t('trials:researchForm:button:historicalRecord') }} {{ $t('trials:researchForm:button:historicalRecord') }}
</div> </div>
<div> <div>
<svg-icon :icon-class="isFullscreen ? 'exit-fullscreen' : 'fullscreen'" <svg-icon :icon-class="isFullscreen?'exit-fullscreen':'fullscreen'" style="vertical-align: baseline;cursor: pointer;font-size: 20px;" @click="isFullscreen=!isFullscreen" />
style="vertical-align: baseline;cursor: pointer;font-size: 20px;" @click="isFullscreen = !isFullscreen" /> <svg-icon icon-class="dClose" style="cursor: pointer;font-size: 25px;margin-left: 10px;" @click="historyVisible = false" />
<svg-icon icon-class="dClose" style="cursor: pointer;font-size: 25px;margin-left: 10px;"
@click="historyVisible = false" />
</div> </div>
</div> </div>
</span> </span>
<div style="height:100%;margin:0;"> <div style="height:100%;margin:0;">
<HistoricalRecord :trial-id="trialId" :site-id="siteId" :trial-site-survey-id="trialSiteSurveyId" /> <HistoricalRecord
:trial-id="trialId"
:site-id="siteId"
:trial-site-survey-id="trialSiteSurveyId"
/>
</div> </div>
</el-dialog> </el-dialog>
@ -152,12 +194,6 @@ import HistoricalRecord from './components/HistoricalRecord'
export default { export default {
name: 'QuestionForm', name: 'QuestionForm',
components: { BaseInfo, HistoricalParticipant, ParticipantList, EquipmentList, TopLang, HistoricalRecord }, components: { BaseInfo, HistoricalParticipant, ParticipantList, EquipmentList, TopLang, HistoricalRecord },
props: {
isPreview: {
type: Boolean,
default: false
}
},
data() { data() {
return { return {
trialId: this.$route.query.trialId, trialId: this.$route.query.trialId,
@ -172,7 +208,7 @@ export default {
btnLoading: false, btnLoading: false,
isFullscreen: false, isFullscreen: false,
historyVisible: false, historyVisible: false,
siteSurveyNoteInfo: {} siteSurveyNoteInfo: null
} }
}, },
mounted() { mounted() {
@ -193,7 +229,6 @@ export default {
if (res.Result.SiteSurveyFiledConfig && res.Result.SiteSurveyFiledConfig.ModifyFiledList.length > 0) { if (res.Result.SiteSurveyFiledConfig && res.Result.SiteSurveyFiledConfig.ModifyFiledList.length > 0) {
this.siteSurveyNoteInfo = res.Result.SiteSurveyFiledConfig.ModifyFiledList.find(i => i.NeedModifyFiled === 'SiteSurveyNote') this.siteSurveyNoteInfo = res.Result.SiteSurveyFiledConfig.ModifyFiledList.find(i => i.NeedModifyFiled === 'SiteSurveyNote')
} }
this.siteSurveyNoteInfo.IsCloseEquipmentSurvey = res.Result.SiteSurveyFiledConfig.IsCloseEquipmentSurvey
this.state = res.Result.TrialSiteSurvey.State this.state = res.Result.TrialSiteSurvey.State
this.siteId = res.Result.TrialSiteSurvey.TrialSiteId this.siteId = res.Result.TrialSiteSurvey.TrialSiteId
this.$refs['baseResearchInfo'].initForm(res.Result.TrialInfo, res.Result.TrialSiteSurvey, res.Result.SiteSurveyFiledConfig ? res.Result.SiteSurveyFiledConfig.NotShowFieldList : null) this.$refs['baseResearchInfo'].initForm(res.Result.TrialInfo, res.Result.TrialSiteSurvey, res.Result.SiteSurveyFiledConfig ? res.Result.SiteSurveyFiledConfig.NotShowFieldList : null)
@ -323,8 +358,7 @@ export default {
this.$emit('refreshPage') this.$emit('refreshPage')
}, },
// 退 // 退
async handleBack() { handleBack() {
await this.$store.dispatch('user/logout')
this.$router.push({ path: `/researchLogin?trialId=${this.trialId}&lang=${this.$i18n.locale}` }) this.$router.push({ path: `/researchLogin?trialId=${this.trialId}&lang=${this.$i18n.locale}` })
}, },
handleHistory() { handleHistory() {
@ -339,16 +373,13 @@ export default {
display: flex; display: flex;
flex-direction: column; flex-direction: column;
height: 100%; height: 100%;
.mt10{ .mt10{
margin-top: 10px; margin-top: 10px;
} }
.header-wrapper{ .header-wrapper{
width: 70%; width: 70%;
margin: 20px auto; margin: 20px auto;
} }
.center-wrapper{ .center-wrapper{
flex: 1; flex: 1;
width: 70%; width: 70%;
@ -356,11 +387,9 @@ export default {
padding-bottom: 20px; padding-bottom: 20px;
overflow-y: auto; overflow-y: auto;
} }
::v-deep.el-card__body{ ::v-deep.el-card__body{
padding: 10px; padding: 10px;
} }
// >>>.el-dialog__body{ // >>>.el-dialog__body{
// padding: 10px 20px 20px 20px; // padding: 10px 20px 20px 20px;
// } // }
@ -370,12 +399,10 @@ export default {
height: calc(100% - 80px); height: calc(100% - 80px);
} }
} }
::v-deep.dialog-container{ ::v-deep.dialog-container{
// margin-top: 50px !important; // margin-top: 50px !important;
width:75%; width:75%;
height:80%; height:80%;
.el-dialog__body{ .el-dialog__body{
padding: 10px; padding: 10px;
height: calc(100% - 80px); height: calc(100% - 80px);

View File

@ -7,8 +7,16 @@
<!-- <TopLang style="position: fixed;top: 40px;right: 40px" /> --> <!-- <TopLang style="position: fixed;top: 40px;right: 40px" /> -->
</h2> </h2>
<el-card shadow="hover"> <el-card shadow="hover">
<el-form ref="resetForm" v-loading="loading" :model="form" label-width="150px" style="width:80%;margin:0 auto;" <el-form
:rules="rules" class="demo-ruleForm" size="small"> ref="resetForm"
v-loading="loading"
:model="form"
label-width="150px"
style="width:80%;margin:0 auto;"
:rules="rules"
class="demo-ruleForm"
size="small"
>
<!-- 项目编号 --> <!-- 项目编号 -->
<el-form-item :label="$t('trials:researchForm:form:trialId')"> <el-form-item :label="$t('trials:researchForm:form:trialId')">
<el-input v-model="form.TrialCode" disabled /> <el-input v-model="form.TrialCode" disabled />
@ -27,10 +35,13 @@
</el-form-item> </el-form-item>
<!-- 中心名称 --> <!-- 中心名称 -->
<el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId"> <el-form-item :label="$t('trials:researchForm:form:siteName')" prop="TrialSiteId">
<el-select v-model="form.TrialSiteId" filterable style="width:100%;" @change="handleSiteChange" <el-select v-model="form.TrialSiteId" filterable style="width:100%;" @change="handleSiteChange">
:disabled="isUpload"> <el-option
<el-option v-for="(item, index) of siteOptions" :key="index" :label="item.TrialSiteAliasName" v-for="(item,index) of siteOptions"
:value="item.TrialSiteId" /> :key="index"
:label="item.TrialSiteAliasName"
:value="item.TrialSiteId"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 中心编号 --> <!-- 中心编号 -->
@ -39,18 +50,17 @@
</el-form-item> </el-form-item>
<el-form-item v-if="form.TrialSiteId && isHaveSiteSurveyRecord" label="" style="text-align:right;"> <el-form-item v-if="form.TrialSiteId && isHaveSiteSurveyRecord" label="" style="text-align:right;">
<!-- 更新调研表 --> <!-- 更新调研表 -->
<el-link v-if="!form.IsUpdate && isNeedUpload" type="primary" @click="form.IsUpdate = true"> <el-link v-if="!form.IsUpdate" type="primary" @click="form.IsUpdate = true">
{{ $t('trials:researchForm:button:updateQsForm') }} {{ $t('trials:researchForm:button:updateQsForm') }}
</el-link> </el-link>
<!-- 取消更新调研表 form.ReplaceUserEmailOrPhone = '' --> <!-- 取消更新调研表 -->
<el-link v-if="form.IsUpdate && isNeedUpload" type="primary" @click="form.IsUpdate = false;"> <el-link v-else type="primary" @click="form.IsUpdate = false;form.ReplaceUserEmailOrPhone=''">
{{ $t('trials:researchForm:button:cancelUpdateQsForm') }} {{ $t('trials:researchForm:button:cancelUpdateQsForm') }}
</el-link> </el-link>
</el-form-item> </el-form-item>
<!-- 原调研表填写人邮箱 --> <!-- 原调研表填写人邮箱 -->
<el-form-item v-if="form.IsUpdate" :label="$t('trials:researchForm:form:originalEmail')" <el-form-item v-if="form.IsUpdate" :label="$t('trials:researchForm:form:originalEmail')" prop="ReplaceUserEmailOrPhone">
prop="ReplaceUserEmailOrPhone"> <el-input v-model="form.ReplaceUserEmailOrPhone" autocomplete="new-password" />
<el-input v-model="form.ReplaceUserEmailOrPhone" autocomplete="new-password" :disabled="isUpload" />
</el-form-item> </el-form-item>
<!-- 联系邮箱 --> <!-- 联系邮箱 -->
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')" prop="EmailOrPhone"> <el-form-item :label="$t('trials:researchForm:form:contactorEmail')" prop="EmailOrPhone">
@ -64,9 +74,13 @@
</el-form-item> </el-form-item>
</el-col> </el-col>
<el-col style="width: 120px;margin-left: 10px"> <el-col style="width: 120px;margin-left: 10px">
<el-button size="small" class="codeBtn" style="width:100%;" <el-button
:disabled="sendDisabled || !form.EmailOrPhone || count > 0" @click="handleSendCode">{{ size="small"
this.$t('trials:researchForm:button:send') }} {{ sendTitle ? `${sendTitle}` : null }}</el-button> type="primary"
style="width:100%;"
:disabled="sendDisabled || !form.EmailOrPhone || count > 0"
@click="handleSendCode"
>{{ this.$t('trials:researchForm:button:send') }} {{ sendTitle ? `${sendTitle}` : null }}</el-button>
</el-col> </el-col>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
@ -189,9 +203,7 @@ export default {
timer: null, timer: null,
msg: '', msg: '',
lang: 'zh', lang: 'zh',
isHaveSiteSurveyRecord: false, isHaveSiteSurveyRecord: false
isUpload: false,
isNeedUpload: true
} }
}, },
computed: { computed: {
@ -209,21 +221,6 @@ export default {
this.trialId = this.$route.query.trialId this.trialId = this.$route.query.trialId
this.initPage() this.initPage()
} }
if (this.$route.query.isUpload) {
this.isUpload = true
this.form.IsUpdate = true
let { email, oldEMail, trialSiteId } = this.$route.query
if (trialSiteId) this.form.TrialSiteId = trialSiteId
if (oldEMail) this.form.ReplaceUserEmailOrPhone = oldEMail
if (email && email !== 'null') {
this.form.EmailOrPhone = email
} else {
this.form.EmailOrPhone = oldEMail
}
if ((email && email !== 'null') || (oldEMail && oldEMail !== 'null')) {
this.isNeedUpload = false
}
}
}, },
methods: { methods: {
...mapMutations({ setLanguage: 'lang/setLanguage' }), ...mapMutations({ setLanguage: 'lang/setLanguage' }),
@ -238,9 +235,6 @@ export default {
this.form[key] = Result[key] this.form[key] = Result[key]
} }
}) })
if (this.isUpload) {
this.handleSiteChange(this.form.TrialSiteId)
}
this.loading = false this.loading = false
}).catch(() => { this.loading = false }) }).catch(() => { this.loading = false })
}, },
@ -271,8 +265,6 @@ export default {
this.setLanguage(this.$route.query.lang) this.setLanguage(this.$route.query.lang)
store.dispatch('user/setToken', res.Result.Token) store.dispatch('user/setToken', res.Result.Token)
zzSessionStorage.setItem('TokenKey', res.Result.Token) zzSessionStorage.setItem('TokenKey', res.Result.Token)
zzSessionStorage.setItem('userId', res.Result.UserRoleId);
zzSessionStorage.setItem('identityUserId', res.Result.IdentityUserId);
var permissions = await getUserPermissions() var permissions = await getUserPermissions()
var menuTree = await getUserMenuTree() var menuTree = await getUserMenuTree()
store.dispatch('user/setTree', menuTree.Result) store.dispatch('user/setTree', menuTree.Result)
@ -353,24 +345,8 @@ export default {
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.codeBtn {
color: #409EFF;
border-color: #409EFF;
}
.codeBtn.is-disabled,
.codeBtn.is-disabled:focus,
.codeBtn.is-disabled:hover {
color: #c0c4cc;
cursor: not-allowed;
background-image: none;
background-color: #fff;
border-color: #ebeef5;
}
.question-login-wrapper { .question-login-wrapper {
padding: 20px; padding: 20px;
.box-wrapper { .box-wrapper {
width: 50%; width: 50%;
margin: 20px auto; margin: 20px auto;

View File

@ -7,20 +7,51 @@
{{ $t('trials:researchForm:form:title') }} {{ $t('trials:researchForm:form:title') }}
</h2> </h2>
<el-card shadow="hover" style="padding-top: 40px"> <el-card shadow="hover" style="padding-top: 40px">
<el-form ref="resetForm" v-loading="loading" :model="form" label-width="150px" <el-form
style="width: 80%; margin: 0 auto" :rules="rules" class="demo-ruleForm" size="small"> ref="resetForm"
v-loading="loading"
:model="form"
label-width="150px"
style="width: 80%; margin: 0 auto"
:rules="rules"
class="demo-ruleForm"
size="small"
>
<!-- 联系邮箱 --> <!-- 联系邮箱 -->
<el-form-item :label="$t('trials:researchForm:form:contactorEmail')" prop="EmailOrPhone"> <el-form-item
<el-input v-model="form.EmailOrPhone" autocomplete="new-password" @change="handleEmailChange" /> :label="$t('trials:researchForm:form:contactorEmail')"
prop="EmailOrPhone"
>
<el-input
v-model="form.EmailOrPhone"
autocomplete="new-password"
@change="handleEmailChange"
/>
</el-form-item> </el-form-item>
<!-- 验证码 --> <!-- 验证码 -->
<el-form-item :label="$t('trials:researchForm:form:verifyCode')" prop="VerificationCode"> <el-form-item
<div style="display: flex;;justify-content: space-between;"> :label="$t('trials:researchForm:form:verifyCode')"
<el-input v-model="form.VerificationCode" autocomplete="new-password" /> required
<el-button size="small" style="margin-left: 10px;" :disabled="sendDisabled" class="codeBtn" >
@click="handleSendCode">{{ this.$t('trials:researchForm:button:send') <el-col :span="20">
}}{{ count || count === 0 ? `(${count}s)` : '' }}</el-button> <el-form-item prop="VerificationCode">
</div> <el-input
v-model="form.VerificationCode"
autocomplete="new-password"
/>
</el-form-item>
</el-col>
<el-col :span="4">
<el-button
size="small"
type="primary"
style="width: 100%"
:disabled="sendDisabled"
@click="handleSendCode"
>{{ this.$t('trials:researchForm:button:send')
}}{{ count || count === 0 ? `(${count}s)` : '' }}</el-button
>
</el-col>
</el-form-item> </el-form-item>
<el-form-item> <el-form-item>
<!-- 取消 --> <!-- 取消 -->
@ -28,7 +59,12 @@
{{ $t('common:button:cancel') }} {{ $t('common:button:cancel') }}
</el-button> </el-button>
<!-- 提交 --> <!-- 提交 -->
<el-button size="small" type="primary" :loading="btnLoading" @click="onSubmit"> <el-button
size="small"
type="primary"
:loading="btnLoading"
@click="onSubmit"
>
{{ $t('common:button:submit') }} {{ $t('common:button:submit') }}
</el-button> </el-button>
</el-form-item> </el-form-item>
@ -213,15 +249,20 @@ export default {
// this.$router.push({ path: `/researchForm?trialId=${this.trialId}&trialSiteSurveyId=${res.Result.TrialSiteSurveyId}` }) // this.$router.push({ path: `/researchForm?trialId=${this.trialId}&trialSiteSurveyId=${res.Result.TrialSiteSurveyId}` })
if (this.$route.query.trialId) { if (this.$route.query.trialId) {
this.$router.push({ this.$router.push({
path: `/curriculumVitae?Id=${res.Result.DoctorId ? res.Result.DoctorId : '' path: `/curriculumVitae?Id=${
}&tabActive=BasicInfo&ReviewStatus=${res.Result.ReviewStatus res.Result.DoctorId ? res.Result.DoctorId : ''
}&trialId=${this.$route.query.trialId}&lang=${this.$route.query.lang }&tabActive=BasicInfo&ReviewStatus=${
res.Result.ReviewStatus
}&trialId=${this.$route.query.trialId}&lang=${
this.$route.query.lang
}`, }`,
}) })
} else { } else {
this.$router.push({ this.$router.push({
path: `/curriculumVitae?Id=${res.Result.DoctorId ? res.Result.DoctorId : '' path: `/curriculumVitae?Id=${
}&tabActive=BasicInfo&ReviewStatus=${res.Result.ReviewStatus res.Result.DoctorId ? res.Result.DoctorId : ''
}&tabActive=BasicInfo&ReviewStatus=${
res.Result.ReviewStatus
}&lang=${this.$route.query.lang}`, }&lang=${this.$route.query.lang}`,
}) })
} }
@ -271,7 +312,8 @@ export default {
this.timer = setInterval(() => { this.timer = setInterval(() => {
if (this.count > 0 && this.count <= TIME_COUNT) { if (this.count > 0 && this.count <= TIME_COUNT) {
this.count-- this.count--
this.sendTitle = `${this.$t('trials:researchForm:button:send')}(${this.count this.sendTitle = `${this.$t('trials:researchForm:button:send')}(${
this.count
}s)` }s)`
this.sendDisabled = true this.sendDisabled = true
} else { } else {
@ -293,7 +335,6 @@ export default {
<style lang="scss" scoped> <style lang="scss" scoped>
.question-login-wrapper { .question-login-wrapper {
padding: 20px; padding: 20px;
.box-wrapper { .box-wrapper {
width: 50%; width: 50%;
margin: 20px auto; margin: 20px auto;
@ -301,19 +342,4 @@ export default {
color: #303133; color: #303133;
} }
} }
.codeBtn {
color: #409EFF;
border-color: #409EFF;
}
.codeBtn.is-disabled,
.codeBtn.is-disabled:focus,
.codeBtn.is-disabled:hover {
color: #c0c4cc;
cursor: not-allowed;
background-image: none;
background-color: #fff;
border-color: #ebeef5;
}
</style> </style>

View File

@ -79,7 +79,10 @@
<el-table-column prop="date" :label="$t('common:action:action')"> <el-table-column prop="date" :label="$t('common:action:action')">
<template <template
slot-scope="scope" slot-scope="scope"
v-if="scope.row.ExperienceDataType != 3" v-if="
scope.row.ExperienceDataType != 2 &&
scope.row.ExperienceDataType != 3
"
> >
<el-button <el-button
type="text" type="text"

View File

@ -2,8 +2,14 @@
<div class="curriculumVitae" v-loading="loading"> <div class="curriculumVitae" v-loading="loading">
<div class="leftMenu"> <div class="leftMenu">
<div class="title">{{ $t('curriculumVitae:menu:title') }}</div> <div class="title">{{ $t('curriculumVitae:menu:title') }}</div>
<el-menu :default-active="activeIndex" class="el-menu-demo" mode="vertical" @select="handleSelect" <el-menu
background-color="#eee" active-text-color="#000"> :default-active="activeIndex"
class="el-menu-demo"
mode="vertical"
@select="handleSelect"
background-color="#eee"
active-text-color="#000"
>
<el-menu-item index="info"> <el-menu-item index="info">
{{ $t('curriculumVitae:menu:info') }} {{ $t('curriculumVitae:menu:info') }}
</el-menu-item> </el-menu-item>
@ -64,58 +70,94 @@
</el-button> </el-button>
</div> </div>
</div> </div>
<!--个人信息-->
<div class="box" id="info"> <div class="box" id="info">
<info :DATA="{ <info
:DATA="{
...reviewerData.BasicInfoView, ...reviewerData.BasicInfoView,
...reviewerData.EmploymentView, ...reviewerData.EmploymentView,
}" :reviewerId.sync="reviewerId" :isEN="isEN" @getInfo="getDetail" /> }"
:reviewerId.sync="reviewerId"
:isEN="isEN"
@getInfo="getDetail"
/>
</div> </div>
<!--概述-->
<div class="box" id="summarize"> <div class="box" id="summarize">
<summarize :DATA="{ <summarize
:DATA="{
...reviewerData.SummarizeInfo, ...reviewerData.SummarizeInfo,
}" :reviewerId.sync="reviewerId" :trialId="trialId" :isEN="isEN" @getInfo="getDetail" /> }"
:reviewerId.sync="reviewerId"
:trialId="trialId"
:isEN="isEN"
@getInfo="getDetail"
/>
</div> </div>
<!--专业-->
<div class="box" id="specialty"> <div class="box" id="specialty">
<specialty :DATA="{ <specialty
:DATA="{
...reviewerData.SpecialtyView, ...reviewerData.SpecialtyView,
}" :isEN="isEN" :reviewerId.sync="reviewerId" @getInfo="getDetail" /> }"
:isEN="isEN"
:reviewerId.sync="reviewerId"
@getInfo="getDetail"
/>
</div> </div>
<!--教育经历-->
<div class="box" id="educationalExperience"> <div class="box" id="educationalExperience">
<educationalExperience :DATA="reviewerData.EducationList" :isEN="isEN" :reviewerId.sync="reviewerId" <educationalExperience
@getInfo="getDetail" /> :DATA="reviewerData.EducationList"
:isEN="isEN"
:reviewerId.sync="reviewerId"
@getInfo="getDetail"
/>
</div> </div>
<!--进修培训-->
<div class="box" id="continuingTraining"> <div class="box" id="continuingTraining">
<continuingTraining :DATA="reviewerData.PostgraduateList" :isEN="isEN" :reviewerId.sync="reviewerId" <continuingTraining
@getInfo="getDetail" /> :DATA="reviewerData.PostgraduateList"
:isEN="isEN"
:reviewerId.sync="reviewerId"
@getInfo="getDetail"
/>
</div> </div>
<!--科研课题-->
<div class="box" id="scientificResearchProject"> <div class="box" id="scientificResearchProject">
<scientificResearchProject :DATA="{ ...reviewerData.ResearchPublicationView }" :isEN="isEN" <scientificResearchProject
:reviewerId.sync="reviewerId" @getInfo="getDetail" /> :DATA="{ ...reviewerData.ResearchPublicationView }"
:isEN="isEN"
:reviewerId.sync="reviewerId"
@getInfo="getDetail"
/>
</div> </div>
<!--临床试验-->
<div class="box" id="clinicalTrials"> <div class="box" id="clinicalTrials">
<clinicalTrials :DATA="{ ...reviewerData.TrialExperienceView }" :isEN="isEN" :reviewerId.sync="reviewerId" <clinicalTrials
:trialId="trialId" @getInfo="getDetail" /> :DATA="{ ...reviewerData.TrialExperienceView }"
:isEN="isEN"
:reviewerId.sync="reviewerId"
:trialId="trialId"
@getInfo="getDetail"
/>
</div> </div>
<!--gcp证书-->
<div class="box" id="treatise"> <div class="box" id="treatise">
<treatise :DATA="{ ...reviewerData.ResearchPublicationView }" :isEN="isEN" :reviewerId.sync="reviewerId" <treatise
@getInfo="getDetail" /> :DATA="{ ...reviewerData.ResearchPublicationView }"
:isEN="isEN"
:reviewerId.sync="reviewerId"
@getInfo="getDetail"
/>
</div> </div>
<!--其他相关经历-->
<div class="box" id="other"> <div class="box" id="other">
<other :DATA="{ ...reviewerData.ResearchPublicationView }" :isEN="isEN" :reviewerId.sync="reviewerId" <other
@getInfo="getDetail" /> :DATA="{ ...reviewerData.ResearchPublicationView }"
:isEN="isEN"
:reviewerId.sync="reviewerId"
@getInfo="getDetail"
/>
</div> </div>
<div class="box" id="pay"> <div class="box" id="pay">
<pay :DATA="{ ...reviewerData.PaymentModeInfo }" :isEN="isEN" :reviewerId.sync="reviewerId" <pay
@getInfo="getDetail" /> :DATA="{ ...reviewerData.PaymentModeInfo }"
:isEN="isEN"
:reviewerId.sync="reviewerId"
@getInfo="getDetail"
/>
</div> </div>
<div class="box" id="setting" v-if="isPM"> <div class="box" id="setting" v-if="isPM">
<setting :isEN="isEN" :reviewerId.sync="reviewerId" /> <setting :isEN="isEN" :reviewerId.sync="reviewerId" />
@ -125,19 +167,38 @@
<!--简历附件--> <!--简历附件-->
<curriculum :isEN="isEN" :reviewerId.sync="reviewerId" /> <curriculum :isEN="isEN" :reviewerId.sync="reviewerId" />
<!--资历证书--> <!--资历证书-->
<certificate :DATA="reviewerData.AttachmentList" :isEN="isEN" :reviewerId.sync="reviewerId" <certificate
@getInfo="getDetail" /> :DATA="reviewerData.AttachmentList"
:isEN="isEN"
:reviewerId.sync="reviewerId"
@getInfo="getDetail"
/>
<!--协议--> <!--协议-->
<agreement :DATA="reviewerData.AttachmentList" :isEN="isEN" :isPM="isPM" :reviewerId.sync="reviewerId" <agreement
@getInfo="getDetail" /> :DATA="reviewerData.AttachmentList"
:isEN="isEN"
:isPM="isPM"
:reviewerId.sync="reviewerId"
@getInfo="getDetail"
/>
</div> </div>
</div> </div>
<el-dialog :visible.sync="visible" fullscreen append-to-body> <el-dialog :visible.sync="visible" fullscreen append-to-body>
<div style="height: 100%; overflow: auto"> <div style="height: 100%; overflow: auto">
<preview :isEN="isEN" :reviewerId.sync="reviewerId" :trialId="trialId" :isAll="isAll" v-if="visible" /> <preview
:isEN="isEN"
:reviewerId.sync="reviewerId"
:trialId="trialId"
:isAll="isAll"
v-if="visible"
/>
</div> </div>
</el-dialog> </el-dialog>
<holiday v-if="holidayVisible" :reviewerId.sync="reviewerId" :visible.sync="holidayVisible" /> <holiday
v-if="holidayVisible"
:reviewerId.sync="reviewerId"
:visible.sync="holidayVisible"
/>
<!-- <setting <!-- <setting
v-if="settingVisible" v-if="settingVisible"
:reviewerId.sync="reviewerId" :reviewerId.sync="reviewerId"
@ -322,14 +383,12 @@ export default {
position: relative; position: relative;
height: 100%; height: 100%;
} }
.title { .title {
line-height: 50px; line-height: 50px;
background-color: #fff; background-color: #fff;
text-align: center; text-align: center;
font-weight: bold; font-weight: bold;
} }
.leftMenu { .leftMenu {
position: absolute; position: absolute;
left: 0; left: 0;
@ -338,15 +397,12 @@ export default {
height: 100%; height: 100%;
background-color: #eee; background-color: #eee;
border-right: 1px solid #eee; border-right: 1px solid #eee;
::v-deep .el-menu { ::v-deep .el-menu {
padding: 5px 5px 0; padding: 5px 5px 0;
} }
::v-deep .is-active { ::v-deep .is-active {
background-color: #fff !important; background-color: #fff !important;
position: relative; position: relative;
&::before { &::before {
display: block; display: block;
content: ''; content: '';
@ -359,7 +415,6 @@ export default {
} }
} }
} }
.main { .main {
width: calc(100% - 300px); width: calc(100% - 300px);
height: 100%; height: 100%;
@ -368,11 +423,9 @@ export default {
display: flex; display: flex;
align-items: flex-start; align-items: flex-start;
} }
.content { .content {
width: calc(100% - 300px); width: calc(100% - 300px);
padding: 0 50px 0 20px; padding: 0 50px 0 20px;
.title { .title {
line-height: 50px; line-height: 50px;
background-color: #fff; background-color: #fff;
@ -381,42 +434,35 @@ export default {
justify-content: space-between; justify-content: space-between;
} }
} }
.box { .box {
border: 1px solid #ddd; border: 1px solid #ddd;
border-radius: 3px; border-radius: 3px;
padding: 15px; padding: 15px;
margin-bottom: 20px; margin-bottom: 20px;
} }
::v-deep .noData { ::v-deep .noData {
color: #909399; color: #909399;
text-align: center; text-align: center;
} }
.rightFile { .rightFile {
width: 300px; width: 300px;
padding-right: 10px; padding-right: 10px;
::v-deep .title { ::v-deep .title {
line-height: 50px; line-height: 50px;
background-color: #fff; background-color: #fff;
text-align: left; text-align: left;
font-weight: bold; font-weight: bold;
} }
::v-deep .fileBox { ::v-deep .fileBox {
background-color: #eee; background-color: #eee;
padding: 10px; padding: 10px;
font-size: 14px; font-size: 14px;
border-radius: 3px; border-radius: 3px;
} }
::v-deep .file_title { ::v-deep .file_title {
line-height: 40px; line-height: 40px;
font-weight: bold; font-weight: bold;
} }
::v-deep .btnBox { ::v-deep .btnBox {
display: flex; display: flex;
align-items: center; align-items: center;
@ -428,23 +474,17 @@ export default {
width: 100%; width: 100%;
display: flex; display: flex;
margin-bottom: 10px; margin-bottom: 10px;
.name { .name {
width: 70%; width: 70%;
white-space: nowrap; white-space: nowrap; /* 文本不会换行,会在同一行内继续,直到遇到<br>标签为止 */
/* 文本不会换行,会在同一行内继续,直到遇到<br>标签为止 */ text-overflow: ellipsis; /* 当文本溢出包含它的容器时,显示省略号(...)来表示被截断的文本 */
text-overflow: ellipsis; overflow: hidden; /* 隐藏溢出容器的文本 */
/* 当文本溢出包含它的容器时,显示省略号(...)来表示被截断的文本 */
overflow: hidden;
/* 隐藏溢出容器的文本 */
} }
i { i {
cursor: pointer; cursor: pointer;
margin: 3px; margin: 3px;
color: #409eff; color: #409eff;
} }
.disable { .disable {
cursor: not-allowed; cursor: not-allowed;
color: #909399; color: #909399;

View File

@ -1,228 +0,0 @@
<template>
<div class="detail">
<div class="attachment" v-if="Array.isArray(info.AttachmentList) && info.AttachmentList.length > 0">
<div class="box" v-for="item of info.AttachmentList" :key="item.AttachmentPath" @click="perview(item)">
<i :class="`icon icon_file icon_${item.type}`" />
<span>{{ item.AttachmentName }}</span>
</div>
<span class="downLoadTip" @click="downloadFile">{{ $t('system:email:tip:allDownLoad') }}</span>
</div>
<div class="content" v-html="info.Content"></div>
<viewer ref="picture_perview" style="margin: 0 10px"
v-if="rowData.type && ['png', 'jpg', 'jpeg'].includes(rowData.type.toLowerCase())"
:images="[`${OSSclientConfig.basePath}${rowData.AttachmentPath}`]" :options="viewerOptions">
<img v-show="false" :src="`${OSSclientConfig.basePath}${rowData.AttachmentPath}`" alt="Image" />
</viewer>
</div>
</template>
<script>
import { downLoadFile } from '@/utils/stream.js'
export default {
name: "emailDetail",
props: {
info: {
type: Object,
default: () => {
return {}
}
}
},
data() {
return {
rowData: {},
viewerOptions: {
toolbar: {
zoomIn: true,
zoomOut: true,
reset: true,
prev: false,
next: false,
rotateLeft: true,
rotateRight: true,
flipHorizontal: true,
flipVertical: true,
}
}
}
},
methods: {
//
perview(data) {
this.rowData = data
if (['.ppt',
'.pptx',
'.doc',
'.docx',
'.xls',
'.xlsx'].includes(`.${data.type.toLowerCase()}`)) {
this.$onlyOffice({
path: data.AttachmentPath,
type: data.type,
title: data.AttachmentName
})
}
if (['.jpg',
'.jpeg',
'.png'].includes(`.${data.type.toLowerCase()}`)) {
this.$refs['picture_perview'].$viewer.show()
}
if (['.pdf'].includes(`.${data.type.toLowerCase()}`)) {
this.$preview({
path: data.Path || data.AttachmentPath,
type: 'pdf',
title: data.AttachmentName,
})
}
},
async downloadFile() {
try {
let { files, name } = this.formatDownloadFile(this.info.AttachmentList)
let res = await downLoadFile(files, name, 'zip')
} catch (err) {
console.log(err)
}
},
//
formatDownloadFile(list) {
let files = [],
name = `Attachment_${new Date().getTime()}.zip`
list.forEach(item => {
let obj = {
name: item.AttachmentName,
url: this.OSSclientConfig.basePath + item.AttachmentPath,
}
files.push(obj)
})
return { files, name }
},
}
}
</script>
<style lang="scss" scoped>
.attachment {
border-bottom: 1px solid #EBEEF5;
padding: 10px 0 0 0;
display: flex;
.box {
padding: 5px 10px;
display: flex;
align-items: center;
max-width: 400px;
overflow: hidden;
white-space: nowrap;
text-overflow: ellipsis;
border-radius: 5px;
background-color: #E4E7ED;
cursor: pointer;
margin-right: 10px;
margin-bottom: 10px;
i {
margin-right: 5px;
}
}
.downLoadTip {
cursor: pointer;
font-size: 14px;
color: #409EFF;
}
}
.content {
width: 100%;
overflow: hidden;
}
.icon {
height: 20px;
width: 20px;
padding: 0px;
line-height: 20px;
margin-right: 6px;
margin-top: 6px;
}
/*文件*/
.icon_file {
width: 16px !important;
height: 16px !important;
margin-right: 6px;
background-size: inherit;
background-image: url(@/assets/0.file-16.png);
background-position: 0 0;
margin-top: -2px;
background-repeat: no-repeat;
font-style: normal;
display: inline-block;
pointer-events: none;
font-size: 85%;
}
/*文件夹*/
.icon_folder {
background-image: url(@/assets/folder_win11_small.png);
margin-top: -6px;
margin-left: 2px;
margin-right: 6px;
background-repeat: no-repeat;
}
/*docx*/
.icon_docx {
background-position: -81px -560px !important;
margin-top: 0;
margin-left: 2px;
}
/*doc*/
.icon_doc {
background-position: -81px -592px !important;
margin-top: 0;
margin-left: 2px;
}
/*xlsx*/
.icon_xlsx {
background-position: -81px -48px !important;
margin-top: 0;
margin-left: 2px;
}
/*pdf*/
.icon_pdf {
background-position: -81px -352px !important;
margin-top: 0;
margin-left: 2px;
}
/*pptx*/
.icon_pptx {
background-position: -81px -288px !important;
margin-top: 0;
margin-left: 2px;
}
/*zip*/
.icon_zip {
background-position: 0 0 !important;
margin-top: -2px;
margin-left: 2px;
}
/*ppt*/
.icon_ppt {
background-position: -81px -304px !important;
margin-top: 0;
margin-left: 2px;
}
/*xls*/
.icon_xls {
background-position: -81px -96px !important;
margin-top: 0;
margin-left: 2px;
}
</style>

View File

@ -1,264 +0,0 @@
<template>
<div class="event">
<div ref="leftContainer" class="left">
<el-form :inline="true">
<el-form-item :label="$t('system:email:search:ToRecipientName')">
<el-input v-model="searchData.ToRecipientName" clearable />
</el-form-item>
<el-form-item :label="$t('system:email:search:CcRecipientName')">
<el-input v-model="searchData.CcRecipientName" clearable />
</el-form-item>
<el-form-item :label="$t('system:email:search:EmailStateEnum')">
<el-select v-model="searchData.EmailStateEnum" clearable filterable placeholder="">
<el-option v-for="item in $d.EmailState" :key="item.id" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<!-- <el-form-item :label="$t('system:email:search:EmailStateEnum')">
<el-select v-model="searchData.EmailStateEnum" clearable filterable placeholder="">
<el-option v-for="item in $d.EmailState" :key="item.id" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item> -->
<el-form-item :label="$t('system:email:search:emailDate')">
<el-date-picker v-model="datetimerange" type="datetimerange"
:default-time="['00:00:00', '23:59:59']" :start-placeholder="$t('feedBack:search:beginTime')"
:end-placeholder="$t('feedBack:search:endTime')" value-format="yyyy-MM-dd HH:mm:ss"
@change="handleDatetimeChange" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="small" @click="getList">
{{ $t('common:button:search') }}
</el-button>
<el-button icon="el-icon-refresh-left" size="small" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
<!-- <el-button type="primary" size="small" @click="synchronizationEmail">
{{ $t('system:email:button:sync') }}
</el-button> -->
</el-form-item>
</el-form>
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 45 }" height="100" :data="list" class="table"
@sort-change="handleSortByColumn">
<el-table-column type="index" width="50" />
<el-table-column :label="$t('system:email:table:messageId')" prop="MessageId" show-overflow-tooltip
sortable="custom" />
<el-table-column :label="$t('system:email:table:emailSubject')" prop="EmailSubject"
show-overflow-tooltip />
<el-table-column :label="$t('system:email:table:ToRecipientName')" prop="ToRecipientName"
show-overflow-tooltip>
<template slot-scope="scope">
<el-tooltip class="item" effect="dark" :content="scope.row.RecipientList.filter(item => item.RecipientTypeEnum === 0).map(item =>
`${item.RecipientName}: ${item.RecipientAddress}`).join('<br/>')" placement="top-start"
v-if="Array.isArray(scope.row.RecipientList) && scope.row.RecipientList.length > 0">
<span>{{Array.isArray(scope.row.RecipientList) && scope.row.RecipientList.length > 0
? scope.row.RecipientList.filter(item => item.RecipientTypeEnum === 0).map(item =>
item.RecipientName).join(", ") : ''
}}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column :label="$t('system:email:table:CcRecipientName')" prop="CcRecipientName"
show-overflow-tooltip>
<template slot-scope="scope">
<el-tooltip class="item" effect="dark" :content="scope.row.RecipientList.filter(item => item.RecipientTypeEnum === 1).map(item =>
`${item.RecipientName}: ${item.RecipientAddress}`).join('<br/>')" placement="top-start"
v-if="Array.isArray(scope.row.RecipientList) && scope.row.RecipientList.length > 0">
<span>{{Array.isArray(scope.row.RecipientList) && scope.row.RecipientList.length > 0
? scope.row.RecipientList.filter(item => item.RecipientTypeEnum === 1).map(item =>
item.RecipientName).join(", ") : ''
}}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column :label="$t('system:email:table:emailDate')" prop="EmailDate" show-overflow-tooltip
sortable="custom" />
<el-table-column :label="$t('system:email:table:emailStateEnum')" prop="EmailStateEnum"
show-overflow-tooltip sortable="custom">
<template slot-scope="scope">
<el-tag :type="scope.row.EmailStateEnum === 1 ? 'danger' : ''">{{ $fd("EmailState",
scope.row.EmailStateEnum) }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('system:email:table:errorInfo')" prop="ErrorInfo" show-overflow-tooltip />
<el-table-column :label="$t('common:action:action')" prop="" show-overflow-tooltip>
<template slot-scope="scope">
<el-button type="text" @click="view(scope.row)">
{{ $t('common:button:view') }}
</el-button>
<!-- <el-button type="text" @click="resendEmail(scope.row)">
{{ $t('system:email:button:resendEmail') }}
</el-button> -->
</template>
</el-table-column>
</el-table>
<div class="pagination" style="text-align: right; margin-top: 5px">
<pagination :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
</div>
</div>
<base-model v-if="model_cfg.visible" :config="model_cfg">
<template slot="dialog-body">
<emailDetail :info="info" />
</template>
</base-model>
</div>
</template>
<script>
import { getReSendEmail, getEmailInfo } from '@/api/admin'
import Pagination from '@/components/Pagination'
import BaseModel from '@/components/BaseModel'
import emailDetail from "./detail"
const searchDataDefault = () => {
return {
// TrialId: null,
// EmailStartDate: null,
// EmailEndDate: null,
// EmailStateEnum: null,
// ToRecipientName: null,
// CcRecipientName: null,
Id: null,
Asc: false,
SortField: 'CreateTime',
PageIndex: 1,
PageSize: 20,
}
}
export default {
name: 'emailLog',
components: { Pagination, BaseModel, emailDetail },
props: {
isSystem: {
type: Boolean,
default: true
},
rowData: {
type: Object,
default: () => {
return {}
}
}
},
data() {
return {
searchData: searchDataDefault(),
list: [],
total: 0,
loading: false,
datetimerange: [],
model_cfg: { visible: false, title: '', width: '500px', fullscreen: true, appendToBody: true },
info: null,
}
},
watch: {
"rowData.Id": {
handler() {
this.getList()
}
}
},
mounted() {
this.getList()
},
methods: {
getList() {
this.loading = true
if (!this.rowData.Id) return false
this.searchData.Id = this.rowData.Id
if (!this.isSystem) this.searchData.TrialId = this.$route.query.trialId
getReSendEmail(this.searchData)
.then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
})
.catch(() => {
this.loading = false
})
},
//
async view(row) {
try {
let data = {
Id: row.Id,
TrialId: this.$route.query.trialId
// Id: "EC660000-BA37-5C60-8680-08DE1CD6931B"
}
let res = await getEmailInfo(data)
if (res.IsSuccess) {
this.info = res.Result
if (Array.isArray(this.info.AttachmentList) && this.info.AttachmentList.length > 0) {
this.info.AttachmentList.forEach(item => {
var type = item.AttachmentName
.substring(item.AttachmentName.lastIndexOf('.'))
.toLocaleLowerCase().split('.')[1];
item.type = type
})
}
this.model_cfg.visible = true
}
} catch (err) {
console.log(err)
}
},
//
handleReset() {
this.searchData = searchDataDefault()
this.datetimerange = []
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()
},
handleDatetimeChange(val) {
if (val) {
this.searchData.EmailStartDate = val[0]
this.searchData.EmailEndDate = val[1]
} else {
this.searchData.EmailStartDate = ''
this.searchData.EmailEndDate = ''
}
},
},
}
</script>
<style lang="scss" scoped>
.event {
height: 100%;
box-sizing: border-box;
display: flex;
padding: 10px;
border-radius: 5px;
.left {
display: flex;
flex-direction: column;
width: 0;
flex-grow: 4;
// border-right: 1px solid #ccc;
.filter-container {
display: flex;
align-items: center;
margin: 5px;
}
.data-table {
flex: 1;
padding: 5px 0px;
}
.pagination-container {
text-align: right;
}
}
}
</style>

View File

@ -1,298 +0,0 @@
<template>
<div class="event">
<div ref="leftContainer" class="left">
<el-form :inline="true">
<el-form-item :label="$t('system:email:search:ToRecipientName')">
<el-input v-model="searchData.ToRecipientName" clearable />
</el-form-item>
<el-form-item :label="$t('system:email:search:CcRecipientName')">
<el-input v-model="searchData.CcRecipientName" clearable />
</el-form-item>
<el-form-item :label="$t('system:email:search:EmailStateEnum')">
<el-select v-model="searchData.EmailStateEnum" clearable filterable placeholder="">
<el-option v-for="item in $d.EmailState" :key="item.id" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item>
<!-- <el-form-item :label="$t('system:email:search:EmailStateEnum')">
<el-select v-model="searchData.EmailStateEnum" clearable filterable placeholder="">
<el-option v-for="item in $d.EmailState" :key="item.id" :label="item.label"
:value="item.value" />
</el-select>
</el-form-item> -->
<el-form-item :label="$t('system:email:search:emailDate')">
<el-date-picker v-model="datetimerange" type="datetimerange"
:default-time="['00:00:00', '23:59:59']" :start-placeholder="$t('feedBack:search:beginTime')"
:end-placeholder="$t('feedBack:search:endTime')" value-format="yyyy-MM-dd HH:mm:ss"
@change="handleDatetimeChange" />
</el-form-item>
<el-form-item>
<el-button type="primary" icon="el-icon-search" size="small" @click="getList">
{{ $t('common:button:search') }}
</el-button>
<el-button icon="el-icon-refresh-left" size="small" @click="handleReset">
{{ $t('common:button:reset') }}
</el-button>
<el-button type="primary" size="small" @click="synchronizationEmail">
{{ $t('system:email:button:sync') }}
</el-button>
</el-form-item>
</el-form>
<el-table v-loading="loading" v-adaptive="{ bottomOffset: 45 }" height="100" :data="list" class="table"
@sort-change="handleSortByColumn">
<el-table-column type="index" width="50" />
<el-table-column :label="$t('system:email:table:messageId')" prop="MessageId" show-overflow-tooltip
sortable="custom" />
<el-table-column :label="$t('system:email:table:emailSubject')" prop="EmailSubject"
show-overflow-tooltip />
<el-table-column :label="$t('system:email:table:ToRecipientName')" prop="ToRecipientName"
show-overflow-tooltip>
<template slot-scope="scope">
<el-tooltip class="item" effect="dark" :content="scope.row.RecipientList.filter(item => item.RecipientTypeEnum === 0).map(item =>
`${item.RecipientName}: ${item.RecipientAddress}`).join('<br/>')" placement="top-start"
v-if="Array.isArray(scope.row.RecipientList) && scope.row.RecipientList.length > 0">
<span>{{Array.isArray(scope.row.RecipientList) && scope.row.RecipientList.length > 0
? scope.row.RecipientList.filter(item => item.RecipientTypeEnum === 0).map(item =>
item.RecipientName).join(", ") : ''
}}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column :label="$t('system:email:table:CcRecipientName')" prop="CcRecipientName"
show-overflow-tooltip>
<template slot-scope="scope">
<el-tooltip class="item" effect="dark" :content="scope.row.RecipientList.filter(item => item.RecipientTypeEnum === 1).map(item =>
`${item.RecipientName}: ${item.RecipientAddress}`).join('<br/>')" placement="top-start"
v-if="Array.isArray(scope.row.RecipientList) && scope.row.RecipientList.length > 0">
<span>{{Array.isArray(scope.row.RecipientList) && scope.row.RecipientList.length > 0
? scope.row.RecipientList.filter(item => item.RecipientTypeEnum === 1).map(item =>
item.RecipientName).join(", ") : ''
}}</span>
</el-tooltip>
</template>
</el-table-column>
<el-table-column :label="$t('system:email:table:emailDate')" prop="EmailDate" show-overflow-tooltip
sortable="custom" />
<el-table-column :label="$t('system:email:table:emailStateEnum')" prop="EmailStateEnum"
show-overflow-tooltip sortable="custom">
<template slot-scope="scope">
<el-tag :type="scope.row.EmailStateEnum === 1 ? 'danger' : ''">{{ $fd("EmailState",
scope.row.EmailStateEnum) }}</el-tag>
</template>
</el-table-column>
<el-table-column :label="$t('system:email:table:errorInfo')" prop="ErrorInfo" show-overflow-tooltip />
<el-table-column :label="$t('common:action:action')" fixed="right" prop="" show-overflow-tooltip
min-width="120px">
<template slot-scope="scope">
<el-button type="text" @click="view(scope.row)">
{{ $t('common:button:view') }}
</el-button>
<el-button type="text" @click="resendEmail(scope.row)">
{{ $t('system:email:button:resendEmail') }}
</el-button>
<el-button type="text" @click="openResendEmailList(scope.row)">
{{ $t('system:email:button:resendEmailList') }}
</el-button>
</template>
</el-table-column>
</el-table>
<div class="pagination" style="text-align: right; margin-top: 5px">
<pagination :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize"
@pagination="getList" />
</div>
</div>
<base-model v-if="model_cfg.visible" :config="model_cfg">
<template slot="dialog-body">
<emailDetail :info="info" />
</template>
</base-model>
<el-dialog title="" :visible.sync="resendVisible" width="30%" :fullscreen='true'>
<resendList :rowData="info" :isSystem="isSystem" />
</el-dialog>
</div>
</template>
<script>
import { getEmailLogList, resendEmail, getEmailInfo, synchronizationEmail } from '@/api/admin'
import Pagination from '@/components/Pagination'
import BaseModel from '@/components/BaseModel'
import emailDetail from "./components/detail"
import resendList from "./components/resendList"
const searchDataDefault = () => {
return {
TrialId: null,
EmailStartDate: null,
EmailEndDate: null,
EmailStateEnum: null,
ToRecipientName: null,
CcRecipientName: null,
Asc: false,
SortField: 'CreateTime',
PageIndex: 1,
PageSize: 20,
}
}
export default {
name: 'emailLog',
components: { Pagination, BaseModel, emailDetail, resendList },
props: {
isSystem: {
type: Boolean,
default: true
}
},
data() {
return {
searchData: searchDataDefault(),
list: [],
total: 0,
loading: false,
datetimerange: [],
model_cfg: { visible: false, title: '', width: '500px', fullscreen: true },
info: null,
resendVisible: false
}
},
mounted() {
this.getList()
},
methods: {
openResendEmailList(row) {
this.info = row
this.resendVisible = true
},
getList() {
this.loading = true
if (!this.isSystem) this.searchData.TrialId = this.$route.query.trialId
getEmailLogList(this.searchData)
.then((res) => {
this.loading = false
this.list = res.Result.CurrentPageData
this.total = res.Result.TotalCount
})
.catch(() => {
this.loading = false
})
},
//
async view(row) {
try {
let data = {
Id: row.Id,
TrialId: this.$route.query.trialId
// Id: "EC660000-BA37-5C60-8680-08DE1CD6931B"
}
let res = await getEmailInfo(data)
if (res.IsSuccess) {
this.info = res.Result
if (Array.isArray(this.info.AttachmentList) && this.info.AttachmentList.length > 0) {
this.info.AttachmentList.forEach(item => {
var type = item.AttachmentName
.substring(item.AttachmentName.lastIndexOf('.'))
.toLocaleLowerCase().split('.')[1];
item.type = type
})
}
this.model_cfg.visible = true
}
} catch (err) {
console.log(err)
}
},
//
async synchronizationEmail() {
try {
let data = {
TrialId: this.$route.query.trialId
}
this.loading = true
let res = await synchronizationEmail(data)
this.loading = false
if (res.IsSuccess) {
this.getList()
this.$message.success(this.$t("system:email:message:syncSuccessfully"))
}
} catch (err) {
this.loading = false
console.log(err)
}
},
//
async resendEmail(row) {
try {
let data = {
Id: row.Id,
TrialId: this.$route.query.trialId
}
this.loading = true
let res = await resendEmail(data)
this.loading = false
if (res.IsSuccess) {
this.getList()
this.$message.success(this.$t("system:email:message:resendSuccessfully"))
}
} catch (err) {
this.loading = false
console.log(err)
}
},
//
handleReset() {
this.searchData = searchDataDefault()
this.datetimerange = []
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()
},
handleDatetimeChange(val) {
if (val) {
this.searchData.EmailStartDate = val[0]
this.searchData.EmailEndDate = val[1]
} else {
this.searchData.EmailStartDate = ''
this.searchData.EmailEndDate = ''
}
},
},
}
</script>
<style lang="scss" scoped>
.event {
height: 100%;
box-sizing: border-box;
display: flex;
padding: 10px;
border-radius: 5px;
.left {
display: flex;
flex-direction: column;
width: 0;
flex-grow: 4;
// border-right: 1px solid #ccc;
.filter-container {
display: flex;
align-items: center;
margin: 5px;
}
.data-table {
flex: 1;
padding: 5px 0px;
}
.pagination-container {
text-align: right;
}
}
}
</style>

View File

@ -2,18 +2,26 @@
<base-model v-if="config.visible" :config="config"> <base-model v-if="config.visible" :config="config">
<template slot="dialog-body"> <template slot="dialog-body">
<el-table :data="curData" border style="width: 100%" size="small"> <el-table :data="curData" border style="width: 100%" size="small">
<el-table-column prop="key" :label="$t('system:loginLog:table:cfgItem')" show-overflow-tooltip /> <el-table-column
<el-table-column prop="value" :label="$t('system:loginLog:table:cfgVal')" show-overflow-tooltip> prop="key"
:label="$t('system:loginLog:table:cfgItem')"
show-overflow-tooltip
/>
<el-table-column
prop="value"
:label="$t('system:loginLog:table:cfgVal')"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-button v-if="scope.row.prop === 'UserAgreementId'" type="text" size="small" <span v-if="scope.row.prop !== 'UserRoleList'">{{
@click.stop="view(scope.row)">{{
$t('dictionary:agreement:button:view')
}}</el-button>
<span v-else-if="scope.row.prop !== 'UserRoleList'">{{
scope.row.value scope.row.value
}}</span> }}</span>
<template v-else> <template v-else>
<div v-for="item in scope.row.value" :key="item.UserTypeEnum" style="margin: 0"> <div
v-for="item in scope.row.value"
:key="item.UserTypeEnum"
style="margin: 0"
>
{{ item.UserTypeShortName {{ item.UserTypeShortName
}}{{ $t('system:loginLog:form:symbol') }}{{ $t('system:loginLog:form:symbol')
}}{{ $fd('IsEnable', !item.IsUserRoleDisabled) }} }}{{ $fd('IsEnable', !item.IsUserRoleDisabled) }}
@ -66,11 +74,7 @@ export default {
'PositionName', 'PositionName',
'DepartmentName', 'DepartmentName',
'UserRoleList', 'UserRoleList',
'UserAgreementTypeEnum',
'FileVersion',
'UserAgreementId',
], ],
IsEn_Us: false
} }
}, },
computed: { computed: {
@ -83,7 +87,6 @@ export default {
let obj = JSON.parse(this.JsonObj) let obj = JSON.parse(this.JsonObj)
let curData = [] let curData = []
Object.keys(obj).forEach((key) => { Object.keys(obj).forEach((key) => {
if (key === 'IsEn_Us') this.IsEn_Us = obj[key]
if (this.curKeys.includes(key)) { if (this.curKeys.includes(key)) {
let o = { let o = {
key: this.$t(`system:loginLog:form:${key}`), key: this.$t(`system:loginLog:form:${key}`),
@ -93,23 +96,12 @@ export default {
if (key === 'Status') { if (key === 'Status') {
o.value = this.$fd('IsUserEnable', obj[key]) o.value = this.$fd('IsUserEnable', obj[key])
} }
if (key === 'UserAgreementTypeEnum') {
o.value = this.$fd('UserAgreementType', obj[key])
}
curData.push(o) curData.push(o)
} }
}) })
return curData return curData
}, },
}, },
methods: {
view(row) {
this.$AGR({
Id: row.value,
IsEn_Us: this.IsEn_Us
})
},
}
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>

View File

@ -1,11 +1,11 @@
<template> <template>
<el-dropdown <el-dropdown
style="height:50px;line-height: 65px;" style="height:50px;line-height: 60px;"
@command="handleSetLanguage" @command="handleSetLanguage"
> >
<span class="el-dropdown-link"> <span class="el-dropdown-link">
<svg-icon icon-class="language" style="font-size:20px;margin:0 10px;" /> <svg-icon icon-class="language" style="font-size:25px;margin:0 10px;" />
<!-- {{ language==='zh'?'语言:中文':'Language: English' }} --> <!-- {{ language==='zh'?'语言:中文':'Language: English' }} -->
<!-- <i class="el-icon-arrow-down el-icon--right" /> --> <!-- <i class="el-icon-arrow-down el-icon--right" /> -->
</span> </span>

View File

@ -1,33 +1,72 @@
<!-- eslint-disable --> <!-- eslint-disable -->
<template> <template>
<el-form ref="trialForm" v-loading="loading" label-width="250px" :rules="trialFormRules" <el-form
class="demo-ruleForm trial-Form" :model="trialForm" label-position="right" :inline="true"> ref="trialForm"
v-loading="loading"
label-width="250px"
:rules="trialFormRules"
class="demo-ruleForm trial-Form"
:model="trialForm"
label-position="right"
:inline="true"
>
<el-row> <el-row>
<!-- 项目编号 --> <!-- 项目编号 -->
<el-form-item v-if="trialForm.Id !== ''" :label="$t('trials:trials-list:form:trialId')" prop="TrialCode"> <el-form-item
<el-input v-model="trialForm.TrialCode" @keyup.native="trialCodekeyUp" /> v-if="trialForm.Id !== ''"
:label="$t('trials:trials-list:form:trialId')"
prop="TrialCode"
>
<el-input
v-model="trialForm.TrialCode"
@keyup.native="trialCodekeyUp"
/>
</el-form-item> </el-form-item>
<!-- 项目类型 --> <!-- 项目类型 -->
<el-form-item :label="$t('trials:trials-list:form:trialType')" prop="TrialType"> <el-form-item
<el-radio-group v-model="trialForm.TrialType" :disabled="trialForm.Id !== ''"> :label="$t('trials:trials-list:form:trialType')"
<el-radio v-for="item of $d.TrialType" :disabled="isTestUser && (item.value === 1 || item.value === 2)" prop="TrialType"
:key="item.id" :label="item.value">{{ item.label }}</el-radio> >
<el-radio-group
v-model="trialForm.TrialType"
:disabled="trialForm.Id !== ''"
>
<el-radio
v-for="item of $d.TrialType"
:disabled="isTestUser && (item.value === 1 || item.value === 2)"
:key="item.id"
:label="item.value"
>{{ item.label }}</el-radio
>
</el-radio-group> </el-radio-group>
</el-form-item> </el-form-item>
</el-row> </el-row>
<el-row> <el-row>
<!-- 试验名称 --> <!-- 试验名称 -->
<el-form-item :label="$t('trials:trials-list:form:experimentName')" prop="ExperimentName"> <el-form-item
<el-input v-model="trialForm.ExperimentName" type="textarea" :autosize="{ minRows: 1, maxRows: 4 }" /> :label="$t('trials:trials-list:form:experimentName')"
prop="ExperimentName"
>
<el-input
v-model="trialForm.ExperimentName"
type="textarea"
:autosize="{ minRows: 1, maxRows: 4 }"
/>
</el-form-item> </el-form-item>
<!-- 研究方案号 --> <!-- 研究方案号 -->
<el-form-item :label="$t('trials:trials-list:form:researchNumber')" prop="ResearchProgramNo"> <el-form-item
:label="$t('trials:trials-list:form:researchNumber')"
prop="ResearchProgramNo"
>
<el-input v-model="trialForm.ResearchProgramNo" /> <el-input v-model="trialForm.ResearchProgramNo" />
</el-form-item> </el-form-item>
</el-row> </el-row>
<el-row> <el-row>
<!-- 主研单位 --> <!-- 主研单位 -->
<el-form-item :label="$t('trials:trials-list:form:researchUnit')" prop="MainResearchUnit"> <el-form-item
:label="$t('trials:trials-list:form:researchUnit')"
prop="MainResearchUnit"
>
<el-input v-model="trialForm.MainResearchUnit" /> <el-input v-model="trialForm.MainResearchUnit" />
</el-form-item> </el-form-item>
<!-- 负责人PI --> <!-- 负责人PI -->
@ -38,28 +77,63 @@
<el-row> <el-row>
<!-- 申办方 --> <!-- 申办方 -->
<el-form-item :label="$t('trials:trials-list:form:sponsor')"> <el-form-item :label="$t('trials:trials-list:form:sponsor')">
<el-select v-model="trialForm.SponsorId" filterable allow-create default-first-option clearable <el-select
@change="(value) => handleSelectChange(value, 'sponsor')" @visible-change=" v-model="trialForm.SponsorId"
filterable
allow-create
default-first-option
@change="(value) => handleSelectChange(value, 'sponsor')"
@visible-change="
(flag) => handleSelectVisibbleChange(flag, 'sponsor') (flag) => handleSelectVisibbleChange(flag, 'sponsor')
"> "
<el-option v-for="item in sponsorList" :key="item.Id" :label="item.SponsorName" :value="item.Id" /> >
<el-option
v-for="item in sponsorList"
:key="item.Id"
:label="item.SponsorName"
:value="item.Id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- CRO --> <!-- CRO -->
<el-form-item :label="$t('trials:trials-list:form:cro')"> <el-form-item :label="$t('trials:trials-list:form:cro')">
<el-select v-model="trialForm.CROId" filterable allow-create default-first-option clearable <el-select
v-model="trialForm.CROId"
filterable
allow-create
default-first-option
@change="(value) => handleSelectChange(value, 'cro')" @change="(value) => handleSelectChange(value, 'cro')"
@visible-change="(flag) => handleSelectVisibbleChange(flag, 'cro')"> @visible-change="(flag) => handleSelectVisibbleChange(flag, 'cro')"
<el-option v-for="item of croList" :key="item.Id" :label="item.CROName" :value="item.Id" /> >
<el-option
v-for="item of croList"
:key="item.Id"
:label="item.CROName"
:value="item.Id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-row> </el-row>
<el-row> <el-row>
<!-- DeclarationType --> <!-- DeclarationType -->
<el-form-item :label="$t('trials:trials-list:form:declarationType')" prop="DeclarationTypeEnumList"> <el-form-item
<el-select v-model="trialForm.DeclarationTypeEnumList" size="small" multiple clearable :label="$t('trials:trials-list:form:declarationType')"
@change="handleDeclarationTypeChange" style="width: 100%"> prop="DeclarationTypeEnumList"
<el-option v-for="item of $d.DeclarationType" :key="item.value" :value="item.value" :label="item.label" /> >
<el-select
v-model="trialForm.DeclarationTypeEnumList"
size="small"
multiple
clearable
@change="handleDeclarationTypeChange"
style="width: 100%"
>
<el-option
v-for="item of $d.DeclarationType"
:key="item.value"
:value="item.value"
:label="item.label"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- Phase --> <!-- Phase -->
@ -71,41 +145,79 @@
:label="item.Value" :label="item.Value"
:value="item.Id" :value="item.Id"
/> --> /> -->
<el-option v-for="item of $d.Trial_Phase" :key="item.id" :label="item.label" :value="item.id" /> <el-option
v-for="item of $d.Trial_Phase"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
</el-row> </el-row>
<el-row> <el-row>
<!-- 适应症类型 IndicationType --> <!-- 适应症类型 IndicationType -->
<el-form-item :label="$t('trials:trials-list:form:indicationType')" prop="IndicationTypeId"> <el-form-item
<el-select v-model="trialForm.IndicationTypeId" @change="handleIndicationTypeChange"> :label="$t('trials:trials-list:form:indicationType')"
prop="IndicationTypeId"
>
<el-select
v-model="trialForm.IndicationTypeId"
@change="handleIndicationTypeChange"
>
<!-- <el-option <!-- <el-option
v-for="item of dictionaryList.IndicationType" v-for="item of dictionaryList.IndicationType"
:key="item.Id" :key="item.Id"
:label="item.Value" :label="item.Value"
:value="item.Id" :value="item.Id"
/> --> /> -->
<el-option v-for="item of $d.IndicationType" :key="item.id" :label="item.label" :value="item.id" /> <el-option
v-for="item of $d.IndicationType"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- Indication --> <!-- Indication -->
<el-form-item :label="$t('trials:trials-list:form:indication')" prop="IndicationEnum"> <el-form-item
:label="$t('trials:trials-list:form:indication')"
prop="IndicationEnum"
>
<!-- <el-input v-model="trialForm.Indication" />--> <!-- <el-input v-model="trialForm.Indication" />-->
<el-select :disabled="!trialForm.IndicationTypeId" v-if="![37, 38, 39].includes(trialForm.IndicationEnum)" <el-select
v-model="trialForm.IndicationEnum"> :disabled="!trialForm.IndicationTypeId"
<el-option v-for="item of $d.Indication" v-show="indicationGrouping === item.raw.ChildGroup" :key="item.id" v-if="![37, 38, 39].includes(trialForm.IndicationEnum)"
:label="item.label" :value="item.value" /> v-model="trialForm.IndicationEnum"
>
<el-option
v-for="item of $d.Indication"
v-show="indicationGrouping === item.raw.ChildGroup"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
<el-row v-if="[37, 38, 39].includes(trialForm.IndicationEnum)"> <el-row v-if="[37, 38, 39].includes(trialForm.IndicationEnum)">
<el-col :span="12"> <el-col :span="12">
<el-select :disabled="!trialForm.IndicationTypeId" v-model="trialForm.IndicationEnum" <el-select
style="width: 100%; margin-right: 10px"> :disabled="!trialForm.IndicationTypeId"
<el-option v-for="item of $d.Indication" v-show="indicationGrouping === item.raw.ChildGroup" v-model="trialForm.IndicationEnum"
:key="item.id" :label="item.label" :value="item.value" /> style="width: 100%; margin-right: 10px"
>
<el-option
v-for="item of $d.Indication"
v-show="indicationGrouping === item.raw.ChildGroup"
:key="item.id"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</el-col> </el-col>
<el-col :span="12"> <el-col :span="12">
<el-input :disabled="!trialForm.IndicationTypeId" v-model="trialForm.Indication" /> <el-input
:disabled="!trialForm.IndicationTypeId"
v-model="trialForm.Indication"
/>
</el-col> </el-col>
</el-row> </el-row>
</el-form-item> </el-form-item>
@ -120,54 +232,99 @@
:label="item.Value" :label="item.Value"
:value="item.Id" :value="item.Id"
/> --> /> -->
<el-option v-for="item of $d.Modality" :key="item.id" :label="item.label" :value="item.id" /> <el-option
v-for="item of $d.Modality"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- Sites --> <!-- Sites -->
<el-form-item :label="$t('trials:trials-list:form:siteCount')"> <el-form-item :label="$t('trials:trials-list:form:siteCount')">
<el-input-number v-model="trialForm.PlanSiteCount" controls-position="right" :min="0" /> <el-input-number
v-model="trialForm.PlanSiteCount"
controls-position="right"
:min="0"
/>
</el-form-item> </el-form-item>
</el-row> </el-row>
<el-row> <el-row>
<!-- Expected Patients Num --> <!-- Expected Patients Num -->
<el-form-item :label="$t('trials:trials-list:form:patientsNum')"> <el-form-item :label="$t('trials:trials-list:form:patientsNum')">
<el-input-number v-model="trialForm.ExpectedPatients" controls-position="right" :min="0" <el-input-number
@change="handleExpectedPatientsChange" /> v-model="trialForm.ExpectedPatients"
controls-position="right"
:min="0"
@change="handleExpectedPatientsChange"
/>
</el-form-item> </el-form-item>
<!-- Timepoints Per Patient --> <!-- Timepoints Per Patient -->
<el-form-item :label="$t('trials:trials-list:form:timePointsPerPatient')"> <el-form-item :label="$t('trials:trials-list:form:timePointsPerPatient')">
<el-input-number v-model="trialForm.TimePointsPerPatient" controls-position="right" :min="0" <el-input-number
@change="handleTpPerPatientChange" /> v-model="trialForm.TimePointsPerPatient"
controls-position="right"
:min="0"
@change="handleTpPerPatientChange"
/>
</el-form-item> </el-form-item>
</el-row> </el-row>
<el-row> <el-row>
<!-- Visits --> <!-- Visits -->
<el-form-item :label="$t('trials:trials-list:form:visitCount')"> <el-form-item :label="$t('trials:trials-list:form:visitCount')">
<el-input-number v-model="trialForm.PlanVisitCount" controls-position="right" :min="0" /> <el-input-number
v-model="trialForm.PlanVisitCount"
controls-position="right"
:min="0"
/>
</el-form-item> </el-form-item>
</el-row> </el-row>
<el-row> <el-row>
<!-- Expedited --> <!-- Expedited -->
<el-form-item :label="$t('trials:trials-list:form:expedited')" prop="Expedited"> <el-form-item
:label="$t('trials:trials-list:form:expedited')"
prop="Expedited"
>
<el-select v-model="trialForm.Expedited"> <el-select v-model="trialForm.Expedited">
<el-option v-for="item in expeditedOption" :key="item.value" :label="item.label" :value="item.value" /> <el-option
v-for="item in expeditedOption"
:key="item.value"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- Turnaround Time --> <!-- Turnaround Time -->
<el-form-item :label="$t('trials:trials-list:form:projectCycle')" prop="ProjectCycle"> <el-form-item
:label="$t('trials:trials-list:form:projectCycle')"
prop="ProjectCycle"
>
<el-input v-model="trialForm.ProjectCycle" /> <el-input v-model="trialForm.ProjectCycle" />
</el-form-item> </el-form-item>
</el-row> </el-row>
<el-row> <el-row>
<!-- Total Reviewers --> <!-- Total Reviewers -->
<el-form-item :label="$t('trials:trials-list:form:totalReviewers')"> <el-form-item :label="$t('trials:trials-list:form:totalReviewers')">
<el-input-number v-model="trialForm.TotalReviewers" controls-position="right" :min="0" /> <el-input-number
v-model="trialForm.TotalReviewers"
controls-position="right"
:min="0"
/>
</el-form-item> </el-form-item>
<!-- Type of Reviewers --> <!-- Type of Reviewers -->
<el-form-item :label="$t('trials:trials-list:form:typeofReviewers')"> <el-form-item :label="$t('trials:trials-list:form:typeofReviewers')">
<el-select v-model="trialForm.AttendedReviewerTypeEnumList" size="small" multiple clearable> <el-select
<el-option v-for="item of $d.AttendedReviewerType" :key="item.value" :value="item.value" v-model="trialForm.AttendedReviewerTypeEnumList"
:label="item.label" /> size="small"
multiple
clearable
>
<el-option
v-for="item of $d.AttendedReviewerType"
:key="item.value"
:value="item.value"
:label="item.label"
/>
</el-select> </el-select>
<!-- <el-row v-if="trialForm.AttendedReviewerTypeEnumList.includes(2)">--> <!-- <el-row v-if="trialForm.AttendedReviewerTypeEnumList.includes(2)">-->
<!-- <el-col :span="12">--> <!-- <el-col :span="12">-->
@ -400,7 +557,6 @@ export default {
}, },
// CRO // CRO
async handleSelectChange(value, key) { async handleSelectChange(value, key) {
if (!value) return false
let arr = key == "sponsor" ? this.sponsorList : this.croList; let arr = key == "sponsor" ? this.sponsorList : this.croList;
let has = arr.some((item) => item.Id === value); let has = arr.some((item) => item.Id === value);
if (!has) { if (!has) {
@ -632,7 +788,6 @@ export default {
.trial-Form .el-textarea { .trial-Form .el-textarea {
width: 340px; width: 340px;
} }
.trial-Form .el-col .el-input { .trial-Form .el-col .el-input {
width: 165px; width: 165px;
margin-right: 10px; margin-right: 10px;

View File

@ -5,61 +5,135 @@
<!-- 账号信息 --> <!-- 账号信息 -->
{{ $t('trials:trials-myinfo:title:accountInfo') }} {{ $t('trials:trials-myinfo:title:accountInfo') }}
</div> </div>
<el-form label-position="right" label-width="100px" :rules="rule" :model="userForm" ref="userFormRef"> <el-form
label-position="right"
label-width="100px"
:rules="rule"
:model="userForm"
ref="userFormRef"
>
<!-- 用户名 --> <!-- 用户名 -->
<el-form-item :label="$t('trials:trials-myinfo:form:userName')" style="margin-bottom: 5px"> <el-form-item
:label="$t('trials:trials-myinfo:form:userName')"
style="margin-bottom: 5px"
>
<span>{{ user.UserName }}</span> <span>{{ user.UserName }}</span>
</el-form-item> </el-form-item>
<el-form-item label="" style="position: relative" prop="UserName"> <el-form-item label="" style="position: relative" prop="UserName">
<el-input v-model="userForm.UserName" :placeholder="$t('trials:trials-myinfo:form:userName')" /> <el-input
v-model="userForm.UserName"
:placeholder="$t('trials:trials-myinfo:form:userName')"
/>
<!-- 修改 --> <!-- 修改 -->
<el-button :disabled="!userForm.UserName" class="saveBtn" type="primary" size="small" @click="setNewUserName"> <el-button
:disabled="!userForm.UserName"
class="saveBtn"
type="primary"
size="small"
@click="setNewUserName"
>
{{ $t('trials:trials-myinfo:button:update') }} {{ $t('trials:trials-myinfo:button:update') }}
</el-button> </el-button>
</el-form-item> </el-form-item>
<!-- 电话 --> <!-- 电话 -->
<el-form-item :label="$t('trials:trials-myinfo:form:phone')" style="margin-bottom: 5px" prop="Phone"> <el-form-item
:label="$t('trials:trials-myinfo:form:phone')"
style="margin-bottom: 5px"
prop="Phone"
>
<span>{{ user.Phone }}</span> <span>{{ user.Phone }}</span>
</el-form-item> </el-form-item>
<el-form-item label="" style="position: relative" prop="Phone"> <el-form-item label="" style="position: relative" prop="Phone">
<el-input v-model="userForm.Phone" :placeholder="$t('trials:trials-myinfo:form:phone')" /> <el-input
v-model="userForm.Phone"
:placeholder="$t('trials:trials-myinfo:form:phone')"
/>
<!-- 修改 --> <!-- 修改 -->
<el-button :disabled="!userForm.Phone" class="saveBtn" type="primary" size="small" @click="setNewPhone"> <el-button
:disabled="!userForm.Phone"
class="saveBtn"
type="primary"
size="small"
@click="setNewPhone"
>
{{ $t('trials:trials-myinfo:button:update') }} {{ $t('trials:trials-myinfo:button:update') }}
</el-button> </el-button>
</el-form-item> </el-form-item>
<!-- 邮箱 --> <!-- 邮箱 -->
<el-form-item :label="$t('trials:trials-myinfo:form:email')" style="margin-bottom: 5px" prop="EMail"> <el-form-item
:label="$t('trials:trials-myinfo:form:email')"
style="margin-bottom: 5px"
prop="EMail"
>
<span>{{ user.EMail }}</span> <span>{{ user.EMail }}</span>
</el-form-item> </el-form-item>
<el-form-item label="" style="margin-bottom: 10px; position: relative" prop="EMail" v-if="IsCanConnectInternet"> <el-form-item
<el-input v-model="userForm.EMail" @input="handleEmailChange" label=""
:placeholder="$t('trials:trials-myinfo:form:email')" /> style="margin-bottom: 10px; position: relative"
prop="EMail"
v-if="IsCanConnectInternet"
>
<el-input
v-model="userForm.EMail"
@input="handleEmailChange"
:placeholder="$t('trials:trials-myinfo:form:email')"
/>
<el-button
class="sendCode"
:disabled="sendDisabled"
type="primary"
size="mini"
@click="sendVerificationCode"
>{{ sendTitle }}</el-button
>
</el-form-item> </el-form-item>
<el-form-item label="" style="position: relative" prop="VerificationCode" v-if="IsCanConnectInternet"> <el-form-item
<div style="display: flex;justify-content: space-between;width: 100%;"> label=""
<el-input v-model="userForm.VerificationCode" :placeholder="$t('trials:researchForm:form:verifyCode')" /> style="position: relative"
<el-button class="codeBtn" :disabled="sendDisabled" size="mini" @click="sendVerificationCode">{{ prop="VerificationCode"
sendTitle v-if="IsCanConnectInternet"
}}</el-button> >
</div> <el-input
v-model="userForm.VerificationCode"
:placeholder="$t('trials:researchForm:form:verifyCode')"
/>
<!-- 修改 --> <!-- 修改 -->
<el-button :disabled="!userForm.EMail || !userForm.VerificationCode" class="saveBtn" type="primary" <el-button
size="small" @click="setNewEmail"> :disabled="!userForm.EMail || !userForm.VerificationCode"
class="saveBtn"
type="primary"
size="small"
@click="setNewEmail"
>
{{ $t('trials:trials-myinfo:button:update') }} {{ $t('trials:trials-myinfo:button:update') }}
</el-button> </el-button>
</el-form-item> </el-form-item>
<el-form-item :label="$t('trials:trials-myinfo:form:toggleRole')" style="position: relative" <el-form-item
prop="VerificationCode" v-if="hasRole"> :label="$t('trials:trials-myinfo:form:toggleRole')"
style="position: relative"
prop="VerificationCode"
v-if="hasRole"
>
<el-radio-group v-model="userRoleId" class="roles" v-if="hasRole"> <el-radio-group v-model="userRoleId" class="roles" v-if="hasRole">
<el-radio v-for="item in roles" :key="item.Id" :label="item.Id" :disabled="item.IsUserRoleDisabled" <el-radio
style="margin-bottom: 10px"> v-for="item in roles"
:key="item.Id"
:label="item.Id"
:disabled="item.IsUserRoleDisabled"
style="margin-bottom: 10px"
>
{{ item.UserTypeShortName }} {{ item.UserTypeShortName }}
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
<!-- 修改 --> <!-- 修改 -->
<el-button :disabled="!userRoleId || saveDisabled" class="saveBtn" :loading="toggleRoleLoading" type="primary" <el-button
size="small" @click="toggleRole"> :disabled="!userRoleId || saveDisabled"
class="saveBtn"
:loading="toggleRoleLoading"
type="primary"
size="small"
@click="toggleRole"
>
{{ $t('trials:trials-myinfo:button:toggleRole') }} {{ $t('trials:trials-myinfo:button:toggleRole') }}
</el-button> </el-button>
</el-form-item> </el-form-item>
@ -271,26 +345,9 @@ export default {
} }
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
.codeBtn {
color: #409EFF;
border-color: #409EFF;
margin-left: 10px;
}
.codeBtn.is-disabled,
.codeBtn.is-disabled:focus,
.codeBtn.is-disabled:hover {
color: #c0c4cc;
cursor: not-allowed;
background-image: none;
background-color: #fff;
border-color: #ebeef5;
}
.el-radio-group { .el-radio-group {
margin-top: 12px; margin-top: 12px;
} }
.el-radio { .el-radio {
width: 60px; width: 60px;
} }

View File

@ -39,22 +39,7 @@
<el-input v-model="searchData.Name" clearable style="width: 120px" /> <el-input v-model="searchData.Name" clearable style="width: 120px" />
</el-form-item> </el-form-item>
<!-- 签署人 --> <!-- 签署人 -->
<el-form-item :label="$t('trials:signRecords:table:user')" v-if="!isSystem"> <el-form-item :label="$t('trials:signRecords:table:user')" v-if="!isDoc">
<el-select v-model="searchData.UserId" clearable filterable style="width: 140px">
<el-option v-for="item of userOptions" :key="item.UserId" :label="item.RealName" :value="item.UserId">
<span style="float: left">{{ item.RealName || item.FullName }}</span>
<span style="
float: right;
color: #8492a6;
font-size: 13px;
margin-left: 5px;
">
{{ item.UserName }}
</span>
</el-option>
</el-select>
</el-form-item>
<el-form-item :label="$t('trials:signRecords:table:user')" v-else-if="!isDoc">
<el-select v-model="searchData.UserId" clearable filterable style="width: 140px"> <el-select v-model="searchData.UserId" clearable filterable style="width: 140px">
<el-option v-for="item of userOptions" :key="item.ConfirmUserId" :label="item.FullName" <el-option v-for="item of userOptions" :key="item.ConfirmUserId" :label="item.FullName"
:value="item.ConfirmUserId"> :value="item.ConfirmUserId">

View File

@ -4,79 +4,176 @@
<el-form :inline="true"> <el-form :inline="true">
<!-- Name --> <!-- Name -->
<el-form-item :label="$t('trials:seletctedReviews:table:name')"> <el-form-item :label="$t('trials:seletctedReviews:table:name')">
<el-input v-model="listQuery.Name" size="small" clearable style="width: 120px" /> <el-input
v-model="listQuery.Name"
size="small"
clearable
style="width: 120px"
/>
</el-form-item> </el-form-item>
<!-- Modality --> <!-- Modality -->
<el-form-item :label="$t('trials:seletctedReviews:form:modality')"> <el-form-item :label="$t('trials:seletctedReviews:form:modality')">
<el-select v-model="listQuery.ReadingTypeIdList" class="handle-select" clearable multiple collapse-tags <el-select
style="width: 160px"> v-model="listQuery.ReadingTypeIdList"
<el-option v-for="item of $d.ReadingType" :key="item.id" :label="item.label" :value="item.id" /> class="handle-select"
clearable
multiple
collapse-tags
style="width: 160px"
>
<el-option
v-for="item of $d.ReadingType"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- Subspeciality --> <!-- Subspeciality -->
<el-form-item :label="$t('trials:seletctedReviews:form:subspeciality')"> <el-form-item :label="$t('trials:seletctedReviews:form:subspeciality')">
<el-select v-model="listQuery.SubspecialityIdList" class="handle-select" clearable multiple collapse-tags <el-select
style="width: 160px"> v-model="listQuery.SubspecialityIdList"
<el-option v-for="item of $d.Subspeciality" :key="item.id" :label="item.label" :value="item.id" /> class="handle-select"
clearable
multiple
collapse-tags
style="width: 160px"
>
<el-option
v-for="item of $d.Subspeciality"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- Position --> <!-- Position -->
<el-form-item :label="$t('trials:seletctedReviews:form:position')"> <el-form-item :label="$t('trials:seletctedReviews:form:position')">
<el-select v-model="listQuery.PositionId" class="handle-select" clearable style="width: 160px"> <el-select
<el-option v-for="item of $d.Position" :key="item.id" :label="item.label" :value="item.id" /> v-model="listQuery.PositionId"
class="handle-select"
clearable
style="width: 160px"
>
<el-option
v-for="item of $d.Position"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- Rank --> <!-- Rank -->
<el-form-item :label="$t('trials:seletctedReviews:form:rank')"> <el-form-item :label="$t('trials:seletctedReviews:form:rank')">
<el-select v-model="listQuery.RankId" class="handle-select" style="width: 160px" clearable> <el-select
<el-option v-for="item of $d.Rank" :key="item.id" :label="item.label" :value="item.id" /> v-model="listQuery.RankId"
class="handle-select"
style="width: 160px"
clearable
>
<el-option
v-for="item of $d.Rank"
:key="item.id"
:label="item.label"
:value="item.id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- Institution --> <!-- Institution -->
<el-form-item :label="$t('trials:seletctedReviews:form:institution')"> <el-form-item :label="$t('trials:seletctedReviews:form:institution')">
<el-select v-model="listQuery.HospitalId" class="handle-select mr10" clearable style="width: 160px"> <el-select
<el-option v-for="(item, index) in hospitalList" :key="index" :label="item.HospitalName" :value="item.Id" /> v-model="listQuery.HospitalId"
class="handle-select mr10"
clearable
style="width: 160px"
>
<el-option
v-for="(item, index) in hospitalList"
:key="index"
:label="item.HospitalName"
:value="item.Id"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 查询 --> <!-- 查询 -->
<el-button type="primary" icon="el-icon-search" :loading="loading" @click="handleSearch"> <el-button
type="primary"
icon="el-icon-search"
:loading="loading"
@click="handleSearch"
>
{{ $t('common:button:search') }} {{ $t('common:button:search') }}
</el-button> </el-button>
<!-- 重置 --> <!-- 重置 -->
<el-button type="primary" icon="el-icon-refresh-left" :loading="loading" @click="handleReset"> <el-button
type="primary"
icon="el-icon-refresh-left"
:loading="loading"
@click="handleReset"
>
{{ $t('common:button:reset') }} {{ $t('common:button:reset') }}
</el-button> </el-button>
<el-button v-if="hasPermi(['role:pm'])" type="primary" :disabled="selectIdArr.length == 0" icon="el-icon-check" <el-button
:loading="loading" @click="handleApply"> v-if="hasPermi(['role:pm'])"
type="primary"
:disabled="selectIdArr.length == 0"
icon="el-icon-check"
:loading="loading"
@click="handleApply"
>
{{ $t('trials:seletctedReviews:button:select') }} {{ $t('trials:seletctedReviews:button:select') }}
</el-button> </el-button>
<!---简历采集--> <!---简历采集-->
<el-button type="primary" @click="resumeCollection" <el-button
v-hasPermi="['trials:trials-panel:attachments:enrollment:viewer']"> type="primary"
@click="resumeCollection"
v-hasPermi="['trials:trials-panel:attachments:enrollment:viewer']"
>
{{ $t('trials:seletctedReviews:button:resumeCollection') }} {{ $t('trials:seletctedReviews:button:resumeCollection') }}
</el-button> </el-button>
<!---添加阅片人--> <!---添加阅片人-->
<el-button icon="el-icon-plus" type="primary" @click="openViewer('add')" <el-button
v-hasPermi="['trials:trials-panel:attachments:enrollment:viewer']"> icon="el-icon-plus"
type="primary"
@click="openViewer('add')"
v-hasPermi="['trials:trials-panel:attachments:enrollment:viewer']"
>
{{ $t('trials:seletctedReviews:button:addViewer') }} {{ $t('trials:seletctedReviews:button:addViewer') }}
</el-button> </el-button>
</el-form> </el-form>
</template> </template>
<template slot="main-container"> <template slot="main-container">
<el-table ref="selectionList" v-loading="listLoading" v-adaptive="{ bottomOffset: 65 }" height="100" :data="list" <el-table
class="table" :row-class-name="handleHighLighRow" @sort-change="handleSortChange" ref="selectionList"
@selection-change="handleSelectionChange"> v-loading="listLoading"
v-adaptive="{ bottomOffset: 65 }"
height="100"
:data="list"
class="table"
:row-class-name="handleHighLighRow"
@sort-change="handleSortChange"
@selection-change="handleSelectionChange"
>
<el-table-column type="selection" :selectable="handleSelectTable" /> <el-table-column type="selection" :selectable="handleSelectTable" />
<el-table-column type="index" width="40" /> <el-table-column type="index" width="40" />
<!-- Name --> <!-- Name -->
<el-table-column prop="LastName" :label="$t('trials:seletctedReviews:table:name')" show-overflow-tooltip <el-table-column
width="120" sortable="custom"> prop="LastName"
:label="$t('trials:seletctedReviews:table:name')"
show-overflow-tooltip
width="120"
sortable="custom"
>
<template slot-scope="scope"> <template slot-scope="scope">
<span style="color: #428bca; cursor: pointer" @click=" <span
style="color: #428bca; cursor: pointer"
@click="
go( go(
`/trialsResume?doctorId=${scope.row.Id}&trialId=${$route.query.trialId}&token=${token}` `/trialsResume?doctorId=${scope.row.Id}&trialId=${$route.query.trialId}&token=${token}`
) )
">{{ scope.row.LastName }} / {{ scope.row.FirstName }}</span> "
>{{ scope.row.LastName }} / {{ scope.row.FirstName }}</span
>
<!-- <el-button type="text" @click="go(`/trialsResume?doctorId=${scope.row.Id}&token=${token}`)">{{ scope.row.LastName }} / {{ scope.row.FirstName }}</el-button> --> <!-- <el-button type="text" @click="go(`/trialsResume?doctorId=${scope.row.Id}&token=${token}`)">{{ scope.row.LastName }} / {{ scope.row.FirstName }}</el-button> -->
<!-- <router-link--> <!-- <router-link-->
<!-- style="color: #428bca;"--> <!-- style="color: #428bca;"-->
@ -89,13 +186,28 @@
</template> </template>
</el-table-column> </el-table-column>
<!-- Name CN --> <!-- Name CN -->
<el-table-column v-if="!isEN" prop="ChineseName" :label="$t('trials:seletctedReviews:table:nameCN')" <el-table-column
show-overflow-tooltip sortable="custom" width="120" /> v-if="!isEN"
prop="ChineseName"
:label="$t('trials:seletctedReviews:table:nameCN')"
show-overflow-tooltip
sortable="custom"
width="120"
/>
<el-table-column prop="DoctorUserName" :label="$t('trials:seletctedReviews:table:doctorUserName')" <el-table-column
show-overflow-tooltip sortable="custom" width="120" /> prop="DoctorUserName"
:label="$t('trials:seletctedReviews:table:doctorUserName')"
show-overflow-tooltip
sortable="custom"
width="120"
/>
<!-- Status --> <!-- Status -->
<el-table-column prop="DoctorTrialState" :label="$t('trials:seletctedReviews:table:status')" width="120"> <el-table-column
prop="DoctorTrialState"
:label="$t('trials:seletctedReviews:table:status')"
width="120"
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag v-if="scope.row.DoctorTrialState === 1" type="primary">{{ <el-tag v-if="scope.row.DoctorTrialState === 1" type="primary">{{
$fd('DoctorTrialState', 16) $fd('DoctorTrialState', 16)
@ -103,16 +215,35 @@
</template> </template>
</el-table-column> </el-table-column>
<!-- Submitted --> <!-- Submitted -->
<el-table-column prop="Submitted" :label="$t('trials:seletctedReviews:table:submitted')" show-overflow-tooltip <el-table-column
sortable="custom" width="140" /> prop="Submitted"
:label="$t('trials:seletctedReviews:table:submitted')"
show-overflow-tooltip
sortable="custom"
width="140"
/>
<!-- Approved --> <!-- Approved -->
<el-table-column prop="Approved" :label="$t('trials:seletctedReviews:table:approved')" show-overflow-tooltip <el-table-column
sortable="custom" width="120" /> prop="Approved"
:label="$t('trials:seletctedReviews:table:approved')"
show-overflow-tooltip
sortable="custom"
width="120"
/>
<!-- Reading --> <!-- Reading -->
<el-table-column prop="Reading" :label="$t('trials:seletctedReviews:table:reading')" show-overflow-tooltip <el-table-column
sortable="custom" width="120" /> prop="Reading"
<el-table-column prop="Speciality" :label="$t('trials:seletctedReviews:form:modality')" show-overflow-tooltip :label="$t('trials:seletctedReviews:table:reading')"
min-width="120"> show-overflow-tooltip
sortable="custom"
width="120"
/>
<el-table-column
prop="Speciality"
:label="$t('trials:seletctedReviews:form:modality')"
show-overflow-tooltip
min-width="120"
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ {{
scope.row.ReadingTypeIds.map((v) => { scope.row.ReadingTypeIds.map((v) => {
@ -122,8 +253,12 @@
</template> </template>
</el-table-column> </el-table-column>
<!-- Specialty --> <!-- Specialty -->
<el-table-column prop="Speciality" :label="$t('trials:seletctedReviews:table:specialty')" show-overflow-tooltip <el-table-column
min-width="120"> prop="Speciality"
:label="$t('trials:seletctedReviews:table:specialty')"
show-overflow-tooltip
min-width="120"
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ {{
scope.row.SpecialityId === otherId scope.row.SpecialityId === otherId
@ -135,8 +270,12 @@
</template> </template>
</el-table-column> </el-table-column>
<!-- Subspecialty --> <!-- Subspecialty -->
<el-table-column prop="Subspeciality" :label="$t('trials:seletctedReviews:table:subspecialty')" <el-table-column
show-overflow-tooltip min-width="150"> prop="Subspeciality"
:label="$t('trials:seletctedReviews:table:subspecialty')"
show-overflow-tooltip
min-width="150"
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ {{
scope.row.SubspecialityIds.map((v) => { scope.row.SubspecialityIds.map((v) => {
@ -147,42 +286,76 @@
</template> </template>
</el-table-column> </el-table-column>
<!-- Institution --> <!-- Institution -->
<el-table-column prop="HospitalName" :label="$t('trials:seletctedReviews:table:institution')" <el-table-column
show-overflow-tooltip width="150"> prop="HospitalName"
:label="$t('trials:seletctedReviews:table:institution')"
show-overflow-tooltip
width="150"
>
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ isEN?scope.row.HospitalName:scope.row.HospitalNameCN }}</span> <span>{{ isEN?scope.row.HospitalName:scope.row.HospitalNameCN }}</span>
</template> </template>
</el-table-column> </el-table-column>
<!-- City --> <!-- City -->
<el-table-column prop="City" :label="$t('trials:seletctedReviews:table:city')" show-overflow-tooltip <el-table-column
width="150"> prop="City"
:label="$t('trials:seletctedReviews:table:city')"
show-overflow-tooltip
width="150"
>
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ isEN?scope.row.City:scope.row.CityCN }}</span> <span>{{ isEN?scope.row.City:scope.row.CityCN }}</span>
</template> </template>
</el-table-column> </el-table-column>
<!-- Country --> <!-- Country -->
<el-table-column prop="Country" :label="$t('trials:seletctedReviews:table:country')" show-overflow-tooltip <el-table-column
width="150"> prop="Country"
:label="$t('trials:seletctedReviews:table:country')"
show-overflow-tooltip
width="150"
>
<template slot-scope="scope"> <template slot-scope="scope">
<span>{{ isEN?scope.row.Country:scope.row.CountryCN }}</span> <span>{{ isEN?scope.row.Country:scope.row.CountryCN }}</span>
</template> </template>
</el-table-column> </el-table-column>
<!-- Selector --> <!-- Selector -->
<el-table-column prop="OptUserName" :label="$t('trials:seletctedReviews:table:selector')" width="150" /> <el-table-column
prop="OptUserName"
:label="$t('trials:seletctedReviews:table:selector')"
width="150"
/>
<!-- Selection Time --> <!-- Selection Time -->
<el-table-column prop="OptTimeStr" :label="$t('trials:seletctedReviews:table:selectionTime')" width="150" /> <el-table-column
<el-table-column fixed="right" prop="OptTimeStr" :label="$t('common:action:action')" width="150" prop="OptTimeStr"
v-if="hasPermi(['trials:trials-panel:attachments:enrollment:viewer'])"> :label="$t('trials:seletctedReviews:table:selectionTime')"
width="150"
/>
<el-table-column
fixed="right"
prop="OptTimeStr"
:label="$t('common:action:action')"
width="150"
v-if="hasPermi(['trials:trials-panel:attachments:enrollment:viewer'])"
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-button icon="el-icon-edit-outline" :title="$t('common:button:edit')" <el-button
icon="el-icon-edit-outline"
:title="$t('common:button:edit')"
@click.stop="openViewer('edit', scope.row)" @click.stop="openViewer('edit', scope.row)"
v-hasPermi="['trials:trials-panel:attachments:enrollment:viewer']" :disabled="scope.row.IsEnroll" v-hasPermi="['trials:trials-panel:attachments:enrollment:viewer']"
circle /> :disabled="scope.row.IsEnroll"
circle
/>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<pagination class="page" :total="total" :page.sync="listQuery.PageIndex" :limit.sync="listQuery.PageSize" <pagination
@pagination="getList" /> class="page"
:total="total"
:page.sync="listQuery.PageIndex"
:limit.sync="listQuery.PageSize"
@pagination="getList"
/>
</template> </template>
<!--简历采集--> <!--简历采集-->
<base-model :config="share_model"> <base-model :config="share_model">
@ -192,8 +365,14 @@
<span>{{ $t('reviewers-list:message:msg1') }}</span> <span>{{ $t('reviewers-list:message:msg1') }}</span>
</div> </div>
<div style="margin: 10px 0"> <div style="margin: 10px 0">
<span style="">{{ $t('reviewers-list:message:msg2') }}</span><el-input type="textarea" <span style="">{{ $t('reviewers-list:message:msg2') }}</span
:autosize="{ minRows: 2, maxRows: 4 }" v-model="shareLink" readonly style="width: 100%; margin-top: 10px" /> ><el-input
type="textarea"
:autosize="{ minRows: 2, maxRows: 4 }"
v-model="shareLink"
readonly
style="width: 100%; margin-top: 10px"
/>
</div> </div>
<div> <div>
<el-button type="primary" round @click="copyCode">{{ <el-button type="primary" round @click="copyCode">{{
@ -201,34 +380,80 @@
}}</el-button> }}</el-button>
</div> </div>
<div class="sendEmailBox"> <div class="sendEmailBox">
<el-input v-model="email" clearable :placeholder="$t('reviewers-list:placeholder:sendEmail')"></el-input> <el-input
<el-button type="primary" round :disabled="!email" @click="sendEmail" :loading="emailLoading" v-model="email"
style="margin-left: 10px"> clearable
:placeholder="$t('reviewers-list:placeholder:sendEmail')"
></el-input>
<el-button
type="primary"
round
:disabled="!email"
@click="sendEmail"
:loading="emailLoading"
style="margin-left: 10px"
>
{{ $t('reviewers-list:button:sendEmail') }} {{ $t('reviewers-list:button:sendEmail') }}
</el-button> </el-button>
</div> </div>
</template> </template>
</base-model> </base-model>
<!--新增或修改简历--> <!--新增或修改简历-->
<el-dialog :title="$t('curriculumVitae:content:title')" :visible.sync="visible" fullscreen v-if="visible" <el-dialog
appendToBody :before-close="beforeClose"> :title="$t('curriculumVitae:content:title')"
:visible.sync="visible"
fullscreen
v-if="visible"
appendToBody
:before-close="beforeClose"
>
<curriculumVitae :reviewerId="reviewerId" /> <curriculumVitae :reviewerId="reviewerId" />
</el-dialog> </el-dialog>
<!--新增阅片人输入邮箱---> <!--新增阅片人输入邮箱--->
<el-dialog :title="$t('curriculumVitae:content:title')" :visible.sync="emailVisible" v-if="emailVisible" <el-dialog
appendToBody :close-on-click-modal="false" v-dialogDrag width="400px"> :title="$t('curriculumVitae:content:title')"
<el-form v-if="emailVisible" ref="emailForm" :model="emailForm" :rules="emailRule" class="demo-form-inline" :visible.sync="emailVisible"
label-width="80px"> v-if="emailVisible"
<el-form-item :label="$t('trials:trials-panel:attachments:enrollment:form:email')" prop="EmailOrPhone"> appendToBody
<el-input v-model="emailForm.EmailOrPhone" clearable :maxlength="400"></el-input> :close-on-click-modal="false"
<el-input style="display: none" v-model="emailForm.EmailOrPhone" clearable :maxlength="400"></el-input> v-dialogDrag
width="400px"
>
<el-form
v-if="emailVisible"
ref="emailForm"
:model="emailForm"
:rules="emailRule"
class="demo-form-inline"
label-width="80px"
>
<el-form-item
:label="$t('trials:trials-panel:attachments:enrollment:form:email')"
prop="EmailOrPhone"
>
<el-input
v-model="emailForm.EmailOrPhone"
clearable
:maxlength="400"
></el-input>
<el-input
style="display: none"
v-model="emailForm.EmailOrPhone"
clearable
:maxlength="400"
></el-input>
</el-form-item> </el-form-item>
</el-form> </el-form>
<span slot="footer" class="dialog-footer"> <span slot="footer" class="dialog-footer">
<el-button size="small" type="primary" @click="handleCancle"> <el-button size="small" type="primary" @click="handleCancle">
{{ $t('common:button:cancel') }} {{ $t('common:button:cancel') }}
</el-button> </el-button>
<el-button size="small" type="primary" @click="handleSave" :loading="emailLoading"> <el-button
size="small"
type="primary"
@click="handleSave"
:loading="emailLoading"
>
{{ $t('common:button:save') }} {{ $t('common:button:save') }}
</el-button> </el-button>
</span> </span>
@ -257,9 +482,9 @@ const getListQueryDefault = () => {
HospitalId: '', HospitalId: '',
Asc: false, Asc: false,
SortField: '', SortField: '',
// AcceptingNewTrial: true, AcceptingNewTrial: true,
// InformationConfirmed: true, InformationConfirmed: true,
// ContractorStatus: 1, ContractorStatus: 1,
} }
} }
export default { export default {
@ -358,7 +583,7 @@ export default {
}, },
copyCode() { copyCode() {
this.$copyText( this.$copyText(
`${this.$t('reviewers-list:message:msg1')}: ${this.shareLink}` `${this.$t('reviewers-list:button:copyCode')}: ${this.shareLink}`
) )
.then((res) => { .then((res) => {
this.$message.success( this.$message.success(
@ -482,7 +707,7 @@ export default {
} }
}, },
handleSelectTable(row) { handleSelectTable(row) {
return row.DoctorTrialState !== 1 && row.ResumeStatus === 1 && row.AcceptingNewTrial && !row.IsVirtual && !row.IsVacation && row.CooperateStatus === 1 return row.DoctorTrialState !== 1
}, },
handleDetail(row) { handleDetail(row) {
const { href } = this.$router.resolve({ const { href } = this.$router.resolve({
@ -508,8 +733,8 @@ export default {
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
} }
::v-deep .el-card__body { ::v-deep .el-card__body {
padding: 20px !important; padding: 20px !important;
} }
</style> </style>

View File

@ -1,230 +0,0 @@
<template>
<div class="ImageManual">
<div class="config">
<div style="margin-bottom: 20px;font-weight: bold;">
{{ $t("trials:researchRecord:ImageManual:BasicQuestion") }}
</div>
<el-form size="small" :model="form" style="width:80%">
<el-form-item>
<el-checkbox v-model="form.AverageEngravingCycle">
{{ $t('trials:researchForm:form:engravingCycle') }}
</el-checkbox>
</el-form-item>
<el-form-item>
<el-checkbox v-model="form.IsConfirmImagingTechnologist"
@change="(val) => handleChange(val, 'IsConfirmImagingTechnologist')">
{{ $t('trials:researchForm:form:isQualified') }}
</el-checkbox>
</el-form-item>
<el-form-item>
<el-checkbox v-model="form.EfficacyEvaluatorType">
{{ $t('trials:researchForm:form:staffType') }}
</el-checkbox>
</el-form-item>
<el-form-item>
<el-checkbox v-model="form.IsFollowStudyParameters"
@change="(val) => handleChange(val, 'IsFollowStudyParameters')">
<span v-html="$t('trials:researchForm:form:isFollowStudyParam')"></span>
</el-checkbox>
</el-form-item>
</el-form>
<div style="margin-bottom: 20px;font-weight: bold;">
{{ $t("trials:researchRecord:ImageManual:TableConfiguration") }}
</div>
<el-form size="small" :model="form" style="width:80%">
<el-form-item :label="$t('trials:researchRecord:ImageManual:Equipment')">
<el-radio-group v-model="form.IsCloseEquipmentSurvey">
<el-radio :label="item.value" v-for="item in $d.YesOrNo" :key="item.id">{{ item.label
}}</el-radio>
</el-radio-group>
</el-form-item>
</el-form>
<div style="margin-bottom: 20px;font-weight: bold;">
{{ $t("trials:researchRecord:ImageManual:Precautions") }}
</div>
<el-input type="textarea" :autosize="{ minRows: 4, maxRows: 99 }" placeholder=""
v-model="form.ReplaceContent" @input="handleInput" style="width: 70%;" />
<div style="text-align: right;margin: 20px;" class="btnBox">
<el-button type="primary" :loading="loading" size="small" @click="handleSave">
{{ $t('common:button:save') }}
</el-button>
</div>
</div>
<div class="preview">
<researchForm ref="ResearchForm" :trialSiteSurveyId="trialSiteSurveyId" />
</div>
</div>
</template>
<script>
import researchForm from '@/views/research/components/ResearchForm'
import { updateTrialExtralConfig, getTrialExtralConfig, getTrialDocumentList } from "@/api/trials"
export default {
name: "ImageManual",
components: { researchForm },
props: {
trialSiteSurveyId: {
type: String,
default: ''
}
},
data() {
return {
form: {
AverageEngravingCycle: false,
IsConfirmImagingTechnologist: false,
NotConfirmReson: false,
EfficacyEvaluatorType: false,
IsFollowStudyParameters: false,
NotFollowReson: false,
ReplaceContent: '',
ReplaceContentCN: '',
IsOpenLostVistRead: false,
IsSupportQCDownloadImage: false,
IsCloseEquipmentSurvey: true
},
obj: {
AverageEngravingCycle: false,
IsConfirmImagingTechnologist: false,
NotConfirmReson: false,
EfficacyEvaluatorType: false,
IsFollowStudyParameters: false,
NotFollowReson: false,
},
loading: false
}
},
mounted() {
this.getInfo()
},
methods: {
handleChange(val, key) {
if (key === 'IsConfirmImagingTechnologist') this.form.NotConfirmReson = val
if (key === 'IsFollowStudyParameters') this.form.NotFollowReson = val
},
handleInput(val) {
this.form.ReplaceContentCN = val
},
async getInfo() {
try {
let param = {
TrialId: this.$route.query.trialId
}
let res = await getTrialExtralConfig(param)
if (res.IsSuccess) {
Object.keys(this.form).forEach(key => {
this.form[key] = true
if (key === 'ReplaceContent' || key === 'ReplaceContentCN') this.form[key] = ''
})
this.form.IsOpenLostVistRead = res.Result.IsOpenLostVistRead
this.form.IsSupportQCDownloadImage = res.Result.IsSupportQCDownloadImage
this.form.IsCloseEquipmentSurvey = !res.Result.IsCloseEquipmentSurvey
if (Array.isArray(res.Result.NotShowFieldList) && res.Result.NotShowFieldList.length > 0) {
res.Result.NotShowFieldList.forEach(key => {
this.form[key] = false
})
}
if (Array.isArray(res.Result.ModifyFiledList) && res.Result.ModifyFiledList.length > 0) {
this.form.ReplaceContent = res.Result.ModifyFiledList[0].ReplaceContent.split('<p>').join('').split('</p>').filter(item => isNaN(item)).join("\n")
this.form.ReplaceContentCN = res.Result.ModifyFiledList[0].ReplaceContentCN.split('<p>').join('').split('</p>').filter(item => isNaN(item)).join("\n")
} else {
let arr = [this.$t('trials:equiptResearch:form:item1'), this.$t('trials:equiptResearch:form:item2'), this.$t('trials:equiptResearch:form:item3'), this.$t('trials:equiptResearch:form:item4')]
this.form.ReplaceContent = arr.join("\n")
this.form.ReplaceContentCN = arr.join("\n")
}
}
} catch (err) {
console.log(err)
}
},
async getTrialDocumentList() {
try {
let data = {
PageIndex: 1,
PageSize: 20,
TrialId: this.$route.query.trialId,
IsPublish: true,
FileTypeCode: 4,
IsDeleted: false
}
let res = await getTrialDocumentList(data)
if (res.IsSuccess) {
const { CurrentPageData } = res.Result
if (CurrentPageData.length <= 0) this.$confirm(this.$t("trials:researchRecord:ImageManual:message:noImageManual"), this.$t('system:menu:confirm:title:warning'), {
type: 'warning'
})
}
} catch (err) {
console.log(err)
}
},
async handleSave() {
try {
let param = {
TrialId: this.$route.query.trialId
}
let data = {
IsOpenLostVistRead: this.form.IsOpenLostVistRead,
IsSupportQCDownloadImage: this.form.IsSupportQCDownloadImage,
IsCloseEquipmentSurvey: !this.form.IsCloseEquipmentSurvey,
ModifyFiledList: [],
NotShowFieldList: []
}
Object.keys(this.obj).forEach(key => {
if (!this.form[key]) data.NotShowFieldList.push(key)
})
let ReplaceContent = ''
this.form.ReplaceContent.split("\n").forEach(item => {
ReplaceContent += `<p>${item}</p>`
})
let ReplaceContentCN = ''
this.form.ReplaceContentCN.split("\n").forEach(item => {
ReplaceContentCN += `<p>${item}</p>`
})
let obj = {
NeedModifyFiled: 'SiteSurveyNote',
ReplaceContent: ReplaceContent,
ReplaceContentCN: ReplaceContentCN,
}
data.ModifyFiledList.push(obj)
this.loading = true
let res = await updateTrialExtralConfig(param, data)
this.loading = false
if (res.IsSuccess) {
this.$refs.ResearchForm.initPage()
if (!data.NotShowFieldList.includes('IsFollowStudyParameters')) this.getTrialDocumentList()
}
} catch (err) {
this.loading = false
console.log(err)
}
}
}
}
</script>
<style lang="scss" scoped>
.ImageManual {
width: 100%;
height: 100%;
display: flex;
position: relative;
.config,
.preview {
width: 65%;
height: 100%;
overflow-y: auto;
}
.config {
width: 35%;
border-right: 1px solid #EBEEF5;
}
::v-deep .el-checkbox__label {
white-space: normal;
i {}
}
}
</style>

View File

@ -5,62 +5,127 @@
<el-form :inline="true"> <el-form :inline="true">
<!-- 中心 --> <!-- 中心 -->
<el-form-item :label="$t('trials:researchRecord:table:siteId')"> <el-form-item :label="$t('trials:researchRecord:table:siteId')">
<el-select v-model="searchData.TrialSiteId" clearable filterable style="width: 120px"> <el-select
<el-option v-for="(item, index) of siteOptions" :key="index" :label="item.TrialSiteCode" v-model="searchData.TrialSiteId"
:value="item.TrialSiteId" /> clearable
filterable
style="width: 120px"
>
<el-option
v-for="(item, index) of siteOptions"
:key="index"
:label="item.TrialSiteCode"
:value="item.TrialSiteId"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 联系人 --> <!-- 联系人 -->
<el-form-item :label="$t('trials:researchRecord:table:contactor')"> <el-form-item :label="$t('trials:researchRecord:table:contactor')">
<el-input v-model="searchData.UserKeyInfo" class="mr" clearable :placeholder="`${$t( <el-input
v-model="searchData.UserKeyInfo"
class="mr"
clearable
:placeholder="`${$t(
'trials:researchRecord:placeholder:contactorInfo' 'trials:researchRecord:placeholder:contactorInfo'
)}`" style="width: 140px" /> )}`"
style="width: 140px"
/>
</el-form-item> </el-form-item>
<!-- 初审人 --> <!-- 初审人 -->
<el-form-item :label="$t('trials:researchRecord:table:preliminaryUser')"> <el-form-item
<el-input v-model="searchData.PreliminaryUserName" class="mr" clearable style="width: 140px" /> :label="$t('trials:researchRecord:table:preliminaryUser')"
>
<el-input
v-model="searchData.PreliminaryUserName"
class="mr"
clearable
style="width: 140px"
/>
</el-form-item> </el-form-item>
<!-- 审核人 --> <!-- 审核人 -->
<el-form-item :label="$t('trials:researchRecord:table:ReviewerUser')"> <el-form-item :label="$t('trials:researchRecord:table:ReviewerUser')">
<el-input v-model="searchData.ReviewerUserName" class="mr" clearable style="width: 140px" /> <el-input
v-model="searchData.ReviewerUserName"
class="mr"
clearable
style="width: 140px"
/>
</el-form-item> </el-form-item>
<!-- 状态 --> <!-- 状态 -->
<el-form-item :label="$t('trials:researchRecord:table:status')"> <el-form-item :label="$t('trials:researchRecord:table:status')">
<el-select v-model="searchData.State" clearable filterable style="width: 120px"> <el-select
<el-option v-for="(item, index) of $d.ResearchRecord" :key="index" :label="item.label" v-model="searchData.State"
:value="item.value" /> clearable
filterable
style="width: 120px"
>
<el-option
v-for="(item, index) of $d.ResearchRecord"
:key="index"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 是否废除 --> <!-- 是否废除 -->
<el-form-item :label="$t('trials:researchRecord:table:isDeleted')"> <el-form-item :label="$t('trials:researchRecord:table:isDeleted')">
<el-select v-model="searchData.IsDeleted" clearable filterable style="width: 120px"> <el-select
<el-option v-for="item of $d.YesOrNo" v-show="item.raw.ValueCN !== ''" :key="`IsDeleted${item.value}`" v-model="searchData.IsDeleted"
:label="item.label" :value="item.value" /> clearable
filterable
style="width: 120px"
>
<el-option
v-for="item of $d.YesOrNo"
v-show="item.raw.ValueCN !== '无'"
:key="`IsDeleted${item.value}`"
:label="item.label"
:value="item.value"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<!-- 更新时间 --> <!-- 更新时间 -->
<el-form-item :label="$t('trials:researchRecord:table:updateTime')"> <el-form-item :label="$t('trials:researchRecord:table:updateTime')">
<el-date-picker v-model="searchData.DateRange" type="daterange" value-format="yyyy-MM-dd" format="yyyy-MM-dd" <el-date-picker
style="width: 250px" /> v-model="searchData.DateRange"
type="daterange"
value-format="yyyy-MM-dd"
format="yyyy-MM-dd"
style="width: 250px"
/>
</el-form-item> </el-form-item>
<!-- 查询 --> <!-- 查询 -->
<el-button type="primary" icon="el-icon-search" @click="handleSearch"> <el-button type="primary" icon="el-icon-search" @click="handleSearch">
{{ $t('common:button:search') }} {{ $t('common:button:search') }}
</el-button> </el-button>
<!-- 重置 --> <!-- 重置 -->
<el-button type="primary" icon="el-icon-refresh-left" @click="handleReset"> <el-button
type="primary"
icon="el-icon-refresh-left"
@click="handleReset"
>
{{ $t('common:button:reset') }} {{ $t('common:button:reset') }}
</el-button> </el-button>
<!-- 中心人员 --> <!-- 中心人员 -->
<el-button v-hasPermi="[ <el-button
v-hasPermi="[
'trials:trials-panel:attachments:site-research:summary-record', 'trials:trials-panel:attachments:site-research:summary-record',
]" type="primary" icon="el-icon-info" @click="showResearchUser"> ]"
type="primary"
icon="el-icon-info"
@click="showResearchUser"
>
{{ $t('trials:researchRecord:button:questionStaffs') }} {{ $t('trials:researchRecord:button:questionStaffs') }}
</el-button> </el-button>
<!-- 调查表链接 --> <!-- 调查表链接 -->
<el-button v-hasPermi="[ <el-button
v-hasPermi="[
'trials:trials-panel:attachments:site-research:questionnaire-link', 'trials:trials-panel:attachments:site-research:questionnaire-link',
]" type="primary" icon="el-icon-link" @click="showResearchLink"> ]"
type="primary"
icon="el-icon-link"
@click="showResearchLink"
>
{{ $t('trials:researchRecord:button:questionLink') }} {{ $t('trials:researchRecord:button:questionLink') }}
</el-button> </el-button>
</el-form> </el-form>
@ -68,27 +133,61 @@
<template slot="main-container"> <template slot="main-container">
<!-- 系统文件列表 --> <!-- 系统文件列表 -->
<el-table ref="siteResearchList" v-loading="loading" v-adaptive="{ bottomOffset: 60 }" :data="list" stripe <el-table
height="100" @sort-change="handleSortByColumn"> ref="siteResearchList"
v-loading="loading"
v-adaptive="{ bottomOffset: 60 }"
:data="list"
stripe
height="100"
@sort-change="handleSortByColumn"
>
<el-table-column type="index" width="50" /> <el-table-column type="index" width="50" />
<!-- 中心编号 --> <!-- 中心编号 -->
<el-table-column prop="TrialSiteCode" :label="$t('trials:researchRecord:table:siteId')" min-width="100" <el-table-column
sortable="custom" show-overflow-tooltip /> prop="TrialSiteCode"
:label="$t('trials:researchRecord:table:siteId')"
min-width="100"
sortable="custom"
show-overflow-tooltip
/>
<!-- 中心名称 --> <!-- 中心名称 -->
<el-table-column prop="SiteName" :label="$t('trials:researchRecord:table:siteName')" min-width="100" <el-table-column
sortable="custom" show-overflow-tooltip /> prop="SiteName"
:label="$t('trials:researchRecord:table:siteName')"
min-width="100"
sortable="custom"
show-overflow-tooltip
/>
<!-- 联系人 --> <!-- 联系人 -->
<el-table-column prop="UserName" :label="$t('trials:researchRecord:table:contactor')" min-width="100" <el-table-column
sortable="custom" show-overflow-tooltip /> prop="UserName"
:label="$t('trials:researchRecord:table:contactor')"
min-width="100"
sortable="custom"
show-overflow-tooltip
/>
<!-- 联系电话 --> <!-- 联系电话 -->
<el-table-column prop="Phone" :label="$t('trials:researchRecord:table:contactorPhone')" min-width="100" <el-table-column
show-overflow-tooltip /> prop="Phone"
:label="$t('trials:researchRecord:table:contactorPhone')"
min-width="100"
show-overflow-tooltip
/>
<!-- 联系邮箱 --> <!-- 联系邮箱 -->
<el-table-column prop="Email" :label="$t('trials:researchRecord:table:contactorEmail')" min-width="150" <el-table-column
show-overflow-tooltip /> prop="Email"
:label="$t('trials:researchRecord:table:contactorEmail')"
min-width="150"
show-overflow-tooltip
/>
<!-- 初审人 --> <!-- 初审人 -->
<el-table-column prop="preliminaryUser" :label="$t('trials:researchRecord:table:preliminaryUser')" <el-table-column
min-width="150" show-overflow-tooltip> prop="preliminaryUser"
:label="$t('trials:researchRecord:table:preliminaryUser')"
min-width="150"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ {{
scope.row.PreliminaryUser scope.row.PreliminaryUser
@ -98,15 +197,24 @@
</template> </template>
</el-table-column> </el-table-column>
<!-- 审核人 --> <!-- 审核人 -->
<el-table-column prop="ReviewerUser" :label="$t('trials:researchRecord:table:ReviewerUser')" min-width="150" <el-table-column
show-overflow-tooltip> prop="ReviewerUser"
:label="$t('trials:researchRecord:table:ReviewerUser')"
min-width="150"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
{{ scope.row.ReviewerUser ? scope.row.ReviewerUser.RealName : '' }} {{ scope.row.ReviewerUser ? scope.row.ReviewerUser.RealName : '' }}
</template> </template>
</el-table-column> </el-table-column>
<!-- 状态 --> <!-- 状态 -->
<el-table-column prop="State" :label="$t('trials:researchRecord:table:status')" min-width="150" <el-table-column
sortable="custom" show-overflow-tooltip> prop="State"
:label="$t('trials:researchRecord:table:status')"
min-width="150"
sortable="custom"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag v-if="scope.row.State === 0" type="primary">{{ <el-tag v-if="scope.row.State === 0" type="primary">{{
$fd('ResearchRecord', scope.row.State) $fd('ResearchRecord', scope.row.State)
@ -123,8 +231,13 @@
</template> </template>
</el-table-column> </el-table-column>
<!-- 是否废除 --> <!-- 是否废除 -->
<el-table-column prop="IsDeleted" :label="$t('trials:researchRecord:table:isDeleted')" min-width="100" <el-table-column
sortable="custom" show-overflow-tooltip> prop="IsDeleted"
:label="$t('trials:researchRecord:table:isDeleted')"
min-width="100"
sortable="custom"
show-overflow-tooltip
>
<template slot-scope="scope"> <template slot-scope="scope">
<el-tag v-if="scope.row.IsDeleted" type="danger">{{ <el-tag v-if="scope.row.IsDeleted" type="danger">{{
$fd('YesOrNo', scope.row.IsDeleted) $fd('YesOrNo', scope.row.IsDeleted)
@ -135,59 +248,88 @@
</template> </template>
</el-table-column> </el-table-column>
<!-- 更新时间 --> <!-- 更新时间 -->
<el-table-column prop="UpdateTime" :label="$t('trials:researchRecord:table:updateTime')" min-width="150" <el-table-column
show-overflow-tooltip sortable="custom" /> prop="UpdateTime"
:label="$t('trials:researchRecord:table:updateTime')"
min-width="150"
show-overflow-tooltip
sortable="custom"
/>
<el-table-column width="150"> <el-table-column width="150">
<template slot-scope="scope"> <template slot-scope="scope">
<!-- 查看 --> <!-- 查看 -->
<el-button :disabled="scope.row.State !== 3" circle :title="$t('common:button:view')" icon="el-icon-view" <el-button
@click="handleViewResearchList(scope.row)" /> :disabled="scope.row.State !== 3"
circle
:title="$t('common:button:view')"
icon="el-icon-view"
@click="handleViewResearchList(scope.row)"
/>
<!-- 审批 --> <!-- 审批 -->
<el-button v-hasPermi="[ <el-button
v-hasPermi="[
'trials:trials-panel:attachments:site-research:auidt', 'trials:trials-panel:attachments:site-research:auidt',
]" :disabled="scope.row.State === 0 || scope.row.State === 3 || scope.row.IsDeleted" circle ]"
:title="$t('trials:researchRecord:action:view')" icon="el-icon-s-check" :disabled="scope.row.State === 0 || scope.row.State === 3 || scope.row.IsDeleted"
@click="handleViewResearchList(scope.row)" /> circle
:title="$t('trials:researchRecord:action:view')"
icon="el-icon-s-check"
@click="handleViewResearchList(scope.row)"
/>
<!-- 废除 --> <!-- 废除 -->
<el-button v-hasPermi="[ <el-button
v-hasPermi="[
'trials:trials-panel:attachments:site-research:abolish', 'trials:trials-panel:attachments:site-research:abolish',
]" :disabled="scope.row.State !== 0 || scope.row.IsDeleted" circle ]"
:title="$t('trials:researchRecord:action:abolish')" icon="el-icon-delete" :disabled="scope.row.State !== 0 || scope.row.IsDeleted"
@click="handleRepealResearch(scope.row)" /> circle
:title="$t('trials:researchRecord:action:abolish')"
icon="el-icon-delete"
@click="handleRepealResearch(scope.row)"
/>
</template> </template>
</el-table-column> </el-table-column>
</el-table> </el-table>
<!-- 分页组件 --> <!-- 分页组件 -->
<pagination class="page" :total="total" :page.sync="searchData.PageIndex" :limit.sync="searchData.PageSize" <pagination
@pagination="getList" /> class="page"
:total="total"
:page.sync="searchData.PageIndex"
:limit.sync="searchData.PageSize"
@pagination="getList"
/>
</template> </template>
<!-- 中心人员 --> <!-- 中心人员 -->
<el-dialog v-if="researchUserVisible" :visible.sync="researchUserVisible" <el-dialog
:title="$t('trials:researchRecord:dialogTitle:questionStaff')" custom-class="base-dialog-wrapper" v-if="researchUserVisible"
:fullscreen="true"> :visible.sync="researchUserVisible"
<div class="base-modal-body" style="border: 1px solid #ccc; padding: 10px"> :title="$t('trials:researchRecord:dialogTitle:questionStaff')"
custom-class="base-dialog-wrapper"
:fullscreen="true"
>
<div
class="base-modal-body"
style="border: 1px solid #ccc; padding: 10px"
>
<Users v-if="researchUserVisible" /> <Users v-if="researchUserVisible" />
</div> </div>
</el-dialog> </el-dialog>
<!-- 调查表 --> <!-- 调查表 -->
<el-dialog v-if="researchInfoVisible" :visible.sync="researchInfoVisible" :fullscreen="true" <el-dialog
:close-on-click-modal="false"> v-if="researchInfoVisible"
:visible.sync="researchInfoVisible"
:fullscreen="true"
:close-on-click-modal="false"
>
<research-form v-if="researchInfoVisible" @refreshPage="getList" /> <research-form v-if="researchInfoVisible" @refreshPage="getList" />
</el-dialog> </el-dialog>
<!-- 调查表编辑 -->
<el-dialog v-if="ImageManualVisible" :visible.sync="ImageManualVisible" :fullscreen="true"
:close-on-click-modal="false" :title="$t('trials:researchRecord:dialogTitle:ImageManualEdit')">
<ImageManual v-if="ImageManualVisible" :trialSiteSurveyId="trialSiteSurveyId" @getList="getList" />
</el-dialog>
<!-- 调查表链接 --> <!-- 调查表链接 -->
<base-model :config="share_model"> <base-model :config="share_model">
<template slot="dialog-body"> <template slot="dialog-body">
<el-button size="small" type="primary" style="margin-bottom: 10px;" @click.stop="openImageManual">{{
$t('trials:researchRecord:label:edit')
}}</el-button>
<div style="width: 100%; display: flex"> <div style="width: 100%; display: flex">
<div class="shareLink"> <div class="shareLink">
<!-- <div> <!-- <div>
@ -199,11 +341,22 @@
<div style="margin: 10px 0"> <div style="margin: 10px 0">
<!-- 链接 --> <!-- 链接 -->
{{ $t('trials:researchRecord:label:link') }} {{ $t('trials:researchRecord:label:link') }}
<el-input ref="shareLink" v-model="shareLink" readonly type="textarea" autosize /> <el-input
ref="shareLink"
v-model="shareLink"
readonly
type="textarea"
autosize
/>
</div> </div>
<div> <div>
<!-- 复制链接 --> <!-- 复制链接 -->
<el-button type="primary" round @click="copyLink" class="shareLinkBtn"> <el-button
type="primary"
round
@click="copyLink"
class="shareLinkBtn"
>
{{ $t('trials:researchRecord:button:copyLink') }} {{ $t('trials:researchRecord:button:copyLink') }}
</el-button> </el-button>
</div> </div>
@ -238,7 +391,6 @@ import Pagination from '@/components/Pagination'
import Users from './components/users' import Users from './components/users'
import ResearchForm from '@/views/research/form' import ResearchForm from '@/views/research/form'
import BaseModel from '@/components/BaseModel' import BaseModel from '@/components/BaseModel'
import ImageManual from './components/ImageManual'
import QRCode from 'qrcodejs2' import QRCode from 'qrcodejs2'
const searchDataDefault = () => { const searchDataDefault = () => {
@ -258,7 +410,7 @@ const searchDataDefault = () => {
} }
export default { export default {
name: 'SiteResearchList', name: 'SiteResearchList',
components: { BaseContainer, Pagination, Users, ResearchForm, BaseModel, ImageManual }, components: { BaseContainer, Pagination, Users, ResearchForm, BaseModel },
data() { data() {
return { return {
searchData: searchDataDefault(), searchData: searchDataDefault(),
@ -277,9 +429,6 @@ export default {
shareLink: '', shareLink: '',
researchState: this.$d.ResearchRecord, researchState: this.$d.ResearchRecord,
qrcode: null, qrcode: null,
ImageManualVisible: false,
trialSiteSurveyId: null
} }
}, },
mounted() { mounted() {
@ -287,10 +436,6 @@ export default {
this.getSite() this.getSite()
}, },
methods: { methods: {
openImageManual() {
// if (!this.trialSiteSurveyId) return false
this.ImageManualVisible = true
},
// //
getList() { getList() {
this.loading = true this.loading = true
@ -343,7 +488,8 @@ export default {
copyLink() { copyLink() {
// //
this.$copyText( this.$copyText(
`${this.$t('trials:researchRecord:message:researchFormLink')}: ${this.shareLink `${this.$t('trials:researchRecord:message:researchFormLink')}: ${
this.shareLink
}` }`
) )
.then((res) => { .then((res) => {
@ -418,7 +564,6 @@ export default {
const trialId = this.trialId const trialId = this.trialId
this.shareLink = `${location.protocol}//${location.host}/researchLogin?trialId=${trialId}&lang=${this.$i18n.locale}` this.shareLink = `${location.protocol}//${location.host}/researchLogin?trialId=${trialId}&lang=${this.$i18n.locale}`
this.share_model.visible = true this.share_model.visible = true
// this.trialSiteSurveyId = this.list[0].Id
this.$nextTick(() => { this.$nextTick(() => {
this.creatQrCode() this.creatQrCode()
}) })
@ -466,21 +611,18 @@ export default {
padding-right: 20px; padding-right: 20px;
width: 50%; width: 50%;
position: relative; position: relative;
.shareLinkBtn { .shareLinkBtn {
position: absolute; position: absolute;
bottom: 0px; bottom: 0px;
left: 0px; left: 0px;
} }
} }
.shareCode { .shareCode {
width: 50%; width: 50%;
border-left: 1px solid #eee; border-left: 1px solid #eee;
display: flex; display: flex;
justify-content: center; justify-content: center;
flex-wrap: wrap; flex-wrap: wrap;
.qrCode { .qrCode {
width: 220px; width: 220px;
height: 220px; height: 220px;
@ -491,7 +633,6 @@ export default {
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
.codeBtnBox { .codeBtnBox {
margin-top: 20px; margin-top: 20px;
width: 100%; width: 100%;

View File

@ -21,7 +21,7 @@
<template slot-scope="scope"> <template slot-scope="scope">
<el-button type="text" @click=" <el-button type="text" @click="
go( go(
`/trialsResume?doctorId=${scope.row.DoctorId}&token=${token}&trialId=${$route.query.trialId}` `/trialsResume?doctorId=${scope.row.DoctorId}&token=${token}`
) )
">{{ scope.row.LastName }} / {{ scope.row.FirstName }}</el-button> ">{{ scope.row.LastName }} / {{ scope.row.FirstName }}</el-button>
</template> </template>

View File

@ -1,5 +1,10 @@
<template> <template>
<el-form v-if="isRender" ref="assessmentForm" :model="form" size="small"> <el-form
v-if="isRender"
ref="assessmentForm"
:model="form"
size="small"
>
<div class="base-dialog-body"> <div class="base-dialog-body">
<!-- <div v-for="qs in questions" :key="qs.Id"> <!-- <div v-for="qs in questions" :key="qs.Id">
<h4 v-if="qs.Type === 'group'">{{ qs.GroupName }}</h4> <h4 v-if="qs.Type === 'group'">{{ qs.GroupName }}</h4>
@ -37,9 +42,14 @@
</el-select> </el-select>
</el-form-item> </el-form-item>
</div> --> </div> -->
<AssessmentFormItem v-for="question of questions" :key="question.Id" :question="question" :question-form="form" <AssessmentFormItem
:readingTaskState="readingTaskState" @setFormItemData="setFormItemData" v-for="question of questions"
@resetFormItemData="resetFormItemData" /> :key="question.Id"
:question="question"
:question-form="form"
@setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData"
/>
</div> </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;">
@ -47,7 +57,11 @@
<el-button size="small" @click="handleCancel"> <el-button size="small" @click="handleCancel">
{{ $t('common:button:cancel') }} {{ $t('common:button:cancel') }}
</el-button> </el-button>
<el-button size="small" type="primary" v-if="readingTaskState < 2" @click="handleSave"> <el-button
size="small"
type="primary"
@click="handleSave"
>
{{ $t('common:button:save') }} {{ $t('common:button:save') }}
</el-button> </el-button>
</el-form-item> </el-form-item>
@ -71,14 +85,6 @@ export default {
default() { default() {
return [] return []
} }
},
readingTaskState: {
type: Number,
default: 0
},
additionalAssessmentsType: {
type: String,
default: 'edit'
} }
}, },
data() { data() {
@ -120,7 +126,7 @@ export default {
} }
const res = await submitTaskAdditionalQuestion(params) const res = await submitTaskAdditionalQuestion(params)
if (res.IsSuccess) { if (res.IsSuccess) {
this.$emit('sign', this.additionalAssessmentsType) this.$emit('sign')
} }
loading.close() loading.close()
} catch (e) { } catch (e) {

View File

@ -1,39 +1,67 @@
<template> <template>
<div> <div>
<div v-if="!!question.GroupName && question.Type === 'group'"> <div
v-if="!!question.GroupName && question.Type==='group'"
>
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;font-size: 15px;"> <h4 style="color: #ddd;padding: 5px 0px;margin: 0;font-size: 15px;">
{{ language==='en'?question.GroupEnName:question.GroupName }} {{ language==='en'?question.GroupEnName:question.GroupName }}
</h4> </h4>
</div> </div>
<template v-else> <template v-else>
<el-form-item :label="`${language === 'en' ? question.QuestionEnName : question.QuestionName}`" <el-form-item
:prop="question.Id" :rules="[ :label="`${language==='en'?question.QuestionEnName:question.QuestionName}`"
{ :prop="question.Id"
required: true, :rules="[
message: $t('common:ruleMessage:select'), trigger: ['blur', 'change'] { required: true,
}, message: $t('common:ruleMessage:select'), trigger: ['blur', 'change']},
]" :class="[question.Type === 'group' ? 'mb' : '']"> ]"
:class="[question.Type==='group'?'mb':'']"
>
<!-- 下拉框 --> <!-- 下拉框 -->
<el-select v-if="question.Type === 'select'" v-model="questionForm[question.Id]" clearable <el-select
@change="((val) => { formItemChange(val, question) })" :disabled="readingTaskState >= 2"> v-if="question.Type==='select'"
v-model="questionForm[question.Id]"
clearable
@change="((val)=>{formItemChange(val, question)})"
>
<template v-if="question.DictionaryCode"> <template v-if="question.DictionaryCode">
<el-option v-for="item of $d[question.DictionaryCode]" :key="item.id" :value="String(item.value)" <el-option
:label="item.label" /> v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:value="String(item.value)"
:label="item.label"
/>
</template> </template>
<template v-else> <template v-else>
<el-option v-for="val in question.TypeValue.split('|')" :key="val" :label="val" :value="val" /> <el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
:value="val"
/>
</template> </template>
</el-select> </el-select>
<!-- 单选 --> <!-- 单选 -->
<el-radio-group v-if="question.Type === 'radio'" v-model="questionForm[question.Id]" <el-radio-group
@change="((val) => { formItemChange(val, question) })" :disabled="readingTaskState >= 2"> v-if="question.Type==='radio'"
v-model="questionForm[question.Id]"
@change="((val)=>{formItemChange(val, question)})"
>
<template v-if="question.DictionaryCode"> <template v-if="question.DictionaryCode">
<el-radio v-for="item of $d[question.DictionaryCode]" :key="item.id" :label="String(item.value)"> <el-radio
v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:label="String(item.value)"
>
{{ item.label }} {{ item.label }}
</el-radio> </el-radio>
</template> </template>
<template v-else-if="question.TypeValue"> <template v-else-if="question.TypeValue">
<el-radio v-for="val in question.TypeValue.split('|')" :key="val" :label="val"> <el-radio
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
>
{{ val }} {{ val }}
</el-radio> </el-radio>
</template> </template>
@ -41,9 +69,14 @@
</el-form-item> </el-form-item>
</template> </template>
<AssessmentFormItem v-for="(item) in question.Childrens" :key="item.Id" :question="item" <AssessmentFormItem
:readingTaskState="readingTaskState" :question-form="questionForm" @setFormItemData="setFormItemData" v-for="(item) in question.Childrens"
@resetFormItemData="resetFormItemData" /> :key="item.Id"
:question="item"
:question-form="questionForm"
@setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData"
/>
</div> </div>
</template> </template>
<script> <script>
@ -62,10 +95,6 @@ export default {
default() { default() {
return [] return []
} }
},
readingTaskState: {
type: Number,
default: 0
} }
}, },
data() { data() {

View File

@ -1194,7 +1194,7 @@ export default {
cornerstoneTools.addToolForElement(element, cornerstoneTools.WwwcRegionTool) cornerstoneTools.addToolForElement(element, cornerstoneTools.WwwcRegionTool)
} }
if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.StackScrollMouseWheelTool)) { if (!cornerstoneTools.getToolForElement(element, cornerstoneTools.StackScrollMouseWheelTool)) {
cornerstoneTools.addToolForElement(element, cornerstoneTools.StackScrollMouseWheelTool, { configuration: { loop: true, } }) cornerstoneTools.addToolForElement(element, cornerstoneTools.StackScrollMouseWheelTool)
} }
cornerstoneTools.setToolActiveForElement(element, 'StackScrollMouseWheel', {}) cornerstoneTools.setToolActiveForElement(element, 'StackScrollMouseWheel', {})
@ -1307,9 +1307,6 @@ export default {
this.isFirstLoadIns = false this.isFirstLoadIns = false
// this.initWwc() // this.initWwc()
this.imageId = instanceId this.imageId = instanceId
if (this.isInitWwwc) {
this.resetWwwc()
}
} }
this.stack.instanceId = instanceId this.stack.instanceId = instanceId
@ -1329,6 +1326,9 @@ export default {
this.scrollSyncInfo.offset = 0 this.scrollSyncInfo.offset = 0
} }
this.renderMeasuredData(e) this.renderMeasuredData(e)
if (this.isInitWwwc) {
this.resetWwwc()
}
}, },
getOrientationMarker(element) { getOrientationMarker(element) {
const enabledElement = cornerstone.getEnabledElement(element) const enabledElement = cornerstone.getEnabledElement(element)
@ -1708,7 +1708,7 @@ export default {
resetWwwc() { resetWwwc() {
// console.log('resetWwwc') // console.log('resetWwwc')
this.isInitWwwc = true this.isInitWwwc = true
// this.toolState.viewportInvert = false this.toolState.viewportInvert = false
var viewport = cornerstone.getViewport(this.canvas) var viewport = cornerstone.getViewport(this.canvas)
// viewport.invert = false // viewport.invert = false
var image = cornerstone.getImage(this.canvas) var image = cornerstone.getImage(this.canvas)
@ -1839,9 +1839,6 @@ export default {
// console.log(toolName) // console.log(toolName)
// cornerstoneTools.setToolPassiveForElement(this.canvas, toolName) // cornerstoneTools.setToolPassiveForElement(this.canvas, toolName)
// }) // })
if (toolName === 'Wwwc') {
this.isInitWwwc = false
}
this.activeToolName = toolName this.activeToolName = toolName
this.$nextTick(() => { this.$nextTick(() => {
// console.log(cornerstoneTools.isToolActiveForElement(this.canvas, 'Bidirectional')) // console.log(cornerstoneTools.isToolActiveForElement(this.canvas, 'Bidirectional'))

View File

@ -214,25 +214,56 @@
<!-- @dblclick.native="reloadViewport('CT_AXIAL')" --> <!-- @dblclick.native="reloadViewport('CT_AXIAL')" -->
<div ref="dicomContainer" class="dicom-container box box_2_2" style="position: relative;" <div ref="dicomContainer" class="dicom-container box box_2_2" style="position: relative;"
@dblclick="reloadViewport"> @dblclick="reloadViewport">
<Viewport ref="CT_AXIAL" :index="1" :active-index="activeIndex" <Viewport
:is-reading-show-subject-info="isReadingShowSubjectInfo" :series-info="ctSeries" ref="CT_AXIAL"
:rendering-engine-id="renderingEngineId" viewport-id="CT_AXIAL" :volume="ctVolume" :index="1"
:measure-datas="measureDatas" :style="1 === activeIndex ? viewportStyle : {}" :active-index="activeIndex"
@upperRangeChange="upperRangeChange" /> :is-reading-show-subject-info="isReadingShowSubjectInfo"
<Viewport ref="PT_AXIAL" :index="2" :active-index="activeIndex" :series-info="ctSeries"
:is-reading-show-subject-info="isReadingShowSubjectInfo" :series-info="petSeries" :rendering-engine-id="renderingEngineId"
:rendering-engine-id="renderingEngineId" viewport-id="PT_AXIAL" :volume="ptVolume" viewport-id="CT_AXIAL" :volume="ctVolume"
:measure-datas="measureDatas" :style="2 === activeIndex ? viewportStyle : {}" :measure-datas="measureDatas"
@upperRangeChange="upperRangeChange" /> :style="1 === activeIndex ? viewportStyle : {}"
<Viewport ref="FUSION_AXIAL" :index="3" :active-index="activeIndex" @upperRangeChange="upperRangeChange"
:is-reading-show-subject-info="isReadingShowSubjectInfo" :series-info="petSeries" />
:rendering-engine-id="renderingEngineId" viewport-id="FUSION_AXIAL" :volume="ptVolume" <Viewport
:measure-datas="measureDatas" :rgb-preset-name="rgbPresetName" :style="3 === activeIndex ? viewportStyle : {}" ref="PT_AXIAL"
@upperRangeChange="upperRangeChange" /> :index="2"
<Viewport ref="PET_MIP_CORONAL" :index="4" :active-index="activeIndex" :active-index="activeIndex"
:is-reading-show-subject-info="isReadingShowSubjectInfo" :series-info="petSeries" :is-reading-show-subject-info="isReadingShowSubjectInfo"
:rendering-engine-id="renderingEngineId" viewport-id="PET_MIP_CORONAL" :measure-datas="measureDatas" :series-info="petSeries"
:style="4 === activeIndex ? viewportStyle : {}" @upperRangeChange="upperRangeChange" /> :rendering-engine-id="renderingEngineId"
viewport-id="PT_AXIAL"
:volume="ptVolume"
:measure-datas="measureDatas"
:style="2 === activeIndex ? viewportStyle : {}"
@upperRangeChange="upperRangeChange"
/>
<Viewport
ref="FUSION_AXIAL"
:index="3"
:active-index="activeIndex"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
:series-info="petSeries"
:rendering-engine-id="renderingEngineId"
viewport-id="FUSION_AXIAL"
:volume="ptVolume"
:measure-datas="measureDatas"
:rgb-preset-name="rgbPresetName"
:style="3 === activeIndex ? viewportStyle : {}"
@upperRangeChange="upperRangeChange"
/>
<Viewport
ref="PET_MIP_CORONAL"
:index="4"
:active-index="activeIndex"
:is-reading-show-subject-info="isReadingShowSubjectInfo"
:series-info="petSeries"
:rendering-engine-id="renderingEngineId"
viewport-id="PET_MIP_CORONAL" :measure-datas="measureDatas"
:style="4 === activeIndex ? viewportStyle : {}"
@upperRangeChange="upperRangeChange"
/>
</div> </div>
<!-- 表单 --> <!-- 表单 -->
<div class="form-container" style="overflow-y: auto;"> <div class="form-container" style="overflow-y: auto;">
@ -242,22 +273,19 @@
<span style="margin-left:5px;">{{ taskBlindName }}</span> <span style="margin-left:5px;">{{ taskBlindName }}</span>
</h3> </h3>
<TableQuestions ref="tableQuestions" @handleReadingChart="handleReadingChart" /> <TableQuestions ref="tableQuestions" />
<Questions ref="questions" @setNonTargetMeasurementStatus="setNonTargetMeasurementStatus" <Questions ref="questions" @setNonTargetMeasurementStatus="setNonTargetMeasurementStatus" />
@handleReadingChart="handleReadingChart" />
</div> </div>
</div> </div>
</div> </div>
<el-dialog v-if="customWwc.visible" :visible.sync="customWwc.visible" :close-on-click-modal="false" <el-dialog v-if="customWwc.visible" :visible.sync="customWwc.visible" :close-on-click-modal="false"
:title="customWwc.title" width="400px" custom-class="base-dialog-wrapper"> :title="customWwc.title" width="400px" custom-class="base-dialog-wrapper">
<custom-wwwc-form :ww="activeCanvasWW" :wc="activeCanvasWC" @close="customWwc.visible = false" <custom-wwwc-form :ww="activeCanvasWW" :wc="activeCanvasWC" @close="customWwc.visible = false" @setWwwc="setWwwc" />
@setWwwc="setWwwc" />
</el-dialog> </el-dialog>
<el-dialog :visible.sync="fusion.visible" :close-on-click-modal="false" :title="$t('trials:lugano:button:record')" <el-dialog :visible.sync="fusion.visible" :close-on-click-modal="false" :title="$t('trials:lugano:button:record')"
width="850px"> width="850px">
<fusion-form @close="fusion.visible = false" /> <fusion-form @close="fusion.visible = false" />
</el-dialog> </el-dialog>
<readingChart ref="readingChart" />
</div> </div>
</template> </template>
<script> <script>
@ -305,7 +333,6 @@ import vtkPiecewiseFunction from '@kitware/vtk.js/Common/DataModel/PiecewiseFunc
// import vtkOrientationMarkerWidget from '@kitware/vtk.js/Interaction/Widgets/OrientationMarkerWidget' // import vtkOrientationMarkerWidget from '@kitware/vtk.js/Interaction/Widgets/OrientationMarkerWidget'
import { mat4, vec3 } from 'gl-matrix' import { mat4, vec3 } from 'gl-matrix'
import html2canvas from 'html2canvas' import html2canvas from 'html2canvas'
import readingChart from '@/components/readingChart'
// import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction' // import vtkColorTransferFunction from '@kitware/vtk.js/Rendering/Core/ColorTransferFunction'
// import vtkMath from '@kitware/vtk.js/Common/Core/Math' // import vtkMath from '@kitware/vtk.js/Common/Core/Math'
// import CircleROITool from './tools/CircleROITool' // import CircleROITool from './tools/CircleROITool'
@ -351,7 +378,6 @@ const ctVolumeName = 'CT_VOLUME_ID' // Id of the volume less loader prefix
const ctVolumeId = `${volumeLoaderScheme}:${ctVolumeName}` // VolumeId with loader id + volume id const ctVolumeId = `${volumeLoaderScheme}:${ctVolumeName}` // VolumeId with loader id + volume id
const ptVolumeName = 'PT_VOLUME_ID' const ptVolumeName = 'PT_VOLUME_ID'
const ptVolumeId = `${volumeLoaderScheme}:${ptVolumeName}` const ptVolumeId = `${volumeLoaderScheme}:${ptVolumeName}`
const ptVolumeId2 = `${volumeLoaderScheme}:${ptVolumeName}2`
const ctToolGroupId = 'CT_TOOLGROUP_ID' const ctToolGroupId = 'CT_TOOLGROUP_ID'
const ptToolGroupId = 'PT_TOOLGROUP_ID' const ptToolGroupId = 'PT_TOOLGROUP_ID'
const fusionToolGroupId = 'FUSION_TOOLGROUP_ID' const fusionToolGroupId = 'FUSION_TOOLGROUP_ID'
@ -394,8 +420,7 @@ export default {
Questions, Questions,
TableQuestions, TableQuestions,
CustomWwwcForm, CustomWwwcForm,
FusionForm, FusionForm
readingChart
}, },
data() { data() {
return { return {
@ -417,10 +442,8 @@ export default {
renderingEngineId: renderingEngineId, renderingEngineId: renderingEngineId,
ctVolumeId: `${volumeLoaderScheme}:${ctVolumeName}`, ctVolumeId: `${volumeLoaderScheme}:${ctVolumeName}`,
ptVolumeId: `${volumeLoaderScheme}:${ptVolumeName}`, ptVolumeId: `${volumeLoaderScheme}:${ptVolumeName}`,
ptVolumeId2: `${volumeLoaderScheme}:${ptVolumeName}2`,
ctVolume: null, ctVolume: null,
ptVolume: null, ptVolume: null,
ptVolume2: null,
isReadingShowSubjectInfo: false, isReadingShowSubjectInfo: false,
subjectCode: '', subjectCode: '',
taskBlindName: '', taskBlindName: '',
@ -559,7 +582,6 @@ export default {
this.screenshotWindow = window.open(routeData.href, '_blank') this.screenshotWindow = window.open(routeData.href, '_blank')
}) })
window.addEventListener('beforeunload', e => { this.beforeUnloadHandler(e) }) window.addEventListener('beforeunload', e => { this.beforeUnloadHandler(e) })
document.addEventListener("click", this.foo);
}, },
beforeDestroy() { beforeDestroy() {
if (this.screenshotWindow) { if (this.screenshotWindow) {
@ -582,21 +604,7 @@ export default {
window.removeEventListener('beforeunload', e => { this.beforeUnloadHandler(e) }) window.removeEventListener('beforeunload', e => { this.beforeUnloadHandler(e) })
}, },
methods: { methods: {
handleReadingChart(row) {
let { e, data } = row
let obj = Object.assign({}, data)
obj.TrialId = this.$route.query.trialId
obj.VisitTaskId = this.$route.query.visitTaskId
let zIndex = 9
if (obj.RowIndex) {
zIndex = 9999
}
this.$refs.readingChart.init(e, obj, zIndex)
},
foo() {
if (!this.$refs.readingChart) return false
this.$refs.readingChart.foo()
},
initPage() { initPage() {
const resizeObserver = new ResizeObserver(() => { const resizeObserver = new ResizeObserver(() => {
if (element_ct.style.width) { if (element_ct.style.width) {
@ -991,9 +999,6 @@ export default {
this.ptVolume = await volumeLoader.createAndCacheVolume(ptVolumeId, { this.ptVolume = await volumeLoader.createAndCacheVolume(ptVolumeId, {
imageIds: ptImageIds imageIds: ptImageIds
}) })
this.ptVolume2 = await volumeLoader.createAndCacheVolume(ptVolumeId2, {
imageIds: ptImageIds
})
// //
this.resetTimer() this.resetTimer()
} catch (error) { } catch (error) {
@ -1500,10 +1505,6 @@ export default {
await setVolumesForViewports( await setVolumesForViewports(
renderingEngine, renderingEngine,
[ [
{
volumeId: ptVolumeId2,
callback: setPetColorMapTransferFunctionForVolumeActor
},
{ {
volumeId: ctVolumeId, volumeId: ctVolumeId,
callback: setCtTransferFunctionForVolumeActor callback: setCtTransferFunctionForVolumeActor

View File

@ -1,6 +1,8 @@
<template> <template>
<div> <div>
<div v-if="!!question.GroupName && question.Type === 'group'"> <div
v-if="!!question.GroupName && question.Type==='group'"
>
<h4 style="color: #ddd;padding: 5px 0px;margin: 0;"> <h4 style="color: #ddd;padding: 5px 0px;margin: 0;">
{{ language==='en'?question.GroupEnName:question.GroupName }} {{ language==='en'?question.GroupEnName:question.GroupName }}
</h4> </h4>
@ -9,211 +11,295 @@
<template v-else> <template v-else>
<el-form-item <el-form-item
v-if="(question.ShowQuestion===1 && question.ParentTriggerValueList.includes(String(questionForm[question.ParentId]))) || question.ShowQuestion===0" v-if="(question.ShowQuestion===1 && question.ParentTriggerValueList.includes(String(questionForm[question.ParentId]))) || question.ShowQuestion===0"
:label="`${question.QuestionName}`" :prop="question.Id" :rules="[ :label="`${question.QuestionName}`"
{ :prop="question.Id"
required: (question.IsRequired === 0 || (question.IsRequired === 1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type !== 'group' && question.Type !== 'summary', :rules="[
message: ['radio', 'select', 'checkbox'].includes(question.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change'] { required: (question.IsRequired === 0 || (question.IsRequired ===1 && question.RelevanceId && (questionForm[question.RelevanceId] === question.RelevanceValue))) && question.Type!=='group' && question.Type!=='summary',
}, message: ['radio', 'select', 'checkbox'].includes(question.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change']},
]" :class="[question.Type === 'group' ? 'mb' : question.Type === 'upload' ? 'uploadWrapper' : '']"> ]"
:class="[question.Type==='group'?'mb':question.Type==='upload'?'uploadWrapper':'']"
>
<template v-if="question.QuestionType === 51 || question.QuestionType === 52"> <template v-if="question.QuestionType === 51 || question.QuestionType === 52">
<!-- question.QuestionType === 51 || question.QuestionType === 52 --> <!-- question.QuestionType === 51 || question.QuestionType === 52 -->
<div style="display: flex;flex-direction: row;justify-content: flex-start;"> <div style="display: flex;flex-direction: row;justify-content: flex-start;">
<div style="display: flex;justify-content: space-between;" v-if="question.Type === 'calculation'"> <el-input
<el-input v-model="questionForm[question.Id]" disabled style="width: 120px;"> v-if="question.Type==='calculation'"
v-model="questionForm[question.Id]"
disabled
style="width: 120px;"
>
<template v-if="question.Unit" slot="append"> <template v-if="question.Unit" slot="append">
{{ $fd('ValueUnit', parseInt(question.Unit)) }} {{ $fd('ValueUnit', parseInt(question.Unit)) }}
</template> </template>
<svg-icon v-if="question.ShowChartTypeEnum > 0" icon-class="readingChart"
class="svg-icon svg-readingChart" @click.stop="(e) => handleReadingChart({
e,
data: {
QuestionId: question.Id,
RowIndex: questionForm.RowIndex,
QuestionName: question.QuestionName
}
})" />
</el-input> </el-input>
</div>
<!-- 测量 --> <!-- 测量 -->
<el-button <el-button v-if="(!questionForm[question.Id] && ((question.QuestionType === 51 && liverIsInsideVolume) || (question.QuestionType === 52 && lungIsInsideVolume)) && readingTaskState!== 2)" size="mini" type="text" @click="addAnnotation(question)">{{ $t('trials:lugano:button:addAnnotation') }}</el-button>
v-if="(!questionForm[question.Id] && ((question.QuestionType === 51 && liverIsInsideVolume) || (question.QuestionType === 52 && lungIsInsideVolume)) && readingTaskState !== 2)"
size="mini" type="text" @click="addAnnotation(question)">{{ $t('trials:lugano:button:addAnnotation')
}}</el-button>
<!-- 清除标记 --> <!-- 清除标记 -->
<el-button <el-button v-if="(questionForm[question.Id] || (question.QuestionType === 51 && !liverIsInsideVolume) || (question.QuestionType === 52 && !lungIsInsideVolume)) && readingTaskState!== 2" size="mini" type="text" style="padding: 7px 5px;margin-left:5px;" @click="removeAnnotation(question)">{{ $t('trials:lugano:button:clearAnnotation') }}</el-button>
v-if="(questionForm[question.Id] || (question.QuestionType === 51 && !liverIsInsideVolume) || (question.QuestionType === 52 && !lungIsInsideVolume)) && readingTaskState !== 2"
size="mini" type="text" style="padding: 7px 5px;margin-left:5px;" @click="removeAnnotation(question)">{{
$t('trials:lugano:button:clearAnnotation') }}</el-button>
<!-- 定位 --> <!-- 定位 -->
<el-button <el-button
v-if="(questionForm[question.Id] || (question.QuestionType === 51 && !liverIsInsideVolume) || (question.QuestionType === 52 && !lungIsInsideVolume))" v-if="(questionForm[question.Id] || (question.QuestionType === 51 && !liverIsInsideVolume) || (question.QuestionType === 52 && !lungIsInsideVolume))"
size="mini" type="text" style="padding: '7px 5px';margin-left:-5px;" size="mini"
@click="locateAnnotation(question)">{{ type="text"
$t('trials:lugano:button:locateAnnotation') }}</el-button> style="padding: '7px 5px';margin-left:-5px;"
@click="locateAnnotation(question)"
>{{ $t('trials:lugano:button:locateAnnotation') }}</el-button>
<!-- 保存 --> <!-- 保存 -->
<el-button v-if="readingTaskState !== 2 && question.SaveEnum === 1" size="mini" type="text" <el-button v-if="readingTaskState!== 2 && question.SaveEnum === 1" size="mini" type="text" style="padding: '7px 5px';margin-left:-5px;" @click="saveAnnotation(question)">
style="padding: '7px 5px';margin-left:-5px;" @click="saveAnnotation(question)">
<!-- 未保存 --> <!-- 未保存 -->
<el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom"> <el-tooltip class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom">
<i class="el-icon-warning" style="color:red" /> <i class="el-icon-warning" style="color:red" />
</el-tooltip> </el-tooltip>
{{ $t('common:button:save') }} {{ $t('common:button:save') }}
</el-button> </el-button>
<el-button v-if="!question.IsBaseLineTask" size="mini" type="text" <el-button v-if="!question.IsBaseLineTask" size="mini" type="text" style="padding: '7px 5px';margin-left:-5px;" @click="viewAnnotations(question)">{{ $t('trials:lugano:button:suvscreenshot') }}</el-button>
style="padding: '7px 5px';margin-left:-5px;" @click="viewAnnotations(question)">{{
$t('trials:lugano:button:suvscreenshot') }}</el-button>
</div> </div>
</template> </template>
<template v-else-if="question.QuestionType === 53"> <template v-else-if="question.QuestionType === 53">
<div style="display: flex;justify-content: space-between;" v-if="question.Type === 'calculation'"> <el-input
<el-input v-model="questionForm[question.Id]" disabled> v-if="question.Type==='calculation'"
v-model="questionForm[question.Id]"
disabled
>
<template v-if="question.Unit" slot="append"> <template v-if="question.Unit" slot="append">
{{ $fd('ValueUnit', parseInt(question.Unit)) }} {{ $fd('ValueUnit', parseInt(question.Unit)) }}
</template> </template>
</el-input> </el-input>
<svg-icon v-if="question.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart"
@click.stop="(e) => handleReadingChart({
e,
data: {
QuestionId: question.Id,
RowIndex: questionForm.RowIndex,
QuestionName: question.QuestionName
}
})" />
</div>
</template> </template>
<template v-else-if="question.QuestionType === 55"> <template v-else-if="question.QuestionType === 55">
<el-select v-model="questionForm[question.Id]" :disabled="readingTaskState >= 2" clearable <el-select
@change="((val) => { formItemChange(val, question) })"> v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 "
clearable
@change="((val)=>{formItemChange(val, question)})"
>
<el-option-group <el-option-group
:label="!isNaN(parseFloat(question.LastTaskAnswer)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(question.DictionaryCode, parseFloat(question.LastTaskAnswer))}` : ''"> :label="!isNaN(parseFloat(question.LastTaskAnswer)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(question.DictionaryCode,parseFloat(question.LastTaskAnswer))}` : ''"
>
<template> <template>
<el-option v-for="item of $d[question.DictionaryCode]" :key="item.id" :value="String(item.value)" <el-option
:label="item.label" /> v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:value="String(item.value)"
:label="item.label"
/>
</template> </template>
</el-option-group> </el-option-group>
</el-select> </el-select>
</template> </template>
<template v-else-if="question.QuestionType === 56"> <template v-else-if="question.QuestionType === 56">
<el-select v-model="questionForm[question.Id]" :disabled="readingTaskState >= 2" clearable <el-select
@change="((val) => { formItemChange(val, question) })"> v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 "
clearable
@change="((val)=>{formItemChange(val, question)})"
>
<el-option-group <el-option-group
:label="!isNaN(parseFloat(question.LastTaskAnswer)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${parseFloat(question.LastTaskAnswer) === 5 ? 'NA' : $fd(question.DictionaryCode, parseFloat(question.LastTaskAnswer))}` : ''"> :label="!isNaN(parseFloat(question.LastTaskAnswer)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${parseFloat(question.LastTaskAnswer) === 5 ? 'NA' : $fd(question.DictionaryCode,parseFloat(question.LastTaskAnswer))}` : ''"
>
<template v-if="pet5PS*1=== -1"> <template v-if="pet5PS*1=== -1">
<el-option v-for="item of $d[question.DictionaryCode]" v-show="item.value !== 4" :key="item.id" <el-option
:value="String(item.value)" :label="item.label" /> v-for="item of $d[question.DictionaryCode]"
v-show="item.value !== 4"
:key="item.id"
:value="String(item.value)"
:label="item.label"
/>
</template> </template>
<template v-else> <template v-else>
<el-option v-for="item of $d[question.DictionaryCode]" :key="item.id" :value="String(item.value)" <el-option
:label="item.label" /> v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:value="String(item.value)"
:label="item.label"
/>
</template> </template>
</el-option-group> </el-option-group>
</el-select> </el-select>
</template> </template>
<template v-else-if="question.QuestionType === 57"> <template v-else-if="question.QuestionType === 57">
<el-select v-model="questionForm[question.Id]" :disabled="readingTaskState >= 2" clearable <el-select
@change="((val) => { formItemChange(val, question) })"> v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 "
clearable
@change="((val)=>{formItemChange(val, question)})"
>
<el-option-group <el-option-group
:label="!isNaN(parseFloat(question.LastTaskAnswer)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(question.DictionaryCode, parseFloat(question.LastTaskAnswer))}` : ''"> :label="!isNaN(parseFloat(question.LastTaskAnswer)) ? `${$t('trials:dicomReading:tip:lastVisitStatus')} ${$fd(question.DictionaryCode,parseFloat(question.LastTaskAnswer))}` : ''"
>
<template v-if="pet5PS*1=== -1"> <template v-if="pet5PS*1=== -1">
<el-option v-for="item of $d[question.DictionaryCode]" v-show="item.value !== 1" :key="item.id" <el-option
:value="String(item.value)" :label="item.label" /> v-for="item of $d[question.DictionaryCode]"
v-show="item.value !== 1"
:key="item.id"
:value="String(item.value)"
:label="item.label"
/>
</template> </template>
<template v-else> <template v-else>
<el-option v-for="item of $d[question.DictionaryCode]" :key="item.id" :value="String(item.value)" <el-option
:label="item.label" /> v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:value="String(item.value)"
:label="item.label"
/>
</template> </template>
</el-option-group> </el-option-group>
</el-select> </el-select>
</template> </template>
<!-- 输入框 --> <!-- 输入框 -->
<el-input v-else-if="question.Type === 'input'" v-model="questionForm[question.Id]" <el-input
:disabled="readingTaskState >= 2" /> v-else-if="question.Type==='input'"
v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2"
/>
<!-- 多行文本输入框 --> <!-- 多行文本输入框 -->
<el-input v-else-if="question.Type === 'textarea'" v-model="questionForm[question.Id]" type="textarea" <el-input
:autosize="{ minRows: 2, maxRows: 4 }" maxlength="500" :disabled="readingTaskState >= 2" /> v-else-if="question.Type==='textarea'"
v-model="questionForm[question.Id]"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
maxlength="500"
:disabled="readingTaskState >= 2"
/>
<!-- 下拉框 --> <!-- 下拉框 -->
<el-select v-else-if="question.Type === 'select'" v-model="questionForm[question.Id]" <el-select
v-else-if="question.Type==='select'"
v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2 || ((question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode) || question.QuestionType === 50" :disabled="readingTaskState >= 2 || ((question.TableQuestionType === 2 || question.QuestionGenre === 2) && !!question.DictionaryCode) || question.QuestionType === 50"
clearable @change="((val) => { formItemChange(val, question) })"> clearable
@change="((val)=>{formItemChange(val, question)})"
>
<template v-if="question.TableQuestionType === 1"> <template v-if="question.TableQuestionType === 1">
<el-option v-for="item in organList" :key="item.Id" :label="item[question.DataTableColumn]" <el-option
:value="item[question.DataTableColumn]" /> v-for="item in organList"
:key="item.Id"
:label="item[question.DataTableColumn]"
:value="item[question.DataTableColumn]"
/>
</template> </template>
<template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3"> <template v-else-if="question.TableQuestionType === 3 || question.QuestionGenre === 3">
<el-option v-for="item of $d[question.DictionaryCode]" :key="item.id" :value="String(item.value)" <el-option
:label="item.label" /> v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:value="String(item.value)"
:label="item.label"
/>
</template> </template>
<template <template v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode">
v-else-if="(question.TableQuestionType === 2 || question.QuestionGenre === 2) && question.DictionaryCode"> <el-option
<el-option v-for="item of $d[question.DictionaryCode]" :key="item.id" :value="String(item.value)" v-for="item of $d[question.DictionaryCode]"
:label="item.label" /> :key="item.id"
:value="String(item.value)"
:label="item.label"
/>
</template> </template>
<template v-else> <template v-else>
<el-option v-for="val in question.TypeValue.split('|')" :key="val" :label="val" :value="val" /> <el-option
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
:value="val"
/>
</template> </template>
</el-select> </el-select>
<!-- 单选 --> <!-- 单选 -->
<el-radio-group v-else-if="question.Type === 'radio'" v-model="questionForm[question.Id]" <el-radio-group
:disabled="readingTaskState >= 2" @change="((val) => { formItemChange(val, question) })"> v-else-if="question.Type==='radio'"
v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2"
@change="((val)=>{formItemChange(val, question)})"
>
<template v-if="question.DictionaryCode"> <template v-if="question.DictionaryCode">
<el-radio v-for="item of $d[question.DictionaryCode]" :key="item.id" :label="String(item.value)"> <el-radio
v-for="item of $d[question.DictionaryCode]"
:key="item.id"
:label="String(item.value)"
>
{{ item.label }} {{ item.label }}
</el-radio> </el-radio>
</template> </template>
<template v-else-if="question.TypeValue"> <template v-else-if="question.TypeValue">
<el-radio v-for="val in question.TypeValue.split('|')" :key="val" :label="val"> <el-radio
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
>
{{ val }} {{ val }}
</el-radio> </el-radio>
</template> </template>
</el-radio-group> </el-radio-group>
<!-- 复选框 --> <!-- 复选框 -->
<el-checkbox-group v-else-if="question.Type === 'checkbox'" v-model="questionForm[question.Id]" <el-checkbox-group
:disabled="readingTaskState >= 2"> v-else-if="question.Type==='checkbox'"
<el-checkbox v-for="val in question.TypeValue.split('|')" :key="val" :label="val"> v-model="questionForm[question.Id]"
:disabled="readingTaskState >= 2"
>
<el-checkbox
v-for="val in question.TypeValue.split('|')"
:key="val"
:label="val"
>
{{ val }} {{ val }}
</el-checkbox> </el-checkbox>
</el-checkbox-group> </el-checkbox-group>
<!-- 数值 --> <!-- 数值 -->
<el-input-number
<div style="display: flex;justify-content: space-between;" v-else-if="question.Type==='number'"
v-else-if="question.Type === 'calculation' || question.Type === 'number'"> v-model="questionForm[question.Id]"
<el-input-number v-if="question.Type === 'number'" v-model="questionForm[question.Id]" :disabled="readingTaskState >= 2"
:disabled="readingTaskState >= 2" /> />
<el-input v-model="questionForm[question.Id]" disabled v-else /> <el-input
<svg-icon v-if="question.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart" v-else-if="question.Type==='calculation'"
@click.stop="(e) => handleReadingChart({ v-model="questionForm[question.Id]"
e, disabled
data: { />
QuestionId: question.Id,
RowIndex: questionForm.RowIndex,
QuestionName: question.QuestionName
}
})" />
</div>
<!-- 上传图像 --> <!-- 上传图像 -->
<el-upload v-if="question.Type === 'upload'" action :accept="accept" :limit="question.ImageCount" <el-upload
:on-preview="handlePictureCardPreview" :before-upload="handleBeforeUpload" :http-request="uploadScreenshot" v-if="question.Type==='upload'"
list-type="picture-card" :on-remove="handleRemove" :file-list="fileList" action
:class="{ disabled: fileList.length >= question.ImageCount }" :disabled="readingTaskState >= 2"> :accept="accept"
:limit="question.ImageCount"
:on-preview="handlePictureCardPreview"
:before-upload="handleBeforeUpload"
:http-request="uploadScreenshot"
list-type="picture-card"
:on-remove="handleRemove"
:file-list="fileList"
:class="{disabled:fileList.length >= question.ImageCount}"
:disabled="readingTaskState >= 2"
>
<i slot="default" class="el-icon-plus" /> <i slot="default" class="el-icon-plus" />
<div slot="file" slot-scope="{file}"> <div slot="file" slot-scope="{file}">
<img class="el-upload-list__item-thumbnail" :src="OSSclientConfig.basePath + file.url" alt=""> <img
class="el-upload-list__item-thumbnail"
:src="OSSclientConfig.basePath + file.url"
alt=""
>
<span class="el-upload-list__item-actions"> <span class="el-upload-list__item-actions">
<span class="el-upload-list__item-preview" @click="handlePictureCardPreview(file)"> <span
class="el-upload-list__item-preview"
@click="handlePictureCardPreview(file)"
>
<i class="el-icon-zoom-in" /> <i class="el-icon-zoom-in" />
</span> </span>
<span v-if="readingTaskState < 2" class="el-upload-list__item-delete" @click="handleRemove(file)"> <span
v-if="readingTaskState < 2"
class="el-upload-list__item-delete"
@click="handleRemove(file)"
>
<i class="el-icon-delete" /> <i class="el-icon-delete" />
</span> </span>
</span> </span>
</div> </div>
</el-upload> </el-upload>
<el-dialog v-if="question.Type === 'upload'" append-to-body :visible.sync="imgVisible" width="600px"> <el-dialog
v-if="question.Type==='upload'"
append-to-body
:visible.sync="imgVisible"
width="600px"
>
<el-image :src="imageUrl" width="100%"> <el-image :src="imageUrl" width="100%">
<div slot="placeholder" class="image-slot"> <div slot="placeholder" class="image-slot">
加载中<span class="dot">...</span> 加载中<span class="dot">...</span>
@ -223,11 +309,19 @@
</el-form-item> </el-form-item>
</template> </template>
<template v-for="item of question.Childrens"> <template v-for="item of question.Childrens">
<QuestionItem v-if="item.QuestionClassify === 0" :key="item.Id" :question="item" <QuestionItem
:reading-task-state="readingTaskState" :question-form="questionForm" :visit-task-id="visitTaskId" v-if="item.QuestionClassify === 0"
:pet5p-s="pet5PS" :lung-is-inside-volume="lungIsInsideVolume" :liver-is-inside-volume="liverIsInsideVolume" :key="item.Id"
@setFormItemData="setFormItemData" @resetFormItemData="resetFormItemData" :question="item"
@handleReadingChart="handleReadingChart" /> :reading-task-state="readingTaskState"
:question-form="questionForm"
:visit-task-id="visitTaskId"
:pet5p-s="pet5PS"
:lung-is-inside-volume="lungIsInsideVolume"
:liver-is-inside-volume="liverIsInsideVolume"
@setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData"
/>
</template> </template>
</div> </div>
</template> </template>
@ -312,9 +406,6 @@ export default {
} }
}, },
methods: { methods: {
handleReadingChart(e) {
this.$emit('handleReadingChart', e)
},
formItemChange(v, question) { formItemChange(v, question) {
if (question.QuestionType === 55) { if (question.QuestionType === 55) {
this.$emit('setFormItemData', { key: question.Id, val: v }) this.$emit('setFormItemData', { key: question.Id, val: v })
@ -415,28 +506,22 @@ export default {
.mb{ .mb{
margin-bottom: 0px; margin-bottom: 0px;
} }
.disabled{ .disabled{
::v-deep .el-upload--picture-card { ::v-deep .el-upload--picture-card {
display: none; display: none;
} }
} }
.uploadWrapper{ .uploadWrapper{
display: flex; display: flex;
flex-direction: column; flex-direction: column;
align-items: flex-start; align-items: flex-start;
} }
::v-deep .el-input.is-disabled .el-input__inner{ ::v-deep .el-input.is-disabled .el-input__inner{
background-color: #646464a1; background-color: #646464a1;
} }
::v-deep .el-input-group__append, .el-input-group__prepend{
::v-deep .el-input-group__append,
.el-input-group__prepend {
padding: 0 5px; padding: 0 5px;
} }
::v-deep .el-select.is-disabled .el-input__inner{ ::v-deep .el-select.is-disabled .el-input__inner{
background-color: #646464a1; background-color: #646464a1;
} }

View File

@ -1,17 +1,29 @@
<template> <template>
<div v-loading="loading" class="ecrf-wrapper"> <div v-loading="loading" class="ecrf-wrapper">
<el-form v-if="questions.length > 0" ref="questions" size="small" :model="questionForm"> <el-form
v-if="questions.length > 0"
ref="questions"
size="small"
:model="questionForm"
>
<template v-for="question of questions"> <template v-for="question of questions">
<QuestionItem v-if="question.QuestionClassify === 0" :key="question.Id" :question="question" <QuestionItem
:question-form="questionForm" :reading-task-state="readingTaskState" :visit-task-id="visitTaskId" v-if="question.QuestionClassify === 0"
:pet5p-s="questionForm[pet5PSId]" :lung-is-inside-volume="lungIsInsideVolume" :key="question.Id"
:liver-is-inside-volume="liverIsInsideVolume" @setFormItemData="setFormItemData" :question="question"
@resetFormItemData="resetFormItemData" @handleReadingChart="handleReadingChart" /> :question-form="questionForm"
:reading-task-state="readingTaskState"
:visit-task-id="visitTaskId"
:pet5p-s="questionForm[pet5PSId]"
:lung-is-inside-volume="lungIsInsideVolume"
:liver-is-inside-volume="liverIsInsideVolume"
@setFormItemData="setFormItemData"
@resetFormItemData="resetFormItemData"
/>
</template> </template>
<el-form-item v-if="readingTaskState < 2"> <el-form-item v-if="readingTaskState < 2">
<div style="text-align:right"> <div style="text-align:right">
<el-button :disabled="!questionFormChangeState" :type="questionFormChangeState ? 'primary' : null" size="mini" <el-button :disabled="!questionFormChangeState" :type="questionFormChangeState ? 'primary' : null" size="mini" @click="handleSave">{{ $t('common:button:save') }}</el-button>
@click="handleSave">{{ $t('common:button:save') }}</el-button>
</div> </div>
</el-form-item> </el-form-item>
</el-form> </el-form>
@ -120,9 +132,6 @@ export default {
FusionEvent.$off('locateAnnotation') FusionEvent.$off('locateAnnotation')
}, },
methods: { methods: {
handleReadingChart(e) {
this.$emit('handleReadingChart', e)
},
getQuestions1() { getQuestions1() {
var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId) var idx = this.visitTaskList.findIndex(i => i.VisitTaskId === this.visitTaskId)
@ -756,37 +765,33 @@ export default {
color: #c3c3c3; color: #c3c3c3;
text-align: left; text-align: left;
} }
::v-deep .el-input__inner{ ::v-deep .el-input__inner{
background-color: transparent; background-color: transparent;
color: #ddd; color: #ddd;
border: 1px solid #5e5e5e; border: 1px solid #5e5e5e;
} }
::v-deep .el-textarea__inner{ ::v-deep .el-textarea__inner{
background-color: transparent; background-color: transparent;
color: #ddd; color: #ddd;
border: 1px solid #5e5e5e; border: 1px solid #5e5e5e;
} }
::v-deep .el-form-item{ ::v-deep .el-form-item{
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: flex-start; justify-content: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
} }
::v-deep .el-form-item__content{ ::v-deep .el-form-item__content{
flex: 1; flex: 1;
} }
::v-deep .el-button--mini, .el-button--mini.is-round {
::v-deep .el-button--mini,
.el-button--mini.is-round {
padding: 7px 10px; padding: 7px 10px;
} }
.el-form-item__content
.el-form-item__content .el-select { .el-select{
width: 100%; width: 100%;
} }
} }
</style> </style>

View File

@ -1,6 +1,12 @@
<template> <template>
<el-form v-if="isRender" ref="measurementForm" v-loading="loading" :model="questionForm" size="mini" <el-form
class="measurement-form"> v-if="isRender"
ref="measurementForm"
v-loading="loading"
:model="questionForm"
size="mini"
class="measurement-form"
>
<div class="base-dialog-body"> <div class="base-dialog-body">
<div style="display: flex;justify-content: space-between;"> <div style="display: flex;justify-content: space-between;">
<h3 v-if="lesionName" style="color: #ddd;padding: 5px 0px;margin: 0;"> <h3 v-if="lesionName" style="color: #ddd;padding: 5px 0px;margin: 0;">
@ -13,151 +19,184 @@
</div> </div>
</div> </div>
<el-form-item :label="$t('trials:reading:title:lesionType')" prop="LesionType" :rules="[ <el-form-item
:label="$t('trials:reading:title:lesionType')"
prop="LesionType"
:rules="[
{ required:true,message: $t('common:ruleMessage:select'), trigger: ['blur']}, { required:true,message: $t('common:ruleMessage:select'), trigger: ['blur']},
]"> ]"
>
<!-- 下拉框 --> <!-- 下拉框 -->
<el-select v-model="questionForm.LesionType" filterable <el-select
v-model="questionForm.LesionType"
filterable
:disabled="!isCurrentTask || readingTaskState>=2 || !isBaseLineTask" :disabled="!isCurrentTask || readingTaskState>=2 || !isBaseLineTask"
@change="((val) => { lesionTypeChange(val) })"> @change="((val)=>{lesionTypeChange(val)})"
>
<el-option v-for="item of $d.LesionType" v-show="!(isBaseLineTask && item.value === 2)" :key="item.id" <el-option
:value="item.value" :label="item.label" /> v-for="item of $d.LesionType"
v-show="!(isBaseLineTask && item.value === 2)"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</el-select> </el-select>
</el-form-item> </el-form-item>
<template v-for="qs in questions"> <template v-for="qs in questions">
<el-form-item v-if="qs.ShowQuestion !== 2 && qs.QuestionClassify === 0" :key="qs.Id" <el-form-item
:label="`${qs.QuestionName}`" :prop="qs.Id" :rules="[ v-if="qs.ShowQuestion!==2 && qs.QuestionClassify === 0"
{ :key="qs.Id"
required: (qs.IsRequired === 0 || (qs.IsRequired === 1 && qs.RelevanceId && (questionForm[qs.RelevanceId] === qs.RelevanceValue)) || (qs.QuestionMark === 6 && questionForm.IsCanEditPosition === true) || (questionForm.IsCanEditPosition && qs.QuestionMark === 10)) && qs.Type !== 'group' && qs.Type !== 'summary', :label="`${qs.QuestionName}`"
message: ['radio', 'select', 'checkbox'].includes(qs.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur', 'change'] :prop="qs.Id"
}, :rules="[
]"> { required: (qs.IsRequired === 0 || (qs.IsRequired ===1 && qs.RelevanceId && (questionForm[qs.RelevanceId] === qs.RelevanceValue)) || (qs.QuestionMark === 6 && questionForm.IsCanEditPosition === true) || (questionForm.IsCanEditPosition && qs.QuestionMark === 10)) && qs.Type!=='group' && qs.Type!=='summary',
message:['radio', 'select', 'checkbox'].includes(qs.Type) ? $t('common:ruleMessage:select') : $t('common:ruleMessage:specify'), trigger: ['blur','change']},
]"
>
<!-- {{ isCurrentTaskAdd }} <!-- {{ isCurrentTaskAdd }}
{{ questionForm.IsCanEditPosition }} --> {{ questionForm.IsCanEditPosition }} -->
<!-- 输入框 --> <!-- 输入框 -->
<template v-if="qs.Type==='input' || qs.Type==='number'"> <template v-if="qs.Type==='input' || qs.Type==='number'">
<div style="display: flex;justify-content: space-between;">
<!-- {{ ((qs.QuestionMark === 6 && isCurrentTaskAdd === 'False') || (qs.QuestionMark === 6 && isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition)) }} --> <!-- {{ ((qs.QuestionMark === 6 && isCurrentTaskAdd === 'False') || (qs.QuestionMark === 6 && isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition)) }} -->
<el-input v-if="qs.Type === 'input' || qs.Type === 'number'" v-model="questionForm[qs.Id]" <el-input
v-if="qs.Type==='input' || qs.Type==='number'"
v-model="questionForm[qs.Id]"
:disabled="!isCurrentTask || readingTaskState>=2 || qs.QuestionMark === 0 || qs.QuestionMark === 1 || qs.QuestionMark === 2 || qs.QuestionMark === 5 || (qs.QuestionMark === 6 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answers.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False' || !!answers.SplitOrMergeLesionName) && lesionType !== 2) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || !!answers.SplitOrMergeLesionName))" :disabled="!isCurrentTask || readingTaskState>=2 || qs.QuestionMark === 0 || qs.QuestionMark === 1 || qs.QuestionMark === 2 || qs.QuestionMark === 5 || (qs.QuestionMark === 6 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answers.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False' || !!answers.SplitOrMergeLesionName) && lesionType !== 2) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || !!answers.SplitOrMergeLesionName))"
@change="((val) => { formItemChange(val, qs) })"> @change="((val)=>{formItemChange(val, qs)})"
>
<template v-if="(qs.QuestionMark===0 || qs.QuestionMark===1) && qs.Unit" slot="append"> <template v-if="(qs.QuestionMark===0 || qs.QuestionMark===1) && qs.Unit" slot="append">
{{ $fd('ValueUnit', parseInt(qs.Unit)) }} {{ $fd('ValueUnit', parseInt(qs.Unit)) }}
</template> </template>
<svg-icon v-if="qs.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart"
@click.stop="(e) => handleReadingChart({
e,
data: {
TableQuestionId: qs.Id,
RowIndex: questionForm.RowIndex,
QuestionName: qs.QuestionName
}
})" />
</el-input> </el-input>
</div>
</template> </template>
<!-- 多行文本输入框 --> <!-- 多行文本输入框 -->
<el-input v-if="qs.Type === 'textarea'" v-model="questionForm[qs.Id]" type="textarea" <el-input
:autosize="{ minRows: 2, maxRows: 4 }" maxlength="500" :disabled="!isCurrentTask || readingTaskState >= 2" v-if="qs.Type==='textarea'"
@change="((val) => { formItemChange(val, qs) })" /> v-model="questionForm[qs.Id]"
type="textarea"
:autosize="{ minRows: 2, maxRows: 4}"
maxlength="500"
:disabled="!isCurrentTask || readingTaskState>=2"
@change="((val)=>{formItemChange(val, qs)})"
/>
<!-- 下拉框 --> <!-- 下拉框 -->
<el-select v-if="qs.Type === 'select'" v-model="questionForm[qs.Id]" filterable <el-select
v-if="qs.Type==='select'"
v-model="questionForm[qs.Id]"
filterable
:placeholder="qs.QuestionMark === 8 ? $t('common:placeholder:selectorsearch') : $t('common:placeholder:select')" :placeholder="qs.QuestionMark === 8 ? $t('common:placeholder:selectorsearch') : $t('common:placeholder:select')"
:disabled="!isCurrentTask || readingTaskState>=2 || qs.QuestionMark === 0 || qs.QuestionMark === 1 || qs.QuestionMark === 2 || qs.QuestionMark === 5 || (qs.QuestionMark === 6 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answers.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False'|| !!answers.SplitOrMergeLesionName)) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answers.SplitOrMergeLesionName))" :disabled="!isCurrentTask || readingTaskState>=2 || qs.QuestionMark === 0 || qs.QuestionMark === 1 || qs.QuestionMark === 2 || qs.QuestionMark === 5 || (qs.QuestionMark === 6 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answers.SplitOrMergeLesionName))|| (qs.QuestionMark === 8 && (isCurrentTaskAdd === 'False'|| !!answers.SplitOrMergeLesionName)) || (qs.QuestionMark === 10 && (isCurrentTaskAdd === 'False' || (isCurrentTaskAdd === 'True' && !questionForm.IsCanEditPosition) || !!answers.SplitOrMergeLesionName))"
@change="((val) => { formItemChange(val, qs) })"> @change="((val)=>{formItemChange(val, qs)})"
>
<template v-if="qs.QuestionMark === 8" #prefix> <template v-if="qs.QuestionMark === 8" #prefix>
<span style="padding-left: 5px;"> <span style="padding-left: 5px;">
<i class="el-icon-search" /> <i class="el-icon-search" />
</span> </span>
</template> </template>
<template v-if="qs.TableQuestionType === 1"> <template v-if="qs.TableQuestionType === 1">
<el-option v-for="item in organList" :key="item.Id" :label="item[qs.DataTableColumn]" <el-option
:value="item[qs.DataTableColumn]" /> v-for="item in organList"
:key="item.Id"
:label="item[qs.DataTableColumn]"
:value="item[qs.DataTableColumn]"
/>
</template> </template>
<template v-else-if="qs.DictionaryCode && qs.QuestionMark !== 7"> <template v-else-if="qs.DictionaryCode && qs.QuestionMark !== 7">
<el-option v-for="item of $d[qs.DictionaryCode]" :key="item.id" :value="item.value" :label="item.label" /> <el-option
v-for="item of $d[qs.DictionaryCode]"
:key="item.id"
:value="item.value"
:label="item.label"
/>
</template> </template>
<template v-else> <template v-else>
<el-option v-for="val in qs.TypeValue.split('|')" :key="val" :label="val" :value="val" /> <el-option
v-for="val in qs.TypeValue.split('|')"
:key="val"
:label="val"
:value="val"
/>
</template> </template>
</el-select> </el-select>
<!-- 单选 --> <!-- 单选 -->
<el-radio-group v-if="qs.Type === 'radio'" v-model="questionForm[qs.id]" <el-radio-group
:disabled="!isCurrentTask || readingTaskState >= 2"> v-if="qs.Type==='radio'"
<el-radio v-for="val in qs.options.split('|')" :key="val" :label="val"> v-model="questionForm[qs.id]"
:disabled="!isCurrentTask || readingTaskState>=2"
>
<el-radio
v-for="val in qs.options.split('|')"
:key="val"
:label="val"
>
{{ val }} {{ val }}
</el-radio> </el-radio>
</el-radio-group> </el-radio-group>
<template v-if="qs.QuestionMark === 20 && qs.Type==='calculation'"> <template v-if="qs.QuestionMark === 20 && qs.Type==='calculation'">
<div style="display: flex;flex-direction: row;justify-content: flex-start;"> <div style="display: flex;flex-direction: row;justify-content: flex-start;">
<div style="display: flex;justify-content: space-between;"> <el-input
<el-input v-if="qs.Type === 'calculation'" v-model="questionForm[qs.Id]" disabled style="width:120px;"> v-if="qs.Type==='calculation'"
v-model="questionForm[qs.Id]"
disabled
style="width:120px;"
>
<template v-if="qs.Unit" slot="append"> <template v-if="qs.Unit" slot="append">
{{ $fd('ValueUnit', parseInt(qs.Unit)) }} {{ $fd('ValueUnit', parseInt(qs.Unit)) }}
</template> </template>
</el-input> </el-input>
<svg-icon v-if="qs.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart"
@click.stop="(e) => handleReadingChart({
e,
data: {
TableQuestionId: qs.Id,
RowIndex: questionForm.RowIndex,
QuestionName: qs.QuestionName
}
})" />
</div>
<!-- <span style="color:#409eff;cursor: pointer" @click="previewImages(answers.RowId)"> <!-- <span style="color:#409eff;cursor: pointer" @click="previewImages(answers.RowId)">
{{ $t('trials:lugano:button:suvscreenshot') }} {{ $t('trials:lugano:button:suvscreenshot') }}
</span> --> </span> -->
<el-button v-if="!isBaseLineTask" type="text" @click="previewImages(answers.RowId)">{{ <el-button v-if="!isBaseLineTask" type="text" @click="previewImages(answers.RowId)">{{ $t('trials:lugano:button:suvscreenshot') }}</el-button>
$t('trials:lugano:button:suvscreenshot') }}</el-button>
</div> </div>
</template> </template>
<div style="display: flex;justify-content: space-between;" <el-input
v-else-if="qs.Type === 'calculation' && qs.QuestionMark !== 20"> v-else-if="qs.Type==='calculation' && qs.QuestionMark !== 20"
<el-input v-model="questionForm[qs.Id]" disabled> v-model="questionForm[qs.Id]"
disabled
>
<template v-if="qs.Unit" slot="append"> <template v-if="qs.Unit" slot="append">
{{ $fd('ValueUnit', parseInt(qs.Unit)) }} {{ $fd('ValueUnit', parseInt(qs.Unit)) }}
</template> </template>
</el-input> </el-input>
<svg-icon v-if="qs.ShowChartTypeEnum > 0" icon-class="readingChart" class="svg-icon svg-readingChart"
@click.stop="(e) => handleReadingChart({
e,
data: {
TableQuestionId: qs.Id,
RowIndex: questionForm.RowIndex,
QuestionName: qs.QuestionName
}
})" />
</div>
</el-form-item> </el-form-item>
</template> </template>
</div> </div>
<div v-if="isCurrentTask && readingTaskState < 2" class="base-dialog-footer" <div
style="text-align:right;margin-top:10px;"> v-if="isCurrentTask && readingTaskState<2"
class="base-dialog-footer"
style="text-align:right;margin-top:10px;"
>
<!-- 清除标记 --> <!-- 清除标记 -->
<el-button v-if="questionForm.OtherMeasureData" size="mini" @click="handleDeleteMeasureData"> <el-button
v-if="questionForm.OtherMeasureData"
size="mini"
@click="handleDeleteMeasureData"
>
{{ $t('trials:reading:button:removeMark') }} {{ $t('trials:reading:button:removeMark') }}
</el-button> </el-button>
<!-- 删除 --> <!-- 删除 -->
<el-button v-if="isCurrentTaskAdd !== 'False'" size="mini" @click="handleDelete"> <el-button
v-if="isCurrentTaskAdd !== 'False'"
size="mini"
@click="handleDelete"
>
{{ $t('common:button:delete') }} {{ $t('common:button:delete') }}
</el-button> </el-button>
<!-- 保存 --> <!-- 保存 -->
<el-button size="mini" @click="handleSave"> <el-button
size="mini"
@click="handleSave"
>
{{ $t('common:button:save') }} {{ $t('common:button:save') }}
</el-button> </el-button>
</div> </div>
@ -249,9 +288,6 @@ export default {
}, },
methods: { methods: {
handleReadingChart(e) {
this.$emit('handleReadingChart', e)
},
async initForm(isRerender = false) { async initForm(isRerender = false) {
const loading = this.$loading({ fullscreen: true }) const loading = this.$loading({ fullscreen: true })
this.questions.forEach(item => { this.questions.forEach(item => {
@ -1023,52 +1059,42 @@ export default {
color: #c3c3c3; color: #c3c3c3;
// text-align: left; // text-align: left;
} }
::v-deep .el-input .el-input__inner{ ::v-deep .el-input .el-input__inner{
background-color: transparent; background-color: transparent;
color: #ddd; color: #ddd;
border: 1px solid #5e5e5e; border: 1px solid #5e5e5e;
} }
::v-deep .el-form-item{ ::v-deep .el-form-item{
display: flex; display: flex;
flex-direction: row; flex-direction: row;
justify-content: flex-start; justify-content: flex-start;
flex-wrap: wrap; flex-wrap: wrap;
} }
::v-deep .el-form-item__content{ ::v-deep .el-form-item__content{
flex: 1; flex: 1;
} }
::v-deep .el-input.is-disabled .el-input__inner{ ::v-deep .el-input.is-disabled .el-input__inner{
background-color: #646464a1; background-color: #646464a1;
} }
::v-deep .el-input-group__append, .el-input-group__prepend{
::v-deep .el-input-group__append,
.el-input-group__prepend {
padding: 0 10px; padding: 0 10px;
} }
::v-deep .el-select.is-disabled .el-input__inner{ ::v-deep .el-select.is-disabled .el-input__inner{
background-color: #646464a1; background-color: #646464a1;
} }
::v-deep .el-button--mini, .el-button--mini.is-round {
::v-deep .el-button--mini,
.el-button--mini.is-round {
padding: 7px 10px; padding: 7px 10px;
} }
.el-form-item__content
.el-form-item__content .el-select { .el-select{
width: 100%; width: 100%;
} }
.input-width1{ .input-width1{
width: calc(100% - 60px)!important; width: calc(100% - 60px)!important;
} }
.input-width2{ .input-width2{
width: 100% !important; width: 100% !important;
} }
} }
</style> </style>

View File

@ -12,57 +12,48 @@
<template v-for="item in qs.Childrens"> <template v-for="item in qs.Childrens">
<div v-if="item.QuestionClassify === 0 && !(isBaseLineTask && item.LesionType === 2)" :key="item.Id"> <div v-if="item.QuestionClassify === 0 && !(isBaseLineTask && item.LesionType === 2)" :key="item.Id">
<div v-if="item.Type === 'table'" class="flex-row" style="margin:3px 0;"> <div v-if="item.Type === 'table'" class="flex-row" style="margin:3px 0;">
<div class="title">{{ item.QuestionName }} <div class="title">{{ item.QuestionName }}</div>
<svg-icon v-if="item.LesionType === 0" icon-class="readingChart" <div v-if="readingTaskState<2 && (isBaseLineTask || item.LesionType === 2)" class="add-icon" @click.prevent="handleAdd(item)">
class="svg-icon svg-readingChart-mini" @click.stop="(e) => handleReadingChart({
e,
data: {
ReportChartTypeEnum: 0,
QuestionName: item.QuestionName
},
})" />
</div>
<div v-if="readingTaskState < 2 && (isBaseLineTask || item.LesionType === 2)" class="add-icon"
@click.prevent="handleAdd(item)">
<i class="el-icon-plus" /> <i class="el-icon-plus" />
</div> </div>
</div> </div>
<!-- @change="handleCollapseChange(qs.Childrens,item)" --> <!-- @change="handleCollapseChange(qs.Childrens,item)" -->
<el-collapse v-if="item.Type === 'table' && item.TableQuestions" v-model="activeName" accordion <el-collapse
@change="handleCollapseChange"> v-if="item.Type === 'table' && item.TableQuestions"
<el-collapse-item v-for="(q, i) in item.TableQuestions.Answers" :key="`${item.Id}_${q.RowIndex}`" v-model="activeName"
accordion
@change="handleCollapseChange"
>
<el-collapse-item
v-for="(q,i) in item.TableQuestions.Answers"
:key="`${item.Id}_${q.RowIndex}`"
:name="`${item.Id}_${q.RowIndex}`" :name="`${item.Id}_${q.RowIndex}`"
@contextmenu.prevent.native="collapseRightClick($event, q, item.Id, q.RowIndex)"> @contextmenu.prevent.native="collapseRightClick($event,q,item.Id,q.RowIndex)"
>
<template slot="title"> <template slot="title">
<div style="width:300px;position: relative;" <div style="width:300px;position: relative;" :style="{color:(activeName===item.Id+q.RowIndex?'#ffeb3b':'#fff')}">
:style="{ color: (activeName === item.Id + q.RowIndex ? '#ffeb3b' : '#fff') }">
{{ getLesionName(item.OrderMark,q.RowIndex) }} {{ getLesionName(item.OrderMark,q.RowIndex) }}
<!-- 未保存 --> <!-- 未保存 -->
<el-tooltip <el-tooltip v-if="readingTaskState<2 && parseInt(item.TableQuestions.Answers[i].saveTypeEnum) === 0" class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom">
v-if="readingTaskState < 2 && parseInt(item.TableQuestions.Answers[i].saveTypeEnum) === 0"
class="item" effect="dark" :content="$t('trials:reading:button:unsaved')" placement="bottom">
<i class="el-icon-warning" style="color:red" /> <i class="el-icon-warning" style="color:red" />
</el-tooltip> </el-tooltip>
<!-- 信息不完整 --> <!-- 信息不完整 -->
<el-tooltip <el-tooltip v-if="readingTaskState<2 && parseInt(item.TableQuestions.Answers[i].saveTypeEnum) ===1" class="item" effect="dark" :content="$t('trials:reading:button:incompleteInfor')" placement="bottom">
v-if="readingTaskState < 2 && parseInt(item.TableQuestions.Answers[i].saveTypeEnum) === 1"
class="item" effect="dark" :content="$t('trials:reading:button:incompleteInfor')"
placement="bottom">
<i class="el-icon-warning" style="color:#ff9800" /> <i class="el-icon-warning" style="color:#ff9800" />
</el-tooltip> </el-tooltip>
<div style="position: absolute;left: 50px;top: 2px;"> <div style="position: absolute;left: 50px;top: 2px;">
<!-- white-space: nowrap;overflow: hidden;text-overflow: ellipsis; --> <!-- white-space: nowrap;overflow: hidden;text-overflow: ellipsis; -->
<div style="font-size: 11px;width:220px;height: 30px;"> <div style="font-size: 11px;width:220px;height: 30px;">
<div v-if="item.TableQuestions.Answers[i].lesionPart" <div
style="margin-left:10px;display: inline-block; white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width:90px"> v-if="item.TableQuestions.Answers[i].lesionPart"
<el-tooltip v-if="!!item.TableQuestions.Answers[i].lesionPart" class="item" effect="dark" style="margin-left:10px;display: inline-block; white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width:90px"
:content="item.TableQuestions.Answers[i].lesionPart" placement="bottom"> >
<el-tooltip v-if="!!item.TableQuestions.Answers[i].lesionPart" class="item" effect="dark" :content="item.TableQuestions.Answers[i].lesionPart" placement="bottom">
<span>{{ item.TableQuestions.Answers[i].lesionPart }}</span> <span>{{ item.TableQuestions.Answers[i].lesionPart }}</span>
</el-tooltip> </el-tooltip>
</div> </div>
<div <div style="display: inline-block;margin-left:5px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width:50px">
style="display: inline-block;margin-left:5px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width:50px">
<span v-if="item.LesionType === 0"> <span v-if="item.LesionType === 0">
{{ $fd('TargetState',parseInt(item.TableQuestions.Answers[i].lesionState)) }} {{ $fd('TargetState',parseInt(item.TableQuestions.Answers[i].lesionState)) }}
</span> </span>
@ -73,18 +64,14 @@
{{ $fd('NewLesionState',parseInt(item.TableQuestions.Answers[i].lesionState)) }} {{ $fd('NewLesionState',parseInt(item.TableQuestions.Answers[i].lesionState)) }}
</span> </span>
</div> </div>
<div <div style="display: inline-block;margin-left:5px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width:60px;color:red;">
style="display: inline-block;margin-left:5px;white-space: nowrap;overflow: hidden;text-overflow: ellipsis;max-width:60px;color:red;"> <template v-if="item.TableQuestions.Answers[i].suvMax && !isNaN(parseFloat(item.TableQuestions.Answers[i].suvMax))">
<template
v-if="item.TableQuestions.Answers[i].suvMax && !isNaN(parseFloat(item.TableQuestions.Answers[i].suvMax))">
{{ item.TableQuestions.Answers[i].suvMax }} SUV {{ item.TableQuestions.Answers[i].suvMax }} SUV
</template> </template>
</div> </div>
</div> </div>
</div> </div>
<div <div v-if="((item.LesionType === 0 && parseInt(item.TableQuestions.Answers[i].lesionState) === 0) || (item.LesionType === 1 && [0,1].includes(parseInt(item.TableQuestions.Answers[i].lesionState))) || (item.LesionType === 2 && parseInt(item.TableQuestions.Answers[i].lesionState) === 0)) && item.TableQuestions.Answers[i].IsCurrentTaskAdd === 'False'" style="position: absolute;right: 5px;top: 2px;transform: rotateY(180deg);">
v-if="((item.LesionType === 0 && parseInt(item.TableQuestions.Answers[i].lesionState) === 0) || (item.LesionType === 1 && [0, 1].includes(parseInt(item.TableQuestions.Answers[i].lesionState))) || (item.LesionType === 2 && parseInt(item.TableQuestions.Answers[i].lesionState) === 0)) && item.TableQuestions.Answers[i].IsCurrentTaskAdd === 'False'"
style="position: absolute;right: 5px;top: 2px;transform: rotateY(180deg);">
<!-- 分裂 --> <!-- 分裂 -->
<!-- <el-tooltip v-show="readingTaskState<2 && !!item.TableQuestions.Answers[i].RowId && !isBaseLineTask" class="item" :content="$t('trials:reading:button:split')" placement="left"> <!-- <el-tooltip v-show="readingTaskState<2 && !!item.TableQuestions.Answers[i].RowId && !isBaseLineTask" class="item" :content="$t('trials:reading:button:split')" placement="left">
<i class="iconfont icon-24gl-split" style="color:#fff;font-size: 16px;" @click.stop="handleSplit(item.TableQuestions.Answers[i].RowId,item.Id)" /> <i class="iconfont icon-24gl-split" style="color:#fff;font-size: 16px;" @click.stop="handleSplit(item.TableQuestions.Answers[i].RowId,item.Id)" />
@ -94,14 +81,25 @@
</div> </div>
</template> </template>
<QuestionForm :ref="`${item.Id}_${q.RowIndex}`" :questions="item.TableQuestions.Questions" <QuestionForm
:answers="item.TableQuestions.Answers[i]" :lesion-type="item.LesionType" :ref="`${item.Id}_${q.RowIndex}`"
:order-mark="item.OrderMark" :table-questions="tableQuestions" :row-index="String(q.RowIndex)" :questions="item.TableQuestions.Questions"
:question-name="item.QuestionName" :parent-qs-id="item.Id" :visit-task-id="visitTaskId" :answers="item.TableQuestions.Answers[i]"
:is-current-task="isCurrentTask" :reading-task-state="readingTaskState" :lesion-type="item.LesionType"
:is-base-line-task="isBaseLineTask" @changeLesionType="changeLesionType" :order-mark="item.OrderMark"
@resetQuestions="resetQuestions" @determineExistsUnsavedLession="determineExistsUnsavedLession" :table-questions="tableQuestions"
@close="close" @handleReadingChart="handleReadingChart" /> :row-index="String(q.RowIndex)"
:question-name="item.QuestionName"
:parent-qs-id="item.Id"
:visit-task-id="visitTaskId"
:is-current-task="isCurrentTask"
:reading-task-state="readingTaskState"
:is-base-line-task="isBaseLineTask"
@changeLesionType="changeLesionType"
@resetQuestions="resetQuestions"
@determineExistsUnsavedLession="determineExistsUnsavedLession"
@close="close"
/>
</el-collapse-item> </el-collapse-item>
</el-collapse> </el-collapse>
@ -172,9 +170,6 @@ export default {
beforeDestroy() { beforeDestroy() {
}, },
methods: { methods: {
handleReadingChart(e) {
this.$emit('handleReadingChart', e)
},
initList(isRerender = false) { initList(isRerender = false) {
this.loading = true this.loading = true
this.activeName = '' this.activeName = ''
@ -834,7 +829,6 @@ export default {
font-size: 15px; font-size: 15px;
} }
.add-icon{ .add-icon{
padding: 5px; padding: 5px;
font-weight: bold; font-weight: bold;
@ -844,7 +838,6 @@ export default {
margin-bottom: 2px; margin-bottom: 2px;
cursor: pointer; cursor: pointer;
} }
.add-icon:hover{ .add-icon:hover{
background-color: #607d8b; background-color: #607d8b;
} }
@ -856,21 +849,17 @@ export default {
background-color: #424242; background-color: #424242;
} }
.lesion_list{ .lesion_list{
position: relative; position: relative;
} }
.el-collapse{ .el-collapse{
border-bottom:none; border-bottom:none;
border-top:none; border-top:none;
::v-deep .el-collapse-item{ ::v-deep .el-collapse-item{
background-color: #000!important; background-color: #000!important;
color: #ddd; color: #ddd;
} }
::v-deep .el-collapse-item__header{ ::v-deep .el-collapse-item__header{
background-color: #000!important; background-color: #000!important;
color: #ddd; color: #ddd;
@ -879,12 +868,10 @@ export default {
height: 35px; height: 35px;
line-height: 35px; line-height: 35px;
} }
::v-deep .el-collapse-item__wrap{ ::v-deep .el-collapse-item__wrap{
background-color: #000!important; background-color: #000!important;
color: #ddd; color: #ddd;
} }
::v-deep .el-collapse-item__content{ ::v-deep .el-collapse-item__content{
width:260px; width:260px;
position: absolute; position: absolute;

View File

@ -1,193 +0,0 @@
import cornerstoneDICOMImageLoader from '@cornerstonejs/dicom-image-loader'
function parseImageId(imageId) {
// build a url by parsing out the url scheme and frame index from the imageId
const firstColonIndex = imageId.indexOf(':');
let url = imageId.substring(firstColonIndex + 1);
const frameIndex = url.indexOf('frame=');
let frame;
if (frameIndex !== -1) {
const frameStr = url.substr(frameIndex + 6);
frame = parseInt(frameStr, 10);
url = url.substr(0, frameIndex - 1);
}
return {
scheme: imageId.substr(0, firstColonIndex),
url,
frame,
};
}
function getNumberValues(dataSet, tag, minimumLength) {
const values = [];
const valueAsString = dataSet.string(tag);
if (!valueAsString) {
return;
}
const split = valueAsString.split('\\');
if (minimumLength && split.length < minimumLength) {
return;
}
for (let i = 0; i < split.length; i++) {
values.push(parseFloat(split[i]));
}
return values;
}
function getImageTypeSubItemFromDataset(dataSet, index) {
const imageType = dataSet.string('x00080008');
if (imageType) {
const subTypes = imageType.split('\\');
if (subTypes.length > index) {
return subTypes[index];
}
}
return undefined;
}
function isNMReconstructable(imageSubType) {
return imageSubType === 'RECON TOMO' || imageSubType === 'RECON GATED TOMO';
}
function extractOrientationFromNMMultiframeDataset(dataSet) {
let imageOrientationPatient;
const modality = dataSet.string('x00080060');
if (modality?.includes('NM')) {
const imageSubType = getImageTypeSubItemFromDataset(dataSet, 2);
if (imageSubType && isNMReconstructable(imageSubType)) {
if (dataSet.elements.x00540022) {
imageOrientationPatient = getNumberValues(dataSet.elements.x00540022.items[0].dataSet, 'x00200037', 6);
}
}
}
return imageOrientationPatient;
}
function extractOrientationFromDataset(dataSet) {
let imageOrientationPatient = getNumberValues(dataSet, 'x00200037', 6);
if (!imageOrientationPatient && dataSet.elements.x00209116) {
imageOrientationPatient = getNumberValues(dataSet.elements.x00209116.items[0].dataSet, 'x00200037', 6);
}
if (!imageOrientationPatient) {
imageOrientationPatient =
extractOrientationFromNMMultiframeDataset(dataSet);
}
return imageOrientationPatient;
}
function extractPositionFromNMMultiframeDataset(dataSet) {
let imagePositionPatient;
const modality = dataSet.string('x00080060');
if (modality?.includes('NM')) {
const imageSubType = getImageTypeSubItemFromDataset(dataSet, 2);
if (imageSubType && isNMReconstructable(imageSubType)) {
if (dataSet.elements.x00540022) {
imagePositionPatient = getNumberValues(dataSet.elements.x00540022.items[0].dataSet, 'x00200032', 3);
}
}
}
return imagePositionPatient;
}
function extractPositionFromDataset(dataSet) {
let imagePositionPatient = getNumberValues(dataSet, 'x00200032', 3);
if (!imagePositionPatient && dataSet.elements.x00209113) {
imagePositionPatient = getNumberValues(dataSet.elements.x00209113.items[0].dataSet, 'x00200032', 3);
}
if (!imagePositionPatient) {
imagePositionPatient = extractPositionFromNMMultiframeDataset(dataSet);
}
return imagePositionPatient;
}
function extractSliceThicknessFromDataset(dataSet) {
let sliceThickness;
if (dataSet.elements.x00180050) {
sliceThickness = dataSet.floatString('x00180050');
}
else if (dataSet.elements.x00289110 &&
dataSet.elements.x00289110.items.length &&
dataSet.elements.x00289110.items[0].dataSet.elements.x00180050) {
sliceThickness =
dataSet.elements.x00289110.items[0].dataSet.floatString('x00180050');
}
return sliceThickness;
}
function extractSpacingFromDataset(dataSet) {
let rowPixelSpacing = null
let columnPixelSpacing = null
let pixelSpacing = getNumberValues(dataSet, 'x00280030', 2);
const imagePixelSpacing = getNumberValues(dataSet, 'x00181164', 2);
const estimatedRadiographicMagnificationFactor = getNumberValues(dataSet, 'x00181114', 2);
if (pixelSpacing) {
rowPixelSpacing = pixelSpacing[0]
columnPixelSpacing = pixelSpacing[1]
} else if (imagePixelSpacing && estimatedRadiographicMagnificationFactor) {
rowPixelSpacing = imagePixelSpacing[0] / estimatedRadiographicMagnificationFactor[0];
columnPixelSpacing = imagePixelSpacing[1] / estimatedRadiographicMagnificationFactor[1];
} else if (imagePixelSpacing && !estimatedRadiographicMagnificationFactor) {
rowPixelSpacing = imagePixelSpacing[0];
columnPixelSpacing = imagePixelSpacing[1];
}
return rowPixelSpacing !== null ? [rowPixelSpacing, columnPixelSpacing] : undefined
}
function metaDataProvider(type, imageId) {
const parsedImageId = parseImageId(imageId);
const dataSet = cornerstoneDICOMImageLoader.wadouri.dataSetCacheManager.get(parsedImageId.url)
if (!dataSet) {
return;
}
if (type === 'imagePlaneModule') {
const imageOrientationPatient = getNumberValues(dataSet, 'x00200037', 6);
const imagePositionPatient = getNumberValues(dataSet, 'x00200032', 3);
const pixelSpacing = extractSpacingFromDataset(dataSet);
let rowCosines = null;
let columnCosines = null;
if (imageOrientationPatient) {
rowCosines = [
parseFloat(imageOrientationPatient[0]),
parseFloat(imageOrientationPatient[1]),
parseFloat(imageOrientationPatient[2]),
];
columnCosines = [
parseFloat(imageOrientationPatient[3]),
parseFloat(imageOrientationPatient[4]),
parseFloat(imageOrientationPatient[5]),
];
}
return {
frameOfReferenceUID: dataSet.string('x00200052'),
rows: dataSet.uint16('x00280010'),
columns: dataSet.uint16('x00280011'),
imageOrientationPatient,
rowCosines,
columnCosines,
imagePositionPatient,
sliceThickness: dataSet.floatString('x00180050'),
sliceLocation: dataSet.floatString('x00201041'),
pixelSpacing: pixelSpacing,
rowPixelSpacing: pixelSpacing ? pixelSpacing[0] : null,
columnPixelSpacing: pixelSpacing ? pixelSpacing[1] : null,
};
}
if (type === 'nmMultiframeGeometryModule') {
const modality = dataSet.string('x00080060');
const imageSubType = getImageTypeSubItemFromDataset(dataSet, 2);
return {
modality,
imageType: dataSet.string('x00080008'),
imageSubType,
imageOrientationPatient: extractOrientationFromDataset(dataSet),
imagePositionPatient: extractPositionFromDataset(dataSet),
sliceThickness: extractSliceThicknessFromDataset(dataSet),
pixelSpacing: extractSpacingFromDataset(dataSet),
numberOfFrames: dataSet.uint16('x00280008'),
isNMReconstructable: isNMReconstructable(imageSubType) && modality.includes('NM'),
};
}
}
export default metaDataProvider;

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