feat: 增加Extrapolation弹窗,对接beta-gamma下的RRR接口

This commit is contained in:
Xu Zhimeng 2023-08-09 19:21:00 +08:00
parent 1562e46313
commit d7f9f9f396
4 changed files with 852 additions and 9 deletions

View File

@ -38,6 +38,8 @@ export default {
case 3:
url = '/spectrumAnalysis/viewARR'
break
case 4:
url = '/spectrumAnalysis/viewRRR'
}
try {
this.content = ''

View File

@ -0,0 +1,760 @@
<template>
<custom-modal
v-model="visible"
:width="1080"
title="Radio-Nuclide Activity by Efficiency Extrapolation"
destroy-on-close
:footer="null"
>
<a-spin :spinning="isLoading">
<!-- Sample Infomation 开始 -->
<div class="sample-infomation">
<div class="title">Sample Infomation</div>
<div class="content">
<div>
<label>Acquisition Start:</label>
<span>{{ detail.acquisitionStart }}</span>
</div>
<div>
<label>Acq Real Time:</label>
<span>{{ detail.acquisitionRealTime }}</span>
</div>
<div>
<label>Acq Live Time:</label>
<span>{{ detail.acquisitionLiveTime }}</span>
</div>
</div>
</div>
<!-- Sample Infomation 结束 -->
<!-- 两个图表开始 -->
<div class="gamma-beta-spectrum-sample border">
<div class="gamma-spectrum-sample">
<div class="title">Gamma Spectrum:Sample</div>
<div class="chart border">
<custom-chart ref="gammaSpectrumChart" :option="gammaSpectrumChartOption" @zr:click="handleChartClick" />
<!-- 自定义tooltip用于点击图表后的tooltip显示 -->
<div
v-if="customToolTip.visible"
class="custom-tool-tip"
:style="{
top: customToolTip.top + 'px',
left: customToolTip.left + 'px'
}"
>
<div class="channel">Channel: {{ customToolTip.channel }}</div>
<div class="channel">Energy: {{ customToolTip.energy }}</div>
</div>
<!-- tooltip结束 -->
</div>
</div>
<div class="beta-spectrum-sample">
<div class="title">Beta Spectrum:Sample</div>
<div class="chart border">
<custom-chart :option="betaSpectrumChartOption" />
</div>
</div>
</div>
<!-- 两个图表结束 -->
<!-- 底部设置和分析开始 -->
<div class="setting-and-analyze">
<!-- 左侧设置开始 -->
<div class="setting border">
<div>
<div class="setting-item">
<div class="title">Gamma Window Setting</div>
<div class="content">
<div class="label">Gamma Window Begin:</div>
<a-input-number size="small"></a-input-number> Channel
<div class="label">Gamma Window End:</div>
<a-input-number size="small"></a-input-number> Channel
</div>
</div>
<div class="setting-item">
<div class="title">Parameter Setting</div>
<div class="content">
<div class="label">Min of Energy:</div>
<a-input-number size="small"></a-input-number> keV
<div class="label">Half Life:</div>
<a-input-number size="small"></a-input-number> Day
</div>
</div>
<div class="setting-item">
<div class="title">Function of Fitting</div>
<div class="content">
<a-radio-group v-model="model.fittingType">
<a-radio value="1">Linear</a-radio>
<a-radio value="2">2-polynomial</a-radio>
</a-radio-group>
</div>
</div>
</div>
<div class="btns">
<a-button type="primary">Analyse</a-button>
<a-button @click="visible = false">Exit</a-button>
</div>
</div>
<!-- 左侧设置结束 -->
<!-- 右侧分析开始 -->
<div class="analyze">
<!-- 表格开始 -->
<a-table
class="result-table"
:columns="columns"
:dataSource="tableList"
:pagination="false"
size="small"
:class="tableList.length ? 'has-data' : ''"
:scroll="{ y: 101 }"
>
<template slot="delete">
<a-button type="link" size="small">Delete</a-button>
</template>
</a-table>
<!-- 表格结束 -->
<!-- 图表开始 -->
<div class="chart border">
<custom-chart ref="chartRef" :option="resultChartOption" />
</div>
<!-- 图表结束 -->
<!-- 图表下的按钮和标题开始 -->
<div class="snapshot-and-title">
<a-button size="small" type="primary" @click="handleSnapshot">Snapshot</a-button>
<span>Analyser Result</span>
</div>
<!-- 图表下的按钮和标题结束 -->
<!-- 右下角信息开始 -->
<div class="info">
<title-over-border title="Function of Fitting">
<template v-if="model.fittingType == '1'">
y = ax + b
</template>
<template v-if="model.fittingType == '2'">
y = axx + bx + c
</template>
</title-over-border>
<title-over-border title="Xe Activity (Bq)">
<div class="xe-activity">
<div class="item">
<label>Reference Time :</label>
<span>
这是内容
</span>
</div>
<div class="item">
<label>Xe Activity (Bq) :</label>
<span>
这是内容
</span>
</div>
</div>
</title-over-border>
</div>
<!-- 右下角信息结束 -->
</div>
<!-- 右侧分析结束 -->
</div>
<!-- 底部设置和分析结束 -->
</a-spin>
</custom-modal>
</template>
<script>
import ModalMixin from '@/mixins/ModalMixin'
import { cloneDeep } from 'lodash'
import CustomChart from '@/components/CustomChart/index.vue'
import { exportEchartImg, getXAxisAndYAxisByPosition, splitAxis } from '@/utils/chartHelper'
import { getAction } from '@/api/manage'
import { useBaseChartSetting } from '../../../useChart'
import TitleOverBorder from '../../TitleOverBorder.vue'
const initialGammaChartOption = {
grid: {
top: 20,
right: 15,
bottom: 10,
left: 10,
containLabel: true
},
xAxis: {
min: 0,
max: 256,
interval: 64,
axisLine: {
lineStyle: {
color: 'rgb(119, 181, 213, 0.5)'
}
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(119, 181, 213, .2)'
}
},
axisTick: {
show: false
},
axisLabel: {
color: '#ade6ee'
}
},
yAxis: {
min: 0,
max: 0,
interval: 0,
axisLine: {
show: true,
lineStyle: {
color: 'rgb(119, 181, 213, 0.5)'
}
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(119, 181, 213, .2)'
}
},
axisTick: {
show: false
},
axisLabel: {
color: '#ade6ee'
}
},
series: [
{
type: 'line',
itemStyle: {
color: '#04ADD9'
},
symbol: 'none',
data: [],
markLine: {
symbol: 'none',
label: {
show: false
},
animation: false,
emphasis: {
disabled: true
},
lineStyle: {
color: '#f00'
},
data: []
}
},
{
type: 'line',
itemStyle: {
color: '#A8DA56'
},
symbol: 'none',
data: []
}
]
}
const initialBetaChartOption = {
grid: {
top: 20,
right: 15,
bottom: 10,
left: 10,
containLabel: true
},
xAxis: {
min: 0,
max: 256,
interval: 64,
axisLine: {
lineStyle: {
color: 'rgb(119, 181, 213, 0.5)'
}
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(119, 181, 213, .2)'
}
},
axisTick: {
show: false
},
axisLabel: {
color: '#ade6ee'
}
},
yAxis: {
min: 0,
max: 0,
interval: 0,
axisLine: {
show: true,
lineStyle: {
color: 'rgb(119, 181, 213, 0.5)'
}
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(119, 181, 213, .2)'
}
},
axisTick: {
show: false
},
axisLabel: {
color: '#ade6ee'
}
},
series: [
{
type: 'line',
itemStyle: {
color: '#04ADD9'
},
symbol: 'none',
data: [],
markLine: {
symbol: 'none',
label: {
show: false
},
animation: false,
emphasis: {
disabled: true
},
lineStyle: {
color: '#f00'
},
data: []
}
},
{
type: 'line',
itemStyle: {
color: '#A8DA56'
},
symbol: 'none',
data: []
}
]
}
const initialResultChartOption = {
...useBaseChartSetting(-100, 100, 50, -100, 100, 50),
series: [
{
type: 'line',
itemStyle: {
color: '#04ADD9'
},
symbol: 'none',
data: [],
markLine: {
symbol: 'none',
label: {
show: false
},
animation: false,
emphasis: {
disabled: true
},
lineStyle: {
color: '#f00'
},
data: []
}
},
{
type: 'line',
itemStyle: {
color: '#A8DA56'
},
symbol: 'none',
data: []
}
]
}
const columns = [
{
title: 'Index',
customRender: (_, __, index) => {
return index + 1
},
align: 'center'
},
{
title: 'Eb',
dataIndex: 'Eb',
align: 'center'
},
{
title: 'Nx',
dataIndex: 'Nx',
align: 'center'
},
{
title: 'Ny',
dataIndex: 'Ny',
align: 'center'
},
{
title: 'Delete',
scopedSlots: {
customRender: 'delete'
},
align: 'center'
}
]
export default {
mixins: [ModalMixin],
components: {
CustomChart,
TitleOverBorder
},
props: {
sampleId: {
type: Number
}
},
data() {
this.columns = columns
return {
gammaSpectrumChartOption: cloneDeep(initialGammaChartOption),
betaSpectrumChartOption: cloneDeep(initialBetaChartOption),
resultChartOption: cloneDeep(initialResultChartOption),
customToolTip: {
top: 0,
left: 0,
visible: false,
channel: '',
energy: ''
},
isLoading: false,
detail: {},
gammaChannelEnergy: [],
model: {
fittingType: '1'
},
tableList: []
}
},
methods: {
beforeModalOpen() {
this.customToolTip.visible = false
this.getDetail()
},
async getDetail() {
try {
this.isLoading = true
const { success, result, message } = await getAction('/spectrumAnalysis/viewExtrapolation', {
sampleId: this.sampleId
})
if (success) {
this.detail = result
const {
betaOriginSeriseData,
betaProjectedSeriseData,
gammaChannelEnergy,
gammaOriginSeriseData,
gammaProjectedSeriseData
} = result
this.gammaChannelEnergy = gammaChannelEnergy
const _max = Math.max(
...gammaOriginSeriseData.map(({ y }) => y),
...gammaProjectedSeriseData.map(({ y }) => y)
)
const { max, interval } = splitAxis(_max, 0, 4)
this.gammaSpectrumChartOption.yAxis.max = max
this.gammaSpectrumChartOption.yAxis.interval = interval
this.gammaSpectrumChartOption.series[0].data = gammaOriginSeriseData.map(({ x, y }) => [x, y])
this.gammaSpectrumChartOption.series[1].data = gammaProjectedSeriseData.map(({ x, y }) => [x, y])
const _max2 = Math.max(
...betaOriginSeriseData.map(({ y }) => y),
...betaProjectedSeriseData.map(({ y }) => y)
)
const { max: max2, interval2 } = splitAxis(_max2, 0, 4)
this.betaSpectrumChartOption.yAxis.max = max2
this.betaSpectrumChartOption.yAxis.interval = interval2
this.betaSpectrumChartOption.series[0].data = betaOriginSeriseData.map(({ x, y }) => [x, y])
this.betaSpectrumChartOption.series[1].data = betaProjectedSeriseData.map(({ x, y }) => [x, y])
this.isLoading = false
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
}
},
//
handleChartClick(param) {
const { offsetX, offsetY } = param
const point = getXAxisAndYAxisByPosition(this.$refs.gammaSpectrumChart.getChartInstance(), offsetX, offsetY)
if (point) {
const xAxis = parseInt(point[0].toFixed())
this.gammaSpectrumChartOption.series[0].markLine.data = [{ xAxis }]
this.customToolTip.top = offsetY
if (xAxis > 225) {
this.customToolTip.left = offsetX - 125
} else {
this.customToolTip.left = offsetX + 20
}
this.customToolTip.visible = true
this.customToolTip.channel = xAxis
const energy = this.gammaChannelEnergy[xAxis] || 0
this.customToolTip.energy = parseInt(energy) + 'keV'
}
},
handleSnapshot() {
exportEchartImg(this.$refs.chartRef.getChartInstance())
}
}
}
</script>
<style lang="less" scoped>
.border {
border: 1px solid #0b8c82;
}
.title {
color: @primary-color;
}
.sample-infomation {
.content {
display: flex;
> div {
flex: 1;
height: 32px;
display: flex;
align-items: center;
}
span {
display: inline-block;
background-color: #01a77e;
margin-left: 20px;
padding: 5px;
width: 200px;
height: 100%;
}
}
}
.gamma-beta-spectrum-sample {
margin-top: 10px;
padding: 10px;
display: flex;
gap: 10px;
.gamma-spectrum-sample,
.beta-spectrum-sample {
flex: 1;
}
.chart {
position: relative;
height: 250px;
margin-top: 5px;
}
}
.custom-tool-tip {
position: absolute;
border-style: solid;
white-space: nowrap;
z-index: 99999;
box-shadow: rgba(0, 0, 0, 0.2) 1px 2px 10px;
border-width: 1px;
border-radius: 4px;
padding: 10px;
border-color: rgb(255, 255, 255);
pointer-events: none;
background-color: #00aa7f;
border-color: #00aa7f;
.channel {
color: #fff;
}
}
.setting-and-analyze {
margin-top: 10px;
display: flex;
gap: 20px;
.setting {
width: 300px;
padding: 10px;
display: flex;
flex-direction: column;
justify-content: space-between;
&-item {
&:not(:first-child) {
margin-top: 10px;
}
}
.btns {
.ant-btn {
display: block;
width: 100%;
&:last-child {
margin-top: 10px;
}
}
}
.label {
line-height: 26px;
}
.content {
padding-left: 30px;
}
.ant-input-number {
margin-right: 10px;
width: 170px;
}
.ant-radio-wrapper {
display: block;
margin-top: 5px;
}
}
.analyze {
flex: 1;
.chart {
margin-top: 10px;
height: 250px;
}
.result-table {
&.has-data {
::v-deep {
.ant-table-body {
height: 101px;
background-color: #06282a;
}
}
}
::v-deep {
.ant-table {
font-size: 14px;
}
.ant-table-placeholder {
height: 102px;
display: flex;
justify-content: center;
align-items: center;
}
}
}
.snapshot-and-title {
position: relative;
margin-top: 20px;
text-align: center;
height: 40px;
.ant-btn {
position: absolute;
left: 0;
top: 0;
}
span {
font-size: 18px;
}
}
.info {
display: flex;
gap: 10px;
.title-over-border {
flex: 1;
}
::v-deep {
.title-over-border-content {
display: flex;
align-items: center;
justify-content: center;
}
}
.xe-activity {
width: 80%;
.item {
display: flex;
gap: 10px;
label {
width: 110px;
text-align: right;
}
span {
flex: 1;
}
}
}
}
}
}
</style>
<style lang="less">
.chart-tooltip {
background-color: #00aa7f !important;
border-color: #00aa7f !important;
.channel {
color: #fff;
}
.energy {
color: #00d1f0;
}
.warning {
color: yellow;
}
}
</style>

View File

@ -155,6 +155,10 @@
/>
<!-- Beta-Gamma 的Energy Calibration结束 -->
<!-- Beta-Gamma Extrapolation 弹窗开始 -->
<beta-gamma-extrapolation-modal v-model="betaGammaExtrapolationModalVisible" :sampleId="sampleData.sampleId" />
<!-- Beta-Gamma Extrapolation 弹窗结束 -->
<!-- Beta-Gamma Spectrum 弹窗 -->
<beta-gamma-spectrum-modal v-model="betaGammaSpectrumModalVisible" :sampleId="this.sampleData.sampleId" />
<!-- Beta-Gamma Spectrum 弹窗 结束 -->
@ -171,7 +175,7 @@
<!-- Beta-Gamma QC Result 弹窗 结束 -->
<!-- Beta-Gamma RLR 弹窗 -->
<beta-gamma-rlr-modal v-model="betaGammaRlrModalVisible" />
<beta-gamma-rlr-modal v-model="betaGammaRlrModalVisible" :sampleId="sampleData.sampleId" />
<!-- Beta-Gamma RLR 弹窗 结束 -->
<!-- Beta-Gamma Statistics Paramer History 弹窗 -->
@ -220,6 +224,7 @@ import FtransltModal from './components/Modals/FtransltModal/index.vue'
import BetaGammaEnergyCalibrationModal from './components/Modals/BetaGammaModals/BetaGammaEnergyCalibrationModal/index.vue'
import StripModal from './components/Modals/StripModal.vue'
import AutomaticAnalysisLogModal from './components/Modals/BetaGammaModals/AutomaticAnalysisLogModal.vue'
import BetaGammaExtrapolationModal from './components/Modals/BetaGammaModals/BetaGammaExtrapolationModal.vue'
//
const ANALYZE_TYPE = {
@ -264,7 +269,8 @@ export default {
FtransltModal,
BetaGammaEnergyCalibrationModal,
StripModal,
AutomaticAnalysisLogModal
AutomaticAnalysisLogModal,
BetaGammaExtrapolationModal
},
data() {
this.ANALYZE_TYPE = ANALYZE_TYPE
@ -321,6 +327,7 @@ export default {
isBetaGammaCommentsAdd: false, // beta-gamma comments
betaGammaEnergyCalibrationModalVisible: false, // beta-gamma Energy Calibration
betaGammaExtrapolationModalVisible: false, // beta-gamma Extrapolation
betaGammaSpectrumModalVisible: false, // beta-gamma spectrum
betaGammaSampleInfomationModalVisible: false, // beta-gamma sample infomation
@ -613,6 +620,18 @@ export default {
show: this.isGamma,
handler: () => (this.energyCalibrationModalShow = true)
},
{
type: 'a-menu-item',
title: 'Resolution',
show: this.isGamma,
handler: () => (this.resolutionCalibrationModalShow = true)
},
{
type: 'a-menu-item',
title: 'Efficiency',
show: this.isGamma,
handler: () => (this.efficiencyCalibrationModalShow = true)
},
{
type: 'a-menu-item',
title: 'Energy Calibration',
@ -621,13 +640,9 @@ export default {
},
{
type: 'a-menu-item',
title: 'Resolution',
handler: () => (this.resolutionCalibrationModalShow = true)
},
{
type: 'a-menu-item',
title: 'Efficiency',
handler: () => (this.efficiencyCalibrationModalShow = true)
title: 'Extrapolation',
show: this.isBetaGamma,
handler: () => (this.betaGammaExtrapolationModalVisible = true)
}
]
}

View File

@ -0,0 +1,66 @@
/**
* 返回一个默认的配置
* @param {*} minX
* @param {*} maxX
* @param {*} intervalX
* @param {*} minY
* @param {*} maxY
* @param {*} intervalY
* @returns
*/
export function useBaseChartSetting(minX = 0, maxX = 265, intervalX = 64, minY = 0, maxY = 0, intervalY = 0) {
return {
grid: {
top: 20,
right: 20,
bottom: 20,
left: 10,
containLabel: true
},
xAxis: {
min: minX,
max: maxX,
interval: intervalX,
axisLine: {
lineStyle: {
color: 'rgb(119, 181, 213, 0.5)'
}
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(119, 181, 213, .2)'
}
},
axisTick: {
show: false
},
axisLabel: {
color: '#ade6ee'
}
},
yAxis: {
min: minY,
max: maxY,
interval: intervalY,
axisLine: {
show: true,
lineStyle: {
color: 'rgb(119, 181, 213, 0.5)'
}
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(119, 181, 213, .2)'
}
},
axisTick: {
show: false
},
axisLabel: {
color: '#ade6ee'
}
}
}
}