|
|
@@ -0,0 +1,1839 @@
|
|
|
+<template>
|
|
|
+ <div class="calculation-selection">
|
|
|
+ <div class="step-content">
|
|
|
+ <div class="step-container">
|
|
|
+ <div class="my-steps">
|
|
|
+ <a-steps :current="activeStep" style="margin-bottom: 10px">
|
|
|
+ <a-step
|
|
|
+ :title="$t(item.title)"
|
|
|
+ v-for="(item, index) in stepItems"
|
|
|
+ :key="index"
|
|
|
+ >
|
|
|
+ <i
|
|
|
+ slot="icon"
|
|
|
+ class="iconfont"
|
|
|
+ style="font-size: 32px; color: #3874f6 !important"
|
|
|
+ v-if="activeStep > index"
|
|
|
+ ></i
|
|
|
+ >
|
|
|
+ </a-step>
|
|
|
+ </a-steps>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 步骤1: 基本信息 -->
|
|
|
+ <div v-if="activeStep === 0" class="step-panel">
|
|
|
+ <el-card class="step-card" shadow="never">
|
|
|
+ <el-form :model="basicInfo" :rules="basicRules" ref="basicForm" label-width="140px" size="small">
|
|
|
+
|
|
|
+ <!-- 环境条件 -->
|
|
|
+ <el-divider content-position="left">{{$t('环境条件')}}</el-divider>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item :label="$t('大气压') + ' (mH₂O)'" prop="pa">
|
|
|
+ <el-input v-model="basicInfo.pa" placeholder="10.339"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item :label="$t('重力加速度') + ' (m/s²)'" prop="g">
|
|
|
+ <el-input v-model="basicInfo.g" placeholder="9.81"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item :label="$t('饱和蒸气压') + ' (mH₂O)'" prop="pv">
|
|
|
+ <el-input v-model="basicInfo.pv" placeholder="0.23"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item :label="$t('温度') + ' (℃)'" prop="t">
|
|
|
+ <el-input v-model="basicInfo.t" placeholder="20"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 阀门条件 -->
|
|
|
+ <el-divider content-position="left">{{$t('阀门条件')}}</el-divider>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="$t('公称通径')" prop="caliber">
|
|
|
+ <el-select v-model="basicInfo.caliber" :placeholder="$t('请选择')" style="width: 100%">
|
|
|
+ <el-option v-for="item in typeList" :label="item.remarks" :value="item.value" :key="item.value"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="$t('公称压力')" prop="pressure">
|
|
|
+ <el-select v-model="basicInfo.pressure" :placeholder="$t('请选择')" style="width: 100%">
|
|
|
+ <el-option v-for="item in pressureList" :label="item.remarks" :value="item.value" :key="item.value"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="$t('管道外径') + ' (mm)'" prop="od">
|
|
|
+ <el-input v-model="basicInfo.od" :placeholder="$t('请输入')"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="$t('壁厚') + ' (mm)'" prop="wt">
|
|
|
+ <el-input v-model="basicInfo.wt" :placeholder="$t('请输入')"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="$t('控制点名称')" prop="cname">
|
|
|
+ <el-input v-model="basicInfo.cname" :placeholder="$t('请输入')"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="$t('应用场景')" prop="purpose">
|
|
|
+ <el-select v-model="basicInfo.purpose" :placeholder="$t('请选择')" style="width: 100%">
|
|
|
+ <el-option :label="$t('通用')" value="通用"></el-option>
|
|
|
+ <el-option :label="$t('水库引水')" value="水库引水"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="$t('介质')" prop="mediatype">
|
|
|
+ <div style="display: flex; align-items: center; gap: 8px;">
|
|
|
+ <el-select v-model="basicInfo.mediatype" @change="onMediumTypeChange" :placeholder="$t('请选择')" style="flex: 1;">
|
|
|
+ <el-option :label="$t('水') +'/'+densityMap[$t('水')]" value="水"></el-option>
|
|
|
+ <el-option :label="$t('蒸汽') +'/'+densityMap[$t('蒸汽')]" value="蒸汽"></el-option>
|
|
|
+ <el-option :label="$t('油') +'/'+densityMap[$t('油')]" value="油"></el-option>
|
|
|
+ <el-option :label="$t('气体') + '/'+densityMap[$t('气体')]" value="气体"></el-option>
|
|
|
+ </el-select>
|
|
|
+ <!-- <span style="color: #606266; font-size: 14px; white-space: nowrap;">{{basicInfo.p}}</span> -->
|
|
|
+ <!-- <el-input v-model="basicInfo.p" :disabled="true" style="width: 80px;"></el-input> -->
|
|
|
+ </div>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="$t('要求最大开度') + ' (%)'" prop="maxli">
|
|
|
+ <el-input v-model="basicInfo.maxli" :placeholder="$t('请输入')"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="$t('要求最小开度') + ' (%)'" prop="minli">
|
|
|
+ <el-input v-model="basicInfo.minli" placeholder="10"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="20">
|
|
|
+
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="$t('起点高程') + ' (m)'">
|
|
|
+ <el-input v-model="basicInfo.z1" :placeholder="$t('请输入')"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="$t('末点高程') + ' (m)'">
|
|
|
+ <el-input v-model="basicInfo.z2" :placeholder="$t('请输入')"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item :label="$t('阀中心高程') + ' (m)'">
|
|
|
+ <el-input v-model="basicInfo.zv" :placeholder="$t('请输入')"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-form>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 步骤2: 工况条件 -->
|
|
|
+ <div v-if="activeStep === 1" class="step-panel">
|
|
|
+ <el-card class="step-card" shadow="never">
|
|
|
+ <el-form :model="workingCondition" :rules="workingRules" ref="workingForm" label-width="120px" size="small">
|
|
|
+ <!-- 条件要求 -->
|
|
|
+ <el-divider content-position="left">{{$t('工况要求')}}</el-divider>
|
|
|
+
|
|
|
+ <!-- 最小流量 -->
|
|
|
+ <el-row :gutter="20" style="margin-bottom: 20px;">
|
|
|
+ <el-col :span="2" style="display: flex; align-items: center; justify-content: center; background-color: #f5f5f5; border: 1px solid #ddd; height: 40px;">
|
|
|
+ <span style="font-weight: bold;">{{$t('最小流量')}}</span>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item :label="$t('流量') + ':'" prop="minCondition.flow" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.minCondition.flow" @input="calculatePressureDrop('min')">
|
|
|
+
|
|
|
+ <span style="color:blue" slot="suffix">
|
|
|
+ m³/h
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item :label="$t('阀前压力') + ':'" prop="minCondition.beforePressure" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.minCondition.beforePressure" @input="calculatePressureDrop('min')">
|
|
|
+ <span style="color:blue" slot="suffix">kpa
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item :label="$t('阀后压力') + ':'" prop="minCondition.afterPressure" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.minCondition.afterPressure" @input="calculatePressureDrop('min')">
|
|
|
+ <span style="color:blue" slot="suffix">kpa
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item :label="$t('前后压差') + ':'" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.minCondition.pressureDrop" :disabled="true">
|
|
|
+ <span style="color:blue" slot="suffix">kpa
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 最大流量 -->
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="2" style="display: flex; align-items: center; justify-content: center; background-color: #f5f5f5; border: 1px solid #ddd; height: 40px;">
|
|
|
+ <span style="font-weight: bold;">{{$t('最大流量')}}</span>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item :label="$t('流量') + ':'" prop="maxCondition.flow" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.maxCondition.flow" @input="calculatePressureDrop('max')">
|
|
|
+ <span style="color:blue" slot="suffix">
|
|
|
+ m³/h
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item :label="$t('阀前压力') + ':'" prop="maxCondition.beforePressure" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.maxCondition.beforePressure" @input="calculatePressureDrop('max')">
|
|
|
+ <span style="color:blue" slot="suffix">kpa
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item :label="$t('阀后压力') + ':'" prop="maxCondition.afterPressure" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.maxCondition.afterPressure" @input="calculatePressureDrop('max')">
|
|
|
+ <span style="color:blue" slot="suffix">kpa
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item :label="$t('前后压差') + ':'" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.maxCondition.pressureDrop" :disabled="true">
|
|
|
+ <span style="color:blue" slot="suffix">kpa
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 数据验证提示 -->
|
|
|
+ <el-alert
|
|
|
+ v-if="validationMessage"
|
|
|
+ :title="validationMessage"
|
|
|
+ :type="validationType"
|
|
|
+ style="margin-top: 20px;"
|
|
|
+ show-icon>
|
|
|
+ </el-alert>
|
|
|
+ </el-form>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 步骤3: 阀门选型 -->
|
|
|
+ <div v-if="activeStep === 2" class="step-panel">
|
|
|
+ <el-card class="step-card" shadow="never">
|
|
|
+ <h3 class="mt-10">
|
|
|
+ 节流件配置
|
|
|
+ </h3>
|
|
|
+ <div class="mt-10">
|
|
|
+ <p style="display: inline-block; width: 100px;;font-size:14px">{{$t('节流件类型')}}: </p>
|
|
|
+ <el-select v-model="valveSelection.throttletype" :placeholder="$t('请选择节流件类型')" size="small">
|
|
|
+ <el-option v-for="item in throttletype" :key="item.value" :label="item.remarks" :value="item.value"></el-option>
|
|
|
+ </el-select>
|
|
|
+ <!-- <el-button type="primary" size="small" disabled>开始选型</el-button> -->
|
|
|
+ </div>
|
|
|
+ <div class="mt-10">
|
|
|
+ <p style="display: inline-block; width: 100px;font-size:14px">{{$t('节流件')}}: </p>
|
|
|
+ <el-select :disabled="!valveSelection.throttletype" v-model="valveSelection.throttleValue" :placeholder="$t('请选择节流件类型')" size="small" @visible-change="queryThrottle">
|
|
|
+ <el-option v-for="item in throttle" :key="item.value" :label="item.itemname" :value="item.itemid"></el-option>
|
|
|
+ </el-select>
|
|
|
+ <el-button type="primary" :disabled="!valveSelection.throttleValue" size="small" @click="beginSelection(() => {},'table')">{{$t('开始选型')}}</el-button>
|
|
|
+ </div>
|
|
|
+ <el-table :data="tableData" style="width: 100%" size="mini" border>
|
|
|
+ <el-table-column prop="workingCondition" :label="$t('工况')" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="conditionName" :label="$t('条件名称')" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="q" :label="$t('流量') + '(q)'" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="p1" :label="$t('阀前压力') + '(p1)'" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="p2" :label="$t('阀后压力') + '(p2)'" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="p" :label="$t('前后压差') + '(p)'" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="pv" :label="$t('饱和蒸汽压') + '(pV)'" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="kv" :label="$t('流量系数') + '(kv)'" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="li" :label="$t('开度') + '(li)'" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="ldc" :label="$t('临界汽蚀系数') + 'σc(Idc)'" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="dc" :label="$t('气蚀系数') + 'σ(dc)'" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="fi" :label="$t('压力恢复系数') + 'FI(fi)'" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="fr" :label="$t('流阻系数') + 'ζ(fr)'" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="fkv" :label="$t('阻塞流修正系数') + 'Fkv(fkv)'" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="v" :label="$t('流速') + 'V(v)'" align="center"></el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <!-- 开度设置 -->
|
|
|
+ <el-divider content-position="left">{{$t('开度设置')}}</el-divider>
|
|
|
+ <div class="opening-settings">
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-input
|
|
|
+ v-model="openingSettings.openingValues"
|
|
|
+ :placeholder="$t('请输入开度值,用逗号分隔,如:10,20,30,40,50')"
|
|
|
+ @blur="parseOpeningValues"
|
|
|
+ size="small">
|
|
|
+ </el-input>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="12">
|
|
|
+ <div class="opening-info">
|
|
|
+ <el-button type="primary" @click="beginSelection(() => {},'chart')" :disabled="!openingSettings.parsedValues.length || !valveSelection.throttleValue" size="small">生成曲线图表</el-button>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 开度值预览 -->
|
|
|
+ <div v-if="openingSettings.parsedValues.length" class="opening-preview">
|
|
|
+ <span class="preview-label">开度值预览:</span>
|
|
|
+ <el-tag v-for="(value, index) in openingSettings.parsedValues" :key="index" size="small" style="margin-right: 8px;">{{ value }}%</el-tag>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-row>
|
|
|
+ <el-col :span="18">
|
|
|
+ <!-- KV曲线图 -->
|
|
|
+ <div v-if="showKvChart" class="chart-container">
|
|
|
+ <el-divider content-position="left">{{$t('KV曲线图')}}</el-divider>
|
|
|
+ <div id="kvChart" style="width: 100%; height: 400px;"></div>
|
|
|
+ </div>
|
|
|
+ <!-- 流阻系数曲线图 -->
|
|
|
+ <div v-if="showZetaChart" class="chart-container">
|
|
|
+ <el-divider content-position="left">{{$t('流阻系数曲线图')}}</el-divider>
|
|
|
+ <div id="zetaCoefficientChart" style="width: 100%; height: 400px;"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 气蚀系数曲线图 -->
|
|
|
+ <div v-if="showCavitationChart" class="chart-container">
|
|
|
+ <el-divider content-position="left">{{$t('气蚀系数曲线图')}}</el-divider>
|
|
|
+ <div id="cavitationCoefficientChart" style="width: 100%; height: 400px;"></div>
|
|
|
+ </div>
|
|
|
+ <!-- 流量开度曲线图 -->
|
|
|
+ <div v-if="showFlowChart" class="chart-container">
|
|
|
+ <el-divider content-position="left">{{$t('流量开度曲线图')}}</el-divider>
|
|
|
+ <div id="flowOpeningChart" style="width: 100%; height: 400px;"></div>
|
|
|
+ </div>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ </el-card>
|
|
|
+ </div>
|
|
|
+ <!-- 操作按钮 -->
|
|
|
+ <div class="button-group">
|
|
|
+ <el-button v-if="activeStep > 0" @click="prevStep">{{$t('上一步')}}</el-button>
|
|
|
+ <el-button v-if="activeStep < 2" type="primary" @click="nextStep">{{$t('下一步')}}</el-button>
|
|
|
+ <el-button v-if="activeStep === 2" type="primary" @click="saveSelection">{{$t('保存选型')}}</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+import './index.css'
|
|
|
+
|
|
|
+export default {
|
|
|
+ name: 'CalculationAndSelection',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ activeStep: 0,
|
|
|
+ stepItems: [
|
|
|
+ { title: this.$t('基本信息') },
|
|
|
+ { title: this.$t('工况条件') },
|
|
|
+ { title: this.$t('阀门选型') }
|
|
|
+ ],
|
|
|
+ densityMap: {
|
|
|
+ [this.$t('水')]: '1000',
|
|
|
+ [this.$t('蒸汽')]: '0.6',
|
|
|
+ [this.$t('油')]: '850',
|
|
|
+ [this.$t('气体')]: '1.2'
|
|
|
+ },
|
|
|
+ issave: false,
|
|
|
+ typeList: [],
|
|
|
+ pressureList: [],
|
|
|
+ throttletype: [],
|
|
|
+ throttle:[],
|
|
|
+ tableData:[],
|
|
|
+ // 基本信息
|
|
|
+ basicInfo: {
|
|
|
+ // 环境条件
|
|
|
+ pa: '101.390',
|
|
|
+ pv: '2.329',
|
|
|
+ pc: '22120',
|
|
|
+ g: '9.81',
|
|
|
+ t: '20',
|
|
|
+
|
|
|
+ // 阀门条件
|
|
|
+ caliber: '',
|
|
|
+ pressure: '',
|
|
|
+ od: '',
|
|
|
+ wt: '',
|
|
|
+ cname: '',
|
|
|
+ purpose: this.$t('通用'),
|
|
|
+ mediatype: this.$t('水'),
|
|
|
+ p: '1000',
|
|
|
+ maxli: '85',
|
|
|
+ minli: '10',
|
|
|
+ z1: '',
|
|
|
+ zv: '',
|
|
|
+ z2: ''
|
|
|
+ },
|
|
|
+
|
|
|
+ // 工况条件
|
|
|
+ workingCondition: {
|
|
|
+ minCondition: {
|
|
|
+ flow: '',
|
|
|
+ beforePressure: '',
|
|
|
+ afterPressure: '',
|
|
|
+ pressureDrop: ''
|
|
|
+ },
|
|
|
+ maxCondition: {
|
|
|
+ flow: '',
|
|
|
+ beforePressure: '',
|
|
|
+ afterPressure: '',
|
|
|
+ pressureDrop: ''
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 验证信息
|
|
|
+ validationMessage: '',
|
|
|
+ validationType: 'warning',
|
|
|
+
|
|
|
+ // 阀门选型
|
|
|
+ valveSelection: {
|
|
|
+ throttletype: '',
|
|
|
+ throttleValue: '',
|
|
|
+ },
|
|
|
+
|
|
|
+ // 开度设置
|
|
|
+ openingSettings: {
|
|
|
+ openingValues: '', // 用户输入的开度值字符串
|
|
|
+ parsedValues: [], // 解析后的开度值数组
|
|
|
+ },
|
|
|
+
|
|
|
+ // 图表显示控制
|
|
|
+ showFlowChart: false,
|
|
|
+ showZetaChart: false,
|
|
|
+ showCavitationChart: false,
|
|
|
+ showKvChart: false,
|
|
|
+
|
|
|
+ // 图表实例
|
|
|
+ flowChartInstance: null,
|
|
|
+ zetaChartInstance: null,
|
|
|
+ cavitationChartInstance: null,
|
|
|
+ kvChartInstance: null,
|
|
|
+
|
|
|
+ // 计算结果
|
|
|
+ calculationResult: {
|
|
|
+ flowCoefficient: '',
|
|
|
+ opening: '',
|
|
|
+ noiseLevel: ''
|
|
|
+ },
|
|
|
+
|
|
|
+ // 表单验证规则
|
|
|
+ basicRules: {
|
|
|
+ cname: [
|
|
|
+ { required: true, message: this.$t('请输入控制点名称'), trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ purpose: [
|
|
|
+ { required: true, message: this.$t('请选择应用场景'), trigger: 'change' }
|
|
|
+ ],
|
|
|
+ mediatype: [
|
|
|
+ { required: true, message: this.$t('请选择介质'), trigger: 'change' }
|
|
|
+ ],
|
|
|
+ od: [
|
|
|
+ { required: true, message: this.$t('请输入管道外径'), trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ wt: [
|
|
|
+ { required: true, message: this.$t('请输入壁厚'), trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ z1: [
|
|
|
+ { required: true, message: this.$t('请输入起点高程'), trigger: 'blur' },
|
|
|
+ { pattern: /^-?\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ zv: [
|
|
|
+ { required: true, message: this.$t('请输入阀中心高程'), trigger: 'blur' },
|
|
|
+ { pattern: /^-?\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ z2: [
|
|
|
+ { required: true, message: this.$t('请输入末点高程'), trigger: 'blur' },
|
|
|
+ { pattern: /^-?\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+
|
|
|
+ workingRules: {
|
|
|
+ 'minCondition.flow': [
|
|
|
+ { required: true, message: this.$t('请输入最小流量'), trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' },
|
|
|
+ {
|
|
|
+ validator: (rule, value, callback) => {
|
|
|
+ if (value && this.workingCondition.maxCondition.flow) {
|
|
|
+ const minFlow = parseFloat(value)
|
|
|
+ const maxFlow = parseFloat(this.workingCondition.maxCondition.flow)
|
|
|
+ if (minFlow >= maxFlow) {
|
|
|
+ callback(new Error(this.$t('最小流量不能大于或等于最大流量')))
|
|
|
+ } else {
|
|
|
+ callback()
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ callback()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ 'minCondition.beforePressure': [
|
|
|
+ { required: true, message: this.$t('请输入阀前压力'), trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ 'minCondition.afterPressure': [
|
|
|
+ { required: true, message: this.$t('请输入阀后压力'), trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ 'maxCondition.flow': [
|
|
|
+ { required: true, message: this.$t('请输入最大流量'), trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' },
|
|
|
+ {
|
|
|
+ validator: (rule, value, callback) => {
|
|
|
+ if (value && this.workingCondition.minCondition.flow) {
|
|
|
+ const minFlow = parseFloat(this.workingCondition.minCondition.flow)
|
|
|
+ const maxFlow = parseFloat(value)
|
|
|
+ if (minFlow >= maxFlow) {
|
|
|
+ callback(new Error(this.$t('最大流量必须大于最小流量')))
|
|
|
+ } else {
|
|
|
+ callback()
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ callback()
|
|
|
+ }
|
|
|
+ },
|
|
|
+ trigger: 'blur'
|
|
|
+ }
|
|
|
+ ],
|
|
|
+ 'maxCondition.beforePressure': [
|
|
|
+ { required: true, message: this.$t('请输入阀前压力'), trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ 'maxCondition.afterPressure': [
|
|
|
+ { required: true, message: this.$t('请输入阀后压力'), trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+
|
|
|
+ conditionRules: {
|
|
|
+ workingPressure: [
|
|
|
+ { required: true, message: this.$t('请输入工作压力'), trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ workingTemperature: [
|
|
|
+ { required: true, message: this.$t('请输入工作温度'), trigger: 'blur' },
|
|
|
+ { pattern: /^-?\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ flowRate: [
|
|
|
+ { required: true, message: this.$t('请输入流量'), trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: this.$t('请输入有效的数值'), trigger: 'blur' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+
|
|
|
+ valveRules: {
|
|
|
+ valveType: [
|
|
|
+ { required: true, message: this.$t('请选择阀门类型'), trigger: 'change' }
|
|
|
+ ],
|
|
|
+ valveSize: [
|
|
|
+ { required: true, message: this.$t('请选择阀门口径'), trigger: 'change' }
|
|
|
+ ],
|
|
|
+ connectionType: [
|
|
|
+ { required: true, message: this.$t('请选择连接方式'), trigger: 'change' }
|
|
|
+ ],
|
|
|
+ material: [
|
|
|
+ { required: true, message: this.$t('请选择材质'), trigger: 'change' }
|
|
|
+ ]
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ methods: {
|
|
|
+ // 下一步
|
|
|
+ nextStep() {
|
|
|
+ const formRefs = ['basicForm', 'workingForm', 'valveForm']
|
|
|
+ const currentForm = formRefs[this.activeStep]
|
|
|
+
|
|
|
+ this.$refs[currentForm].validate((valid) => {
|
|
|
+ if (valid) {
|
|
|
+ this.activeStep++
|
|
|
+ } else {
|
|
|
+ this.$message.error(this.$t('请完善当前步骤的必填信息'))
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 上一步
|
|
|
+ prevStep() {
|
|
|
+ this.activeStep--
|
|
|
+ // 清除当前步骤的表单验证状态
|
|
|
+ this.$nextTick(() => {
|
|
|
+ const formRefs = ['basicForm', 'workingForm', 'valveForm']
|
|
|
+ const currentForm = formRefs[this.activeStep]
|
|
|
+ if (this.$refs[currentForm]) {
|
|
|
+ this.$refs[currentForm].clearValidate()
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 介质类型变化时自动设置密度
|
|
|
+ onMediumTypeChange(value) {
|
|
|
+
|
|
|
+ this.basicInfo.p = this.densityMap[value] || '1000'
|
|
|
+ },
|
|
|
+
|
|
|
+ // 计算前后压差
|
|
|
+ calculatePressureDrop(type) {
|
|
|
+ const condition = this.workingCondition[type + 'Condition']
|
|
|
+
|
|
|
+ if (condition.beforePressure && condition.afterPressure) {
|
|
|
+ const beforePressure = parseFloat(condition.beforePressure)
|
|
|
+ const afterPressure = parseFloat(condition.afterPressure)
|
|
|
+
|
|
|
+ if (!isNaN(beforePressure) && !isNaN(afterPressure)) {
|
|
|
+ condition.pressureDrop = (beforePressure - afterPressure).toFixed(2)
|
|
|
+
|
|
|
+ // 验证数据合理性
|
|
|
+ this.validateWorkingCondition()
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 触发流量字段的验证,确保流量比较验证能够实时生效
|
|
|
+ this.$nextTick(() => {
|
|
|
+ if (this.$refs.workingForm) {
|
|
|
+ this.$refs.workingForm.validateField('minCondition.flow')
|
|
|
+ this.$refs.workingForm.validateField('maxCondition.flow')
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 验证工况条件数据
|
|
|
+ validateWorkingCondition() {
|
|
|
+ const minCondition = this.workingCondition.minCondition
|
|
|
+ const maxCondition = this.workingCondition.maxCondition
|
|
|
+
|
|
|
+ this.validationMessage = ''
|
|
|
+ this.validationType = 'success'
|
|
|
+
|
|
|
+ // 检查流量大小关系
|
|
|
+ if (minCondition.flow && maxCondition.flow) {
|
|
|
+ const minFlow = parseFloat(minCondition.flow)
|
|
|
+ const maxFlow = parseFloat(maxCondition.flow)
|
|
|
+
|
|
|
+ if (minFlow >= maxFlow) {
|
|
|
+ this.validationMessage = this.$t('最大流量必须大于最小流量')
|
|
|
+ this.validationType = 'error'
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 检查阀前压力是否大于等于阀后压力
|
|
|
+ const conditions = [minCondition, maxCondition]
|
|
|
+ for (let condition of conditions) {
|
|
|
+ if (condition.beforePressure && condition.afterPressure) {
|
|
|
+ const beforePressure = parseFloat(condition.beforePressure)
|
|
|
+ const afterPressure = parseFloat(condition.afterPressure)
|
|
|
+
|
|
|
+ if (beforePressure < afterPressure) {
|
|
|
+ this.validationMessage = this.$t('阀前压力必须大于等于阀后压力')
|
|
|
+ this.validationType = 'error'
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果所有验证都通过
|
|
|
+ if (minCondition.flow && maxCondition.flow &&
|
|
|
+ minCondition.beforePressure && minCondition.afterPressure &&
|
|
|
+ maxCondition.beforePressure && maxCondition.afterPressure) {
|
|
|
+ this.validationMessage = this.$t('工况条件数据验证通过')
|
|
|
+ this.validationType = 'success'
|
|
|
+ }
|
|
|
+
|
|
|
+ return true
|
|
|
+ },
|
|
|
+
|
|
|
+ // 保存选型
|
|
|
+ saveSelection() {
|
|
|
+ this.issave = true
|
|
|
+ this.beginSelection(()=>{
|
|
|
+ this.$message({
|
|
|
+ message: this.$t('选型方案保存成功!'),
|
|
|
+ type: 'success'
|
|
|
+ })
|
|
|
+ this.issave = false
|
|
|
+ },'save')
|
|
|
+ },
|
|
|
+ optionList() {
|
|
|
+ this.$store.dispatch("optiontypeselect", "caliber2").then((res) => {
|
|
|
+ this.typeList = res.data;
|
|
|
+ console.log(this.typeList, this.$t('公称通径'));
|
|
|
+ });
|
|
|
+ this.$store.dispatch("optiontypeselect", "pressure").then((res) => {
|
|
|
+ this.pressureList = res.data;
|
|
|
+ console.log(this.pressureList, this.$t('公称压力'));
|
|
|
+ });
|
|
|
+
|
|
|
+ this.$store.dispatch("optiontypeselect", "throttletype").then((res) => {
|
|
|
+ this.throttletype = res.data;
|
|
|
+ console.log(this.throttletype, this.$t('节流件类型'));
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 查询节流件
|
|
|
+ async queryThrottle() {
|
|
|
+ const res = await this.$api.requested( {
|
|
|
+ "content": {
|
|
|
+ "isExport": 0,
|
|
|
+ "pageNumber": 1,
|
|
|
+ "pageSize": 100,
|
|
|
+ "where": {
|
|
|
+ "condition": "",
|
|
|
+ "throttletype": this.valveSelection.throttletype
|
|
|
+ }
|
|
|
+ },
|
|
|
+ "id": 2025091915552702,
|
|
|
+ })
|
|
|
+ if(res.data){
|
|
|
+ this.throttle = res.data
|
|
|
+ }
|
|
|
+ },
|
|
|
+ // 开始选型
|
|
|
+ async beginSelection(callback,type) {
|
|
|
+
|
|
|
+ const res = await this.$api.requested({
|
|
|
+ "content": {
|
|
|
+ "itemid":this.valveSelection.throttleValue,
|
|
|
+ "issave":this.issave,//是否保存当前选型
|
|
|
+ "p_lis":this.openingSettings.parsedValues.length ? this.openingSettings.parsedValues : [10,20],//计算流量压差曲线值
|
|
|
+ "pa": parseFloat(this.basicInfo.pa), //大气压Pa
|
|
|
+ "pv": parseFloat(this.basicInfo.pv), //饱和蒸气压Pv
|
|
|
+ "pc": parseFloat(this.basicInfo.pc), //饱和蒸气压Pv
|
|
|
+ "g": parseFloat(this.basicInfo.g), //重力加速度
|
|
|
+ "t": parseFloat(this.basicInfo.t), //温度t(20℃)
|
|
|
+ "minli": parseFloat(this.basicInfo.minli), //要求最小开度(输入,默认值10%),后端默认除100
|
|
|
+ "maxli": parseFloat(this.basicInfo.maxli), //要求最大开度(输入,默认为85%),后端默认除100
|
|
|
+ "pressure": this.basicInfo.pressure, //公称压力(自定义选项)
|
|
|
+ "caliber": this.basicInfo.caliber, //公称通径(自定义选项)、
|
|
|
+ "od": parseFloat(this.basicInfo.od), //管道外径(mm)
|
|
|
+ "cname": this.basicInfo.cname, //控制点名称(必填,文本)
|
|
|
+ "wt": parseFloat(this.basicInfo.wt), //壁厚(mm)
|
|
|
+ "purpose": this.basicInfo.purpose, //用途(必填,自定义选项:通用、水库引水,默认通用)
|
|
|
+ "mediatype": this.basicInfo.mediatype, //介质类型(必填,自定义选项,默认为水)
|
|
|
+ "p": parseFloat(this.basicInfo.p), //液体密度ρ(根据介质类型自动带出)
|
|
|
+ "z1": parseFloat(this.basicInfo.z1), //起点高程(Z1)
|
|
|
+ "zv": parseFloat(this.basicInfo.zv), //阀中心高程(Zv)
|
|
|
+ "z2": parseFloat(this.basicInfo.z2), //末点高程(Z2),
|
|
|
+ "min": {
|
|
|
+ q: parseFloat(this.workingCondition.minCondition.flow),
|
|
|
+ q_unit: 'm³/h',
|
|
|
+ p1: parseFloat(this.workingCondition.minCondition.beforePressure),
|
|
|
+ p1_unit: 'kPa',
|
|
|
+ p2: parseFloat(this.workingCondition.minCondition.afterPressure),
|
|
|
+ p2_unit: 'kPa'
|
|
|
+ }, //最小流量
|
|
|
+ "max": {
|
|
|
+ q: parseFloat(this.workingCondition.maxCondition.flow),
|
|
|
+ q_unit: 'm³/h',
|
|
|
+ p1: parseFloat(this.workingCondition.maxCondition.beforePressure),
|
|
|
+ p1_unit: 'kPa',
|
|
|
+ p2: parseFloat(this.workingCondition.maxCondition.afterPressure),
|
|
|
+ p2_unit: 'kPa'
|
|
|
+ }, //最大流量
|
|
|
+ },
|
|
|
+ "id": 2025091909425802,
|
|
|
+ })
|
|
|
+ if(res.code == 1){
|
|
|
+ // 处理返回的图表数据
|
|
|
+ if(res.data.lines && type == 'chart') {
|
|
|
+ this.processChartData(res.data.lines)
|
|
|
+ }
|
|
|
+ if(callback && type == 'save'){
|
|
|
+ callback()
|
|
|
+ }
|
|
|
+ // 处理表格数据
|
|
|
+ const minData = {
|
|
|
+ ...res.data.min,
|
|
|
+ workingCondition: this.$t('通用'),
|
|
|
+ conditionName: this.$t('最小流量')
|
|
|
+ }
|
|
|
+ const maxData = {
|
|
|
+ ...res.data.max,
|
|
|
+ workingCondition: this.$t('通用'),
|
|
|
+ conditionName: this.$t('最大流量')
|
|
|
+ }
|
|
|
+ this.tableData = [minData, maxData]
|
|
|
+ } else {
|
|
|
+ // 如果没有返回数据,显示错误信息
|
|
|
+ this.$message.error(res.msg || this.$t('API调用失败,请检查网络连接或联系管理员'))
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 解析开度值
|
|
|
+ parseOpeningValues() {
|
|
|
+ if (!this.openingSettings.openingValues.trim()) {
|
|
|
+ this.openingSettings.parsedValues = []
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ const values = this.openingSettings.openingValues
|
|
|
+ .split(',')
|
|
|
+ .map(val => {
|
|
|
+ const num = parseFloat(val.trim())
|
|
|
+ return isNaN(num) ? null : num
|
|
|
+ })
|
|
|
+ .filter(val => val !== null && val >= 0 && val <= 100)
|
|
|
+ .sort((a, b) => a - b)
|
|
|
+
|
|
|
+ // 去重
|
|
|
+ this.openingSettings.parsedValues = [...new Set(values)]
|
|
|
+
|
|
|
+ if (this.openingSettings.parsedValues.length === 0) {
|
|
|
+ this.$message.warning(this.$t('请输入有效的开度值(0-100之间的数字)'))
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理API返回的图表数据
|
|
|
+ processChartData(lineData) {
|
|
|
+ console.log('processChartData被调用,数据:', lineData)
|
|
|
+
|
|
|
+ if (!lineData) {
|
|
|
+ this.$message.error(this.$t('未获取到图表数据'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 显示所有图表
|
|
|
+ console.log('设置图表显示状态为true')
|
|
|
+ this.showFlowChart = true
|
|
|
+ this.showZetaChart = true
|
|
|
+ this.showCavitationChart = true
|
|
|
+ this.showKvChart = true
|
|
|
+
|
|
|
+ console.log('图表显示状态:', {
|
|
|
+ showFlowChart: this.showFlowChart,
|
|
|
+ showZetaChart: this.showZetaChart,
|
|
|
+ showCavitationChart: this.showCavitationChart,
|
|
|
+ showKvChart: this.showKvChart
|
|
|
+ })
|
|
|
+
|
|
|
+ // 等待DOM更新后初始化图表
|
|
|
+ this.$nextTick(() => {
|
|
|
+ // 从API数据中提取不同类型的曲线数据
|
|
|
+ const chartData = this.extractChartDataFromAPI(lineData)
|
|
|
+
|
|
|
+ // 初始化四个图表
|
|
|
+ this.initFlowChart(chartData.flowData)
|
|
|
+ this.initZetaChart(chartData.zetaData)
|
|
|
+ this.initCavitationChart(chartData.cavitationData)
|
|
|
+ this.initKvChart(chartData.kvData)
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 从API数据中提取图表数据
|
|
|
+ extractChartDataFromAPI(lineData) {
|
|
|
+ // 根据实际API数据结构解析数据
|
|
|
+
|
|
|
+ // 提取流量压差数据
|
|
|
+ const flowData = []
|
|
|
+ const pressureDropData = []
|
|
|
+
|
|
|
+ // 提取流阻系数数据
|
|
|
+ const zetaData = []
|
|
|
+
|
|
|
+ // 提取气蚀系数数据
|
|
|
+ const cavitationData = []
|
|
|
+
|
|
|
+ // 提取KV数据
|
|
|
+ const kvData = []
|
|
|
+
|
|
|
+ // 解析dc气蚀系数曲线数据
|
|
|
+ if (lineData.dc && Array.isArray(lineData.dc)) {
|
|
|
+ lineData.dc.forEach(item => {
|
|
|
+ const opening = parseFloat(item.li) // 直接使用li原数据
|
|
|
+ const value = parseFloat(item.value)
|
|
|
+ if (!isNaN(opening) && !isNaN(value)) {
|
|
|
+ cavitationData.push([opening, value])
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析flow流量压差开度曲线数据(嵌套对象结构)
|
|
|
+ if (lineData.flow && typeof lineData.flow === 'object') {
|
|
|
+ // 遍历不同压差条件(如"10", "20"等)
|
|
|
+ Object.keys(lineData.flow).forEach(pressureKey => {
|
|
|
+ const pressureData = lineData.flow[pressureKey]
|
|
|
+ if (Array.isArray(pressureData)) {
|
|
|
+ pressureData.forEach(item => {
|
|
|
+ const opening = parseFloat(item.li) // 直接使用li原数据
|
|
|
+ const value = parseFloat(item.value)
|
|
|
+ if (!isNaN(opening) && !isNaN(value)) {
|
|
|
+ flowData.push([opening, value, pressureKey]) // 添加压差条件标识
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析其他类型的曲线数据(如果存在)
|
|
|
+ if (lineData.pressureDrop && Array.isArray(lineData.pressureDrop)) {
|
|
|
+ lineData.pressureDrop.forEach(item => {
|
|
|
+ const opening = parseFloat(item.li) // 直接使用li原数据
|
|
|
+ const value = parseFloat(item.value)
|
|
|
+ if (!isNaN(opening) && !isNaN(value)) {
|
|
|
+ pressureDropData.push([opening, value])
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ if (lineData.zeta && Array.isArray(lineData.zeta)) {
|
|
|
+ lineData.zeta.forEach(item => {
|
|
|
+ const opening = parseFloat(item.li) // 直接使用li原数据
|
|
|
+ const value = parseFloat(item.value)
|
|
|
+ if (!isNaN(opening) && !isNaN(value)) {
|
|
|
+ zetaData.push([opening, value])
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 解析kv曲线数据
|
|
|
+ if (lineData.kv && Array.isArray(lineData.kv)) {
|
|
|
+ lineData.kv.forEach(item => {
|
|
|
+ const opening = parseFloat(item.li) // 直接使用li原数据
|
|
|
+ const value = parseFloat(item.value)
|
|
|
+ if (!isNaN(opening) && !isNaN(value)) {
|
|
|
+ kvData.push([opening, value])
|
|
|
+ }
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ return {
|
|
|
+ flowData: {
|
|
|
+ flowData,
|
|
|
+ pressureDropData
|
|
|
+ },
|
|
|
+ zetaData: {
|
|
|
+ zetaData
|
|
|
+ },
|
|
|
+ cavitationData: {
|
|
|
+ cavitationData
|
|
|
+ },
|
|
|
+ kvData: {
|
|
|
+ kvData
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 生成流量开度曲线
|
|
|
+ async generateFlowCurve() {
|
|
|
+ if (!this.openingSettings.parsedValues.length) {
|
|
|
+ this.$message.warning(this.$t('请先设置开度值'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.valveSelection.throttleValue) {
|
|
|
+ this.$message.warning(this.$t('请先选择节流件'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 模拟生成曲线数据(实际应该调用API获取)
|
|
|
+ const chartData = this.generateMockChartData()
|
|
|
+
|
|
|
+ this.showFlowChart = true
|
|
|
+
|
|
|
+ // 等待DOM更新后初始化图表
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.initFlowChart(chartData)
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 生成模拟图表数据
|
|
|
+ generateMockChartData() {
|
|
|
+ const openings = this.openingSettings.parsedValues
|
|
|
+ const flowData = []
|
|
|
+ const pressureDropData = []
|
|
|
+
|
|
|
+ openings.forEach(opening => {
|
|
|
+ // 模拟流量数据(基于开度的二次函数关系)
|
|
|
+ const flow = Math.pow(opening / 100, 1.5) * 100 + Math.random() * 10
|
|
|
+ flowData.push([opening, parseFloat(flow.toFixed(2))])
|
|
|
+
|
|
|
+ // 模拟压差数据
|
|
|
+ const pressureDrop = Math.pow(opening / 100, 2) * 50 + Math.random() * 5
|
|
|
+ pressureDropData.push([opening, parseFloat(pressureDrop.toFixed(2))])
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ openings,
|
|
|
+ flowData,
|
|
|
+ pressureDropData
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 初始化流量开度图表
|
|
|
+ initFlowChart(data) {
|
|
|
+ console.log('initFlowChart被调用,数据:', data)
|
|
|
+
|
|
|
+ // 销毁已存在的图表实例
|
|
|
+ if (this.flowChartInstance) {
|
|
|
+ this.flowChartInstance.destroy()
|
|
|
+ }
|
|
|
+
|
|
|
+ const chartDom = document.getElementById('flowOpeningChart')
|
|
|
+ console.log('查找流量图表容器flowOpeningChart:', chartDom)
|
|
|
+
|
|
|
+ if (!chartDom) {
|
|
|
+ this.$message.error(this.$t('图表容器未找到'))
|
|
|
+ console.error(this.$t('DOM容器flowOpeningChart未找到'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用G2图表库
|
|
|
+ import('@antv/g2').then(({ Chart }) => {
|
|
|
+ // 清空容器
|
|
|
+ chartDom.innerHTML = ''
|
|
|
+
|
|
|
+ // 创建图表实例
|
|
|
+ this.flowChartInstance = new Chart({
|
|
|
+ container: chartDom,
|
|
|
+ autoFit: true,
|
|
|
+ height: 400,
|
|
|
+ padding: [60, 80, 60, 80]
|
|
|
+ })
|
|
|
+
|
|
|
+ // 准备数据 - 使用传入的真实数据或生成模拟数据
|
|
|
+ let chartData = []
|
|
|
+
|
|
|
+ if (data && data.flowData && data.pressureDropData) {
|
|
|
+ // 使用真实数据 - 处理多条曲线
|
|
|
+ data.flowData.forEach(item => {
|
|
|
+ const pressureCondition = item[2] || this.$t('默认') // 获取压差条件
|
|
|
+ chartData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: `流量-${pressureCondition}kPa`,
|
|
|
+ unit: 'm³/h'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ data.pressureDropData.forEach(item => {
|
|
|
+ const pressureCondition = item[2] || this.$t('默认') // 获取压差条件
|
|
|
+ chartData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: `压差-${pressureCondition}kPa`,
|
|
|
+ unit: 'kPa'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 使用模拟数据作为后备
|
|
|
+ const mockData = this.generateMockChartData()
|
|
|
+ mockData.flowData.forEach(item => {
|
|
|
+ chartData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: this.$t('流量'),
|
|
|
+ unit: 'm³/h'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ mockData.pressureDropData.forEach(item => {
|
|
|
+ chartData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: this.$t('压差'),
|
|
|
+ unit: 'kPa'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置数据
|
|
|
+ this.flowChartInstance.data(chartData)
|
|
|
+
|
|
|
+ // 设置度量
|
|
|
+ this.flowChartInstance.scale({
|
|
|
+ opening: {
|
|
|
+ nice: true
|
|
|
+ },
|
|
|
+ value: {
|
|
|
+ nice: true
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置坐标轴
|
|
|
+ this.flowChartInstance.axis('opening', {
|
|
|
+ title: {
|
|
|
+ text: this.$t('开度 (%)')
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.flowChartInstance.axis('value', {
|
|
|
+ title: {
|
|
|
+ text: this.$t('数值')
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置图例
|
|
|
+ this.flowChartInstance.legend({
|
|
|
+ position: 'top'
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置提示信息
|
|
|
+ this.flowChartInstance.tooltip({
|
|
|
+ shared: true,
|
|
|
+ showCrosshairs: true,
|
|
|
+ crosshairs: {
|
|
|
+ type: 'xy'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 绘制线图
|
|
|
+ this.flowChartInstance
|
|
|
+ .line()
|
|
|
+ .position('opening*value')
|
|
|
+ .color('type', ['#409EFF', '#67C23A'])
|
|
|
+ .shape('smooth')
|
|
|
+ .tooltip('opening*value*type*unit', (opening, value, type, unit) => {
|
|
|
+ return {
|
|
|
+ name: type,
|
|
|
+ value: `${value} ${unit} (开度: ${opening}%)`
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.flowChartInstance
|
|
|
+ .point()
|
|
|
+ .position('opening*value')
|
|
|
+ .color('type', ['#409EFF', '#67C23A'])
|
|
|
+ .size(4)
|
|
|
+ .shape('circle')
|
|
|
+ .style({
|
|
|
+ stroke: '#fff',
|
|
|
+ lineWidth: 1
|
|
|
+ })
|
|
|
+
|
|
|
+ // 渲染图表
|
|
|
+ this.flowChartInstance.render()
|
|
|
+ }).catch(error => {
|
|
|
+ console.error(this.$t('图表库加载失败') + ':', error)
|
|
|
+ this.$message.error(this.$t('图表组件加载失败,请刷新页面重试'))
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 初始化KV图表
|
|
|
+ initKvChart(chartData) {
|
|
|
+ // 销毁已存在的图表实例
|
|
|
+ if (this.kvChartInstance) {
|
|
|
+ this.kvChartInstance.destroy()
|
|
|
+ }
|
|
|
+
|
|
|
+ const chartDom = document.getElementById('kvChart')
|
|
|
+ if (!chartDom) {
|
|
|
+ this.$message.error(this.$t('KV图表容器未找到'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用G2图表库
|
|
|
+ import('@antv/g2').then(({ Chart }) => {
|
|
|
+ // 清空容器
|
|
|
+ chartDom.innerHTML = ''
|
|
|
+
|
|
|
+ // 创建图表实例
|
|
|
+ this.kvChartInstance = new Chart({
|
|
|
+ container: chartDom,
|
|
|
+ autoFit: true,
|
|
|
+ height: 400,
|
|
|
+ padding: [60, 80, 60, 80]
|
|
|
+ })
|
|
|
+
|
|
|
+ // 准备数据 - 使用传入的真实数据或生成模拟数据
|
|
|
+ let allData = []
|
|
|
+
|
|
|
+ if (chartData && chartData.kvData) {
|
|
|
+ // 使用真实数据
|
|
|
+ chartData.kvData.forEach(item => {
|
|
|
+ allData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: this.$t('KV系数')
|
|
|
+ })
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 使用模拟数据作为后备
|
|
|
+ const mockData = this.generateKvChartData()
|
|
|
+ mockData.kvData.forEach(item => {
|
|
|
+ allData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: this.$t('KV系数')
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置数据
|
|
|
+ this.kvChartInstance.data(allData)
|
|
|
+
|
|
|
+ // 设置度量
|
|
|
+ this.kvChartInstance.scale({
|
|
|
+ opening: {
|
|
|
+ nice: true
|
|
|
+ },
|
|
|
+ value: {
|
|
|
+ nice: true
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置坐标轴
|
|
|
+ this.kvChartInstance.axis('opening', {
|
|
|
+ title: {
|
|
|
+ text: this.$t('开度 (%)')
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.kvChartInstance.axis('value', {
|
|
|
+ title: {
|
|
|
+ text: this.$t('KV系数')
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置图例
|
|
|
+ this.kvChartInstance.legend({
|
|
|
+ position: 'top'
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置提示信息
|
|
|
+ this.kvChartInstance.tooltip({
|
|
|
+ shared: true,
|
|
|
+ showCrosshairs: true,
|
|
|
+ crosshairs: {
|
|
|
+ type: 'xy'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 绘制线图
|
|
|
+ this.kvChartInstance
|
|
|
+ .line()
|
|
|
+ .position('opening*value')
|
|
|
+ .color('#409EFF')
|
|
|
+ .shape('smooth')
|
|
|
+ .tooltip('opening*value*type', (opening, value, type) => {
|
|
|
+ return {
|
|
|
+ name: type,
|
|
|
+ value: `${value} (开度: ${opening}%)`
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.kvChartInstance
|
|
|
+ .point()
|
|
|
+ .position('opening*value')
|
|
|
+ .color('#409EFF')
|
|
|
+ .size(4)
|
|
|
+ .shape('circle')
|
|
|
+ .style({
|
|
|
+ stroke: '#fff',
|
|
|
+ lineWidth: 1
|
|
|
+ })
|
|
|
+
|
|
|
+ // 渲染图表
|
|
|
+ this.kvChartInstance.render()
|
|
|
+ }).catch(error => {
|
|
|
+ console.error(this.$t('图表库加载失败') + ':', error)
|
|
|
+ this.$message.error(this.$t('图表组件加载失败,请刷新页面重试'))
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 生成KV模拟数据
|
|
|
+ generateKvChartData() {
|
|
|
+ const openings = this.openingSettings.parsedValues
|
|
|
+ const kvData = []
|
|
|
+
|
|
|
+ openings.forEach(opening => {
|
|
|
+ // 模拟KV系数数据(随开度变化的线性关系)
|
|
|
+ const kv = (opening / 100) * 50 + Math.random() * 5
|
|
|
+ kvData.push([opening, parseFloat(kv.toFixed(3))])
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ openings,
|
|
|
+ kvData
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 生成流阻系数曲线
|
|
|
+ async generateZetaCurve() {
|
|
|
+ if (!this.openingSettings.parsedValues.length) {
|
|
|
+ this.$message.warning(this.$t('请先设置开度值'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.valveSelection.throttleValue) {
|
|
|
+ this.$message.warning(this.$t('请先选择节流件'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 模拟生成流阻系数数据
|
|
|
+ const chartData = this.generateZetaChartData()
|
|
|
+
|
|
|
+ this.showZetaChart = true
|
|
|
+
|
|
|
+ // 等待DOM更新后初始化图表
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.initZetaChart(chartData)
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 生成气蚀系数曲线
|
|
|
+ async generateCavitationCurve() {
|
|
|
+ if (!this.openingSettings.parsedValues.length) {
|
|
|
+ this.$message.warning(this.$t('请先设置开度值'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.valveSelection.throttleValue) {
|
|
|
+ this.$message.warning(this.$t('请先选择节流件'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 模拟生成气蚀系数数据
|
|
|
+ const chartData = this.generateCavitationChartData()
|
|
|
+
|
|
|
+ this.showCavitationChart = true
|
|
|
+
|
|
|
+ // 等待DOM更新后初始化图表
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.initCavitationChart(chartData)
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 生成流阻系数模拟数据
|
|
|
+ generateZetaChartData() {
|
|
|
+ const openings = this.openingSettings.parsedValues
|
|
|
+ const zetaData = []
|
|
|
+
|
|
|
+ openings.forEach(opening => {
|
|
|
+ // 模拟流阻系数数据(随开度变化的非线性关系)
|
|
|
+ const zeta = Math.pow((100 - opening) / 100, 2) * 50 + Math.random() * 5
|
|
|
+ zetaData.push([opening, parseFloat(zeta.toFixed(3))])
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ openings,
|
|
|
+ zetaData
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 生成气蚀系数模拟数据
|
|
|
+ generateCavitationChartData() {
|
|
|
+ const openings = this.openingSettings.parsedValues
|
|
|
+ const cavitationData = []
|
|
|
+
|
|
|
+ openings.forEach(opening => {
|
|
|
+ // 模拟气蚀系数数据(开度越小气蚀系数越大)
|
|
|
+ const cavitation = Math.pow((100 - opening) / 100, 1.5) * 2 + 0.1 + Math.random() * 0.2
|
|
|
+ cavitationData.push([opening, parseFloat(cavitation.toFixed(3))])
|
|
|
+ })
|
|
|
+
|
|
|
+ return {
|
|
|
+ openings,
|
|
|
+ cavitationData
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 初始化流阻系数图表
|
|
|
+ initZetaChart(chartData) {
|
|
|
+ // 销毁已存在的图表实例
|
|
|
+ if (this.zetaChartInstance) {
|
|
|
+ this.zetaChartInstance.destroy()
|
|
|
+ }
|
|
|
+
|
|
|
+ const chartDom = document.getElementById('zetaCoefficientChart')
|
|
|
+ if (!chartDom) {
|
|
|
+ this.$message.error(this.$t('流阻系数图表容器未找到'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用G2图表库
|
|
|
+ import('@antv/g2').then(({ Chart }) => {
|
|
|
+ // 清空容器
|
|
|
+ chartDom.innerHTML = ''
|
|
|
+
|
|
|
+ // 创建图表实例
|
|
|
+ this.zetaChartInstance = new Chart({
|
|
|
+ container: chartDom,
|
|
|
+ autoFit: true,
|
|
|
+ height: 400,
|
|
|
+ padding: [60, 80, 60, 80]
|
|
|
+ })
|
|
|
+
|
|
|
+ // 准备数据 - 使用传入的真实数据或生成模拟数据
|
|
|
+ let allData = []
|
|
|
+
|
|
|
+ if (chartData && chartData.zetaData) {
|
|
|
+ // 使用真实数据
|
|
|
+ chartData.zetaData.forEach(item => {
|
|
|
+ allData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: this.$t('流阻系数ζ')
|
|
|
+ })
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 使用模拟数据作为后备
|
|
|
+ const mockData = this.generateZetaChartData()
|
|
|
+ mockData.zetaData.forEach(item => {
|
|
|
+ allData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: this.$t('流阻系数ζ')
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置数据
|
|
|
+ this.zetaChartInstance.data(allData)
|
|
|
+
|
|
|
+ // 设置度量
|
|
|
+ this.zetaChartInstance.scale({
|
|
|
+ opening: {
|
|
|
+ nice: true
|
|
|
+ },
|
|
|
+ value: {
|
|
|
+ nice: true
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置坐标轴
|
|
|
+ this.zetaChartInstance.axis('opening', {
|
|
|
+ title: {
|
|
|
+ text: this.$t('开度 (%)')
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.zetaChartInstance.axis('value', {
|
|
|
+ title: {
|
|
|
+ text: this.$t('流阻系数ζ')
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置图例
|
|
|
+ this.zetaChartInstance.legend({
|
|
|
+ position: 'top'
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置提示信息
|
|
|
+ this.zetaChartInstance.tooltip({
|
|
|
+ shared: true,
|
|
|
+ showCrosshairs: true,
|
|
|
+ crosshairs: {
|
|
|
+ type: 'xy'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 绘制线图
|
|
|
+ this.zetaChartInstance
|
|
|
+ .line()
|
|
|
+ .position('opening*value')
|
|
|
+ .color('#E6A23C')
|
|
|
+ .shape('smooth')
|
|
|
+ .tooltip('opening*value*type', (opening, value, type) => {
|
|
|
+ return {
|
|
|
+ name: type,
|
|
|
+ value: `${value} (开度: ${opening}%)`
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.zetaChartInstance
|
|
|
+ .point()
|
|
|
+ .position('opening*value')
|
|
|
+ .color('#E6A23C')
|
|
|
+ .size(4)
|
|
|
+ .shape('circle')
|
|
|
+ .style({
|
|
|
+ stroke: '#fff',
|
|
|
+ lineWidth: 1
|
|
|
+ })
|
|
|
+
|
|
|
+ // 渲染图表
|
|
|
+ this.zetaChartInstance.render()
|
|
|
+ }).catch(error => {
|
|
|
+ console.error(this.$t('图表库加载失败') + ':', error)
|
|
|
+ this.$message.error(this.$t('图表组件加载失败,请刷新页面重试'))
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 初始化气蚀系数图表
|
|
|
+ initCavitationChart(chartData) {
|
|
|
+ // 销毁已存在的图表实例
|
|
|
+ if (this.cavitationChartInstance) {
|
|
|
+ this.cavitationChartInstance.destroy()
|
|
|
+ }
|
|
|
+
|
|
|
+ const chartDom = document.getElementById('cavitationCoefficientChart')
|
|
|
+ if (!chartDom) {
|
|
|
+ this.$message.error(this.$t('气蚀系数图表容器未找到'))
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 使用G2图表库
|
|
|
+ import('@antv/g2').then(({ Chart }) => {
|
|
|
+ // 清空容器
|
|
|
+ chartDom.innerHTML = ''
|
|
|
+
|
|
|
+ // 创建图表实例
|
|
|
+ this.cavitationChartInstance = new Chart({
|
|
|
+ container: chartDom,
|
|
|
+ autoFit: true,
|
|
|
+ height: 400,
|
|
|
+ padding: [60, 80, 60, 80]
|
|
|
+ })
|
|
|
+
|
|
|
+ // 准备数据 - 使用传入的真实数据或生成模拟数据
|
|
|
+ let allData = []
|
|
|
+
|
|
|
+ if (chartData && chartData.cavitationData) {
|
|
|
+ // 使用真实数据
|
|
|
+ chartData.cavitationData.forEach(item => {
|
|
|
+ allData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: this.$t('气蚀系数σ')
|
|
|
+ })
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 使用模拟数据作为后备
|
|
|
+ const mockData = this.generateCavitationChartData()
|
|
|
+ mockData.cavitationData.forEach(item => {
|
|
|
+ allData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: this.$t('气蚀系数σ')
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置数据
|
|
|
+ this.cavitationChartInstance.data(allData)
|
|
|
+
|
|
|
+ // 设置度量
|
|
|
+ this.cavitationChartInstance.scale({
|
|
|
+ opening: {
|
|
|
+ nice: true
|
|
|
+ },
|
|
|
+ value: {
|
|
|
+ nice: true
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置坐标轴
|
|
|
+ this.cavitationChartInstance.axis('opening', {
|
|
|
+ title: {
|
|
|
+ text: this.$t('开度 (%)')
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.cavitationChartInstance.axis('value', {
|
|
|
+ title: {
|
|
|
+ text: this.$t('气蚀系数σ')
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置图例
|
|
|
+ this.cavitationChartInstance.legend({
|
|
|
+ position: 'top'
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置提示信息
|
|
|
+ this.cavitationChartInstance.tooltip({
|
|
|
+ shared: true,
|
|
|
+ showCrosshairs: true,
|
|
|
+ crosshairs: {
|
|
|
+ type: 'xy'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 绘制线图
|
|
|
+ this.cavitationChartInstance
|
|
|
+ .line()
|
|
|
+ .position('opening*value')
|
|
|
+ .color('#F56C6C')
|
|
|
+ .shape('smooth')
|
|
|
+ .tooltip('opening*value*type', (opening, value, type) => {
|
|
|
+ return {
|
|
|
+ name: type,
|
|
|
+ value: `${value} (开度: ${opening}%)`
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.cavitationChartInstance
|
|
|
+ .point()
|
|
|
+ .position('opening*value')
|
|
|
+ .color('#F56C6C')
|
|
|
+ .size(4)
|
|
|
+ .shape('circle')
|
|
|
+ .style({
|
|
|
+ stroke: '#fff',
|
|
|
+ lineWidth: 1
|
|
|
+ })
|
|
|
+
|
|
|
+ // 渲染图表
|
|
|
+ this.cavitationChartInstance.render()
|
|
|
+ }).catch(error => {
|
|
|
+ console.error(this.$t('图表库加载失败') + ':', error)
|
|
|
+ this.$message.error(this.$t('图表组件加载失败,请刷新页面重试'))
|
|
|
+ })
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ mounted() {
|
|
|
+ this.optionList()
|
|
|
+ },
|
|
|
+
|
|
|
+ beforeDestroy() {
|
|
|
+ // 销毁图表实例,避免内存泄漏
|
|
|
+ if (this.flowChartInstance) {
|
|
|
+ this.flowChartInstance.destroy()
|
|
|
+ this.flowChartInstance = null
|
|
|
+ }
|
|
|
+ if (this.zetaChartInstance) {
|
|
|
+ this.zetaChartInstance.destroy()
|
|
|
+ this.zetaChartInstance = null
|
|
|
+ }
|
|
|
+ if (this.cavitationChartInstance) {
|
|
|
+ this.cavitationChartInstance.destroy()
|
|
|
+ this.cavitationChartInstance = null
|
|
|
+ }
|
|
|
+ if (this.kvChartInstance) {
|
|
|
+ this.kvChartInstance.destroy()
|
|
|
+ this.kvChartInstance = null
|
|
|
+ }
|
|
|
+ },
|
|
|
+}
|
|
|
+</script>
|
|
|
+<style>
|
|
|
+ .step-content .ant-steps-item-process > .ant-steps-item-container > .ant-steps-item-content > .ant-steps-item-title {
|
|
|
+ color: #3874f6 !important;
|
|
|
+ }
|
|
|
+</style>
|
|
|
+<style scoped>
|
|
|
+.calculation-selection {
|
|
|
+ padding: 20px;
|
|
|
+ background-color: #fff;
|
|
|
+ min-height: calc(100vh - 40px);
|
|
|
+}
|
|
|
+
|
|
|
+.page-header {
|
|
|
+ margin-bottom: 30px;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+
|
|
|
+.page-header h2 {
|
|
|
+ color: #303133;
|
|
|
+ font-size: 24px;
|
|
|
+ font-weight: 500;
|
|
|
+ margin: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.step-container {
|
|
|
+ padding: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+.step-content {
|
|
|
+ margin-bottom: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+.step-panel {
|
|
|
+ animation: fadeIn 0.3s ease-in-out;
|
|
|
+}
|
|
|
+
|
|
|
+@keyframes fadeIn {
|
|
|
+ from {
|
|
|
+ opacity: 0;
|
|
|
+ transform: translateY(20px);
|
|
|
+ }
|
|
|
+ to {
|
|
|
+ opacity: 1;
|
|
|
+ transform: translateY(0);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+.step-card {
|
|
|
+ /* box-shadow: 0 2px 12px 0 rgba(0, 0, 0, 0.1); */
|
|
|
+ border-radius: 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.card-header {
|
|
|
+ font-size: 18px;
|
|
|
+ font-weight: 500;
|
|
|
+ color: #303133;
|
|
|
+}
|
|
|
+
|
|
|
+.button-group {
|
|
|
+ text-align: center;
|
|
|
+ padding: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.button-group .el-button {
|
|
|
+ margin: 0 10px;
|
|
|
+ min-width: 100px;
|
|
|
+}
|
|
|
+
|
|
|
+.el-form-item {
|
|
|
+ margin-bottom: 22px;
|
|
|
+}
|
|
|
+
|
|
|
+.el-divider {
|
|
|
+ margin: 30px 0 20px 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+/* 工况条件表格样式 */
|
|
|
+.condition-table {
|
|
|
+ border: 1px solid #ddd;
|
|
|
+ border-radius: 4px;
|
|
|
+ overflow: hidden;
|
|
|
+}
|
|
|
+
|
|
|
+.condition-row {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ min-height: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+.condition-label {
|
|
|
+ background-color: #f5f5f5;
|
|
|
+ border-right: 1px solid #ddd;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ font-weight: bold;
|
|
|
+ height: 40px;
|
|
|
+}
|
|
|
+
|
|
|
+.condition-input {
|
|
|
+ padding: 0 10px;
|
|
|
+}
|
|
|
+
|
|
|
+.condition-input .el-form-item {
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.condition-input .el-form-item__label {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #666;
|
|
|
+}
|
|
|
+
|
|
|
+/* 开度设置样式 */
|
|
|
+.opening-settings {
|
|
|
+ margin-top: 20px;
|
|
|
+}
|
|
|
+
|
|
|
+.input-tip {
|
|
|
+ font-size: 12px;
|
|
|
+ color: #909399;
|
|
|
+ margin-top: 5px;
|
|
|
+}
|
|
|
+
|
|
|
+.opening-info {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ height: 32px;
|
|
|
+}
|
|
|
+
|
|
|
+.info-text {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+}
|
|
|
+
|
|
|
+.opening-preview {
|
|
|
+ margin-top: 15px;
|
|
|
+ padding: 10px;
|
|
|
+ background-color: #f5f7fa;
|
|
|
+ border-radius: 4px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 图表控制按钮样式 */
|
|
|
+.chart-controls {
|
|
|
+ margin: 20px 0;
|
|
|
+ text-align: center;
|
|
|
+}
|
|
|
+
|
|
|
+.chart-controls .el-button {
|
|
|
+ margin: 0 10px 10px 0;
|
|
|
+ min-width: 140px;
|
|
|
+}
|
|
|
+
|
|
|
+.chart-controls .el-button:last-child {
|
|
|
+ margin-right: 0;
|
|
|
+}
|
|
|
+
|
|
|
+.preview-label {
|
|
|
+ font-size: 14px;
|
|
|
+ color: #606266;
|
|
|
+ margin-right: 10px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 图表容器样式 */
|
|
|
+.chart-container {
|
|
|
+ margin-top: 30px;
|
|
|
+}
|
|
|
+#kvChart,
|
|
|
+#flowOpeningChart,
|
|
|
+#zetaCoefficientChart,
|
|
|
+#cavitationCoefficientChart {
|
|
|
+ border: 1px solid #e4e7ed;
|
|
|
+ border-radius: 4px;
|
|
|
+ background-color: #fff;
|
|
|
+}
|
|
|
+
|
|
|
+.my-steps {
|
|
|
+ padding: 0px 68px;
|
|
|
+}
|
|
|
+
|
|
|
+/* 响应式设计 */
|
|
|
+@media (max-width: 768px) {
|
|
|
+ .calculation-selection {
|
|
|
+ padding: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .step-container {
|
|
|
+ padding: 20px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .el-col {
|
|
|
+ margin-bottom: 10px;
|
|
|
+ }
|
|
|
+
|
|
|
+ .condition-row {
|
|
|
+ flex-direction: column;
|
|
|
+ }
|
|
|
+
|
|
|
+ .condition-label {
|
|
|
+ width: 100%;
|
|
|
+ border-right: none;
|
|
|
+ border-bottom: 1px solid #ddd;
|
|
|
+ }
|
|
|
+
|
|
|
+ #flowOpeningChart {
|
|
|
+ height: 300px !important;
|
|
|
+ }
|
|
|
+}
|
|
|
+</style>
|