9 Commits

Author SHA1 Message Date
wangxiaoshuang 45e6a20988 Merge branch 'uat'
continuous-integration/drone/push Build encountered an error
# Conflicts:
#	src/utils/metaDataProvider.js
2025-05-26 12:30:44 +08:00
wangxiaoshuang 5141eb5cbd 发布配置修改
continuous-integration/drone/push Build is passing
2025-05-23 18:12:49 +08:00
wangxiaoshuang 073b06a76f 1
continuous-integration/drone/push Build is passing
2025-05-23 17:10:45 +08:00
wangxiaoshuang 20723e8d2c 1
continuous-integration/drone/push Build is passing
2025-05-23 16:25:30 +08:00
wangxiaoshuang fba00157a1 crc一致性核查回复弹窗添加取消按钮
continuous-integration/drone/push Build is passing
2025-05-23 16:06:12 +08:00
wangxiaoshuang e0321bae72 影像预览问题解决
continuous-integration/drone/push Build encountered an error
2025-04-12 12:04:20 +08:00
wangxiaoshuang 1e720e399d 确认收入项,修改选项后,其他文件也改了
continuous-integration/drone/push Build encountered an error
2025-04-03 11:15:54 +08:00
wangxiaoshuang 1368397da9 项目总览—>上传记录:中心编号 查询条件,查询结果不对 2025-04-03 11:15:36 +08:00
wangxiaoshuang c8c049b5d0 DICOM影像中,存在Tag最大像素值、最小像素值等,但是和实际的数据统计结果不同 2025-04-03 11:15:22 +08:00
7 changed files with 218 additions and 104 deletions
+137 -10
View File
@@ -39,6 +39,108 @@ function getNumberValues(dataSet, tag, minimumLength) {
return values;
}
function getLutDescriptor(dataSet, tag) {
if (!dataSet.elements[tag] || dataSet.elements[tag].length !== 6) {
return;
}
return [
dataSet.uint16(tag, 0),
dataSet.uint16(tag, 1),
dataSet.uint16(tag, 2),
];
}
function getLutData(lutDataSet, tag, lutDescriptor) {
const lut = [];
const lutData = lutDataSet.elements[tag];
for (let i = 0; i < lutDescriptor[0]; i++) {
// Output range is always unsigned
if (lutDescriptor[2] === 16) {
lut[i] = lutDataSet.uint16(tag, i);
} else {
lut[i] = lutDataSet.byteArray[i + lutData.dataOffset];
}
}
return lut;
}
function populateSmallestLargestPixelValues(dataSet, imagePixelModule) {
const pixelRepresentation = dataSet.uint16('x00280103');
if (pixelRepresentation === 0) {
imagePixelModule.smallestPixelValue = dataSet.uint16('x00280106');
imagePixelModule.largestPixelValue = dataSet.uint16('x00280107');
} else {
imagePixelModule.smallestPixelValue = dataSet.int16('x00280106');
imagePixelModule.largestPixelValue = dataSet.int16('x00280107');
}
imagePixelModule.largestPixelValue = imagePixelModule.largestPixelValue === 0 ? undefined : imagePixelModule.largestPixelValue;
}
function populatePaletteColorLut(dataSet, imagePixelModule) {
imagePixelModule.redPaletteColorLookupTableDescriptor = getLutDescriptor(
dataSet,
'x00281101'
);
imagePixelModule.greenPaletteColorLookupTableDescriptor = getLutDescriptor(
dataSet,
'x00281102'
);
imagePixelModule.bluePaletteColorLookupTableDescriptor = getLutDescriptor(
dataSet,
'x00281103'
);
// The first Palette Color Lookup Table Descriptor value is the number of entries in the lookup table.
// When the number of table entries is equal to 2ˆ16 then this value shall be 0.
// See http://dicom.nema.org/MEDICAL/DICOM/current/output/chtml/part03/sect_C.7.6.3.html#sect_C.7.6.3.1.5
if (imagePixelModule.redPaletteColorLookupTableDescriptor[0] === 0) {
imagePixelModule.redPaletteColorLookupTableDescriptor[0] = 65536;
imagePixelModule.greenPaletteColorLookupTableDescriptor[0] = 65536;
imagePixelModule.bluePaletteColorLookupTableDescriptor[0] = 65536;
}
// The third Palette Color Lookup Table Descriptor value specifies the number of bits for each entry in the Lookup Table Data.
// It shall take the value of 8 or 16.
// The LUT Data shall be stored in a format equivalent to 8 bits allocated when the number of bits for each entry is 8, and 16 bits allocated when the number of bits for each entry is 16, where in both cases the high bit is equal to bits allocated-1.
// The third value shall be identical for each of the Red, Green and Blue Palette Color Lookup Table Descriptors.
//
// Note: Some implementations have encoded 8 bit entries with 16 bits allocated, padding the high bits;
// this can be detected by comparing the number of entries specified in the LUT Descriptor with the actual value length of the LUT Data entry.
// The value length in bytes should equal the number of entries if bits allocated is 8, and be twice as long if bits allocated is 16.
const numLutEntries =
imagePixelModule.redPaletteColorLookupTableDescriptor[0];
const lutData = dataSet.elements.x00281201;
const lutBitsAllocated = lutData.length === numLutEntries ? 8 : 16;
// If the descriptors do not appear to have the correct values, correct them
if (
imagePixelModule.redPaletteColorLookupTableDescriptor[2] !==
lutBitsAllocated
) {
imagePixelModule.redPaletteColorLookupTableDescriptor[2] = lutBitsAllocated;
imagePixelModule.greenPaletteColorLookupTableDescriptor[2] =
lutBitsAllocated;
imagePixelModule.bluePaletteColorLookupTableDescriptor[2] =
lutBitsAllocated;
}
imagePixelModule.redPaletteColorLookupTableData = getLutData(
dataSet,
'x00281201',
imagePixelModule.redPaletteColorLookupTableDescriptor
);
imagePixelModule.greenPaletteColorLookupTableData = getLutData(
dataSet,
'x00281202',
imagePixelModule.greenPaletteColorLookupTableDescriptor
);
imagePixelModule.bluePaletteColorLookupTableData = getLutData(
dataSet,
'x00281203',
imagePixelModule.bluePaletteColorLookupTableDescriptor
);
}
function metaDataProvider(type, imageId) {
const parsedImageId = parseImageId(imageId);
const dataSet = cornerstoneWADOImageLoader.wadouri.dataSetCacheManager.get(parsedImageId.url);
@@ -100,7 +202,7 @@ function metaDataProvider(type, imageId) {
};
}
if (type === 'imagePixelModule') {
return {
const imagePixelModule = {
samplesPerPixel: dataSet.uint16('x00280002'),
photometricInterpretation: dataSet.string('x00280004'),
rows: dataSet.uint16('x00280010'),
@@ -110,16 +212,41 @@ function metaDataProvider(type, imageId) {
highBit: dataSet.uint16('x00280102'),
pixelRepresentation: dataSet.uint16('x00280103'),
planarConfiguration: dataSet.uint16('x00280006'),
pixelAspectRatio: dataSet.uint16('x00280034'),
smallestPixelValue: null,
largestPixelValue: null,
redPaletteColorLookupTableDescriptor: dataSet.string('x00281101'),
greenPaletteColorLookupTableDescriptor: dataSet.string('x00281102'),
bluePaletteColorLookupTableDescriptor: dataSet.string('x00281103'),
redPaletteColorLookupTableData: dataSet.string('x00281201'),
greenPaletteColorLookupTableData: dataSet.string('x00281202'),
bluePaletteColorLookupTableData: dataSet.string('x00281203')
pixelAspectRatio: dataSet.string('x00280034'),
};
populateSmallestLargestPixelValues(dataSet, imagePixelModule);
if (
imagePixelModule.photometricInterpretation === 'PALETTE COLOR' &&
dataSet.elements.x00281101
) {
populatePaletteColorLut(dataSet, imagePixelModule);
}
return imagePixelModule;
}
// if (type === 'imagePixelModule') {
// return {
// samplesPerPixel: dataSet.uint16('x00280002'),
// photometricInterpretation: dataSet.string('x00280004'),
// rows: dataSet.uint16('x00280010'),
// columns: dataSet.uint16('x00280011'),
// bitsAllocated: dataSet.uint16('x00280100'),
// bitsStored: dataSet.uint16('x00280101'),
// highBit: dataSet.uint16('x00280102'),
// pixelRepresentation: dataSet.uint16('x00280103'),
// planarConfiguration: dataSet.uint16('x00280006'),
// pixelAspectRatio: dataSet.uint16('x00280034'),
// smallestPixelValue: null,
// largestPixelValue: null,
// // smallestPixelValue: dataSet.uint16('x00280106'),
// // largestPixelValue: dataSet.uint16('x00280107'),
// redPaletteColorLookupTableDescriptor: dataSet.string('x00281101'),
// greenPaletteColorLookupTableDescriptor: dataSet.string('x00281102'),
// bluePaletteColorLookupTableDescriptor: dataSet.string('x00281103'),
// redPaletteColorLookupTableData: dataSet.string('x00281201'),
// greenPaletteColorLookupTableData: dataSet.string('x00281202'),
// bluePaletteColorLookupTableData: dataSet.string('x00281203')
// }
// }
}
export default metaDataProvider;
@@ -124,7 +124,7 @@
<el-table-column prop="Name" :label="$t('trials:signRecords:table:fileName')" show-overflow-tooltip
sortable="custom" />
<el-table-column :label="$t('trials:signRecords:table:AttachmentCount')" prop="AttachmentCount"
show-overflow-tooltip sortable="custom">
show-overflow-tooltip>
<template slot-scope="scope">
<el-button type="text" @click.stop="openAttachment(scope.row, true)">{{ scope.row.AttachmentCount
}}</el-button>
@@ -359,7 +359,6 @@ export default {
status: 'add',
upload: null,
},
DATA: {},
doctorList: [],
}
},
@@ -632,12 +631,6 @@ export default {
},
immediate: true,
},
rowData: {
handler() {
this.DATA = Object.assign({}, this.rowData)
},
immediate: true,
},
},
created() {
let typeArr = ['', 'Report', 'Doc', 'Record', 'Reviewer', 'Template']
@@ -1,11 +1,11 @@
<template>
<div v-loading="loading" class="chat-wrapper">
<div v-if="recordContent.length>0" class="chat-content">
<div v-for="(record,index) in recordContent" :key="`${record.CreateTime}${index}`">
<div v-if="recordContent.length > 0" class="chat-content">
<div v-for="(record, index) in recordContent" :key="`${record.CreateTime}${index}`">
<div v-if="!record.IsCurrentUser" class="word">
<img v-if="record.UserTypeEnum*1 === 8" :src="adminAvatar" alt="Admin">
<img v-else-if="record.UserTypeEnum*1 === 1" :src="pmAvatar" alt="PM">
<img v-else-if="record.UserTypeEnum*1 === 2" :src="crcAvatar" alt="CRC">
<img v-if="record.UserTypeEnum * 1 === 8" :src="adminAvatar" alt="Admin">
<img v-else-if="record.UserTypeEnum * 1 === 1" :src="pmAvatar" alt="PM">
<img v-else-if="record.UserTypeEnum * 1 === 2" :src="crcAvatar" alt="CRC">
<div class="info">
<p class="user-info">
<span style="font-weight:700;">{{ record.CreateUserName }} </span>
@@ -24,9 +24,9 @@
<div class="info-content" v-html="record.TalkContent" />
</div>
<!-- <img :src="record.headUrl"> -->
<img v-if="record.UserTypeEnum*1 === 8" :src="adminAvatar" alt="Admin">
<img v-else-if="record.UserTypeEnum*1 === 1" :src="pmAvatar" alt="PM">
<img v-else-if="record.UserTypeEnum*1 === 2" :src="crcAvatar" alt="CRC">
<img v-if="record.UserTypeEnum * 1 === 8" :src="adminAvatar" alt="Admin">
<img v-else-if="record.UserTypeEnum * 1 === 1" :src="pmAvatar" alt="PM">
<img v-else-if="record.UserTypeEnum * 1 === 2" :src="crcAvatar" alt="CRC">
</div>
</div>
</div>
@@ -36,83 +36,50 @@
</div>
<div v-if="checkChallengeState !== 3 && checkState !== 11" class="chat-message">
<div class="message">
<el-input
v-model="newMessage"
v-hasPermi="['trials:trials-panel:visit:consistency-check:fallback']"
type="textarea"
:rows="2"
/>
<el-input v-model="newMessage" v-hasPermi="['trials:trials-panel:visit:consistency-check:fallback']"
type="textarea" :rows="2" />
</div>
<div class="function">
<!-- 申请回退 -->
<el-button
v-hasPermi="['trials:trials-panel:visit:consistency-check:apply-fallback']"
type="primary"
<el-button v-hasPermi="['trials:trials-panel:visit:consistency-check:apply-fallback']" type="primary"
:disabled="!(checkState === 10 && (requestBackState === 0 || requestBackState === 3))"
@click="handleApplyBack"
>
@click="handleApplyBack">
{{ $t('trials:consistencyCheck:action:applyFallback') }}
</el-button>
<!-- 拒绝回退 -->
<el-button
v-hasPermi="['trials:trials-panel:visit:consistency-check:fallback']"
type="primary"
:disabled="!(requestBackState === 1)"
@click="handleRejectBack"
>
<el-button v-hasPermi="['trials:trials-panel:visit:consistency-check:fallback']" type="primary"
:disabled="!(requestBackState === 1)" @click="handleRejectBack">
{{ $t('trials:consistencyCheck:button:rejectBack') }}
</el-button>
<!-- 回退 -->
<el-button
v-hasPermi="['trials:trials-panel:visit:consistency-check:fallback']"
type="primary"
:disabled="!(requestBackState === 1)"
@click="handleBack"
>
<el-button v-hasPermi="['trials:trials-panel:visit:consistency-check:fallback']" type="primary"
:disabled="!(requestBackState === 1)" @click="handleBack">
{{ $t('trials:consistencyCheck:action:fallback') }}
</el-button>
<!-- 发送 -->
<el-button
v-hasPermi="['role:pm']"
:disabled="!(checkState === 10 && checkChallengeState !== 3) || newMessage === ''"
type="primary"
:loading="btnLoading"
@click="handleReply()"
>
<el-button v-hasPermi="['role:pm']"
:disabled="!(checkState === 10 && checkChallengeState !== 3) || newMessage === ''" type="primary"
:loading="btnLoading" @click="handleReply()">
{{ $t('trials:consistencyCheck:button:sendMessage') }}
</el-button>
<!-- 回复 -->
<el-button
v-hasPermi="['role:crc']"
<el-button v-hasPermi="['role:crc']" type="primary"
:disabled="!(checkState === 10 && checkChallengeState !== 3) || (recordContent && recordContent.length > 0 ? recordContent[recordContent.length - 1].UserTypeEnum * 1 === 2 : false)"
type="primary"
:loading="btnLoading"
@click="handleCRCReply"
>
:loading="btnLoading" @click="handleCRCReply">
{{ $t('trials:consistencyCheck:title:reply') }}
</el-button>
<!-- 关闭 -->
<el-button
type="primary"
:loading="btnLoading"
@click="close"
>
<el-button type="primary" :loading="btnLoading" @click="close">
{{ $t('trials:consistencyCheck:title:close') }}
</el-button>
</div>
</div>
<!-- 回复一致性核查 -->
<el-dialog
v-if="sendMessageCRCVisible"
v-dialogDrag
:visible.sync="sendMessageCRCVisible"
:close-on-click-modal="false"
append-to-body
custom-class="base-dialog-wrapper"
:width="'600px'"
:title="$t('trials:consistencyCheck:title:replyConsistency')"
>
<crcSendMessage :crc-message-info="crcMessageInfo" @sendMessage="handleReply" />
<el-dialog v-if="sendMessageCRCVisible" v-dialogDrag :visible.sync="sendMessageCRCVisible"
:close-on-click-modal="false" append-to-body custom-class="base-dialog-wrapper" :width="'600px'"
:title="$t('trials:consistencyCheck:title:replyConsistency')">
<crcSendMessage :crc-message-info="crcMessageInfo" :visible.sync="sendMessageCRCVisible"
@sendMessage="handleReply" />
</el-dialog>
</div>
</template>
@@ -277,46 +244,54 @@ export default {
}
</script>
<style lang="scss">
.chat-wrapper{
::-webkit-scrollbar {
.chat-wrapper {
::-webkit-scrollbar {
width: 7px;
height: 7px;
}
::-webkit-scrollbar-thumb {
border-radius: 10px;
background: #d0d0d0;
}
.chat-content{
width:100%;
.chat-content {
width: 100%;
padding: 20px;
height: 500px;
overflow-y: auto;
.word{
.word {
display: flex;
margin-bottom: 20px;
img{
width:40px;
img {
width: 40px;
height: 40px;
border-radius: 50%;
}
.info{
.info {
margin-left: 10px;
.user-info{
.user-info {
font-size: 12px;
color:rgba(51,51,51,0.8);
margin:0;
color: rgba(51, 51, 51, 0.8);
margin: 0;
height: 20px;
line-height: 20px;
margin-top: -5px;
}
.info-content{
.info-content {
padding: 10px;
font-size: 14px;
background-color: #ebeef5;
position: relative;
margin-top: 8px;
}
.info-content::before{
.info-content::before {
position: absolute;
left: -8px;
top: 8px;
@@ -327,29 +302,34 @@ export default {
}
}
}
.word-my{
.word-my {
display: flex;
justify-content: flex-end;
margin-bottom: 20px;
img{
img {
width: 40px;
height: 40px;
border-radius: 50%;
}
.info{
.info {
width: 90%;
margin-left: 10px;
text-align: right;
.user-info{
.user-info {
font-size: 12px;
color: rgba(51,51,51,0.8);
color: rgba(51, 51, 51, 0.8);
margin: 0;
height: 20px;
line-height: 20px;
margin-top: -5px;
margin-right: 10px;
}
.info-content{
.info-content {
position: relative;
max-width: 70%;
padding: 10px;
@@ -361,7 +341,8 @@ export default {
color: #fff;
text-align: left;
}
.info-content::after{
.info-content::after {
position: absolute;
right: -8px;
top: 8px;
@@ -373,9 +354,11 @@ export default {
}
}
}
.chat-message{
.chat-message {
padding: 0 50px;
.function{
.function {
margin-top: 10px;
text-align: right;
}
@@ -71,6 +71,10 @@
</div>
</div>
<div class="function">
<!-- 取消 -->
<el-button @click="close">
{{ $t('common:button:cancel') }}
</el-button>
<!-- 发送 -->
<el-button type="primary" @click="handleReply">
{{ $t('trials:consistencyCheck:button:sendMessage') }}
@@ -118,6 +122,10 @@ export default {
TalkContent: null
}
}
},
visible: {
type: Boolean,
default: false
}
},
data() {
@@ -149,6 +157,9 @@ export default {
this.compareStudy()
},
methods: {
close() {
this.$emit('update:visible', false)
},
compareStudy() {
var isLackOf = false
this.IRCList = []
@@ -194,10 +194,10 @@
<template slot="dialog-body">
<el-form ref="imageBackform" :model="form" class="demo-form-inline" :rules="rules"
:label-width="isEN ? '150px' : '100px'">
<el-form-item :label="$t('trials:reuploadAudit:table:Matters') + ': '" prop="Matters">
<el-form-item :label="$t('trials:reuploadAudit:table:Matters')" prop="Matters">
<span>{{ rowData.title }}</span>
</el-form-item>
<el-form-item :label="$t('trials:reuploadAudit:table:ApplyReason') + ': '" prop="ApplyReason">
<el-form-item :label="$t('trials:reuploadAudit:form:ApplyReason')" prop="ApplyReason">
<span>{{ rowData.ApplyReason }}</span>
</el-form-item>
<el-form-item :label="$t('trials:reuploadAudit:form:IsAgree')" prop="IsAgree">
@@ -206,7 +206,7 @@
<el-radio :label="false">{{ $t('trials:reuploadAudit:button:auditNo') }}</el-radio>
</el-radio-group>
</el-form-item>
<el-form-item :label="$t('trials:reuploadAudit:table:ResultRemark') + ': '" prop="ResultRemark">
<el-form-item :label="$t('trials:reuploadAudit:form:ResultRemark')" prop="ResultRemark">
<el-input type="textarea" :autosize="{ minRows: 2, maxRows: 4 }" placeholder=""
v-model="form.ResultRemark">
</el-input>
+1 -1
View File
@@ -97,7 +97,7 @@ module.exports = defineConfig({
]
}),
// new BundleAnalyzerPlugin(),
process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'prod' || process.env.NODE_ENV === 'production' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? function () { }
process.env.NODE_ENV === 'development' || process.env.NODE_ENV === 'production' || process.env.VUE_APP_OSS_CONFIG_BUCKET === 'zyypacs-usa' ? function () { }
: new WebpackAliyunOss({
from: ['./dist/**'],
dist: process.env.VUE_APP_OSS_PATH + distDate,