fix:修改测试出的问题

This commit is contained in:
he-zhi-cheng
2025-09-18 17:23:05 +08:00
parent 77ed33e66c
commit c414e66e2b
11 changed files with 794 additions and 312 deletions

View File

@ -1 +1 @@
{"pathofsave":null,"Filename":"testaa","caijiavgNumber":"1","useSG":false,"usehighpass":false,"Dispatcher":{"isenable":true,"begin":"06:25","end":"23:59"},"sensor_typeforset":"IRIS-IS11"}
{"pathofsave":null,"Filename":"testaa","caijiavgNumber":"1","useSG":false,"usehighpass":false,"Dispatcher":{"isenable":true,"begin":"09:28","end":"23:59"},"sensor_typeforset":"IS11"}

View File

@ -13,7 +13,7 @@
</GuiLeftSider>
<template #content>
<a-doption @click="onShowCurvesClick">显示曲线</a-doption>
<!-- <a-doption>Option 2</a-doption> -->
<a-doption @click="openCurveSaveDialogForSelectedFiles">数据导出</a-doption>
<!-- <a-doption>Option 3</a-doption> -->
</template>
</a-dropdown>
@ -36,6 +36,7 @@ import GuiForDataShow from './vuecomponents/GuiForDataShow.vue';
import GuiLeftSider from './vuecomponents/GuiLeftSider.vue';
import SaveFileDialog from './vuecomponents/SaveFileDialog.vue';
import { fs } from '@tauri-apps/api';
import { ElMessage } from 'element-plus';
export default {
name: 'APPDataview',
@ -171,7 +172,7 @@ export default {
await fs.copyFile(file.path, targetPath)
}
this.$message.success(`成功保存 ${files.length} 个文件到 ${location}`)
ElMessage.success(`成功保存 ${files.length} 个文件到 ${location}`)
} catch (error) {
console.error('保存文件失败:', error)
alert('保存文件失败: ' + error.message)
@ -182,13 +183,21 @@ export default {
handleCancelSave() {
this.showSaveDialog = false
this.filesToSave = []
}
},
async openCurveSaveDialogForSelectedFiles() {
const paths = (this.selectedFilePaths && this.selectedFilePaths.length > 0)
? this.selectedFilePaths
: (this.selectedFilePath ? [this.selectedFilePath] : []);
if (!paths.length) {
alert('请先选择一个或多个文件后再导出');
return;
}
this.$refs.GuiForDataShow.openSaveCurveDialogByPaths(paths);
},
},
}
</script>
<style scoped>

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 7.4 KiB

View File

@ -49,9 +49,19 @@ export default {
},
mounted() {
window.addEventListener("keydown", this.handlekeydown)
// 仅注册总线,键盘监听放在 activated
EventBus.on('SetMenubutton', this.setbutton);
},
activated() {
window.addEventListener("keydown", this.handlekeydown);
},
deactivated() {
window.removeEventListener("keydown", this.handlekeydown);
},
beforeUnmount() {
window.removeEventListener("keydown", this.handlekeydown);
EventBus.off && EventBus.off('SetMenubutton', this.setbutton);
},
methods: {
setbutton(command) {
if (command.name == "DC") {
@ -66,6 +76,15 @@ export default {
showbox() {
EventBus.emit('showbox', "hello", "提示11")
},
quit() {
EventBus.emit('triggerClearData');
setTimeout(() => {
EventBus.emit('changemainvue');
}, 100);
},
changemainvue() {
EventBus.emit('changemainvue');
},
@ -83,7 +102,20 @@ export default {
// this.$emit("menubalclicked", command)
},
handlekeydown(event) {
// console.log(event.key);
const t = event.target || {};
const tag = (t.tagName || '').toLowerCase();
const isEditable = t.isContentEditable || tag === 'input' || tag === 'textarea' || tag === 'select';
if (isEditable) return;
// 只处理来自 #app 内部的事件,忽略外部悬浮窗/插件
const appRoot = document.getElementById('app');
if (!appRoot || !appRoot.contains(event.target)) return;
// 不劫持系统复制快捷键 Ctrl+C
if (event.ctrlKey && !event.shiftKey && (event.key === 'c' || event.key === 'C')) {
return;
}
if (event.ctrlKey) {
if (event.key == "n" || event.key == "N") {
this.onmenuclick('Set', 'Workmode');
@ -94,15 +126,16 @@ export default {
if (event.key == "w" || event.key == "W") {
this.onmenuclick('Set', 'Weavelenth');
}
if (event.key == "c" || event.key == "C") {
// 与采集页保持一致:定标改为 Ctrl + Shift + C
if (event.shiftKey && (event.key == "c" || event.key == "C")) {
this.onmenuclick('Set', 'Calibrate');
}
}
},
openFolder() {
// 打开:先清理再打开
EventBus.emit('triggerClearData');
EventBus.emit('triggerOpenFolder');
},
@ -130,27 +163,27 @@ export default {
<BNavbarNav>
<BNavItemDropdown text="文件" right>
<BDropdownItem href="#">新建</BDropdownItem>
<!-- <BDropdownItem href="#">新建</BDropdownItem> -->
<BDropdownItem href="#" @click="openFolder">打开</BDropdownItem>
<BDropdownItem href="#" @click="saveFiles">保存</BDropdownItem>
<BDropdownItem href="#">另存为</BDropdownItem>
<!-- <BDropdownItem href="#">另存为</BDropdownItem> -->
<BDropdownDivider></BDropdownDivider>
<BDropdownItem href="#">退出</BDropdownItem>
<BDropdownItem href="#" @click="onmenuclick('File', 'Advance')">高级</BDropdownItem>
<BDropdownItem @click="onmenuclick('info', 'help')">帮助</BDropdownItem>
<BDropdownItem href="#" @click="quit()">退出</BDropdownItem>
<!-- <BDropdownItem href="#" @click="onmenuclick('File', 'Advance')">高级</BDropdownItem> -->
<!-- <BDropdownItem @click="onmenuclick('info', 'help')">帮助</BDropdownItem> -->
</BNavItemDropdown>
<!-- &lt;!&ndash; Navbar dropdowns &ndash;&gt;-->
<BNavItemDropdown text="设置" right>
<!-- <BDropdownItem @click="onmenuclick('Set','Workmode')">工作模式</BDropdownItem>
<!-- <BNavItemDropdown text="设置" right> -->
<!-- <BDropdownItem @click="onmenuclick('Set','Workmode')">工作模式</BDropdownItem>
<BDropdownItem @click="onmenuclick('Set','DevInfo')">设备信息</BDropdownItem> -->
<!-- <BDropdownItem @click="onmenuclick('Set','Weavelenth')">波长系数</BDropdownItem> -->
<!-- <BDropdownItem @click="onmenuclick('Set','Weavelenthcoeff')">波长设定</BDropdownItem>
<!-- <BDropdownItem @click="onmenuclick('Set','Weavelenth')">波长系数</BDropdownItem> -->
<!-- <BDropdownItem @click="onmenuclick('Set','Weavelenthcoeff')">波长设定</BDropdownItem>
<BDropdownItem @click="onmenuclick('Set','Calibrate')">定标</BDropdownItem>
<BDropdownItem @click="onmenuclick('Set','CalibrateHH3')">HH3定标</BDropdownItem> -->
</BNavItemDropdown>
<!-- </BNavItemDropdown> -->
<BNavItemDropdown text="窗口" right>

View File

@ -5,7 +5,7 @@
justify-content: space-between;">
<el-row class="secondhang">
<GuiForPlotShow @onComBox1="onComBox1" @onComBox2="onComBox2" @legendselectchanged="legendselectchanged"
ref="ASDPlotShow" class="plotcontainer">
@useDarkDnChanged="onUseDarkDnChanged" ref="ASDPlotShow" class="plotcontainer">
</GuiForPlotShow>
</el-row>
<el-row class="firsthang">
@ -30,9 +30,11 @@
import GuiForPlotShow from "./GuiForPlotShow.vue";
import GuiForDivesInfo from "./GuiForDivesInfo.vue";
import PictureDisplayInterface from "./PictureDisplayInterface.vue";
import { ref } from 'vue';
import { spectralTypeList } from '../../utils/irisDataDispose';
import { SpectralDataService } from '../../utils/spectralDataService';
import { ref, onMounted, onBeforeUnmount } from 'vue';
import { spectralTypeList, spectralProcessTypeList, getIrisDataDispose } from '../../utils/irisDataDispose';
import { SpectralDataService } from '../../utils/spectralDataService';
import { ElMessage } from 'element-plus';
import EventBus from "../../eventBus.js";
defineOptions({
name: "GuiForDataShow"
@ -42,20 +44,21 @@ const fromData = ref({
comBox1: spectralTypeList[0].value,
comBox2: '',
});
const useDarkDn = ref(true);
const ASDPlotShow = ref(null);
const GuiForDivesInforef = ref(null);
const PictureDisplayInterfaceRef = ref(null);
const spectralDataList = ref([]);
const spectralDataForInfo = ref([]); // 新增:专供 Info/图片使用的数据
const imgeList = ref([]);
const fileData = ref([]);
async function onloaddata(data) {
// 重置数据
spectralDataList.value = [];
spectralDataForInfo.value = []; // 新增:同步清空
imgeList.value = [];
fileData.value = [];
if (!data || data.length === 0) {
updateChildComponents([], [], []);
return;
@ -78,15 +81,43 @@ async function processSpectralData() {
const result = SpectralDataService.processSpectralData(
fileData.value,
fromData.value.comBox1,
fromData.value.comBox2
fromData.value.comBox2,
useDarkDn.value
);
spectralDataList.value = result.spectralDataList;
imgeList.value = result.imageList;
// 新增:构造独立于 spectralDataList 的 spectralDataForInfo
if (Array.isArray(result.spectralDataList) && result.spectralDataList.length > 0) {
spectralDataForInfo.value = result.spectralDataList;
} else {
// fallback基于 fileData 提取 environmentData 作为占位项
const envOnlyList = [];
for (const item of fileData.value) {
try {
const dispose = new getIrisDataDispose(item.data, fromData.value.comBox1, useDarkDn.value);
const env = dispose?.environmentData;
if (env) {
envOnlyList.push({
name: item.name || '',
datax: [],
datay: [],
environmentData: { ...env, fileName: item.name },
isEnvironmentOnly: true
});
}
} catch (e) {
console.warn('提取环境信息失败:', e);
}
}
spectralDataForInfo.value = envOnlyList;
}
updateChildComponents(
result.processedData,
result.spectralDataList,
spectralDataForInfo.value,
result.imageList
);
} catch (error) {
@ -95,20 +126,33 @@ async function processSpectralData() {
}
function updateChildComponents(processedData, spectralData, imageData) {
ASDPlotShow.value?.onloaddata(processedData, fileData.value);
GuiForDivesInforef.value?.onloaddata(spectralData);
PictureDisplayInterfaceRef.value?.onloaddata(imageData, spectralData);
}
const onComBox1 = (e) => {
// 光谱类型
const onComBox1 = async (e) => {
fromData.value.comBox1 = e;
processSpectralData();
await processSpectralData();
if (!spectralDataList.value || spectralDataList.value.length === 0) {
const typeLabel = spectralTypeList.find(i => i.value === fromData.value.comBox1)?.label || fromData.value.comBox1;
ElMessage.warning(`当前数据没有${typeLabel}数据`);
}
};
const onComBox2 = (val) => {
// 处理方式
const onComBox2 = async (val) => {
fromData.value.comBox2 = val;
if (fromData.value.comBox1) {
processSpectralData();
await processSpectralData();
if (!spectralDataList.value || spectralDataList.value.length === 0) {
const typeLabel = spectralTypeList.find(i => i.value === fromData.value.comBox1)?.label || fromData.value.comBox1;
ElMessage.warning(`当前数据没有${typeLabel}数据`);
}
}
};
@ -118,10 +162,10 @@ const legendselectchanged = (nameTable) => {
if (!element || element.length === 0) return false;
return element.some(item => {
const str = item.name.split('.')[0];
return nameTable.includes(str);
const str1 = (str || '').toString()?.split('_')[0];
return nameTable.split('_')[0] === str1;
});
});
const selectedSpectral = spectralDataList.value.filter(e =>
nameTable.includes(e.name)
);
@ -131,14 +175,53 @@ const legendselectchanged = (nameTable) => {
PictureDisplayInterfaceRef.value?.onloaddata(filteredImages, selectedSpectral);
}
} else {
GuiForDivesInforef.value?.onloaddata(spectralDataList.value);
PictureDisplayInterfaceRef.value?.onloaddata(imgeList.value, spectralDataList.value);
GuiForDivesInforef.value?.onloaddata(spectralDataForInfo.value);
PictureDisplayInterfaceRef.value?.onloaddata(imgeList.value, spectralDataForInfo.value);
}
};
function openSaveCurveDialog(selectedPaths) {
const selectedNames = Array.isArray(selectedPaths)
? selectedPaths.map(p => (p || '').toString().split(/[\\\/]/).pop()).filter(Boolean)
: [];
ASDPlotShow.value?.openSaveCurveDialog(selectedNames);
}
function openSaveCurveDialogByPaths(selectedPaths) {
ASDPlotShow.value?.openSaveCurveDialogByPaths(selectedPaths || []);
}
defineExpose({
onloaddata
onloaddata,
openSaveCurveDialog,
openSaveCurveDialogByPaths
});
// 新增:统一清理函数,响应 triggerClearData
function clearAll() {
// 清空本组件状态
spectralDataList.value = [];
spectralDataForInfo.value = []; // 新增:同步清空
imgeList.value = [];
fileData.value = [];
// 通知子组件清空
ASDPlotShow.value?.onloaddata([], []); // 清空图表
GuiForDivesInforef.value?.onloaddata([]); // 清空设备信息
PictureDisplayInterfaceRef.value?.clear?.(); // 清空图片显示
}
onMounted(() => {
EventBus.on('triggerClearData', clearAll);
});
onBeforeUnmount(() => {
EventBus.off('triggerClearData', clearAll);
});
// 新增:接收子组件复选框切换事件
const onUseDarkDnChanged = async (val) => {
useDarkDn.value = !!val;
await processSpectralData();
};
</script>
<style scoped>

View File

@ -8,6 +8,8 @@
@change="onComBox2">
<el-option v-for="item in spectralProcessTypeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
<el-checkbox class="blue-checkbox" v-model="fromDataPlot.useDarkDn"
@change="onUseDarkDnChanged">启用暗噪校正</el-checkbox>
<!-- <el-button class="plotbutton">求导</el-button>
<el-checkbox v-model="Prameter.smooth" @change="singleshowclicked($event, 'Smooth')">平滑</el-checkbox>
@ -56,21 +58,37 @@
<div class="save-select-group">
<div class="save-select-item">
<span class="save-label">光谱类型</span>
<el-select v-model="saveOptions.comBox1" placeholder="请选择" class="save-blue-select" style="width: 73%"
:rules="[{ required: true, message: '请选择光谱类型', trigger: 'change' }]">
<el-select
v-model="saveOptions.comBox1"
placeholder="请选择"
class="save-blue-select"
style="width: 73%"
:rules="[{ required: true, message: '请选择光谱类型', trigger: 'change' }]"
@change="onSaveComBox1"
>
<el-option v-for="item in spectralTypeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
<div class="save-select-item">
<span class="save-label">处理方式</span>
<el-select clearable v-model="saveOptions.comBox2" placeholder="请选择" class="save-blue-select"
style="width: 73%" :rules="[{ required: true, message: '请选择处理方式', trigger: 'change' }]">
<el-option v-for="item in spectralProcessTypeList" :key="item.value" :label="item.label"
:value="item.value" />
<el-select
clearable
v-model="saveOptions.comBox2"
placeholder="请选择"
class="save-blue-select"
style="width: 73%"
:rules="[{ required: true, message: '请选择处理方式', trigger: 'change' }]"
@change="onSaveComBox2"
>
<el-option v-for="item in spectralProcessTypeList" :key="item.value" :label="item.label" :value="item.value" />
</el-select>
</div>
</div>
<div class="save-setting" style="margin: 8px 0 12px 0; width: 104px;">
<el-checkbox v-model="saveOptions.useDarkDn" class="blue-checkbox">启用暗噪校正</el-checkbox>
</div>
<!-- 文件选择 -->
<div class="file-selection">
<div class="selection-header">
@ -129,11 +147,12 @@ defineOptions({
inheritAttrs: false
});
const emit = defineEmits(['onComBox1', 'legendselectchanged'])
const emit = defineEmits(['onComBox1', 'onComBox2', 'legendselectchanged', 'useDarkDnChanged'])
const images = import.meta.glob('../assets/*.png', { eager: true, import: 'default' })
const fromDataPlot = ref({
comBox1: spectralTypeList[0].value,
comBox2: '',
useDarkDn: true,
})
const dialogVisible = ref(false);
const colorList = [
@ -148,6 +167,11 @@ const onComBox1 = (val) => {
emit('onComBox1', val);
};
// 暗噪开关变更事件
const onUseDarkDnChanged = (val) => {
emit('useDarkDnChanged', !!val);
};
const echartsMenulist = ref([
{
@ -179,10 +203,63 @@ const saveOptions = reactive({
selectedFiles: [],
selectAllFiles: false,
fileName: '',
savePath: ''
savePath: '',
useDarkDn: true
});
// 添加半选状态
function openSaveCurveDialog(selectedNames) {
try {
if (!fileData.value || fileData.value.length === 0) {
alert('暂无有效的曲线数据!');
return;
}
// 打开弹窗并初始化默认项
saveDialogVisible.value = true;
initSaveOptions();
// 按照外部传入的文件名进行预选(文件名需与 fileData.value[*].name 匹配)
if (Array.isArray(selectedNames) && selectedNames.length > 0) {
const onlyNames = selectedNames.map(n => (n || '').toString().split(/[\\\/]/).pop());
const allNames = fileData.value.map(f => f.name);
saveOptions.selectedFiles = allNames.filter(n => onlyNames.includes(n));
updateSelectAllState();
}
} catch (error) {
alert('打开保存对话框失败: ' + error);
}
}
async function openSaveCurveDialogByPaths(filePaths) {
try {
const paths = Array.isArray(filePaths) ? filePaths.filter(Boolean) : [];
if (paths.length === 0) {
alert('请选择要导出的文件');
return;
}
// 仅为保存弹窗临时加载数据,不更新图表
const loaded = await SpectralDataService.loadFileData(paths);
if (!loaded || loaded.length === 0) {
alert('未能加载到有效的文件数据');
return;
}
fileData.value = loaded;
// 打开并初始化弹窗
saveDialogVisible.value = true;
initSaveOptions();
// 预勾选当前传入的文件
const onlyNames = paths.map(p => (p || '').toString().split(/[\\\/]/).pop());
const allNames = fileData.value.map(f => f.name);
saveOptions.selectedFiles = allNames.filter(n => onlyNames.includes(n));
updateSelectAllState();
} catch (error) {
alert('打开保存对话框失败: ' + error);
}
}
const isIndeterminate = ref(false);
// 处理保存对话框关闭
@ -225,6 +302,7 @@ function updateSelectAllState() {
function initSaveOptions() {
saveOptions.comBox1 = fromDataPlot.value.comBox1;
saveOptions.comBox2 = fromDataPlot.value.comBox2;
saveOptions.useDarkDn = fromDataPlot.value.useDarkDn;
// 默认选中所有文件
if (fileData.value && fileData.value.length > 0) {
@ -337,7 +415,7 @@ async function saveCurveData() {
await fs.writeTextFile(filePath, bom + content);
console.log("文件已成功保存到: " + filePath);
this.$message.success(`文件已成功保存到 ${filePath}`)
ElMessage.success(`文件已成功保存到 ${filePath}`)
saveDialogVisible.value = false;
} catch (error) {
@ -345,6 +423,38 @@ async function saveCurveData() {
}
}
// 保存弹窗:光谱类型选择变更
function onSaveComBox1(val) {
try {
saveOptions.comBox1 = val;
const targets = getPitchOnData(saveOptions);
if (!targets || !Array.isArray(targets) || targets.length === 0) {
const typeLabel = spectralTypeList.find(i => i.value === saveOptions.comBox1)?.label || saveOptions.comBox1;
ElMessage.warning(`当前数据没有${typeLabel}数据`);
}
} catch (error) {
console.error('保存弹窗光谱类型切换处理失败:', error);
}
}
// 保存弹窗:处理方式选择变更
function onSaveComBox2(val) {
try {
saveOptions.comBox2 = val;
if (saveOptions.comBox1) {
const targets = getPitchOnData(saveOptions);
if (!targets || !Array.isArray(targets) || targets.length === 0) {
const typeLabel = spectralTypeList.find(i => i.value === saveOptions.comBox1)?.label || saveOptions.comBox1;
ElMessage.warning(`当前数据没有${typeLabel}数据`);
}
}
} catch (error) {
console.error('保存弹窗处理方式切换处理失败:', error);
}
}
// 文件数据处理
function getPitchOnData(saveOptions) {
try {
@ -352,7 +462,8 @@ function getPitchOnData(saveOptions) {
fileData.value,
saveOptions.selectedFiles,
saveOptions.comBox1,
saveOptions.comBox2
saveOptions.comBox2,
saveOptions.useDarkDn
);
return result.processedData;
} catch (error) {
@ -462,10 +573,14 @@ function onloaddata(data, files) {
min: null,
max: null
};
option.value.yAxis = {
...option.value.yAxis,
min: null,
max: null
if (Array.isArray(option.value.yAxis)) {
option.value.yAxis = option.value.yAxis.map(ax => ({ ...ax, min: null, max: null }));
} else {
option.value.yAxis = {
...option.value.yAxis,
min: null,
max: null
};
};
// 遍历数据创建多条折线
@ -505,10 +620,14 @@ function onloaddata(data, files) {
min: -100,
max: 100
};
option.value.yAxis = {
...option.value.yAxis,
min: -100,
max: 100
if (Array.isArray(option.value.yAxis)) {
option.value.yAxis = option.value.yAxis.map(ax => ({ ...ax, min: -100, max: 100 }));
} else {
option.value.yAxis = {
...option.value.yAxis,
min: -100,
max: 100
};
};
option.value.series = [];
option.value.legend.data = [];
@ -532,12 +651,16 @@ function initChart() {
color: colorList,
grid: {
left: 10,
right: 40,
bottom: 0,
right: 30,
bottom: 30,
containLabel: true
},
toolbox: {
left: 'center',
feature: {
dataZoom: {},
restore: {}
}
},
animation: false,
xAxis: {
@ -549,36 +672,43 @@ function initChart() {
color: 'rgba(0, 0, 0, 0.2)'
}
},
axisTick: {
show: false
},
axisLabel: {
color: 'rgba(0, 0, 0, 0.70)'
}
axisTick: { show: false },
axisLabel: { color: 'rgba(0, 0, 0, 0.70)' }
},
yAxis: {
type: 'value',
min: -100,
max: 100,
axisLine: {
lineStyle: {
color: 'rgba(0, 0, 0, 0.2)'
}
yAxis: [
{
type: 'value',
min: -100,
max: 100,
axisLine: {
lineStyle: {
color: 'rgba(0, 0, 0, 0.2)'
}
},
axisTick: { show: false },
axisLabel: { color: 'rgba(0, 0, 0, 0.70)' },
position: 'left'
},
axisTick: {
show: false
},
axisLabel: {
color: 'rgba(0, 0, 0, 0.70)'
{
type: 'value',
min: -100,
max: 100,
axisLine: {
lineStyle: {
color: 'rgba(0, 0, 0, 0.2)'
}
},
axisTick: { show: false },
axisLabel: { color: 'rgba(0, 0, 0, 0.70)' },
position: 'right' // 右侧轴
}
},
],
dataZoom: [
{
type: 'inside',
},
{
type: 'inside',
}
// 显式绑定到 x/y 轴,支持框选缩放
{ type: 'inside', xAxisIndex: [0], filterMode: 'none' },
{ type: 'inside', yAxisIndex: [0], filterMode: 'none' },
{ type: 'slider', xAxisIndex: [0], filterMode: 'none', height: 35, bottom: 15 },
{ type: 'slider', yAxisIndex: [0], filterMode: 'none', width: 35, right: 25 }
],
legend: {
itemHeight: 2,
@ -592,14 +722,10 @@ function initChart() {
height: 30,
width: 400,
pageIconColor: '#4271EE',
pageTextStyle: {
color: '#4271EE'
},
pageTextStyle: { color: '#4271EE' },
itemWidth: 14,
itemHeight: 10,
textStyle: {
color: 'rgba(0, 0, 0, 0.70)'
},
textStyle: { color: 'rgba(0, 0, 0, 0.70)' },
selectedMode: 'multiple'
},
series: [
@ -607,13 +733,21 @@ function initChart() {
data: [],
type: 'line',
symbol: 'none',
smooth: true,
smooth: true
}
]
};
let selectedLegend = null;
chart.setOption(option.value, true);
// 启用“左键框选缩放”模式
chart.dispatchAction({
type: 'takeGlobalCursor',
key: 'dataZoomSelect',
dataZoomSelectActive: true
});
window.addEventListener('resize', echartresize);
// 监听图例点击事件,控制单条显示与恢复全部
@ -623,7 +757,6 @@ function initChart() {
if (selectedLegend === clickedName) {
emit("legendselectchanged", '')
// 恢复全部
selectedLegend = null;
option.value.series.forEach(item => {
chart.dispatchAction({ type: 'legendSelect', name: item.name });
@ -641,7 +774,13 @@ function initChart() {
}
});
// 双击恢复缩放到初始范围
chart.getZr().off('dblclick');
chart.getZr().on('dblclick', () => {
(option.value.dataZoom || []).forEach((_, idx) => {
chart.dispatchAction({ type: 'dataZoom', dataZoomIndex: idx, start: 0, end: 100 });
});
});
}
@ -670,12 +809,19 @@ function flushplot() {
const chart = echarts.getInstanceByDom(chartDom);
if (chart) {
setTimeout(() => {
chart.setOption(option.value, true);
chart.setOption(option.value, true);
chart.dispatchAction({
type: 'dataZoom',
start: 0,
end: 100
});
chart.dispatchAction({
type: 'takeGlobalCursor',
key: 'dataZoomSelect',
dataZoomSelectActive: true
});
chart.resize();
}, 0);
}
}
@ -709,7 +855,9 @@ onBeforeUnmount(() => {
defineExpose({
onloaddata,
Prameter,
fromDataPlot
fromDataPlot,
openSaveCurveDialog,
openSaveCurveDialogByPaths
});
</script>
@ -755,8 +903,17 @@ defineExpose({
.blue-select :deep(.el-input__wrapper.is-focus) {}
.blue-select:nth-child(2) {
margin-left: 20px;
.blue-select {
margin-right: 20px;
}
.blue-checkbox :deep(.el-checkbox__input.is-checked .el-checkbox__inner) {
background-color: rgba(66, 113, 238, 1);
border-color: rgba(66, 113, 238, 1);
}
.blue-checkbox :deep(.el-checkbox__input.is-checked+.el-checkbox__label) {
color: #4271EE;
}
.save-blue-select:deep(.el-select__wrapper) {

View File

@ -54,14 +54,27 @@ export default {
async mounted() {
window.addEventListener("keydown", this.handleKeyDown);
window.addEventListener("keyup", this.handleKeyUp);
// 额外增加:用鼠标事件同步按键状态,防止 keyup 丢失导致“多选卡住”
window.addEventListener("mousedown", this.handleMouseDown, true); // 捕获阶段更稳妥
window.addEventListener("mouseup", this.handleMouseUp, true);
window.addEventListener("blur", this.resetModifierKeys); // 窗口失焦时重置
document.addEventListener("visibilitychange", this.handleVisibilityChange);
// 事件总线
EventBus.on('triggerOpenFolder', this.onopendata);
EventBus.on('triggerSaveFiles', this.handleSaveFiles);
EventBus.on('triggerClearData', this.clearData);
},
beforeUnmount() {
window.removeEventListener("keydown", this.handleKeyDown);
window.removeEventListener("keyup", this.handleKeyUp);
// 配套移除新增的监听
window.removeEventListener("mousedown", this.handleMouseDown, true);
window.removeEventListener("mouseup", this.handleMouseUp, true);
window.removeEventListener("blur", this.resetModifierKeys);
document.removeEventListener("visibilitychange", this.handleVisibilityChange);
EventBus.off('triggerOpenFolder', this.onopendata);
EventBus.off('triggerSaveFiles', this.handleSaveFiles);
EventBus.off('triggerClearData', this.clearData);
},
methods: {
handleKeyDown(event) {
@ -80,6 +93,26 @@ export default {
this.shiftKeyPressed = false;
}
},
// 新增:鼠标按下/松开时同步 Ctrl/Shift 状态(点击流程更可靠)
handleMouseDown(e) {
this.ctrlKeyPressed = !!e.ctrlKey;
this.shiftKeyPressed = !!e.shiftKey;
},
handleMouseUp(e) {
// 鼠标抬起时再次以实际状态为准(若用户已松开 Ctrl/Shift这里会回到 false
this.ctrlKeyPressed = !!e.ctrlKey;
this.shiftKeyPressed = !!e.shiftKey;
},
// 新增:窗口不可见/失焦时,重置修饰键,避免卡住
handleVisibilityChange() {
if (document.visibilityState !== 'visible') {
this.resetModifierKeys();
}
},
resetModifierKeys() {
this.ctrlKeyPressed = false;
this.shiftKeyPressed = false;
},
collectAllFiles(node) {
const files = [];
@ -295,29 +328,84 @@ export default {
this.$emit("reset");
this.data = []
const folderTree = await this.$tauriApi.getFolderList(this.DefualtPath);
// 添加唯一ID
const getComparableLabel = (node) => {
if (typeof node?.label !== "string") return "";
if (node.isLeaf) {
return node.label.replace(/\.[^/.]+$/, "");
}
return node.label;
};
// 工具从名称中提取日期YYYY[_-]M[M]?[_-]D[D]?),返回时间戳,未匹配返回 null
const extractDateStamp = (node) => {
const base = getComparableLabel(node);
// 支持 2025_9_3、2025-9-3、2025_09_03、2025-09-03
const m = base.match(/(\d{4})[_-](\d{1,2})[_-](\d{1,2})/);
if (!m) return null;
const y = parseInt(m[1], 10);
const M = parseInt(m[2], 10);
const d = parseInt(m[3], 10);
const dt = new Date(y, M - 1, d);
if (
Number.isNaN(dt.getTime()) ||
dt.getFullYear() !== y ||
dt.getMonth() !== (M - 1) ||
dt.getDate() !== d
) {
return null;
}
return dt.getTime();
};
// 添加唯一ID并进行过滤 + 排序(同级文件夹与文件按日期由近到远,无日期排后且保持原序)
let idCounter = 1;
const addUniqueIdsAndFilter = (node) => {
node.id = idCounter++;
if (node.isFolder) {
if (Array.isArray(node.children) && node.children.length) {
// 过滤:仅保留文件夹与 .iris 文件
node.children = node.children.filter(child => {
if (child.isFolder) return true;
if (child.isLeaf && typeof child.label === 'string') {
return child.label.endsWith('.iris');
if (child.isLeaf && typeof child.label === "string") {
return child.label.endsWith(".iris");
}
return false;
});
// 排序:按包含的日期(忽略后缀)由近到远;无日期排在后面并保持原有顺序
const decorated = node.children.map((child, idx) => ({
child,
idx,
stamp: extractDateStamp(child) // number | null
}));
decorated.sort((a, b) => {
const aHas = typeof a.stamp === "number";
const bHas = typeof b.stamp === "number";
if (aHas && bHas) {
return b.stamp - a.stamp; // 近(新) -> 远(旧)
}
if (aHas && !bHas) return -1; // 有日期在前
if (!aHas && bHas) return 1; // 无日期在后
// 都没有日期:保持原有顺序(稳定)
return a.idx - b.idx;
});
node.children = decorated.map(d => d.child);
// 递归处理
node.children.forEach(child => addUniqueIdsAndFilter(child));
}
} else {
// 非文件夹无需处理子项
}
};
addUniqueIdsAndFilter(folderTree);
if (folderTree && folderTree.label != "请选择") {
this.data = [folderTree];
}
// 收集所有id用于默认展开
const expandedKeys = [];
this.collectAllNodeIds(folderTree, expandedKeys);
@ -366,7 +454,15 @@ export default {
return allFiles;
},
// 清空数据
clearData() {
this.$emit("reset");
this.data = []
}
}
}
</script>
@ -388,7 +484,7 @@ el-tree {
.el-treecontain {
width: 100%;
text-align: left;
max-height: 96vh;
max-height: 88vh;
overflow-y: auto;
}

View File

@ -172,10 +172,21 @@ const fullscreenChangeHandler = () => {
isFullscreen.value = !!document.fullscreenElement;
};
// 新增:清空地图矢量图层的方法
const clearMap = () => {
if (vectorLayer.value && vectorLayer.value.getSource()) {
vectorLayer.value.getSource().clear();
}
};
watch(
() => props.dataListMap,
(newVal) => {
if (!Array.isArray(newVal) || newVal.length === 0) return;
// 当传入空数组或非法数据时,清空图层中的点
if (!Array.isArray(newVal) || newVal.length === 0) {
clearMap();
return;
}
const tryAdd = () => {
if (isMapReady.value) {
@ -205,6 +216,10 @@ onBeforeUnmount(() => {
document.removeEventListener('fullscreenchange', fullscreenChangeHandler);
});
// 对外暴露清空方法,供父组件调用
defineExpose({
clearMap
});
</script>
<style scoped>

View File

@ -49,9 +49,22 @@ export default {
},
mounted() {
window.addEventListener("keydown",this.handlekeydown)
// 仅在挂载时注册总线,不在这里绑定全局键盘事件(避免 KeepAlive 导致的重复/遗留绑定)
EventBus.on('SetMenubutton',this.setbutton);
},
activated() {
// 仅在当前页面处于激活状态时绑定
window.addEventListener("keydown", this.handlekeydown);
},
deactivated() {
// 从可见切换为缓存(隐藏)时,解绑,避免隐藏页误触发
window.removeEventListener("keydown", this.handlekeydown);
},
beforeUnmount() {
// 彻底卸载时,兜底解绑
window.removeEventListener("keydown", this.handlekeydown);
EventBus.off && EventBus.off('SetMenubutton', this.setbutton);
},
methods: {
setbutton(command){
if (command.name == "DC"){
@ -83,7 +96,21 @@ export default {
this.$emit("menubalclicked", command)
},
handlekeydown(event) {
// console.log(event.key);
// 在可编辑环境中不触发应用快捷键
const t = event.target || {};
const tag = (t.tagName || '').toLowerCase();
const isEditable = t.isContentEditable || tag === 'input' || tag === 'textarea' || tag === 'select';
if (isEditable) return;
// 只处理来自本应用根节点(#app)内的事件,忽略外部悬浮窗/插件
const appRoot = document.getElementById('app');
if (!appRoot || !appRoot.contains(event.target)) return;
// 不劫持系统复制快捷键 Ctrl+C
if (event.ctrlKey && !event.shiftKey && (event.key === 'c' || event.key === 'C')) {
return;
}
if (event.ctrlKey) {
if (event.key == "n" || event.key == "N") {
this.onmenuclick('Set', 'Workmode');
@ -94,11 +121,10 @@ export default {
if (event.key == "w" || event.key == "W") {
this.onmenuclick('Set', 'Weavelenth');
}
if (event.key == "c" || event.key == "C") {
// 将“定标”快捷键改为 Ctrl + Shift + C避免与系统复制冲突
if (event.shiftKey && (event.key == "c" || event.key == "C")) {
this.onmenuclick('Set', 'Calibrate');
}
}
}
}

View File

@ -7,11 +7,12 @@ class getIrisDataDispose {
devinfoData;
environmentData;
constructor(irisData, spectralName) {
constructor(irisData, spectralName, useDarkDn = true) {
this.irisData = irisData;
this.spectralName = spectralName;
this.spectral_data = irisData.spectral_data_section;
this.image_info = irisData.image_info_section;
this.useDarkDn = useDarkDn;
for (const element of irisData.spectral_info_section) {
if (element.info_type == "devinfo") {
@ -40,10 +41,79 @@ class getIrisDataDispose {
//获取一般后端直接返回的类型
getFileSpectralData() {
// 基础类型适配暗噪开关ground_dn / flat_dn 在启用暗噪时做 “- dark_dn”
const nameLower = (this.spectralName || '').toLowerCase();
const bands = this.devinfoData?.bandnum ?? 0;
const needDarkCorr =
this.useDarkDn && (nameLower === 'ground_dn' || nameLower === 'flat_dn');
if (needDarkCorr) {
let mainEl = null; // ground_dn 或 flat_dn 的原始 element
let darkEl = null; // dark_dn 的原始 element
for (const element of this.spectral_data) {
const lower = (element.name || '').toLowerCase();
if (!mainEl && lower.includes(nameLower)) {
mainEl = element;
} else if (!darkEl && lower.includes('dark_dn')) {
darkEl = element;
}
if (mainEl && darkEl) break;
}
if (!mainEl) {
console.error(`未找到 ${nameLower} 数据,无法计算`);
return undefined;
}
const mainTyped = manageSpectralData(mainEl, this.devinfoData);
const main = Array.isArray(mainTyped) ? mainTyped : Array.from(mainTyped || []);
const darkTyped = darkEl ? manageSpectralData(darkEl, this.devinfoData) : null;
const dark = darkTyped ? (Array.isArray(darkTyped) ? darkTyped : Array.from(darkTyped)) : null;
const corrected = [];
const invalidCount = { missing: 0, invalidResult: 0 };
for (let i = 0; i < bands; i++) {
const mv = main[i];
const dv = dark ? (dark[i] ?? 0) : 0;
if (mv === undefined) {
corrected.push(0);
invalidCount.missing++;
continue;
}
const v = mv - dv;
if (Number.isFinite(v) && !Number.isNaN(v)) {
corrected.push(v);
} else {
corrected.push(0);
invalidCount.invalidResult++;
}
}
if (!dark) {
console.warn(`${nameLower} 去暗噪: 未找到 dark_dn按 0 处理`);
} else if (dark.length !== bands) {
console.warn(
`${nameLower} 去暗噪: dark_dn 长度(${dark.length})与波段数(${bands})不一致,按可用索引减,缺失部分按 0`
);
}
if (invalidCount.missing > 0 || invalidCount.invalidResult > 0) {
console.warn(
`${nameLower} 去暗噪: 缺失值 ${invalidCount.missing} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${corrected.length}`
);
}
return { ...mainEl, normalArray: corrected };
}
// 默认路径:保持原逻辑(未启用暗噪或其它基础类型)
for (const element of this.spectral_data) {
const typedArray = manageSpectralData(element, this.devinfoData);
const normalArray = Array.from(typedArray);
if (element.name.toLowerCase().includes(this.spectralName)) {
if ((element.name || '').toLowerCase().includes(nameLower)) {
return { ...element, normalArray };
}
}
@ -74,196 +144,178 @@ class getIrisDataDispose {
spectralDataMap.set("gain", { ...element, normalArray });
}
}
if (
spectralDataMap.get("ground_dn") &&
spectralDataMap.get("flat_dn") &&
spectralDataMap.get("dark_dn") &&
spectralDataMap.get("gain")
) {
const obj1 = {
ground_dn: spectralDataMap.get("ground_dn").normalArray,
flat_dn: spectralDataMap.get("flat_dn").normalArray,
dark_dn: spectralDataMap.get("dark_dn").normalArray,
gain: spectralDataMap.get("gain").normalArray,
};
const arrAll = mergeObjectArrays(obj1);
const name = spectralDataMap.get("ground_dn").name.split("_")[0];
// 通用的数值验证函数
const validateAndPush = (array, value, type, invalidCount) => {
if (isFinite(value) && !isNaN(value)) {
array.push(value);
return true;
// 分支依赖校验与辅助函数
const has = (key) => !!spectralDataMap.get(key);
const requireDeps = (deps) => deps.every((k) => has(k));
const buildArrAll = (keys) => {
const obj = {};
for (const k of keys) obj[k] = spectralDataMap.get(k).normalArray;
return mergeObjectArrays(obj);
};
const baseName = (...preferredKeys) => {
for (const k of preferredKeys) {
if (has(k)) return spectralDataMap.get(k).name.split("_")[0];
}
return "unknown";
};
// 结果验证(依赖不够时不会走到这里)
const validateResult = (array, name, type) => {
if (array.length === 0) {
console.error(`${type}计算错误: 没有有效的数据点,无法生成图表`);
return { normalArray: [], name: name };
}
return { normalArray: array, name: name };
};
if (this.spectralName == "radiance_ground") {
const deps = ["gain", "ground_dn"].concat(this.useDarkDn ? ["dark_dn"] : []);
if (!requireDeps(deps)) return undefined; // 依赖不够,直接返回空,保持原逻辑
const arrAll = buildArrAll(deps);
const name = baseName("ground_dn", "gain");
const radiance_ground = [];
const invalidCount = { zeroDiv: 0, invalidResult: 0 };
for (const element of arrAll) {
const gainExposure = spectralDataMap.get("gain").exposure;
const groundExposure = spectralDataMap.get("ground_dn").exposure;
if (Math.abs(groundExposure) < 1e-10) {
invalidCount.zeroDiv++;
radiance_ground.push(0);
continue;
}
const exposureRatio = gainExposure / groundExposure;
const dnDiff = element.ground_dn - (this.useDarkDn ? element.dark_dn : 0);
const a = exposureRatio * (element.gain * dnDiff);
if (isFinite(a) && !isNaN(a)) {
radiance_ground.push(a);
} else {
invalidCount.invalidResult++;
return false;
radiance_ground.push(0);
}
};
// 通用的除零检查函数
const checkDivision = (numerator, denominator, type, invalidCount) => {
}
if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
console.warn(`radiance_ground计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${radiance_ground.length}`);
}
return validateResult(radiance_ground, name + "_radiance_ground", "radiance_ground");
} else if (this.spectralName == "radiance_flat") {
const deps = ["gain", "flat_dn"].concat(this.useDarkDn ? ["dark_dn"] : []);
if (!requireDeps(deps)) return undefined; // 依赖不够,直接返回空
const arrAll = buildArrAll(deps);
const name = baseName("flat_dn", "gain");
const radiance_flat = [];
const invalidCount = { zeroDiv: 0, invalidResult: 0 };
for (const element of arrAll) {
const gainExposure = spectralDataMap.get("gain").exposure;
const flatExposure = spectralDataMap.get("flat_dn").exposure;
if (Math.abs(flatExposure) < 1e-10) {
invalidCount.zeroDiv++;
radiance_flat.push(0);
continue;
}
const exposureRatio = gainExposure / flatExposure;
const dnDiff = element.flat_dn - (this.useDarkDn ? element.dark_dn : 0);
const b = exposureRatio * (element.gain * dnDiff);
if (isFinite(b) && !isNaN(b)) {
radiance_flat.push(b);
} else {
invalidCount.invalidResult++;
radiance_flat.push(0);
}
}
if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
console.warn(`radiance_flat计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${radiance_flat.length}`);
}
return validateResult(radiance_flat, name + "_radiance_flat", "radiance_flat");
} else if (this.spectralName == "refrad") {
const deps = ["gain", "ground_dn", "flat_dn"].concat(this.useDarkDn ? ["dark_dn"] : []);
if (!requireDeps(deps)) return undefined; // 依赖不够,直接返回空
const arrAll = buildArrAll(deps);
const name = baseName("ground_dn", "flat_dn", "gain");
const refrad = [];
const invalidCount = { zeroDiv: 0, invalidResult: 0 };
for (const element of arrAll) {
const gainExposure = spectralDataMap.get("gain").exposure;
const groundExposure = spectralDataMap.get("ground_dn").exposure;
const flatExposure = spectralDataMap.get("flat_dn").exposure;
if (Math.abs(groundExposure) < 1e-10 || Math.abs(flatExposure) < 1e-10) {
invalidCount.zeroDiv++;
refrad.push(0);
continue;
}
const groundRatio = gainExposure / groundExposure;
const flatRatio = gainExposure / flatExposure;
const groundDnDiff = element.ground_dn - (this.useDarkDn ? element.dark_dn : 0);
const flatDnDiff = element.flat_dn - (this.useDarkDn ? element.dark_dn : 0);
const a = groundRatio * (element.gain * groundDnDiff);
const b = flatRatio * (element.gain * flatDnDiff);
if (Math.abs(b) < 1e-10) {
invalidCount.zeroDiv++;
refrad.push(0);
} else {
const c = a / b;
if (isFinite(c) && !isNaN(c)) {
refrad.push(c);
} else {
invalidCount.invalidResult++;
refrad.push(0);
}
}
}
if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
console.warn(`refrad计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${refrad.length}`);
}
return validateResult(refrad, name + "_refrad", "refrad");
} else if (this.spectralName == "flat_ref") {
const deps = ["ground_dn", "flat_dn"].concat(this.useDarkDn ? ["dark_dn"] : []);
if (!requireDeps(deps)) return undefined; // 依赖不够,直接返回空
const arrAll = buildArrAll(deps);
const name = baseName("ground_dn", "flat_dn");
const validData = [];
const invalidCount = { zeroDiv: 0, invalidResult: 0 };
for (const element of arrAll) {
const denominator = element.flat_dn - (this.useDarkDn ? element.dark_dn : 0);
const numerator = element.ground_dn - (this.useDarkDn ? element.dark_dn : 0);
if (Math.abs(denominator) < 1e-10) {
invalidCount.zeroDiv++;
return null;
}
return numerator / denominator;
};
// 通用的结果验证和返回函数
const validateResult = (array, name, type) => {
if (array.length === 0) {
console.error(`${type}计算错误: 没有有效的数据点,无法生成图表`);
return { normalArray: [], name: name };
}
return { normalArray: array, name: name };
};
if (this.spectralName == "radiance_ground") {
const radiance_ground = [];
const invalidCount = { zeroDiv: 0, invalidResult: 0 };
for (const element of arrAll) {
const gainExposure = spectralDataMap.get("gain").exposure;
const groundExposure = spectralDataMap.get("ground_dn").exposure;
// 检查曝光时间除零 - 改为补充0值
if (Math.abs(groundExposure) < 1e-10) {
invalidCount.zeroDiv++;
radiance_ground.push(0);
continue;
}
const exposureRatio = gainExposure / groundExposure;
const dnDiff = element.ground_dn - element.dark_dn;
const a = exposureRatio * (element.gain * dnDiff);
// 验证结果无效时补充0值
if (isFinite(a) && !isNaN(a)) {
radiance_ground.push(a);
} else {
invalidCount.invalidResult++;
radiance_ground.push(0);
}
}
// 记录统计信息
if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
console.warn(`radiance_ground计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${radiance_ground.length}`);
}
return validateResult(radiance_ground, name + "_radiance_ground", 'radiance_ground');
} else if (this.spectralName == "radiance_flat") {
const radiance_flat = [];
const invalidCount = { zeroDiv: 0, invalidResult: 0 };
for (const element of arrAll) {
const gainExposure = spectralDataMap.get("gain").exposure;
const flatExposure = spectralDataMap.get("flat_dn").exposure;
// 检查曝光时间除零 - 改为补充0值
if (Math.abs(flatExposure) < 1e-10) {
invalidCount.zeroDiv++;
radiance_flat.push(0);
continue;
}
const exposureRatio = gainExposure / flatExposure;
const dnDiff = element.flat_dn - element.dark_dn;
const b = exposureRatio * (element.gain * dnDiff);
// 验证结果无效时补充0值
validData.push(0);
} else {
const b = numerator / denominator;
if (isFinite(b) && !isNaN(b)) {
radiance_flat.push(b);
validData.push(b);
} else {
invalidCount.invalidResult++;
radiance_flat.push(0);
}
}
// 记录统计信息
if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
console.warn(`radiance_flat计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${radiance_flat.length}`);
}
return validateResult(radiance_flat, name + "_radiance_flat", 'radiance_flat');
} else if (this.spectralName == "refrad") {
const refrad = [];
const invalidCount = { zeroDiv: 0, invalidResult: 0 };
for (const element of arrAll) {
const gainExposure = spectralDataMap.get("gain").exposure;
const groundExposure = spectralDataMap.get("ground_dn").exposure;
const flatExposure = spectralDataMap.get("flat_dn").exposure;
// 检查曝光时间除零 - 改为补充0值
if (Math.abs(groundExposure) < 1e-10 || Math.abs(flatExposure) < 1e-10) {
invalidCount.zeroDiv++;
refrad.push(0);
continue;
}
const groundRatio = gainExposure / groundExposure;
const flatRatio = gainExposure / flatExposure;
const groundDnDiff = element.ground_dn - element.dark_dn;
const flatDnDiff = element.flat_dn - element.dark_dn;
const a = groundRatio * (element.gain * groundDnDiff);
const b = flatRatio * (element.gain * flatDnDiff);
// 检查分母b是否为零 - 改为补充0值
if (Math.abs(b) < 1e-10) {
invalidCount.zeroDiv++;
refrad.push(0);
} else {
const c = a / b;
if (isFinite(c) && !isNaN(c)) {
refrad.push(c);
} else {
invalidCount.invalidResult++;
refrad.push(0);
}
}
}
// 记录统计信息
if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
console.warn(`refrad计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${refrad.length}`);
}
return validateResult(refrad, name + "_refrad", 'refrad');
} else if (this.spectralName == "flat_ref") {
const validData = [];
const invalidCount = { zeroDiv: 0, invalidResult: 0 };
for (const element of arrAll) {
const denominator = element.flat_dn - element.dark_dn;
const numerator = element.ground_dn - element.dark_dn;
// 检查分母是否为零或接近零 - 改为补充0值
if (Math.abs(denominator) < 1e-10) {
invalidCount.zeroDiv++;
validData.push(0);
} else {
const b = numerator / denominator;
if (isFinite(b) && !isNaN(b)) {
validData.push(b);
} else {
invalidCount.invalidResult++;
validData.push(0);
}
}
}
// 记录统计信息
if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
console.warn(`flat_ref计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${validData.length}`);
}
return validateResult(validData, name + "_flat_ref", 'flat_ref');
}
if (invalidCount.zeroDiv > 0 || invalidCount.invalidResult > 0) {
console.warn(`flat_ref计算统计: 除零错误 ${invalidCount.zeroDiv} 个,无效结果 ${invalidCount.invalidResult} 个,有效数据 ${validData.length}`);
}
return validateResult(validData, name + "_flat_ref", "flat_ref");
}
}
@ -399,22 +451,22 @@ const spectralTypeList = [
value: "radiance_flat",
label: "参考辐射亮度",
},
{
value: "refrad",
label: "反射率能量",
},
{
value: "jdfs",
label: "绝对反射率",
},
{
value: "ckbzwj",
label: "参考校准文件",
},
{
value: "fszd",
label: "辐射照度",
},
// {
// value: "refrad",
// label: "反射率能量",
// },
// {
// value: "jdfs",
// label: "绝对反射率",
// },
// {
// value: "ckbzwj",
// label: "参考校准文件",
// },
// {
// value: "fszd",
// label: "辐射照度",
// },
];
const spectralProcessTypeList = [

View File

@ -33,7 +33,7 @@ export class SpectralDataService {
/**
* 处理光谱数据
*/
static processSpectralData(fileData, spectralType, processType = '') {
static processSpectralData(fileData, spectralType, processType = '', useDarkDn = true) {
const spectralDataList = [];
const imageList = [];
@ -41,12 +41,20 @@ export class SpectralDataService {
if (!element.data) continue;
try {
const dispose = new getIrisDataDispose(element.data, spectralType);
// 传入暗噪开关
const dispose = new getIrisDataDispose(element.data, spectralType, useDarkDn);
const datay = dispose.initData();
const datax = dispose.getSpectralInfoData();
const environmentData = dispose.environmentData;
const img = dispose.parseImageData(element.data.image_info_section);
if (img && img.length) {
imageList.push(img);
} else {
imageList.push([{
name: element.name,
url: 'jzsb'
}]);
}
if (datay?.normalArray && datax) {
spectralDataList.push({
name: datay?.name || '',
@ -54,8 +62,8 @@ export class SpectralDataService {
datay: datay.normalArray,
environmentData: { ...environmentData, fileName: element.name }
});
imageList.push(img);
}
} catch (error) {
console.error(`处理光谱数据失败: ${element.name}`, error);
}
@ -70,6 +78,7 @@ export class SpectralDataService {
/**
* 应用数据处理D1/D2等
* 注意:该方法需要在类内部,避免顶层出现 static 关键字导致语法错误
*/
static applyProcessing(spectralDataList, processType) {
if (!processType) return spectralDataList;
@ -97,10 +106,11 @@ export class SpectralDataService {
/**
* 批量处理选定文件的光谱数据
*/
static processSelectedFiles(fileData, selectedFileNames, spectralType, processType = '') {
const filteredData = fileData.filter(file =>
static processSelectedFiles(fileData, selectedFileNames, spectralType, processType = '', useDarkDn = true) {
const filteredData = fileData.filter(file =>
selectedFileNames.includes(file.name)
);
return this.processSpectralData(filteredData, spectralType, processType);
// 透传暗噪开关
return this.processSpectralData(filteredData, spectralType, processType, useDarkDn);
}
}