ParamSettingDialog.vue 12.5 KB
<template>
  <el-dialog
    :model-value="visible"
    @update:model-value="$emit('update:visible', $event)"
    title=""
    width="calc(100vw - 40px)"
    :style="{ maxWidth: '1400px' }"
    top="3vh"
    destroy-on-close
    class="param-dialog"
  >
    <template #header>
      <div class="dialog-header">
        <span class="title-text">{{ device?.name || '能耗设备1' }}</span>
        <div class="header-right">
          <el-icon :size="16" style="cursor:pointer;color:#409eff;"><Refresh /></el-icon>
          <el-icon :size="16" style="cursor:pointer;color:#409eff;margin-left:6px;"><Grid /></el-icon>
          <el-icon :size="16" style="cursor:pointer;color:#409eff;margin-left:6px;"><List /></el-icon>
          <el-icon :size="16" style="cursor:pointer;color:#409eff;margin-left:6px;" @click="$emit('update:visible', false)"><Close /></el-icon>
        </div>
      </div>
    </template>

    <div class="param-body">
      <!-- 相位标签 -->
      <div class="phase-tabs">
        <div v-for="p in phases" :key="p" :class="['phase-tab', { active: activePhase === p }]"
             @click="activePhase = p">{{ p }}:0</div>
      </div>

      <!-- 主内容区:左侧数据表 + 右侧统计 -->
      <div class="main-grid">
        <!-- 左侧:电压电流功率温度表格 + 曲线 -->
        <div class="left-panel">
          <div class="data-table-area">
            <table class="param-table">
              <thead>
                <tr><th></th><th>电压</th><th>电流</th><th>功率</th><th>温度</th></tr>
              </thead>
              <tbody>
                <tr v-for="row in tableRows" :key="row.label">
                  <td class="row-label">{{ row.label }}</td>
                  <td>{{ row.voltage }}</td>
                  <td>{{ row.current }}</td>
                  <td>{{ row.power }}</td>
                  <td>{{ row.temp }}</td>
                </tr>
              </tbody>
            </table>
            <!-- 右侧额外信息 -->
            <div class="extra-info">
              <div v-for="(info, i) in extraInfos" :key="i" class="ei-item">{{ info }}:0</div>
            </div>
          </div>

          <!-- 电流均值/峰值曲线 -->
          <div class="curve-section">
            <div class="curve-header">
              <span class="curve-title">电流均值/峰值曲线 ▼</span>
              <el-date-picker v-model="curveDate" type="date" size="small" placeholder="2026-04-28" />
            </div>
            <div class="curve-chart">
              <svg viewBox="0 0 700 180">
                <g font-size="10" fill="#999" text-anchor="end">
                  <text x="24" y="18">5</text><text x="24" y="53">4</text><text x="24" y="88">3</text>
                  <text x="24" y="123">2</text><text x="24" y="158">1</text>
                </g>
                <line x1="30" y1="154" x2="680" y2="154" stroke="#ddd"/>
                <polyline points="36,154 56,154 76,154 ... 660,154" fill="none" stroke="#f5a623" stroke-width="1.2"/>
                <g font-size="8" fill="#666" text-anchor="middle">
                  <text x="46" y="168">00:00</text><text x="130" y="168">04:00</text>
                  <text x="220" y="168">08:00</text><text x="310" y="168">12:00</text>
                  <text x="400" y="168">16:00</text><text x="490" y="168">20:00</text><text x="580" y="168">24:00</text>
                </g>
              </svg>
            </div>
            <div class="curve-legend">
              <span class="leg"><i class="dot y"/>电流最大值</span>
              <span class="leg"><i class="dot g"/>电流最小值</span>
              <span class="leg"><i class="dot r"/>电流瞬时平均值</span>
            </div>
          </div>

          <!-- 电能 & 相位角 -->
          <div class="bottom-row">
            <div class="power-card">
              <div class="pc-title">电能</div>
              <div class="pc-list">
                <div v-for="(p, i) in powerItems" :key="i" :class="['pc-item', p.color]">
                  <span class="pc-dot"></span> {{ p.label }}
                  <span class="pc-val">{{ p.val }}</span>
                </div>
              </div>
            </div>
            <div class="angle-card">
              <div class="ac-title">相位角</div>
              <div class="ac-charts">
                <div class="ac-pie-wrap">
                  <svg viewBox="0 0 120 120"><circle cx="60" cy="60" r="48" fill="#e8f4fd"/><text x="60" y="55" text-anchor="middle" font-size="11" fill="#333">电压相位角</text>
                    <g font-size="10" fill="#666"><text x="45" y="72">A相 0</text><text x="75" y="72">B相 0</text><text x="60" y="86">C相 0</text></g>
                    <circle cx="35" cy="90" r="3" fill="#e74c3c"/><circle cx="60" cy="93" r="3" fill="#67c23a"/><circle cx="85" cy="90" r="3" fill="#409eff"/>
                  </svg>
                </div>
                <div class="ac-pie-wrap">
                  <svg viewBox="0 0 120 120"><circle cx="60" cy="60" r="48" fill="#e8f4fd"/><text x="60" y="55" text-anchor="middle" font-size="11" fill="#333">电流相位角</text>
                    <g font-size="10" fill="#666"><text x="42" y="70">A相 0</text><text x="78" y="70">B相 0</text><text x="60" y="84">C相 0</text></g>
                    <circle cx="32" cy="92" r="3" fill="#e74c3c"/><circle cx="58" cy="95" r="3" fill="#67c23a"/><circle cx="84" cy="92" r="3" fill="#409eff"/>
                  </svg>
                </div>
              </div>
              <div class="ac-ref">参考值: A相 120 &nbsp; B相 120 &nbsp; C相 240</div>
            </div>
          </div>
        </div>

        <!-- 右侧:功率统计 -->
        <div class="right-panel">
          <div class="rp-title">功率</div>
          <div class="power-stats">
            <div v-for="(ps, i) in powerStats" :key="i" :class="['ps-item', 'ps-'+ps.color]">
              <div class="ps-circle">
                <svg viewBox="0 0 50 50"><circle cx="25" cy="25" r="20" fill="none" stroke="#eee" stroke-width="5"/>
                  <text x="25" y="28" text-anchor="middle" font-size="13" font-weight="bold" fill="#333">{{ ps.val }}</text>
                </svg>
              </div>
              <div class="ps-info">
                <div class="ps-bars">
                  <span :class="'ps-bar '+pb.color" v-for="(pb, j) in ps.bars" :key="j">
                    {{ pb.label }}{{ pb.val }}
                  </span>
                </div>
                <div class="ps-result">视在功率 &nbsp;&nbsp; {{ ps.result }}</div>
              </div>
            </div>
          </div>

          <!-- 温度图表 -->
          <div class="temp-card">
            <div class="temp-header">温度 <b>▼</b></div>
            <div class="temp-chart">
              <svg viewBox="0 0 280 140">
                <g font-size="9" fill="#999" text-anchor="end">
                  <text x="22" y="15">1</text><text x="22" y="43">0.8</text><text x="22" y="71">0.6</text>
                  <text x="22" y="99">0.4</text><text x="22" y="127">0.2</text>
                </g>
                <line x1="28" y1="124" x2="268" y2="124" stroke="#ddd"/>
                <g font-size="7" fill="#666" text-anchor="middle">
                  <text x="38" y="136">温度TA</text><text x="68" y="136">温度TB</text>
                  <text x="98" y="136">温度TC</text><text x="128" y="136">温度TN</text>
                  <text x="158" y="136">温度TE</text>
                </g>
              </svg>
            </div>
          </div>
        </div>
      </div>
    </div>
  </el-dialog>
</template>

<script setup>
import { ref } from 'vue'
import { Refresh, Grid, List, Close } from '@element-plus/icons-vue'

defineProps({ visible: Boolean, device: Object })
defineEmits(['update:visible'])

const phases = ['UA', 'UB', 'UC', 'UAB', 'UBC', 'UAC', 'UF']
const activePhase = ref('UA')
const curveDate = ref('')

const tableRows = [
  { label: '极大值', voltage: 0, current: 0, power: 0, temp: 0 },
  { label: '平均值', voltage: 0, current: 0, power: 0, temp: 0 },
  { label: '极小值', voltage: 0, current: 0, power: 0, temp: 0 }
]
const extraInfos = ['IA', 'IB', 'IC']
const powerItems = [
  { label: 'A相', val: 0, color: 'o' },
  { label: 'B相', val: 0, color: 'g' },
  { label: 'C相', val: 0, color: 'r' },
  { label: '合相', val: 0, color: 'b' }
]
const powerStats = [
  {
    color: 'o', val: 0,
    bars: [
      { label: '有功功率', val: 0, color: '' },
      { label: 'A相 ', val: '', color: 'o' }, { label: '无功功率', val: 0, color: '' }
    ],
    result: 0
  },
  {
    color: 'g', val: 0,
    bars: [
      { label: '有功功率', val: 0, color: '' },
      { label: 'B相 ', val: '', color: 'g' }, { label: '无功功率', val: 0, color: '' }
    ],
    result: 0
  },
  {
    color: 'r', val: 0,
    bars: [
      { label: '有功功率', val: 0, color: '' },
      { label: 'C相 ', val: '', color: 'r' }, { label: '无功功率', val: 0, color: '' }
    ],
    result: 0
  },
  {
    color: 'b', val: 0,
    bars: [
      { label: '有功功率', val: 0, color: '' },
      { label: '合相 ', val: '', color: 'b' }, { label: '无功功率', val: 0, color: '' }
    ],
    result: 0
  }
]
</script>

<style scoped>
.param-dialog :deep(.el-dialog){max-height:92vh;display:flex;flex-direction:column;}
.param-dialog :deep(.el-dialog__header){padding:10px 20px;border-bottom:1px solid #e8e8e8;margin:0;flex-shrink:0;}
.param-dialog :deep(.el-dialog__body){overflow-y:auto;flex:1;padding:12px;}
.dialog-header{display:flex;align-items:center;justify-content:space-between;}
.title-text{font-size:15px;font-weight:bold;color:#333;}
.header-right{display:flex;align-items:center;}

.phase-tabs{display:flex;gap:4px;background:#fff;border:1px solid #eee;border-radius:6px 6px 0 0;padding:8px 14px;}
.phase-tab{padding:6px 14px;font-size:12px;cursor:pointer;color:#666;border-radius:4px;}
.phase-tab.active{background:#409eff;color:#fff;font-weight:bold;}

.main-grid{display:flex;gap:14px;background:#fff;border:1px solid #eee;border-top:none;border-radius:0 0 6px 6px;padding:14px;}

.left-panel{flex:1;min-width:0;}
.data-table-area{background:#408aff;border-radius:6px;padding:14px;display:flex;gap:16px;margin-bottom:12px;color:#fff;}
.param-table{border-collapse:collapse;font-size:13px;}
.param-table th{padding:6px 16px;text-align:center;font-weight:normal;opacity:0.85;border-bottom:1px solid rgba(255,255,255,0.2);}
.param-table td{padding:6px 16px;text-align:center;}
.row-label{text-align:left!important;font-weight:bold;}
.extra-info{font-size:12px;opacity:0.85;line-height:2;}

.curve-section{border:1px solid #eee;border-radius:6px;padding:12px;margin-bottom:12px;}
.curve-header{display:flex;justify-content:space-between;align-items:center;margin-bottom:8px;}
.curve-title{font-size:13px;font-weight:bold;color:#333;}
.curve-legend{display:flex;gap:14px;font-size:11px;color:#666;margin-top:6px;}
.curve-chart svg{width:100%;height:auto;}

.bottom-row{display:flex;gap:12px;}
.power-card,.angle-card{flex:1;border:1px solid #eee;border-radius:6px;padding:12px;}
.pc-title,.ac-title{font-size:13px;font-weight:bold;color:#333;margin-bottom:8px;}
.pc-list{display:flex;flex-direction:column;gap:6px;}
.pc-item{display:flex;align-items:center;gap:6px;font-size:12px;color:#666;}
.pc-dot{width:10px;height:10px;border-radius:2px;}
.pc-dot.o{background:#f56c6c;}.pc-dot.g{background:#67c23a;}
.pc-dot.r{background:#e74c3c;}.pc-dot.b{background:#409eff;}
.pc-val{margin-left:auto;font-weight:bold;color:#333;}

.ac-charts{display:flex;gap:12px;justify-content:center;}
.ac-pie-wrap svg{width:110px;height:110px;}
.ac-ref{text-align:center;font-size:11px;color:#999;margin-top:6px;}

.right-panel{width:260px;flex-shrink:0;}
.rp-title{font-size:14px;font-weight:bold;color:#333;margin-bottom:10px;}
.power-stats{display:flex;flex-direction:column;gap:10px;margin-bottom:14px;}
.ps-item{display:flex;align-items:center;gap:8px;}
.ps-circle svg{width:44px;height:44px;flex-shrink:0;}
.ps-info{flex:1;font-size:10px;color:#666;}
.ps-bar{display:inline-block;padding:2px 4px;border-radius:2px;margin-right:4px;}
.ps-bar.o{background:#fff3e0;color:#e65100;}.ps-bar.g{background:#e8f5e9;color:#2e7d32;}
.ps-bar.r{background:#ffebee;color:#c62828;}.ps-bar.b{background:#e3f2fd;color:#1565c0;}
.ps-result{margin-top:2px;}

.temp-card{border:1px solid #eee;border-radius:6px;padding:12px;}
.temp-header{font-size:13px;font-weight:bold;color:#333;margin-bottom:8px;}
.temp-chart svg{width:100%;height:auto;}

.leg{display:flex;align-items:center;gap:3px;}
.dot{display:inline-block;width:10px;height:10px;border-radius:2px;}
.dot.y{background:#f5a623;}.dot.g{background:#67c23a;}.dot.r{background:#f56c6c;}
</style>