Merge branch 'feature-spectrum-analysis' into feature-analysis-RLR-renpy

# Conflicts:
#	src/api/manage.js
#	src/views/spectrumAnalysis/gamma-analysis.vue
#	src/views/spectrumAnalysis/index.vue
This commit is contained in:
任珮宇 2023-09-15 16:25:47 +08:00
commit 8fa955e4f4
25 changed files with 52017 additions and 1425 deletions

View File

@ -70,7 +70,7 @@ export function putAction(url, parameter) {
} }
//get //get
export function getAction(url, parameter) { export function getAction(url, parameter, cancelToken) {
let sign = signMd5Utils.getSign(url, parameter); let sign = signMd5Utils.getSign(url, parameter);
//将签名和时间戳,添加在请求接口 Header //将签名和时间戳,添加在请求接口 Header
// update-begin--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯 // update-begin--author:taoyan---date:20220421--for: VUEN-410【签名改造】 X-TIMESTAMP牵扯
@ -81,7 +81,8 @@ export function getAction(url, parameter) {
url: url, url: url,
method: 'get', method: 'get',
params: parameter, params: parameter,
headers: signHeader headers: signHeader,
cancelToken
}) })
} }

View File

@ -5,7 +5,7 @@
</div> </div>
<div class="color-picker-mask" :class="show ? 'show' : ''" @click="show = false"> <div class="color-picker-mask" :class="show ? 'show' : ''" @click="show = false">
<div class="color-picker-panel" :style="style" @click.stop> <div class="color-picker-panel" :style="style" @click.stop>
<chrome v-model="color"></chrome> <chrome v-model="color" disableAlpha></chrome>
</div> </div>
</div> </div>
</div> </div>
@ -16,8 +16,8 @@ import { Chrome } from 'vue-color'
export default { export default {
props: { props: {
value: { value: {
type: Object, type: String,
default: () => ({ rgba: { r: 255, g: 255, b: 255, a: 1 } }) required: true
} }
}, },
components: { components: {
@ -43,7 +43,7 @@ export default {
computed: { computed: {
color: { color: {
set(val) { set(val) {
this.$emit('input', val) this.$emit('input', val.hex)
}, },
get() { get() {
return this.value return this.value

View File

@ -1,88 +0,0 @@
<template>
<div class="custom-chart" ref="containerRef" :style="{ height: height + 'px' }"></div>
</template>
<script>
import * as echarts from 'echarts'
import 'echarts-gl'
const events = ['click', 'brushEnd']
const zrEvents = ['mousemove', 'mousedown', 'mouseup', 'click']
export default {
props: {
option: {
type: Object,
default: () => ({})
},
opts: {
type: Object,
default: () => {}
},
height: {
type: Number,
default: 0
}
},
data() {
return {}
},
mounted() {
this._chart = echarts.init(this.$refs.containerRef)
this._chart.setOption(this.option, this.opts)
this.initEventListener()
},
destroyed() {
if(this._chart) {
this._chart.dispose()
}
},
methods: {
initEventListener() {
events.forEach(eventName => {
this._chart.on(eventName, params => {
this.$emit(eventName, params)
})
})
const zr = this.getZRender()
zrEvents.forEach(eventName => {
zr.on(eventName, params => {
this.$emit(`zr:${eventName}`, params)
})
})
},
resize() {
this._chart && this._chart.resize()
},
// echart
getChartInstance() {
return this._chart
},
getZRender() {
return this._chart.getZr()
}
},
watch: {
option: {
handler() {
if (this._chart) {
this._chart.setOption(this.option, this.opts)
}
},
deep: true
},
height() {
this.$nextTick(() => {
this._chart && this._chart.resize()
})
}
}
}
</script>
<style lang="less" scoped>
.custom-chart {
height: 100% !important;
}
</style>

View File

@ -3,10 +3,10 @@
</template> </template>
<script> <script>
import * as echarts from 'echarts' import * as echarts from 'echarts'
import 'echarts-gl'
const events = ['brushEnd'] const events = ['click', 'brushEnd']
const zrEvents = ['mousemove', 'mousedown', 'mouseup', 'click'] const zrEvents = ['mousemove', 'mousedown', 'mouseup', 'click']
export default { export default {
props: { props: {
option: { option: {

View File

@ -30,13 +30,6 @@
@input-bg: @formInputBgColor; @input-bg: @formInputBgColor;
@input-border-color: @formInputBorderColor; @input-border-color: @formInputBorderColor;
.ant-btn:hover,
.ant-btn:active,
.ant-btn:focus {
color: #fff !important;
border-color: transparent;
}
@font-face { @font-face {
font-family: MicrogrammaD-MediExte; font-family: MicrogrammaD-MediExte;
src: url(~@/assets/fonts/MicrogrammaDMedExt.ttf); src: url(~@/assets/fonts/MicrogrammaDMedExt.ttf);

View File

@ -219,6 +219,14 @@ export default {
statisticModalVisible: false, // Qc Flags statisticModalVisible: false, // Qc Flags
statisticsType: StatisticsType['Collection Time'], statisticsType: StatisticsType['Collection Time'],
currSample: {},
}
},
mounted() {
if (this.currSample.sampleId) {
this.getSampleDetail()
} else {
this.getSampleDetail_file()
} }
}, },
methods: { methods: {
@ -392,12 +400,11 @@ export default {
sample: { sample: {
handler(newVal, oldVal) { handler(newVal, oldVal) {
if (newVal.sampleId) { if (newVal.sampleId) {
this.getSampleDetail() this.currSample = newVal
} else {
this.getSampleDetail_file()
} }
}, },
immediate: true, immediate: true,
deep: true,
}, },
analyseCurrentSpectrum: { analyseCurrentSpectrum: {
handler(newVal, oldVal) { handler(newVal, oldVal) {

View File

@ -15,7 +15,7 @@
<div class="beta-gamma-spectrum-chart-main"> <div class="beta-gamma-spectrum-chart-main">
<!-- 2D 图表为了相应Unzoom采用的v-show --> <!-- 2D 图表为了相应Unzoom采用的v-show -->
<div class="_2d-chart" v-show="active == 0"> <div class="_2d-chart" v-show="active == 0">
<Custom3DChart <CustomChart
ref="chartRef" ref="chartRef"
:option="twoDOption" :option="twoDOption"
@zr:mousemove="handleMouseMove" @zr:mousemove="handleMouseMove"
@ -33,17 +33,17 @@
<!-- 2D图表结束 --> <!-- 2D图表结束 -->
<!-- 3D Surface开始 --> <!-- 3D Surface开始 -->
<Custom3DChart v-if="active == 1" key="1" ref="_3dSurfaceRef" :option="threeDSurfaceOption" /> <CustomChart v-if="active == 1" key="1" ref="_3dSurfaceRef" :option="threeDSurfaceOption" />
<!-- 3D Surface结束 --> <!-- 3D Surface结束 -->
<!-- 3D Scatter --> <!-- 3D Scatter -->
<Custom3DChart v-if="active == 2" key="2" ref="_3dScannerRef" :option="threeDScatterOption" /> <CustomChart v-if="active == 2" key="2" ref="_3dScannerRef" :option="threeDScatterOption" />
<!-- 3D Scatter结束 --> <!-- 3D Scatter结束 -->
</div> </div>
</div> </div>
</template> </template>
<script> <script>
import Custom3DChart from '@/components/Custom3DChart/index.vue' import CustomChart from '@/components/CustomChart/index.vue'
import ColorPalette from './ColorPalette.vue' import ColorPalette from './ColorPalette.vue'
import { getXAxisAndYAxisByPosition, rangeNumber } from '@/utils/chartHelper.js' import { getXAxisAndYAxisByPosition, rangeNumber } from '@/utils/chartHelper.js'
@ -314,7 +314,7 @@ export default {
} }
}, },
components: { components: {
Custom3DChart, CustomChart,
ColorPalette ColorPalette
}, },
data() { data() {

View File

@ -1,48 +0,0 @@
<template>
<custom-modal v-model="visible" :title="type + ' Comment'" :okHandler="handleOk">
<a-textarea :rows="10" v-model="content"></a-textarea>
</custom-modal>
</template>
<script>
export default {
props: {
value: {
type: Boolean
},
type: {
type: String
}
},
data() {
return {
content: ''
}
},
methods: {
async handleOk() {
if (!this.content) {
this.$message.warn('Please Input Comment')
throw new Error('Content Is Empty')
}
console.log('%c [ ]-29', 'font-size:13px; background:pink; color:#bf2c9f;', this.type, this.content)
}
},
computed: {
visible: {
get() {
if (this.value) {
this.content = ''
}
return this.value
},
set(val) {
this.$emit('input', val)
}
}
}
}
</script>
<style></style>

View File

@ -0,0 +1,60 @@
<template>
<custom-modal v-model="visible" :title="'Slope at ' + (index + 1)" :width="250">
<a-input-number v-model="value"></a-input-number>
<template slot="custom-footer">
<div class="footer">
<a-button type="primary" @click="handleOK">Ok</a-button>
<a-button @click="visible = false">Cancel</a-button>
</div>
</template>
</custom-modal>
</template>
<script>
export default {
data() {
return {
index: -1,
value: 0,
prevValue: 0,
allowNaN: false,
visible: false
}
},
methods: {
/**
* 打开弹窗
* @param {{ index: number; value: number; allowNaN: boolean; }} config
*/
open(config) {
this.index = config.index
this.value = config.value
this.prevValue = config.value
this.allowNaN = config.allowNaN
this.visible = true
},
handleOK() {
if (this.allowNaN || this.value) {
this.$emit('change', this.value || 0, this.index, this.prevValue)
this.visible = false
} else {
this.$message.warn('Input value invalid.')
}
}
}
}
</script>
<style lang="less" scoped>
.ant-input-number {
width: 100%;
}
.footer {
display: flex;
justify-content: center;
gap: 10px;
}
</style>

View File

@ -0,0 +1,69 @@
<template>
<custom-modal v-model="visible" title="General Comment" :okHandler="handleOk">
<a-spin :spinning="isLoading">
<a-textarea :rows="10" v-model="content"></a-textarea>
</a-spin>
</custom-modal>
</template>
<script>
import { getAction, postAction } from '@/api/manage'
import ModalMixin from '@/mixins/ModalMixin'
import SampleDataMixin from '@/views/spectrumAnalysis/SampleDataMixin'
export default {
mixins: [ModalMixin, SampleDataMixin],
data() {
return {
content: ''
}
},
methods: {
async handleOk() {
if (!this.content) {
this.$message.warn('Please Input Comment')
throw new Error('Comment is Empty')
}
try {
this.isSubmitting = true
const { inputFileName: fileName } = this.sampleData
const { success, message } = await postAction('/gamma/addGeneralComment', {
fileName,
comments: this.content
})
if (!success) {
this.$message.error(message)
throw new Error(message)
}
} catch (error) {
console.error(error)
}
},
async getComment() {
try {
this.isLoading = true
const { inputFileName: fileName } = this.sampleData
const { success, result, message } = await getAction('/gamma/viewGeneralComment', {
fileName
})
if (success) {
this.content = result
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
} finally {
this.isLoading = false
}
},
beforeModalOpen() {
this.content = ''
this.getComment()
}
}
}
</script>
<style></style>

View File

@ -86,7 +86,7 @@ export default {
type: 'line', type: 'line',
data: pointlist.map(({ x, y }) => [x, y]), data: pointlist.map(({ x, y }) => [x, y]),
itemStyle: { itemStyle: {
color: `rgb(${color})` color
}, },
symbol: 'none', symbol: 'none',
animation: false animation: false

View File

@ -0,0 +1,76 @@
<template>
<custom-modal v-model="visible" title="Peak Comment" :okHandler="handleOk">
<a-spin :spinning="isLoading">
<a-textarea :rows="10" v-model="content"></a-textarea>
</a-spin>
</custom-modal>
</template>
<script>
import { getAction, postAction } from '@/api/manage'
import ModalMixin from '@/mixins/ModalMixin'
import SampleDataMixin from '@/views/spectrumAnalysis/SampleDataMixin'
export default {
mixins: [ModalMixin, SampleDataMixin],
props: {
curRow: {
type: Number
}
},
data() {
return {
content: ''
}
},
methods: {
async handleOk() {
if (!this.content) {
this.$message.warn('Please Input Comment')
throw new Error('Comment is Empty')
}
try {
this.isSubmitting = true
const { inputFileName: fileName } = this.sampleData
const { success, message } = await postAction('/gamma/addPeakComment', {
fileName,
comments: this.content,
curRow: this.curRow
})
if (!success) {
this.$message.error(message)
throw new Error(message)
}
} catch (error) {
console.error(error)
}
},
async getComment() {
try {
this.isLoading = true
const { inputFileName: fileName } = this.sampleData
const { success, result, message } = await getAction('/gamma/viewPeakComment', {
fileName,
curRow: this.curRow
})
if (success) {
this.content = result
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
} finally {
this.isLoading = false
}
},
beforeModalOpen() {
this.content = ''
this.getComment()
}
}
}
</script>
<style></style>

View File

@ -156,6 +156,7 @@ export default {
.analysis-settings { .analysis-settings {
&-item { &-item {
display: flex; display: flex;
margin-top: 5px;
&:not(:first-child) { &:not(:first-child) {
margin-top: 20px; margin-top: 20px;

View File

@ -1,66 +1,69 @@
<template> <template>
<custom-modal v-model="visible" :width="700" title="Color Config"> <custom-modal v-model="visible" :width="700" title="Color Config" :okHandler="handleApply">
<div class="color-config"> <a-spin :spinning="isLoading">
<div class="color-config-item" v-for="(item, index) in configList" :key="index"> <div class="color-config">
<div class="title">{{ item.title }}</div> <div class="color-config-item" v-for="(item, index) in configList" :key="index">
<color-picker v-model="config[item.key]"> <div class="title">{{ item.title }}</div>
<div class="color-picker-picker" :style="{ background: combineRGBA(config[item.key]) }"></div> <color-picker v-model="config[item.key]">
</color-picker> <div class="color-picker-picker" :style="{ background: combineRGBA(config[item.key]) }"></div>
</color-picker>
<div class="desc">{{ item.desc }}</div> <div class="desc">{{ item.desc }}</div>
</div>
</div> </div>
</div> </a-spin>
</custom-modal> </custom-modal>
</template> </template>
<script> <script>
import ModalMixin from '@/mixins/ModalMixin' import ModalMixin from '@/mixins/ModalMixin'
import ColorPicker from '@/components/ColorPicker/index.vue' import ColorPicker from '@/components/ColorPicker/index.vue'
import { getAction, putAction } from '@/api/manage'
const configList = [ const configList = [
{ {
title: 'Spectrum Line', title: 'Spectrum Line',
key: 'spectrumLine', key: 'Color_Spec',
desc: 'Color of the original spectrum line' desc: 'Color of the original spectrum line'
}, },
{ {
title: 'Baseline', title: 'Baseline',
key: 'baseline', key: 'Color_Base',
desc: 'Color of baseline' desc: 'Color of baseline'
}, },
{ {
title: 'Lc Line', title: 'Lc Line',
key: 'lcLine', key: 'Color_Lc',
desc: 'Color of lc line' desc: 'Color of lc line'
}, },
{ {
title: 'Scac Line', title: 'Scac Line',
key: 'scacLine', key: 'Color_Scac',
desc: 'Color of scac line' desc: 'Color of scac line'
}, },
{ {
title: 'Peak Line', title: 'Peak Line',
key: 'peakLine', key: 'Color_Peak',
desc: "Color of all peaks' curve" desc: "Color of all peaks' curve"
}, },
{ {
title: 'Compare Line', title: 'Compare Line',
key: 'compareLine', key: 'Color_Compare',
desc: 'Color of another spectrum line which is used to compare with current spectrum' desc: 'Color of another spectrum line which is used to compare with current spectrum'
}, },
{ {
title: 'Spect Sum Line', title: 'Spec Sum Line',
key: 'spectSumLine', key: 'Color_Strip',
desc: 'Color of the line which is the sum of current spectrum and other spectrum Multiplied by a ratio' desc: 'Color of the line which is the sum of current spectrum and other spectrum Multiplied by a ratio'
}, },
{ {
title: 'Spect Cut Line', title: 'Spec Cut Line',
key: 'spectCutLine', key: 'spectCutLine',
desc: 'Color of the line which is the difference of current spectrum and other spectrum Multiplied by a ratio' desc: 'Color of the line which is the difference of current spectrum and other spectrum Multiplied by a ratio'
}, },
{ {
title: 'FitBase Line', title: 'FitBase Line',
key: 'fitBaseLine', key: 'Color_Fitbase',
desc: 'Color of the base line in edit state' desc: 'Color of the base line in edit state'
} }
] ]
@ -73,21 +76,79 @@ export default {
this.configList = configList this.configList = configList
return { return {
config: { config: {
spectrumLine: { rgba: { r: 255, g: 255, b: 0, a: 1 } }, Color_Spec: 'yellow', // Spectrum
baseline: { rgba: { r: 0, g: 246, b: 255, a: 1 } }, Color_Base: 'rgb(0, 246, 255)', // 线
lcLine: { rgba: { r: 255, g: 0, b: 0, a: 1 } }, Color_Lc: 'red', // LC
scacLine: { rgba: { r: 244, g: 112, b: 247, a: 1 } }, Color_Scac: 'rgb(244, 112, 247)', // Scac
peakLine: { rgba: { r: 255, g: 127, b: 39, a: 1 } }, Color_Peak: 'rgb(255, 127, 39)', // Peak
compareLine: { rgba: { r: 0, g: 255, b: 0, a: 1 } }, Color_Compare: 'green', // Sample -> Compare
spectSumLine: { rgba: { r: 0, g: 0, b: 255, a: 1 } }, Color_Strip: 'rgb(0, 0, 255)', // Sample -> Compare
spectCutLine: { rgba: { r: 34, g: 90, b: 106, a: 1 } }, spectCutLine: 'rgb(33, 90, 104)', //
fitBaseLine: { rgba: { r: 255, g: 255, b: 255, a: 1 } } Color_Fitbase: 'white' // Interactive Tool BaseLine线
} }
} }
}, },
methods: { methods: {
combineRGBA({ rgba: { r, g, b, a } }) { combineRGBA(color) {
return `rgba(${r}, ${g}, ${b}, ${a})` return color
},
async getData() {
try {
this.isLoading = true
const { success, result, message } = await getAction('/gamma/viewColorConfig')
if (success) {
Object.entries(result).forEach(([k, v]) => {
this.config[k] = v
})
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
} finally {
this.isLoading = false
}
},
beforeModalOpen() {
this.getData()
},
//
async handleApply() {
const {
Color_Spec,
Color_Peak,
Color_Lc,
Color_Base,
Color_Scac,
Color_Compare,
Color_Strip,
Color_Fitbase
} = this.config
const { success, message } = await putAction('/gamma/updateColorConfig', {
colorSpec: Color_Spec,
colorPeak: Color_Peak,
colorLc: Color_Lc,
colorBase: Color_Base,
colorScac: Color_Scac,
colorCompare: Color_Compare,
colorFitbase: Color_Fitbase,
colorStrip: Color_Strip
})
if (success) {
this.$bus.$emit(
'colorChange',
Object.entries(this.config).reduce((prev, [key, value]) => {
prev[key] = value
return prev
}, {})
)
} else {
this.$message.error(message)
throw new Error(message)
}
} }
} }
} }
@ -119,4 +180,9 @@ export default {
} }
} }
} }
.footer {
display: flex;
justify-content: space-between;
}
</style> </style>

View File

@ -1,94 +1,105 @@
<template> <template>
<custom-modal v-model="visible" :width="1280" title="Efficiency Calibration" :footer="null"> <custom-modal v-model="visible" :width="1280" title="Efficiency Calibration" :footer="null" destroy-on-close>
<div class="efficiency-calibration"> <a-spin :spinning="isLoading">
<div class="left"> <div class="energy-calibration">
<!-- Calibration Data --> <div class="left">
<title-over-border title="Calibration Data"> <!-- Calibration Data -->
<div class="calibration-data"> <title-over-border title="Calibration Data">
<a-form-model <div class="calibration-data">
:colon="false" <a-form-model
:labelCol="{ :colon="false"
style: { :labelCol="{
width: '70px', style: {
textAlign: 'left', width: '70px',
flexShrink: 0 textAlign: 'left',
} flexShrink: 0
}" }
:wrapperCol="{ }"
style: { :wrapperCol="{
flex: 1 style: {
} flex: 1
}" }
> }"
<a-form-model-item label="Energy"> >
<a-input></a-input> <a-form-model-item label="Energy">
</a-form-model-item> <a-input type="number" v-model="model.energy"></a-input>
<a-form-model-item label="Efficiency"> </a-form-model-item>
<a-input></a-input> <a-form-model-item label="Efficiency">
</a-form-model-item> <a-input type="number" v-model="model.efficiency"></a-input>
<a-form-model-item :label="' '"> </a-form-model-item>
<a-button type="primary">Insert</a-button> <a-form-model-item :label="' '">
</a-form-model-item> <a-button type="primary" @click="handleInsert">Insert</a-button>
<a-form-model-item :label="' '"> </a-form-model-item>
<a-button type="primary">Modify</a-button> <a-form-model-item :label="' '">
</a-form-model-item> <a-button type="primary" @click="handleModify">Modify</a-button>
<a-form-model-item :label="' '"> </a-form-model-item>
<a-button type="primary">Delete</a-button> <a-form-model-item :label="' '">
</a-form-model-item> <a-button type="primary" @click="handleDelete">Delete</a-button>
</a-form-model> </a-form-model-item>
<!-- 表格 --> </a-form-model>
<a-table <!-- 表格 -->
:columns="columns" <custom-table
:dataSource="list" :columns="columns"
:pagination="false" :list="list"
:class="list.length ? 'has-data' : ''" :pagination="false"
:scroll="{ y: 182 }" size="small"
></a-table> :class="list.length ? 'has-data' : ''"
<!-- 表格结束 --> :scroll="{ y: 182 }"
<div class="operators"> :selectedRowKeys.sync="selectedRowKeys"
<div> :canDeselect="false"
<a-button type="primary">Call</a-button> @rowClick="handleRowClick"
<a-button type="primary">Save</a-button> ></custom-table>
</div> <!-- 表格结束 -->
<div> <div class="operators">
<a-select :value="''"> <div>
<a-select-option value=""> <a-button type="primary">Call</a-button>
Interpolation <a-button type="primary">Save</a-button>
</a-select-option> </div>
</a-select> <div>
<a-button type="primary">Apply</a-button> <a-select v-model="funcId" @change="recalculate">
<a-select-option v-for="(func, index) in functions" :key="index" :value="func.value">
{{ func.label }}
</a-select-option>
</a-select>
<a-button type="primary" @click="handleApply">Apply</a-button>
</div>
</div> </div>
</div> </div>
</div> </title-over-border>
</title-over-border> <!-- Equation -->
<!-- Equation --> <title-over-border class="mt-20" title="Equation">
<title-over-border class="mt-20" title="Equation"> <div class="equation" v-html="equation"></div>
<div class="equation"> </title-over-border>
Efficiency = 59.541 + (88.034 - 59.541) * (E - 1) / (0.058243 - 1) <!-- curve -->
</div> <title-over-border class="mt-20" title="curve">
</title-over-border> <div class="curve">
<!-- curve --> <custom-chart :option="option" :opts="opts" />
<title-over-border class="mt-20" title="curve">
<div class="curve">
<custom-chart :option="option" />
</div>
</title-over-border>
</div>
<div class="right">
<title-over-border title="Data Source" style="height: 100%">
<div class="data-source">
<div class="data-source-main">
<div class="title">PHD</div>
<div class="content"></div>
</div> </div>
<div class="footer mt-20"> </title-over-border>
<a-button type="primary">Set to Current</a-button> </div>
<div class="mt-20">PHD</div> <div class="right">
<title-over-border title="Data Source" style="height: 100%">
<div class="data-source">
<div class="content">
<div
class="item"
:class="item == currSelectedDataSource ? 'active' : ''"
v-for="(item, index) in dataSourceList"
:key="index"
@click="handleDataSourceClick(item)"
>
{{ item }}
</div>
</div>
<div class="footer mt-20">
<a-button type="primary" @click="handleSetToCurrent">Set to Current</a-button>
<div class="mt-20">{{ appliedDataSource }}</div>
</div>
</div> </div>
</div> </title-over-border>
</title-over-border> </div>
</div> </div>
</div> </a-spin>
</custom-modal> </custom-modal>
</template> </template>
@ -96,6 +107,10 @@
import ModalMixin from '@/mixins/ModalMixin' import ModalMixin from '@/mixins/ModalMixin'
import TitleOverBorder from '../TitleOverBorder.vue' import TitleOverBorder from '../TitleOverBorder.vue'
import CustomChart from '@/components/CustomChart/index.vue' import CustomChart from '@/components/CustomChart/index.vue'
import { getAction, postAction } from '@/api/manage'
import { cloneDeep } from 'lodash'
import { buildLineSeries } from '@/utils/chartHelper'
import SampleDataMixin from '../../SampleDataMixin'
const columns = [ const columns = [
{ {
@ -107,7 +122,7 @@ const columns = [
dataIndex: 'efficiency' dataIndex: 'efficiency'
}, },
{ {
title: 'Fit', title: 'Fit(keV)',
dataIndex: 'fit' dataIndex: 'fit'
}, },
{ {
@ -124,7 +139,7 @@ const initialOption = {
left: 70 left: 70
}, },
title: { title: {
text: 'Energy(keV)', text: 'Channel',
textStyle: { textStyle: {
color: '#8FD4F8', color: '#8FD4F8',
fontSize: 14, fontSize: 14,
@ -133,9 +148,20 @@ const initialOption = {
right: 10, right: 10,
bottom: 0 bottom: 0
}, },
tooltip: {
trigger: 'axis',
formatter: params => {
const [x, y] = params[0].value
const energy = parseInt(x)
const efficiency = y.toFixed(3)
return `<div class="channel">Energy: ${energy}</div>
<div class="energy">Efficiency: ${efficiency}</div>`
},
className: 'figure-chart-option-tooltip'
},
xAxis: { xAxis: {
min: 42, min: 1,
max: 2740, max: 'dataMax',
axisLabel: { axisLabel: {
color: '#fff' color: '#fff'
}, },
@ -163,7 +189,7 @@ const initialOption = {
splitLine: { splitLine: {
show: false show: false
}, },
name: 'Efficiency', name: 'keV',
nameLocation: 'center', nameLocation: 'center',
nameGap: 50, nameGap: 50,
nameTextStyle: { nameTextStyle: {
@ -171,48 +197,319 @@ const initialOption = {
fontSize: 14 fontSize: 14
} }
}, },
series: [ series: []
{
type: 'line',
symbol: 'square',
itemStyle: {
color: '#FF0000' //
},
lineStyle: {
color: '#C2CC11' // 线
},
data: [
[42, 0],
[100, 0.2],
[978, 0.1]
]
}
]
} }
const functions = [
{
label: 'Interpolation',
value: 1
},
{
label: 'HT Efficiency',
value: 5
},
{
label: 'Log Polynomial',
value: 6
},
{
label: 'Invlog Polynomial',
value: 8
},
{
label: 'HAE Efficiency(1-3)',
value: 93
},
{
label: 'HAE Efficiency(1-2)',
value: 94
},
{
label: 'HAE Efficiency(1-2-3)',
value: 95
}
]
export default { export default {
components: { TitleOverBorder, CustomChart }, components: { TitleOverBorder, CustomChart },
mixins: [ModalMixin], mixins: [ModalMixin, SampleDataMixin],
data() { data() {
this.columns = columns this.columns = columns
this.functions = functions
return { return {
list: [ isLoading: false,
{ equation: '',
energy: 'energy', dataSourceList: [],
efficiency: 'efficiency', list: [],
fit: 'fit', option: cloneDeep(initialOption),
delta: 'delta' selectedRowKeys: [],
model: {},
currSelectedDataSource: '',
appliedDataSource: '',
opts: {
notMerge: true
},
ECutAnalysis_Low: -1,
G_energy_span: -1,
funcId: 1
}
},
methods: {
async getData(currentText) {
try {
this.isLoading = true
const { sampleId, inputFileName: fileName } = this.sampleData
const { success, result, message } = await getAction('/gamma/EfficiencyCalibration', {
sampleId,
fileName,
currentText
})
this.isLoading = false
if (success) {
console.log('%c [ ]-220', 'font-size:13px; background:pink; color:#bf2c9f;', result)
const { list_dataSource, ECutAnalysis_Low, G_energy_span } = result
this.dataSourceList = list_dataSource
if (!currentText) {
this.currSelectedDataSource = list_dataSource[list_dataSource.length - 1]
this.appliedDataSource = list_dataSource[list_dataSource.length - 1]
}
this.ECutAnalysis_Low = ECutAnalysis_Low
this.G_energy_span = G_energy_span
this.handleResult(result)
} else {
this.$message.error(message)
} }
], } catch (error) {
option: initialOption console.error(error)
}
},
handleResult(result) {
const { AllData, equation, param, table, uncert } = result
//
if (AllData) {
const [linePoint, scatterPoint] = AllData
this.equation = equation
this.param = param
this.uncert = uncert
this.list = table
this.generateTableId()
const series = []
series.push(
buildLineSeries(
'LineSeries',
linePoint.pointlist.map(({ x, y }) => [x, y]),
linePoint.color
)
)
series.push({
type: 'scatter',
data: scatterPoint.pointlist.map(({ x, y }) => {
return {
value: [x, y],
itemStyle: {
color: scatterPoint.color,
borderWidth: 0
}
}
}),
emphasis: {
disabled: true
},
animation: false,
zlevel: 20
})
this.option.series = series
}
//
else {
this.option.series = []
}
},
beforeModalOpen() {
this.selectedRowKeys = []
this.funcId = 1
this.getData()
},
//
handleRowClick(row) {
this.model = cloneDeep(row)
},
//
handleInsert() {
const energy = parseFloat(this.model.energy)
const efficiency = parseFloat(this.model.efficiency)
if (Number.isNaN(energy) || Number.isNaN(efficiency)) {
this.$message.warn('Format is invalid.')
return
}
if (energy <= this.ECutAnalysis_Low || energy >= this.G_energy_span) {
this.$message.warn('Energy is out of analysis range.')
return
}
let i,
num = this.list.length
for (i = 0; i < num; ++i) {
const currEnergy = this.list[i].energy
if (Math.abs(currEnergy - energy) < 0.001) {
this.$message.warn('The centroid has already existed!')
return
} else if (currEnergy > energy) {
break
}
}
this.list.splice(i, 0, {
energy: energy,
efficiency
})
this.uncert.splice(i, 0, 0.5)
this.selectedRowKeys = [i]
this.generateTableId()
this.recalculate()
},
// tableid
generateTableId() {
this.list.forEach((item, index) => {
item.id = index
})
},
//
handleModify() {
if (this.selectedRowKeys.length) {
const energy = parseFloat(this.model.energy)
const efficiency = parseFloat(this.model.efficiency)
if (Number.isNaN(energy) || Number.isNaN(efficiency)) {
this.$message.warn('Format is invalid.')
return
}
if (energy <= this.ECutAnalysis_Low || energy >= this.G_energy_span) {
this.$message.warn('Energy is out of analysis range.')
return
}
const [currSelectedIndex] = this.selectedRowKeys
this.list[currSelectedIndex].energy = energy
this.list[currSelectedIndex].efficiency = efficiency
this.uncert[currSelectedIndex] = 0
this.recalculate()
}
},
//
handleDelete() {
if (this.selectedRowKeys.length) {
const [currSelectedIndex] = this.selectedRowKeys
this.list.splice(currSelectedIndex, 1)
this.uncert.splice(currSelectedIndex, 1)
this.generateTableId()
if (this.list.length) {
const selectedKey = this.selectedRowKeys[0]
if (selectedKey > this.list.length - 1) {
this.selectedRowKeys[0] = selectedKey - 1
}
} else {
this.selectedRowKeys = []
}
this.recalculate()
}
},
//
async recalculate() {
try {
this.isLoading = true
const { sampleId, inputFileName: fileName } = this.sampleData
const { success, result, message } = await postAction('/gamma/changeDataEfficiency', {
sampleId,
fileName,
m_vCurEnergy: this.list.map(item => item.energy),
m_vCurEffi: this.list.map(item => item.efficiency),
m_vCurUncert: this.uncert,
m_curParam: this.param,
funcId: this.funcId
})
if (success) {
this.handleResult(result)
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
} finally {
this.isLoading = false
}
},
//
async handleApply() {
try {
let curCalName = this.currSelectedDataSource
// InputPHD
if (!curCalName.includes('Input')) {
curCalName = `Input ${this.dataSourceList.filter(item => item.includes('Input')).length + 1}`
}
const { sampleId, inputFileName: fileName } = this.sampleData
const { success, result, message } = await postAction('/gamma/applyDataEfficiency', {
m_vCurEnergy: this.list.map(item => item.energy),
m_vCurEffi: this.list.map(item => item.efficiency),
m_vCurUncert: this.uncert,
m_curParam: this.param,
curCalName,
sampleId,
fileName
})
if (success) {
this.handleDataSourceClick(curCalName)
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
}
},
// DataSource
handleDataSourceClick(item) {
this.currSelectedDataSource = item
this.getData(item)
},
handleSetToCurrent() {
this.appliedDataSource = this.currSelectedDataSource
} }
} }
} }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.efficiency-calibration { .energy-calibration {
display: flex; display: flex;
margin-top: 5px;
.left { .left {
flex: 1; flex: 1;
@ -286,10 +583,11 @@ export default {
} }
.equation { .equation {
height: 32px; height: 40px;
line-height: 32px;
text-align: center;
background-color: #1b5465; background-color: #1b5465;
display: flex;
justify-content: center;
align-items: center;
} }
.curve { .curve {
@ -302,16 +600,21 @@ export default {
margin-left: 20px; margin-left: 20px;
.data-source { .data-source {
.title {
height: 32px;
line-height: 32px;
background-color: #296d81;
padding: 0 5px;
}
.content { .content {
height: 300px; height: 330px;
background-color: #275466; background-color: #275466;
overflow: auto;
.item {
height: 32px;
line-height: 32px;
padding: 0 5px;
cursor: pointer;
&.active {
background-color: #296d81;
}
}
} }
.footer { .footer {

View File

@ -56,7 +56,7 @@
<a-button type="primary">Save</a-button> <a-button type="primary">Save</a-button>
</div> </div>
<div> <div>
<a-button type="primary">Apply</a-button> <a-button type="primary" @click="handleApply">Apply</a-button>
</div> </div>
</div> </div>
</div> </div>
@ -68,7 +68,7 @@
<!-- curve --> <!-- curve -->
<title-over-border class="mt-20" title="curve"> <title-over-border class="mt-20" title="curve">
<div class="curve"> <div class="curve">
<custom-chart :option="option" /> <custom-chart :option="option" :opts="opts" />
</div> </div>
</title-over-border> </title-over-border>
</div> </div>
@ -102,7 +102,7 @@
import ModalMixin from '@/mixins/ModalMixin' import ModalMixin from '@/mixins/ModalMixin'
import TitleOverBorder from '../TitleOverBorder.vue' import TitleOverBorder from '../TitleOverBorder.vue'
import CustomChart from '@/components/CustomChart/index.vue' import CustomChart from '@/components/CustomChart/index.vue'
import { getAction } from '@/api/manage' import { getAction, postAction } from '@/api/manage'
import { cloneDeep } from 'lodash' import { cloneDeep } from 'lodash'
import { buildLineSeries } from '@/utils/chartHelper' import { buildLineSeries } from '@/utils/chartHelper'
import SampleDataMixin from '../../SampleDataMixin' import SampleDataMixin from '../../SampleDataMixin'
@ -143,6 +143,17 @@ const initialOption = {
right: 10, right: 10,
bottom: 0 bottom: 0
}, },
tooltip: {
trigger: 'axis',
formatter: params => {
const [x, y] = params[0].value
const channel = parseInt(x)
const energy = y.toFixed(3)
return `<div class="channel">Channel: ${channel}</div>
<div class="energy">Energy: ${energy}</div>`
},
className: 'figure-chart-option-tooltip'
},
xAxis: { xAxis: {
min: 1, min: 1,
max: 'dataMax', max: 'dataMax',
@ -198,61 +209,38 @@ export default {
selectedRowKeys: [], selectedRowKeys: [],
model: {}, model: {},
currSelectedDataSource: '', currSelectedDataSource: '',
appliedDataSource: '' appliedDataSource: '',
opts: {
notMerge: true
},
rg_high: -1,
rg_low: -1
} }
}, },
methods: { methods: {
async getData() { async getData(currentText) {
try { try {
this.isLoading = true this.isLoading = true
const { sampleId, inputFileName: fileName } = this.sampleData const { sampleId, inputFileName: fileName } = this.sampleData
const { success, result, message } = await getAction('/gamma/energyCalibration', { const { success, result, message } = await getAction('/gamma/energyCalibration', {
sampleId, sampleId,
fileName fileName,
currentText
}) })
this.isLoading = false this.isLoading = false
if (success) { if (success) {
console.log('%c [ ]-220', 'font-size:13px; background:pink; color:#bf2c9f;', result) const { list_dataSource, rg_high, rg_low } = result
const { AllData, equation, list_dataSource, param, table, uncert } = result this.dataSourceList = list_dataSource
const [linePoint, scatterPoint] = AllData if (!currentText) {
this.currSelectedDataSource = list_dataSource[list_dataSource.length - 1]
this.appliedDataSource = list_dataSource[list_dataSource.length - 1]
}
this.dataSourceList = [...list_dataSource, 'other'] this.rg_high = rg_high
this.currSelectedDataSource = list_dataSource[0] this.rg_low = rg_low
this.appliedDataSource = list_dataSource[0]
this.equation = equation this.handleResult(result)
table.forEach((item, index) => {
item.id = index
})
this.list = table
const series = []
series.push(
buildLineSeries(
'LineSeries',
linePoint.pointlist.map(({ x, y }) => [x, y]),
`rgb(${linePoint.color})`
)
)
series.push({
type: 'scatter',
data: scatterPoint.pointlist.map(({ x, y }) => {
return {
value: [x, y],
itemStyle: {
color: scatterPoint.color,
borderWidth: 0
}
}
}),
emphasis: {
disabled: true
},
animation: false,
zlevel: 20
})
this.option.series = series
} else { } else {
this.$message.error(message) this.$message.error(message)
} }
@ -261,14 +249,59 @@ export default {
} }
}, },
handleResult(result) {
const { AllData, equation, param, table, uncert } = result
//
if (AllData) {
const [linePoint, scatterPoint] = AllData
this.equation = equation
this.param = param
this.uncert = uncert
this.list = table
this.generateTableId()
const series = []
series.push(
buildLineSeries(
'LineSeries',
linePoint.pointlist.map(({ x, y }) => [x, y]),
linePoint.color
)
)
series.push({
type: 'scatter',
data: scatterPoint.pointlist.map(({ x, y }) => {
return {
value: [x, y],
itemStyle: {
color: scatterPoint.color,
borderWidth: 0
}
}
}),
emphasis: {
disabled: true
},
animation: false,
zlevel: 20
})
this.option.series = series
}
//
else {
this.option.series = []
}
},
beforeModalOpen() { beforeModalOpen() {
this.selectedRowKeys = []
this.getData() this.getData()
}, },
// //
handleRowClick(row, index) { handleRowClick(row) {
this.model = cloneDeep(row) this.model = cloneDeep(row)
this.currSelectedIndex = index
}, },
// //
@ -281,7 +314,7 @@ export default {
return return
} }
if (centroid <= 100 || centroid >= 16342) { if (centroid <= this.rg_low || centroid >= this.rg_high) {
this.$message.warn('Centroid must be in the range of analysis!') this.$message.warn('Centroid must be in the range of analysis!')
return return
} }
@ -298,22 +331,131 @@ export default {
} }
} }
console.log('%c [ 在位置插入 ]-297', 'font-size:13px; background:pink; color:#bf2c9f;', i)
this.list.splice(i, 0, { this.list.splice(i, 0, {
channel: centroid, channel: centroid,
energy energy
}) })
this.uncert.splice(i, 0, 0.5)
this.selectedRowKeys = [i]
this.generateTableId()
this.recalculate()
},
// tableid
generateTableId() {
this.list.forEach((item, index) => {
item.id = index
})
}, },
// //
handleModify() {}, handleModify() {
if (this.selectedRowKeys.length) {
const centroid = parseFloat(this.model.channel)
const energy = parseFloat(this.model.energy)
if (Number.isNaN(centroid) || Number.isNaN(energy)) {
this.$message.warn('Format is invalid.')
return
}
if (centroid <= this.rg_low || centroid >= this.rg_high) {
this.$message.warn('Centroid must be in the range of analysis!')
return
}
const [currSelectedIndex] = this.selectedRowKeys
this.list[currSelectedIndex].channel = centroid
this.list[currSelectedIndex].energy = energy
this.uncert[currSelectedIndex] = 0
this.recalculate()
}
},
// //
handleDelete() {}, handleDelete() {
if (this.selectedRowKeys.length) {
const [currSelectedIndex] = this.selectedRowKeys
this.list.splice(currSelectedIndex, 1)
this.uncert.splice(currSelectedIndex, 1)
this.generateTableId()
if (this.list.length) {
const selectedKey = this.selectedRowKeys[0]
if (selectedKey > this.list.length - 1) {
this.selectedRowKeys[0] = selectedKey - 1
}
} else {
this.selectedRowKeys = []
}
this.recalculate()
}
},
//
async recalculate() {
try {
this.isLoading = true
const { sampleId, inputFileName: fileName } = this.sampleData
const { success, result, message } = await postAction('/gamma/changeDataEnergy', {
sampleId,
fileName,
m_vCurCentroid: this.list.map(item => item.channel),
m_vCurEnergy: this.list.map(item => item.energy),
m_vCurUncert: this.uncert,
m_curParam: this.param
})
if (success) {
this.handleResult(result)
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
} finally {
this.isLoading = false
}
},
//
async handleApply() {
try {
let curCalName = this.currSelectedDataSource
// InputPHD
if (!curCalName.includes('Input')) {
curCalName = `Input ${this.dataSourceList.filter(item => item.includes('Input')).length + 1}`
}
const { sampleId, inputFileName: fileName } = this.sampleData
const { success, result, message } = await postAction('/gamma/applyDataEnergy', {
m_vCurCentroid: this.list.map(item => item.channel),
m_vCurEnergy: this.list.map(item => item.energy),
m_vCurUncert: this.uncert,
m_curParam: this.param,
curCalName,
sampleId,
fileName
})
if (success) {
this.handleDataSourceClick(curCalName)
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
}
},
// DataSource // DataSource
handleDataSourceClick(item) { handleDataSourceClick(item) {
this.currSelectedDataSource = item this.currSelectedDataSource = item
this.getData(item)
}, },
handleSetToCurrent() { handleSetToCurrent() {
@ -326,6 +468,7 @@ export default {
<style lang="less" scoped> <style lang="less" scoped>
.energy-calibration { .energy-calibration {
display: flex; display: flex;
margin-top: 5px;
.left { .left {
flex: 1; flex: 1;
@ -400,9 +543,10 @@ export default {
.equation { .equation {
height: 40px; height: 40px;
line-height: 32px;
text-align: center;
background-color: #1b5465; background-color: #1b5465;
display: flex;
justify-content: center;
align-items: center;
} }
.curve { .curve {

View File

@ -290,6 +290,7 @@ export default {
.nuclide-library { .nuclide-library {
display: flex; display: flex;
gap: 20px; gap: 20px;
margin-top: 5px;
&-list { &-list {
padding: 5px; padding: 5px;

View File

@ -1,89 +1,100 @@
<template> <template>
<custom-modal v-model="visible" :width="1280" title="Resolution Calibration" :footer="null"> <custom-modal v-model="visible" :width="1280" title="Resolution Calibration" :footer="null" destroy-on-close>
<div class="resolution-calibration"> <a-spin :spinning="isLoading">
<div class="left"> <div class="energy-calibration">
<!-- Calibration Data --> <div class="left">
<title-over-border title="Calibration Data"> <!-- Calibration Data -->
<div class="calibration-data"> <title-over-border title="Calibration Data">
<a-form-model <div class="calibration-data">
:colon="false" <a-form-model
:labelCol="{ :colon="false"
style: { :labelCol="{
width: '70px', style: {
textAlign: 'left', width: '70px',
flexShrink: 0 textAlign: 'left',
} flexShrink: 0
}" }
:wrapperCol="{ }"
style: { :wrapperCol="{
flex: 1 style: {
} flex: 1
}" }
> }"
<a-form-model-item label="Energy "> >
<a-input></a-input> <a-form-model-item label="Energy">
</a-form-model-item> <a-input type="number" v-model="model.energy"></a-input>
<a-form-model-item label="FWHM"> </a-form-model-item>
<a-input></a-input> <a-form-model-item label="FWHM">
</a-form-model-item> <a-input type="number" v-model="model.fwhm"></a-input>
<a-form-model-item :label="' '"> </a-form-model-item>
<a-button type="primary">Insert</a-button> <a-form-model-item :label="' '">
</a-form-model-item> <a-button type="primary" @click="handleInsert">Insert</a-button>
<a-form-model-item :label="' '"> </a-form-model-item>
<a-button type="primary">Modify</a-button> <a-form-model-item :label="' '">
</a-form-model-item> <a-button type="primary" @click="handleModify">Modify</a-button>
<a-form-model-item :label="' '"> </a-form-model-item>
<a-button type="primary">Delete</a-button> <a-form-model-item :label="' '">
</a-form-model-item> <a-button type="primary" @click="handleDelete">Delete</a-button>
</a-form-model> </a-form-model-item>
<!-- 表格 --> </a-form-model>
<a-table <!-- 表格 -->
:columns="columns" <custom-table
:dataSource="list" :columns="columns"
:pagination="false" :list="list"
:class="list.length ? 'has-data' : ''" :pagination="false"
:scroll="{ y: 182 }" size="small"
></a-table> :class="list.length ? 'has-data' : ''"
<!-- 表格结束 --> :scroll="{ y: 182 }"
<div class="operators"> :selectedRowKeys.sync="selectedRowKeys"
<div> :canDeselect="false"
<a-button type="primary">Call</a-button> @rowClick="handleRowClick"
<a-button type="primary">Save</a-button> ></custom-table>
</div> <!-- 表格结束 -->
<div> <div class="operators">
<a-button type="primary">Apply</a-button> <div>
<a-button type="primary">Call</a-button>
<a-button type="primary">Save</a-button>
</div>
<div>
<a-button type="primary" @click="handleApply">Apply</a-button>
</div>
</div> </div>
</div> </div>
</div> </title-over-border>
</title-over-border> <!-- Equation -->
<!-- Equation --> <title-over-border class="mt-20" title="Equation">
<title-over-border class="mt-20" title="Equation"> <div class="equation" v-html="equation"></div>
<div class="equation"> </title-over-border>
FWHM = (0.514363 + E * 0/00281408)<sup>1/2</sup> <!-- curve -->
</div> <title-over-border class="mt-20" title="curve">
</title-over-border> <div class="curve">
<!-- curve --> <custom-chart :option="option" :opts="opts" />
<title-over-border class="mt-20" title="curve">
<div class="curve">
<custom-chart :option="option" />
</div>
</title-over-border>
</div>
<div class="right">
<title-over-border title="Data Source" style="height: 100%">
<div class="data-source">
<div class="data-source-main">
<div class="title">PHD</div>
<div class="content"></div>
</div> </div>
<div class="footer mt-20"> </title-over-border>
<a-button type="primary">Set to Current</a-button> </div>
<div class="mt-20">CalResUpdate</div> <div class="right">
<title-over-border title="Data Source" style="height: 100%">
<div class="data-source">
<div class="content">
<div
class="item"
:class="item == currSelectedDataSource ? 'active' : ''"
v-for="(item, index) in dataSourceList"
:key="index"
@click="handleDataSourceClick(item)"
>
{{ item }}
</div>
</div>
<div class="footer mt-20">
<a-button type="primary" @click="handleSetToCurrent">Set to Current</a-button>
<div class="mt-20">{{ appliedDataSource }}</div>
</div>
</div> </div>
</div> </title-over-border>
</title-over-border> </div>
</div> </div>
</div> </a-spin>
</custom-modal> </custom-modal>
</template> </template>
@ -91,6 +102,10 @@
import ModalMixin from '@/mixins/ModalMixin' import ModalMixin from '@/mixins/ModalMixin'
import TitleOverBorder from '../TitleOverBorder.vue' import TitleOverBorder from '../TitleOverBorder.vue'
import CustomChart from '@/components/CustomChart/index.vue' import CustomChart from '@/components/CustomChart/index.vue'
import { getAction, postAction } from '@/api/manage'
import { cloneDeep } from 'lodash'
import { buildLineSeries } from '@/utils/chartHelper'
import SampleDataMixin from '../../SampleDataMixin'
const columns = [ const columns = [
{ {
@ -128,9 +143,20 @@ const initialOption = {
right: 10, right: 10,
bottom: 0 bottom: 0
}, },
tooltip: {
trigger: 'axis',
formatter: params => {
const [x, y] = params[0].value
const energy = parseInt(x)
const fwhm = y.toFixed(3)
return `<div class="channel">Energy: ${energy}</div>
<div class="energy">Fwhm: ${fwhm}</div>`
},
className: 'figure-chart-option-tooltip'
},
xAxis: { xAxis: {
min: 42, min: 1,
max: 2740, max: 'dataMax',
axisLabel: { axisLabel: {
color: '#fff' color: '#fff'
}, },
@ -166,48 +192,283 @@ const initialOption = {
fontSize: 14 fontSize: 14
} }
}, },
series: [ series: []
{
type: 'line',
symbol: 'square',
itemStyle: {
color: '#FF0000' //
},
lineStyle: {
color: '#C2CC11' // 线
},
data: [
[42, 0],
[100, 0.2],
[978, 0.1]
]
}
]
} }
export default { export default {
components: { TitleOverBorder, CustomChart }, components: { TitleOverBorder, CustomChart },
mixins: [ModalMixin], mixins: [ModalMixin, SampleDataMixin],
data() { data() {
this.columns = columns this.columns = columns
return { return {
list: [ isLoading: false,
{ equation: '',
energy: 'energy', dataSourceList: [],
fwhm: 'fwhm', list: [],
fit: 'fit', option: cloneDeep(initialOption),
delta: 'delta' selectedRowKeys: [],
model: {},
currSelectedDataSource: '',
appliedDataSource: '',
opts: {
notMerge: true
},
ECutAnalysis_Low: -1,
G_energy_span: -1
}
},
methods: {
async getData(currentText) {
try {
this.isLoading = true
const { sampleId, inputFileName: fileName } = this.sampleData
const { success, result, message } = await getAction('/gamma/resolutionCalibration', {
sampleId,
fileName,
currentText
})
this.isLoading = false
if (success) {
console.log('%c [ ]-220', 'font-size:13px; background:pink; color:#bf2c9f;', result)
const { list_dataSource, ECutAnalysis_Low, G_energy_span } = result
this.dataSourceList = list_dataSource
if (!currentText) {
this.currSelectedDataSource = list_dataSource[list_dataSource.length - 1]
this.appliedDataSource = list_dataSource[list_dataSource.length - 1]
}
this.ECutAnalysis_Low = ECutAnalysis_Low
this.G_energy_span = G_energy_span
this.handleResult(result)
} else {
this.$message.error(message)
} }
], } catch (error) {
option: initialOption console.error(error)
}
},
handleResult(result) {
const { AllData, equation, param, table, uncert } = result
//
if (AllData) {
const [linePoint, scatterPoint] = AllData
this.equation = equation
this.param = param
this.uncert = uncert
this.list = table
this.generateTableId()
const series = []
series.push(
buildLineSeries(
'LineSeries',
linePoint.pointlist.map(({ x, y }) => [x, y]),
linePoint.color
)
)
series.push({
type: 'scatter',
data: scatterPoint.pointlist.map(({ x, y }) => {
return {
value: [x, y],
itemStyle: {
color: scatterPoint.color,
borderWidth: 0
}
}
}),
emphasis: {
disabled: true
},
animation: false,
zlevel: 20
})
this.option.series = series
}
//
else {
this.option.series = []
}
},
beforeModalOpen() {
this.selectedRowKeys = []
this.getData()
},
//
handleRowClick(row) {
this.model = cloneDeep(row)
},
//
handleInsert() {
const energy = parseFloat(this.model.energy)
const fwhm = parseFloat(this.model.fwhm)
if (Number.isNaN(energy) || Number.isNaN(fwhm)) {
this.$message.warn('Format is invalid.')
return
}
if (energy <= this.ECutAnalysis_Low || energy >= this.G_energy_span) {
this.$message.warn('Energy is out of analysis range.')
return
}
let i,
num = this.list.length
for (i = 0; i < num; ++i) {
const currEnergy = this.list[i].energy
if (Math.abs(currEnergy - energy) < 0.001) {
this.$message.warn('The centroid has already existed!')
return
} else if (currEnergy > energy) {
break
}
}
this.list.splice(i, 0, {
energy: energy,
fwhm
})
this.uncert.splice(i, 0, 0.5)
this.selectedRowKeys = [i]
this.generateTableId()
this.recalculate()
},
// tableid
generateTableId() {
this.list.forEach((item, index) => {
item.id = index
})
},
//
handleModify() {
if (this.selectedRowKeys.length) {
const energy = parseFloat(this.model.energy)
const fwhm = parseFloat(this.model.fwhm)
if (Number.isNaN(energy) || Number.isNaN(fwhm)) {
this.$message.warn('Format is invalid.')
return
}
if (energy <= this.ECutAnalysis_Low || energy >= this.G_energy_span) {
this.$message.warn('Energy is out of analysis range.')
return
}
const [currSelectedIndex] = this.selectedRowKeys
this.list[currSelectedIndex].energy = energy
this.list[currSelectedIndex].fwhm = fwhm
this.uncert[currSelectedIndex] = 0
this.recalculate()
}
},
//
handleDelete() {
if (this.selectedRowKeys.length) {
const [currSelectedIndex] = this.selectedRowKeys
this.list.splice(currSelectedIndex, 1)
this.uncert.splice(currSelectedIndex, 1)
this.generateTableId()
if (this.list.length) {
const selectedKey = this.selectedRowKeys[0]
if (selectedKey > this.list.length - 1) {
this.selectedRowKeys[0] = selectedKey - 1
}
} else {
this.selectedRowKeys = []
}
this.recalculate()
}
},
//
async recalculate() {
try {
this.isLoading = true
const { sampleId, inputFileName: fileName } = this.sampleData
const { success, result, message } = await postAction('/gamma/changeDataResolution', {
sampleId,
fileName,
m_vCurEnergy: this.list.map(item => item.energy),
m_vCurReso: this.list.map(item => item.fwhm),
m_vCurUncert: this.uncert,
m_curParam: this.param
})
if (success) {
this.handleResult(result)
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
} finally {
this.isLoading = false
}
},
//
async handleApply() {
try {
let curCalName = this.currSelectedDataSource
// InputPHD
if (!curCalName.includes('Input')) {
curCalName = `Input ${this.dataSourceList.filter(item => item.includes('Input')).length + 1}`
}
const { sampleId, inputFileName: fileName } = this.sampleData
const { success, result, message } = await postAction('/gamma/applyDataResolution', {
m_vCurEnergy: this.list.map(item => item.energy),
m_vCurReso: this.list.map(item => item.fwhm),
m_vCurUncert: this.uncert,
m_curParam: this.param,
curCalName,
sampleId,
fileName
})
if (success) {
this.handleDataSourceClick(curCalName)
} else {
this.$message.error(message)
}
} catch (error) {
console.error(error)
}
},
// DataSource
handleDataSourceClick(item) {
this.currSelectedDataSource = item
this.getData(item)
},
handleSetToCurrent() {
this.appliedDataSource = this.currSelectedDataSource
} }
} }
} }
</script> </script>
<style lang="less" scoped> <style lang="less" scoped>
.resolution-calibration { .energy-calibration {
display: flex; display: flex;
margin-top: 5px;
.left { .left {
flex: 1; flex: 1;
@ -281,10 +542,11 @@ export default {
} }
.equation { .equation {
height: 32px; height: 40px;
line-height: 32px;
text-align: center;
background-color: #1b5465; background-color: #1b5465;
display: flex;
justify-content: center;
align-items: center;
} }
.curve { .curve {
@ -297,16 +559,21 @@ export default {
margin-left: 20px; margin-left: 20px;
.data-source { .data-source {
.title {
height: 32px;
line-height: 32px;
background-color: #296d81;
padding: 0 5px;
}
.content { .content {
height: 300px; height: 330px;
background-color: #275466; background-color: #275466;
overflow: auto;
.item {
height: 32px;
line-height: 32px;
padding: 0 5px;
cursor: pointer;
&.active {
background-color: #296d81;
}
}
} }
.footer { .footer {

View File

@ -3,8 +3,8 @@
<i @click="handleClick('left')"> <i @click="handleClick('left')">
<img src="@/assets/images/spectrum/left-arrow.png" /> <img src="@/assets/images/spectrum/left-arrow.png" />
</i> </i>
<span> <span @click="handleBtnClick">
<slot></slot> Peak Information
</span> </span>
<i @click="handleClick('right')"> <i @click="handleClick('right')">
<img src="@/assets/images/spectrum/right-arrow.png" /> <img src="@/assets/images/spectrum/right-arrow.png" />
@ -17,6 +17,9 @@ export default {
methods: { methods: {
handleClick(direction) { handleClick(direction) {
this.$emit('change', direction) this.$emit('change', direction)
},
handleBtnClick() {
this.$emit('click')
} }
} }
} }
@ -25,6 +28,7 @@ export default {
<style lang="less" scoped> <style lang="less" scoped>
.btn-with-switch-icon { .btn-with-switch-icon {
display: flex; display: flex;
gap: 10px;
justify-content: space-between; justify-content: space-between;
align-items: center; align-items: center;
border: 1px solid #0a544e; border: 1px solid #0a544e;
@ -41,9 +45,9 @@ export default {
} }
span { span {
white-space: nowrap; flex: 1;
overflow: hidden; text-align: center;
text-overflow: ellipsis; cursor: pointer;
} }
} }
</style> </style>

View File

@ -20,6 +20,8 @@
</template> </template>
<script> <script>
import { cloneDeep } from 'lodash'
const items = [ const items = [
{ {
label: ['Linear', 'Log10'], label: ['Linear', 'Log10'],
@ -56,7 +58,7 @@ const items = [
export default { export default {
data() { data() {
return { return {
items items: cloneDeep(items)
} }
}, },
methods: { methods: {

View File

@ -1,41 +1,19 @@
<template> <template>
<div class="nuclear-library"> <div class="nuclear-library">
<div class="nuclear-library-item" v-for="item in list" :key="item.id"> <div class="nuclear-library-item" v-for="(item, index) in list" :key="index">
{{ item.title }} {{ item }}
</div>
<div v-if="!list.length" class="is-empty">
<a-empty></a-empty>
</div> </div>
</div> </div>
</template> </template>
<script> <script>
export default { export default {
data() { props: {
return { list: {
list: [ type: Array
{
id: '1',
title: 'Ac228'
},
{
id: '2',
title: 'Ac229'
},
{
id: '3',
title: 'Ac230'
},
{
id: '4',
title: 'Eu152'
},
{
id: '5',
title: 'I132'
},
{
id: '6',
title: 'Ir192'
}
]
} }
} }
} }
@ -49,11 +27,10 @@ export default {
&-item { &-item {
padding: 4px 14px; padding: 4px 14px;
// cursor: pointer; }
// &:hover { .is-empty {
// background-color: #055565; padding: 20px 0;
// }
} }
} }
</style> </style>

File diff suppressed because it is too large Load Diff

View File

@ -81,11 +81,7 @@
<!-- 分析-设置弹窗结束 --> <!-- 分析-设置弹窗结束 -->
<!-- 分析工具弹窗开始 --> <!-- 分析工具弹窗开始 -->
<analyze-interactive-tool-modal <analyze-interactive-tool-modal v-model="analyzeInteractiveToolModalVisible" :sampleId="sampleData.sampleId" />
v-model="analyzeInteractiveToolModalVisible"
:sampleId="sampleData.sampleId"
@refresh="handleRefreshGamma"
/>
<!-- 分析工具弹窗结束 --> <!-- 分析工具弹窗结束 -->
<!-- Korsum 弹窗开始 --> <!-- Korsum 弹窗开始 -->
@ -493,11 +489,6 @@ export default {
this.$refs.betaGammaAnalysisRef && this.$refs.betaGammaAnalysisRef.resize() this.$refs.betaGammaAnalysisRef && this.$refs.betaGammaAnalysisRef.resize()
}, },
// gamma
handleRefreshGamma(data) {
this.$refs.gammaAnalysisRef.refresh(data)
},
// Beta-Gamma Energy Calibration // Beta-Gamma Energy Calibration
handleReanalyse(...data) { handleReanalyse(...data) {
this.$refs.betaGammaAnalysisRef.reanalyse(data) this.$refs.betaGammaAnalysisRef.reanalyse(data)