|
@@ -0,0 +1,1765 @@
|
|
|
+<template>
|
|
|
+ <div class="calculation-selection">
|
|
|
+ <div class="step-content">
|
|
|
+ <div class="step-container">
|
|
|
+ <el-steps :active="activeStep" finish-status="success" align-center>
|
|
|
+ <el-step title="基本信息"></el-step>
|
|
|
+ <el-step title="工况条件"></el-step>
|
|
|
+ <el-step title="选型计算"></el-step>
|
|
|
+ </el-steps>
|
|
|
+ </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">环境条件</el-divider>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item label="大气压 (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="重力加速度 (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="饱和蒸气压 (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="温度 (℃)" prop="t">
|
|
|
+ <el-input v-model="basicInfo.t" placeholder="20"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+
|
|
|
+ <!-- 阀门条件 -->
|
|
|
+ <el-divider content-position="left">阀门条件</el-divider>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="公称通径" prop="caliber">
|
|
|
+ <el-select v-model="basicInfo.caliber" placeholder="请选择" 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="公称压力" prop="pressure">
|
|
|
+ <el-select v-model="basicInfo.pressure" placeholder="请选择" 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="管道外径 (mm)" prop="od">
|
|
|
+ <el-input v-model="basicInfo.od" placeholder="请输入"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="壁厚 (mm)" prop="wt">
|
|
|
+ <el-input v-model="basicInfo.wt" placeholder="请输入"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="控制点名称" prop="cname">
|
|
|
+ <el-input v-model="basicInfo.cname" placeholder="请输入"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="应用场景" prop="purpose">
|
|
|
+ <el-select v-model="basicInfo.purpose" placeholder="请选择" style="width: 100%">
|
|
|
+ <el-option label="通用" value="通用"></el-option>
|
|
|
+ <el-option label="水库引水" value="水库引水"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="介质" prop="mediatype">
|
|
|
+ <el-select v-model="basicInfo.mediatype" @change="onMediumTypeChange" placeholder="请选择" style="width: 100%">
|
|
|
+ <el-option label="水" value="水"></el-option>
|
|
|
+ <el-option label="蒸汽" value="蒸汽"></el-option>
|
|
|
+ <el-option label="油" value="油"></el-option>
|
|
|
+ <el-option label="气体" value="气体"></el-option>
|
|
|
+ </el-select>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="密度" prop="p">
|
|
|
+ <el-input v-model="basicInfo.p" placeholder="1.0" :disabled="true"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="要求最大开度 (%)" prop="maxli">
|
|
|
+ <el-input v-model="basicInfo.maxli" placeholder="请输入"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="要求最小开度 (%)" prop="minli">
|
|
|
+ <el-input v-model="basicInfo.minli" placeholder="10"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="起点高程 (m)" prop="z1">
|
|
|
+ <el-input v-model="basicInfo.z1" placeholder="请输入"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="末点高程 (m)" prop="z2">
|
|
|
+ <el-input v-model="basicInfo.z2" placeholder="请输入"></el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ </el-row>
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="8">
|
|
|
+ <el-form-item label="阀中心高程 (m)" prop="zv">
|
|
|
+ <el-input v-model="basicInfo.zv" placeholder="请输入"></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">工况要求</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;">最小流量</span>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item label="流量:" prop="minCondition.flow" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.minCondition.flow" @input="calculatePressureDrop('min')" placeholder="300">
|
|
|
+
|
|
|
+ <span style="color:blue" slot="suffix">
|
|
|
+ >m³/h
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item label="阀前压力:" prop="minCondition.beforePressure" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.minCondition.beforePressure" @input="calculatePressureDrop('min')" placeholder="500">
|
|
|
+ <span style="color:blue" slot="suffix">kpa
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item label="阀后压力:" prop="minCondition.afterPressure" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.minCondition.afterPressure" @input="calculatePressureDrop('min')" placeholder="200">
|
|
|
+ <span style="color:blue" slot="suffix">kpa
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item label="前后压差:" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.minCondition.pressureDrop" placeholder="300" :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;">最大流量</span>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item label="流量:" prop="maxCondition.flow" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.maxCondition.flow" @input="calculatePressureDrop('max')" placeholder="800">
|
|
|
+ <span style="color:blue" slot="suffix">
|
|
|
+ >m³/h
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item label="阀前压力:" prop="maxCondition.beforePressure" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.maxCondition.beforePressure" @input="calculatePressureDrop('max')" placeholder="150">
|
|
|
+ <span style="color:blue" slot="suffix">kpa
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item label="阀后压力:" prop="maxCondition.afterPressure" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.maxCondition.afterPressure" @input="calculatePressureDrop('max')" placeholder="100">
|
|
|
+ <span style="color:blue" slot="suffix">kpa
|
|
|
+ </span>
|
|
|
+ </el-input>
|
|
|
+ </el-form-item>
|
|
|
+ </el-col>
|
|
|
+ <el-col :span="5">
|
|
|
+ <el-form-item label="前后压差:" style="margin-bottom: 0;">
|
|
|
+ <el-input v-model="workingCondition.maxCondition.pressureDrop" placeholder="50" :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">节流件类型: </p>
|
|
|
+ <el-select v-model="valveSelection.throttletype" placeholder="请选择节流件类型" 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">节流件: </p>
|
|
|
+ <el-select :disabled="!valveSelection.throttletype" v-model="valveSelection.throttleValue" placeholder="请选择节流件类型" 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')">开始选型</el-button>
|
|
|
+ </div>
|
|
|
+ <el-table :data="tableData" style="width: 100%" size="mini" border>
|
|
|
+ <el-table-column prop="workingCondition" label="工况" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="conditionName" label="条件名称" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="q" label="流量(q)" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="p1" label="阀前压力(p1)" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="p2" label="阀后压力(p2)" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="p" label="前后压差(p)" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="pv" label="饱和蒸汽压(pV)" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="kv" label="KV(kv)" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="li" label="开度(li)" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="ldc" label="临界汽蚀系数σc(Idc)" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="dc" label="气蚀系数σ(dc)" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="fi" label="压力恢复系数FI(fi)" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="fr" label="流阻系数ζ(fr)" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="fkv" label="阻塞流修正系数Fkv(fkv)" align="center"></el-table-column>
|
|
|
+ <el-table-column prop="v" label="流速V(v)" align="center"></el-table-column>
|
|
|
+ </el-table>
|
|
|
+ <!-- 开度设置 -->
|
|
|
+ <el-divider content-position="left">开度设置</el-divider>
|
|
|
+ <div class="opening-settings">
|
|
|
+ <el-row :gutter="20">
|
|
|
+ <el-col :span="12">
|
|
|
+ <el-input
|
|
|
+ v-model="openingSettings.openingValues"
|
|
|
+ placeholder="请输入开度值,用逗号分隔,如: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">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">流阻系数曲线图</el-divider>
|
|
|
+ <div id="zetaCoefficientChart" style="width: 100%; height: 400px;"></div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <!-- 气蚀系数曲线图 -->
|
|
|
+ <div v-if="showCavitationChart" class="chart-container">
|
|
|
+ <el-divider content-position="left">气蚀系数曲线图</el-divider>
|
|
|
+ <div id="cavitationCoefficientChart" style="width: 100%; height: 400px;"></div>
|
|
|
+ </div>
|
|
|
+ <!-- 流量开度曲线图 -->
|
|
|
+ <div v-if="showFlowChart" class="chart-container">
|
|
|
+ <el-divider content-position="left">流量开度曲线图</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">上一步</el-button>
|
|
|
+ <el-button v-if="activeStep < 2" type="primary" @click="nextStep">下一步</el-button>
|
|
|
+ <el-button v-if="activeStep === 2" type="primary" @click="saveSelection">保存选型</el-button>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+
|
|
|
+
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+
|
|
|
+<script>
|
|
|
+export default {
|
|
|
+ name: 'CalculationAndSelection',
|
|
|
+ data() {
|
|
|
+ return {
|
|
|
+ activeStep: 0,
|
|
|
+ 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: '通用',
|
|
|
+ mediatype: '水',
|
|
|
+ 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: '请输入控制点名称', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ purpose: [
|
|
|
+ { required: true, message: '请选择应用场景', trigger: 'change' }
|
|
|
+ ],
|
|
|
+ mediatype: [
|
|
|
+ { required: true, message: '请选择介质', trigger: 'change' }
|
|
|
+ ],
|
|
|
+ od: [
|
|
|
+ { required: true, message: '请输入管道外径', trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ wt: [
|
|
|
+ { required: true, message: '请输入壁厚', trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ z1: [
|
|
|
+ { required: true, message: '请输入起点高程', trigger: 'blur' },
|
|
|
+ { pattern: /^-?\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ zv: [
|
|
|
+ { required: true, message: '请输入阀中心高程', trigger: 'blur' },
|
|
|
+ { pattern: /^-?\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ z2: [
|
|
|
+ { required: true, message: '请输入末点高程', trigger: 'blur' },
|
|
|
+ { pattern: /^-?\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+
|
|
|
+ workingRules: {
|
|
|
+ 'minCondition.flow': [
|
|
|
+ { required: true, message: '请输入最小流量', trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ 'minCondition.beforePressure': [
|
|
|
+ { required: true, message: '请输入阀前压力', trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ 'minCondition.afterPressure': [
|
|
|
+ { required: true, message: '请输入阀后压力', trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ 'maxCondition.flow': [
|
|
|
+ { required: true, message: '请输入最大流量', trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ 'maxCondition.beforePressure': [
|
|
|
+ { required: true, message: '请输入阀前压力', trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ 'maxCondition.afterPressure': [
|
|
|
+ { required: true, message: '请输入阀后压力', trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+
|
|
|
+ conditionRules: {
|
|
|
+ workingPressure: [
|
|
|
+ { required: true, message: '请输入工作压力', trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ workingTemperature: [
|
|
|
+ { required: true, message: '请输入工作温度', trigger: 'blur' },
|
|
|
+ { pattern: /^-?\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ],
|
|
|
+ flowRate: [
|
|
|
+ { required: true, message: '请输入流量', trigger: 'blur' },
|
|
|
+ { pattern: /^\d+(\.\d+)?$/, message: '请输入有效的数值', trigger: 'blur' }
|
|
|
+ ]
|
|
|
+ },
|
|
|
+
|
|
|
+ valveRules: {
|
|
|
+ valveType: [
|
|
|
+ { required: true, message: '请选择阀门类型', trigger: 'change' }
|
|
|
+ ],
|
|
|
+ valveSize: [
|
|
|
+ { required: true, message: '请选择阀门口径', trigger: 'change' }
|
|
|
+ ],
|
|
|
+ connectionType: [
|
|
|
+ { required: true, message: '请选择连接方式', trigger: 'change' }
|
|
|
+ ],
|
|
|
+ material: [
|
|
|
+ { required: true, message: '请选择材质', 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('请完善当前步骤的必填信息')
|
|
|
+ }
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 上一步
|
|
|
+ prevStep() {
|
|
|
+ this.activeStep--
|
|
|
+ },
|
|
|
+
|
|
|
+ // 介质类型变化时自动设置密度
|
|
|
+ onMediumTypeChange(value) {
|
|
|
+ const densityMap = {
|
|
|
+ '水': '1000',
|
|
|
+ '蒸汽': '0.6',
|
|
|
+ '油': '850',
|
|
|
+ '气体': '1.2'
|
|
|
+ }
|
|
|
+ this.basicInfo.p = 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()
|
|
|
+ }
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 验证工况条件数据
|
|
|
+ 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.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.validationType = 'error'
|
|
|
+ return false
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 如果所有验证都通过
|
|
|
+ if (minCondition.flow && maxCondition.flow &&
|
|
|
+ minCondition.beforePressure && minCondition.afterPressure &&
|
|
|
+ maxCondition.beforePressure && maxCondition.afterPressure) {
|
|
|
+ this.validationMessage = '工况条件数据验证通过'
|
|
|
+ this.validationType = 'success'
|
|
|
+ }
|
|
|
+
|
|
|
+ return true
|
|
|
+ },
|
|
|
+
|
|
|
+ // 保存选型
|
|
|
+ saveSelection() {
|
|
|
+ this.issave = true
|
|
|
+ this.beginSelection(()=>{
|
|
|
+ this.$message({
|
|
|
+ message: '选型方案保存成功!',
|
|
|
+ type: 'success'
|
|
|
+ })
|
|
|
+ this.issave = false
|
|
|
+ },'save')
|
|
|
+ },
|
|
|
+ optionList() {
|
|
|
+ this.$store.dispatch("optiontypeselect", "caliber2").then((res) => {
|
|
|
+ this.typeList = res.data;
|
|
|
+ console.log(this.typeList, "公称通径");
|
|
|
+ });
|
|
|
+ this.$store.dispatch("optiontypeselect", "pressure").then((res) => {
|
|
|
+ this.pressureList = res.data;
|
|
|
+ console.log(this.pressureList, "公称压力");
|
|
|
+ });
|
|
|
+
|
|
|
+ this.$store.dispatch("optiontypeselect", "throttletype").then((res) => {
|
|
|
+ this.throttletype = res.data;
|
|
|
+ console.log(this.throttletype, "节流件类型");
|
|
|
+ });
|
|
|
+ },
|
|
|
+
|
|
|
+ // 查询节流件
|
|
|
+ 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: '通用',
|
|
|
+ conditionName: '最小流量'
|
|
|
+ }
|
|
|
+ const maxData = {
|
|
|
+ ...res.data.max,
|
|
|
+ workingCondition: '通用',
|
|
|
+ conditionName: '最大流量'
|
|
|
+ }
|
|
|
+ this.tableData = [minData, maxData]
|
|
|
+ } else {
|
|
|
+ // 如果没有返回数据,显示错误信息
|
|
|
+ this.$message.error(res.msg || '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('请输入有效的开度值(0-100之间的数字)')
|
|
|
+ }
|
|
|
+ },
|
|
|
+
|
|
|
+ // 处理API返回的图表数据
|
|
|
+ processChartData(lineData) {
|
|
|
+ console.log('processChartData被调用,数据:', lineData)
|
|
|
+
|
|
|
+ if (!lineData) {
|
|
|
+ this.$message.error('未获取到图表数据')
|
|
|
+ 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('请先设置开度值')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.valveSelection.throttleValue) {
|
|
|
+ this.$message.warning('请先选择节流件')
|
|
|
+ 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('图表容器未找到')
|
|
|
+ console.error('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] || '默认' // 获取压差条件
|
|
|
+ chartData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: `流量-${pressureCondition}kPa`,
|
|
|
+ unit: 'm³/h'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ data.pressureDropData.forEach(item => {
|
|
|
+ const pressureCondition = item[2] || '默认' // 获取压差条件
|
|
|
+ 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: '流量',
|
|
|
+ unit: 'm³/h'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ mockData.pressureDropData.forEach(item => {
|
|
|
+ chartData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: '压差',
|
|
|
+ unit: 'kPa'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置数据
|
|
|
+ this.flowChartInstance.data(chartData)
|
|
|
+
|
|
|
+ // 设置度量
|
|
|
+ this.flowChartInstance.scale({
|
|
|
+ opening: {
|
|
|
+ nice: true
|
|
|
+ },
|
|
|
+ value: {
|
|
|
+ nice: true
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置坐标轴
|
|
|
+ this.flowChartInstance.axis('opening', {
|
|
|
+ title: {
|
|
|
+ text: '开度 (%)'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.flowChartInstance.axis('value', {
|
|
|
+ title: {
|
|
|
+ text: '数值'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置图例
|
|
|
+ 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('图表库加载失败:', error)
|
|
|
+ this.$message.error('图表组件加载失败,请刷新页面重试')
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 初始化KV图表
|
|
|
+ initKvChart(chartData) {
|
|
|
+ // 销毁已存在的图表实例
|
|
|
+ if (this.kvChartInstance) {
|
|
|
+ this.kvChartInstance.destroy()
|
|
|
+ }
|
|
|
+
|
|
|
+ const chartDom = document.getElementById('kvChart')
|
|
|
+ if (!chartDom) {
|
|
|
+ this.$message.error('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: 'KV系数'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 使用模拟数据作为后备
|
|
|
+ const mockData = this.generateKvChartData()
|
|
|
+ mockData.kvData.forEach(item => {
|
|
|
+ allData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: 'KV系数'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置数据
|
|
|
+ this.kvChartInstance.data(allData)
|
|
|
+
|
|
|
+ // 设置度量
|
|
|
+ this.kvChartInstance.scale({
|
|
|
+ opening: {
|
|
|
+ nice: true
|
|
|
+ },
|
|
|
+ value: {
|
|
|
+ nice: true
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置坐标轴
|
|
|
+ this.kvChartInstance.axis('opening', {
|
|
|
+ title: {
|
|
|
+ text: '开度 (%)'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.kvChartInstance.axis('value', {
|
|
|
+ title: {
|
|
|
+ text: '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('图表库加载失败:', error)
|
|
|
+ this.$message.error('图表组件加载失败,请刷新页面重试')
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 生成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('请先设置开度值')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.valveSelection.throttleValue) {
|
|
|
+ this.$message.warning('请先选择节流件')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ // 模拟生成流阻系数数据
|
|
|
+ const chartData = this.generateZetaChartData()
|
|
|
+
|
|
|
+ this.showZetaChart = true
|
|
|
+
|
|
|
+ // 等待DOM更新后初始化图表
|
|
|
+ this.$nextTick(() => {
|
|
|
+ this.initZetaChart(chartData)
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 生成气蚀系数曲线
|
|
|
+ async generateCavitationCurve() {
|
|
|
+ if (!this.openingSettings.parsedValues.length) {
|
|
|
+ this.$message.warning('请先设置开度值')
|
|
|
+ return
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!this.valveSelection.throttleValue) {
|
|
|
+ this.$message.warning('请先选择节流件')
|
|
|
+ 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('流阻系数图表容器未找到')
|
|
|
+ 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: '流阻系数ζ'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 使用模拟数据作为后备
|
|
|
+ const mockData = this.generateZetaChartData()
|
|
|
+ mockData.zetaData.forEach(item => {
|
|
|
+ allData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: '流阻系数ζ'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置数据
|
|
|
+ this.zetaChartInstance.data(allData)
|
|
|
+
|
|
|
+ // 设置度量
|
|
|
+ this.zetaChartInstance.scale({
|
|
|
+ opening: {
|
|
|
+ nice: true
|
|
|
+ },
|
|
|
+ value: {
|
|
|
+ nice: true
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置坐标轴
|
|
|
+ this.zetaChartInstance.axis('opening', {
|
|
|
+ title: {
|
|
|
+ text: '开度 (%)'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.zetaChartInstance.axis('value', {
|
|
|
+ title: {
|
|
|
+ text: '流阻系数ζ'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置图例
|
|
|
+ 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('图表库加载失败:', error)
|
|
|
+ this.$message.error('图表组件加载失败,请刷新页面重试')
|
|
|
+ })
|
|
|
+ },
|
|
|
+
|
|
|
+ // 初始化气蚀系数图表
|
|
|
+ initCavitationChart(chartData) {
|
|
|
+ // 销毁已存在的图表实例
|
|
|
+ if (this.cavitationChartInstance) {
|
|
|
+ this.cavitationChartInstance.destroy()
|
|
|
+ }
|
|
|
+
|
|
|
+ const chartDom = document.getElementById('cavitationCoefficientChart')
|
|
|
+ if (!chartDom) {
|
|
|
+ this.$message.error('气蚀系数图表容器未找到')
|
|
|
+ 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: '气蚀系数σ'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ } else {
|
|
|
+ // 使用模拟数据作为后备
|
|
|
+ const mockData = this.generateCavitationChartData()
|
|
|
+ mockData.cavitationData.forEach(item => {
|
|
|
+ allData.push({
|
|
|
+ opening: item[0],
|
|
|
+ value: item[1],
|
|
|
+ type: '气蚀系数σ'
|
|
|
+ })
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置数据
|
|
|
+ this.cavitationChartInstance.data(allData)
|
|
|
+
|
|
|
+ // 设置度量
|
|
|
+ this.cavitationChartInstance.scale({
|
|
|
+ opening: {
|
|
|
+ nice: true
|
|
|
+ },
|
|
|
+ value: {
|
|
|
+ nice: true
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置坐标轴
|
|
|
+ this.cavitationChartInstance.axis('opening', {
|
|
|
+ title: {
|
|
|
+ text: '开度 (%)'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ this.cavitationChartInstance.axis('value', {
|
|
|
+ title: {
|
|
|
+ text: '气蚀系数σ'
|
|
|
+ }
|
|
|
+ })
|
|
|
+
|
|
|
+ // 设置图例
|
|
|
+ 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('图表库加载失败:', error)
|
|
|
+ this.$message.error('图表组件加载失败,请刷新页面重试')
|
|
|
+ })
|
|
|
+ },
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ 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 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;
|
|
|
+}
|
|
|
+
|
|
|
+/* 响应式设计 */
|
|
|
+@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>
|