spring
6 天以前 f7165c61dd8a808132c09096f5a367565387f3e4
Merge remote-tracking branch 'origin/dev_JLMY' into dev_JLMY
已修改1个文件
已添加2个文件
2289 ■■■■■ 文件已修改
src/views/warehouseManagement/KeyCoalLocks/index.vue 1138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/warehouseManagement/index.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/warehouseManagement/stockWarning/index.vue 1138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/warehouseManagement/KeyCoalLocks/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1138 @@
<template>
  <div class="app-container">
    <!-- æœç´¢è¡¨å• -->
    <div class="search_form">
      <el-form :model="searchForm" :inline="true">
        <el-form-item label="储气罐名称:">
          <el-input v-model="searchForm.tankName" placeholder="请输入储气罐名称" clearable style="width: 200px" />
        </el-form-item>
        <el-form-item label="储气罐类型:">
          <el-select v-model="searchForm.tankType" placeholder="请选择储气罐类型" clearable style="width: 200px">
            <el-option label="液化气储罐" value="液化气储罐" />
            <el-option label="压缩气储罐" value="压缩气储罐" />
            <el-option label="天然气储罐" value="天然气储罐" />
            <el-option label="氧气储罐" value="氧气储罐" />
          </el-select>
        </el-form-item>
        <el-form-item label="预警类型:">
          <el-select v-model="searchForm.warningType" placeholder="请选择预警类型" clearable style="width: 200px">
            <el-option label="气体不足" value="气体不足" />
            <el-option label="压力异常" value="压力异常" />
            <el-option label="温度异常" value="温度异常" />
            <el-option label="泄漏预警" value="泄漏预警" />
          </el-select>
        </el-form-item>
        <el-form-item label="预警级别:">
          <el-select v-model="searchForm.warningLevel" placeholder="请选择预警级别" clearable style="width: 200px">
            <el-option label="紧急" value="紧急" />
            <el-option label="重要" value="重要" />
            <el-option label="一般" value="一般" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleQuery">搜索</el-button>
          <el-button @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- æ•°æ®è¡¨æ ¼ -->
    <div class="table_list">
      <!-- æ“ä½œæŒ‰é’® -->
      <div class="table-operations">
        <el-button type="primary" @click="handleAdd">新增预警规则</el-button>
        <el-button type="success" @click="handleBatchProcess">批量处理</el-button>
        <el-button @click="handleExport">导出</el-button>
      </div>
      <el-table
          :data="tableData"
          border
          v-loading="tableLoading"
          @selection-change="handleSelectionChange"
          style="width: 100%"
          height="calc(100vh - 280px)"
      >
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column align="center" label="序号" type="index" width="60" />
        <!-- åŸºç¡€ä¿¡æ¯å­—段 -->
        <el-table-column label="储气罐编码" prop="tankCode" width="120" show-overflow-tooltip />
        <el-table-column label="储气罐名称" prop="tankName" width="200" show-overflow-tooltip />
        <el-table-column label="储气罐类型" prop="tankType" width="120" show-overflow-tooltip />
        <el-table-column label="规格型号" prop="specificationModel" width="150" show-overflow-tooltip />
        <el-table-column label="容积(m³)" prop="volume" width="100" show-overflow-tooltip />
        <!-- åº“存相关字段 -->
        <el-table-column label="当前气体量" prop="currentGasLevel" width="120" show-overflow-tooltip>
          <template #default="scope">
            <span :class="getGasLevelClass(scope.row)">{{ scope.row.currentGasLevel }}%</span>
          </template>
        </el-table-column>
        <el-table-column label="安全气体量" prop="safetyGasLevel" width="120" show-overflow-tooltip />
        <el-table-column label="最低气体量" prop="minGasLevel" width="120" show-overflow-tooltip />
        <el-table-column label="最高气体量" prop="maxGasLevel" width="120" show-overflow-tooltip />
        <el-table-column label="当前压力(MPa)" prop="currentPressure" width="140" show-overflow-tooltip />
        <!-- é¢„警规则字段 -->
        <el-table-column label="预警类型" prop="warningType" width="100" show-overflow-tooltip>
          <template #default="scope">
            <el-tag :type="getWarningTypeTag(scope.row.warningType)">
              {{ scope.row.warningType }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="预警级别" prop="warningLevel" width="100" show-overflow-tooltip>
          <template #default="scope">
            <el-tag :type="getWarningLevelTag(scope.row.warningLevel)">
              {{ scope.row.warningLevel }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="预警阈值" prop="warningThreshold" width="100" show-overflow-tooltip />
        <el-table-column label="是否启用" prop="isEnabled" width="100" show-overflow-tooltip>
          <template #default="scope">
            <el-switch v-model="scope.row.isEnabled" @change="handleEnableChange(scope.row)" />
          </template>
        </el-table-column>
        <!-- æ—¶é—´ç›¸å…³å­—段 -->
        <el-table-column label="预警时间" prop="warningTime" width="150" show-overflow-tooltip />
        <el-table-column label="预警持续天数" prop="warningDuration" width="120" show-overflow-tooltip />
        <el-table-column label="最后更新时间" prop="lastUpdateTime" width="150" show-overflow-tooltip />
        <el-table-column label="预计充装时间" prop="expectedRefillTime" width="150" show-overflow-tooltip />
        <el-table-column label="预计缺气时间" prop="expectedShortageTime" width="150" show-overflow-tooltip>
          <template #default="scope">
            <div v-if="scope.row.expectedShortageTime">
              <div v-if="getCountdown(scope.row.expectedShortageTime).isExpired" class="countdown-expired">
                <el-tag type="danger">已缺气</el-tag>
              </div>
              <div v-else class="countdown-timer">
                <span :class="getCountdownClass(scope.row.expectedShortageTime)">
                  {{ getCountdown(scope.row.expectedShortageTime).text }}
                </span>
              </div>
            </div>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <!-- æ“ä½œåˆ— -->
        <el-table-column fixed="right" label="操作" width="200" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button link type="success" size="small" @click="handleProcess(scope.row)">处理</el-button>
            <el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- åˆ†é¡µ -->
      <pagination
          v-show="total > 0"
          :total="total"
          layout="total, sizes, prev, pager, next, jumper"
          :page="page.current"
          :limit="page.size"
          @pagination="paginationChange"
      />
    </div>
    <!-- æ–°å¢ž/编辑预警规则弹窗 -->
    <el-dialog
        v-model="dialogFormVisible"
        :title="operationType === 'add' ? '新增预警规则' : '编辑预警规则'"
        width="50%"
        @close="closeDialog"
    >
      <el-form :model="form" :rules="rules" ref="formRef" label-width="140px">
        <el-row :gutter="20">
          <!-- åŸºç¡€ä¿¡æ¯ -->
          <el-col :span="12">
            <el-form-item label="储气罐编码:" prop="tankCode">
              <el-input v-model="form.tankCode" placeholder="请输入储气罐编码" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="储气罐名称:" prop="tankName">
              <el-input v-model="form.tankName" placeholder="请输入储气罐名称" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="储气罐类型:" prop="tankType">
              <el-select v-model="form.tankType" placeholder="请选择储气罐类型" style="width: 100%">
                <el-option label="液化气储罐" value="液化气储罐" />
                <el-option label="压缩气储罐" value="压缩气储罐" />
                <el-option label="天然气储罐" value="天然气储罐" />
                <el-option label="氧气储罐" value="氧气储罐" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="规格型号:" prop="specificationModel">
              <el-input v-model="form.specificationModel" placeholder="请输入规格型号" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="容积(m³):" prop="volume">
              <el-input-number v-model="form.volume" :min="0" :precision="2" style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="当前气体量(%):" prop="currentGasLevel">
              <el-input-number v-model="form.currentGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- åº“存相关 -->
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="安全气体量(%):" prop="safetyGasLevel">
              <el-input-number v-model="form.safetyGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="最低气体量(%):" prop="minGasLevel">
              <el-input-number v-model="form.minGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="最高气体量(%):" prop="maxGasLevel">
              <el-input-number v-model="form.maxGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="当前压力(MPa):" prop="currentPressure">
              <el-input-number v-model="form.currentPressure" :min="0" :precision="2" style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- é¢„警规则 -->
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="预警类型:" prop="warningType">
              <el-select v-model="form.warningType" placeholder="请选择预警类型" style="width: 100%">
                <el-option label="气体不足" value="气体不足" />
                <el-option label="压力异常" value="压力异常" />
                <el-option label="温度异常" value="温度异常" />
                <el-option label="泄漏预警" value="泄漏预警" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="预警级别:" prop="warningLevel">
              <el-select v-model="form.warningLevel" placeholder="请选择预警级别" style="width: 100%">
                <el-option label="紧急" value="紧急" />
                <el-option label="重要" value="重要" />
                <el-option label="一般" value="一般" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="预警阈值:" prop="warningThreshold">
              <el-input-number v-model="form.warningThreshold" :min="0" :precision="2" style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="是否启用:" prop="isEnabled">
              <el-switch v-model="form.isEnabled" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- æ—¶é—´ç›¸å…³ -->
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="预警时间:" prop="warningTime">
              <el-date-picker
                  v-model="form.warningTime"
                  type="datetime"
                  placeholder="请选择预警时间"
                  style="width: 100%"
                  value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="预计充装时间:" prop="expectedRefillTime">
              <el-date-picker
                  v-model="form.expectedRefillTime"
                  type="datetime"
                  placeholder="请选择预计充装时间"
                  style="width: 100%"
                  value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="预计缺气时间:" prop="expectedShortageTime">
              <el-date-picker
                  v-model="form.expectedShortageTime"
                  type="datetime"
                  placeholder="请选择预计缺气时间"
                  style="width: 100%"
                  value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="预警规则描述:" prop="warningRule">
              <el-input
                  v-model="form.warningRule"
                  type="textarea"
                  :rows="3"
                  placeholder="请输入预警规则描述"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDialog">取消</el-button>
          <el-button type="primary" @click="submitForm">确认</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- ç¼ºæ°”预警弹框 -->
    <el-dialog
        v-model="shortageWarningVisible"
        title="⚠️ ç¼ºæ°”预警"
        width="400px"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        :show-close="false"
    >
      <div class="shortage-warning-content">
        <div class="warning-icon">
          <el-icon size="48" color="#f56c6c"><WarningFilled /></el-icon>
        </div>
        <div class="warning-message">
          <h3>{{ currentWarningTank.tankName }}</h3>
          <p>储气罐已缺气,请及时处理!</p>
          <p class="warning-details">
            å‚¨æ°”罐编码:{{ currentWarningTank.tankCode }}<br>
            å‚¨æ°”罐类型:{{ currentWarningTank.tankType }}<br>
            å½“前气体量:{{ currentWarningTank.currentGasLevel }}%
          </p>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="handleShortageWarning">立即处理</el-button>
          <el-button @click="closeShortageWarning">稍后处理</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- ç¼ºæ°”预警弹框 -->
    <el-dialog
        v-model="shortageWarningVisible"
        title="⚠️ ç¼ºæ°”预警"
        width="400px"
        :close-on-click-modal="false"
        :close-on-press-escape="false"
        :show-close="false"
    >
      <div class="shortage-warning-content">
        <div class="warning-icon">
          <el-icon size="48" color="#f56c6c"><WarningFilled /></el-icon>
        </div>
        <div class="warning-message">
          <h3>{{ currentWarningTank.tankName }}</h3>
          <p>储气罐已缺气,请及时处理!</p>
          <p class="warning-details">
            å‚¨æ°”罐编码:{{ currentWarningTank.tankCode }}<br>
            å‚¨æ°”罐类型:{{ currentWarningTank.tankType }}<br>
            å½“前气体量:{{ currentWarningTank.currentGasLevel }}%
          </p>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="handleShortageWarning">立即处理</el-button>
          <el-button @click="closeShortageWarning">稍后处理</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, reactive, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { WarningFilled } from '@element-plus/icons-vue'
import pagination from '@/components/PIMTable/Pagination.vue'
// æ³¨é‡ŠæŽ‰API导入,使用假数据
// import {
//   getStockWarningPage,
//   addStockWarning,
//   updateStockWarning,
//   deleteStockWarning,
//   batchProcessStockWarning,
//   exportStockWarning,
//   toggleStockWarningStatus
// } from '@/api/inventoryManagement/stockWarning.js'
const { proxy } = getCurrentInstance()
// å“åº”式数据
const tableData = ref([])
const tableLoading = ref(false)
const selectedRows = ref([])
const dialogFormVisible = ref(false)
const operationType = ref('add')
const total = ref(0)
// ç¼ºæ°”预警相关
const shortageWarningVisible = ref(false)
const currentWarningTank = ref({})
const countdownTimer = ref(null)
// åˆ†é¡µå‚æ•°
const page = reactive({
  current: 1,
  size: 10
})
// æœç´¢è¡¨å•
const searchForm = reactive({
  tankName: '',
  tankType: '',
  warningType: '',
  warningLevel: ''
})
// è¡¨å•数据
const form = reactive({
  id: null,
  tankCode: '',
  tankName: '',
  tankType: '',
  specificationModel: '',
  volume: 0,
  currentGasLevel: 0,
  safetyGasLevel: 0,
  minGasLevel: 0,
  maxGasLevel: 0,
  currentPressure: 0,
  warningType: '',
  warningLevel: '',
  warningThreshold: 0,
  isEnabled: true,
  warningTime: '',
  warningDuration: 0,
  lastUpdateTime: '',
  expectedRefillTime: '',
  expectedShortageTime: '',
  warningRule: ''
})
// è¡¨å•验证规则
const rules = {
  tankCode: [{ required: true, message: '请输入储气罐编码', trigger: 'blur' }],
  tankName: [{ required: true, message: '请输入储气罐名称', trigger: 'blur' }],
  tankType: [{ required: true, message: '请选择储气罐类型', trigger: 'change' }],
  warningType: [{ required: true, message: '请选择预警类型', trigger: 'change' }],
  warningLevel: [{ required: true, message: '请选择预警级别', trigger: 'change' }],
  warningThreshold: [{ required: true, message: '请输入预警阈值', trigger: 'blur' }]
}
// èŽ·å–å€’è®¡æ—¶ä¿¡æ¯
const getCountdown = (expectedTime) => {
  if (!expectedTime) return { text: '-', isExpired: false }
  const now = new Date().getTime()
  const expected = new Date(expectedTime).getTime()
  const diff = expected - now
  if (diff <= 0) {
    return { text: '已缺气', isExpired: true }
  }
  const days = Math.floor(diff / (1000 * 60 * 60 * 24))
  const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
  const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
  if (days > 0) {
    return { text: `${days}天${hours}小时`, isExpired: false }
  } else if (hours > 0) {
    return { text: `${hours}小时${minutes}分钟`, isExpired: false }
  } else {
    return { text: `${minutes}分钟`, isExpired: false }
  }
}
// èŽ·å–å€’è®¡æ—¶æ ·å¼ç±»
const getCountdownClass = (expectedTime) => {
  if (!expectedTime) return ''
  const now = new Date().getTime()
  const expected = new Date(expectedTime).getTime()
  const diff = expected - now
  if (diff <= 0) {
    return 'countdown-expired'
  } else if (diff <= 24 * 60 * 60 * 1000) { // 24小时内
    return 'countdown-urgent'
  } else if (diff <= 7 * 24 * 60 * 60 * 1000) { // 7天内
    return 'countdown-warning'
  } else {
    return 'countdown-normal'
  }
}
// æ£€æŸ¥ç¼ºæ°”预警
const checkShortageWarnings = () => {
  tableData.value.forEach(tank => {
    if (tank.expectedShortageTime) {
      const countdown = getCountdown(tank.expectedShortageTime)
      if (countdown.isExpired && !tank.warningShown) {
        // æ ‡è®°å·²æ˜¾ç¤ºé¢„警,避免重复弹框
        tank.warningShown = true
        showShortageWarning(tank)
      }
    }
  })
}
// æ˜¾ç¤ºç¼ºæ°”预警弹框
const showShortageWarning = (tank) => {
  currentWarningTank.value = tank
  shortageWarningVisible.value = true
  // æ’­æ”¾æç¤ºéŸ³ï¼ˆå¯é€‰ï¼‰
  // const audio = new Audio('/path/to/warning-sound.mp3')
  // audio.play()
}
// å¤„理缺气预警
const handleShortageWarning = () => {
  ElMessage.success(`正在处理储气罐 ${currentWarningTank.value.tankName} çš„缺气问题`)
  shortageWarningVisible.value = false
  // è¿™é‡Œå¯ä»¥è°ƒç”¨å¤„理API
}
// å¤„理缺气预警
const closeShortageWarning = () => {
  // ElMessage.success(`正在处理储气罐 ${currentWarningTank.value.tankName} çš„缺气问题`)
  shortageWarningVisible.value = false
  // è¿™é‡Œå¯ä»¥è°ƒç”¨å¤„理API
}
// ç”Ÿæˆå‡æ•°æ®
const generateMockData = () => {
  const mockData = [
    {
      id: 1,
      tankCode: 'TANK001',
      tankName: '液化气储罐A',
      tankType: '液化气储罐',
      specificationModel: 'LPG-5000L',
      volume: 5000,
      currentGasLevel: 15,
      safetyGasLevel: 30,
      minGasLevel: 10,
      maxGasLevel: 95,
      currentPressure: 2.5,
      warningType: '气体不足',
      warningLevel: '紧急',
      warningThreshold: 20,
      isEnabled: true,
      warningTime: '2024-01-15 08:30:00',
      warningDuration: 3,
      lastUpdateTime: '2024-01-15 10:00:00',
      expectedRefillTime: '2024-01-16 14:00:00',
      expectedShortageTime: '2024-01-15 18:30:00', // ä»Šå¤©ä¸‹åˆ6:30缺气
      warningRule: '当气体量低于20%时触发预警'
    },
    {
      id: 2,
      tankCode: 'TANK002',
      tankName: '压缩气储罐B',
      tankType: '压缩气储罐',
      specificationModel: 'COMP-3000L',
      volume: 3000,
      currentGasLevel: 45,
      safetyGasLevel: 25,
      minGasLevel: 15,
      maxGasLevel: 90,
      currentPressure: 8.2,
      warningType: '压力异常',
      warningLevel: '重要',
      warningThreshold: 10,
      isEnabled: true,
      warningTime: '2024-01-14 16:20:00',
      warningDuration: 2,
      lastUpdateTime: '2024-01-15 09:15:00',
      expectedRefillTime: '2024-01-17 09:00:00',
      expectedShortageTime: '2024-01-18 12:00:00', // 3天后缺气
      warningRule: '当压力超过8MPa时触发预警'
    },
    {
      id: 3,
      tankCode: 'TANK003',
      tankName: '天然气储罐C',
      tankType: '天然气储罐',
      specificationModel: 'NG-8000L',
      volume: 8000,
      currentGasLevel: 75,
      safetyGasLevel: 20,
      minGasLevel: 10,
      maxGasLevel: 95,
      currentPressure: 4.8,
      warningType: '温度异常',
      warningLevel: '一般',
      warningThreshold: 5,
      isEnabled: true,
      warningTime: '2024-01-13 11:45:00',
      warningDuration: 1,
      lastUpdateTime: '2024-01-15 08:45:00',
      expectedRefillTime: '2024-01-20 10:00:00',
      expectedShortageTime: '2024-01-22 15:30:00', // 7天后缺气
      warningRule: '当温度超过60°C时触发预警'
    },
    {
      id: 4,
      tankCode: 'TANK004',
      tankName: '氧气储罐D',
      tankType: '氧气储罐',
      specificationModel: 'O2-2000L',
      volume: 2000,
      currentGasLevel: 8,
      safetyGasLevel: 25,
      minGasLevel: 5,
      maxGasLevel: 90,
      currentPressure: 6.5,
      warningType: '泄漏预警',
      warningLevel: '紧急',
      warningThreshold: 15,
      isEnabled: true,
      warningTime: '2024-01-15 07:15:00',
      warningDuration: 4,
      lastUpdateTime: '2024-01-15 11:30:00',
      expectedRefillTime: '2024-01-15 16:00:00',
      expectedShortageTime: '2024-01-15 14:00:00', // ä»Šå¤©ä¸‹åˆ2点缺气
      warningRule: '当检测到气体泄漏时触发预警'
    },
    {
      id: 5,
      tankCode: 'TANK005',
      tankName: '液化气储罐E',
      tankType: '液化气储罐',
      specificationModel: 'LPG-6000L',
      volume: 6000,
      currentGasLevel: 35,
      safetyGasLevel: 30,
      minGasLevel: 15,
      maxGasLevel: 95,
      currentPressure: 3.2,
      warningType: '气体不足',
      warningLevel: '重要',
      warningThreshold: 20,
      isEnabled: false,
      warningTime: '2024-01-14 14:30:00',
      warningDuration: 2,
      lastUpdateTime: '2024-01-15 09:00:00',
      expectedRefillTime: '2024-01-19 08:00:00',
      expectedShortageTime: '2024-01-21 10:00:00', // 6天后缺气
      warningRule: '当气体量低于20%时触发预警'
    },
    {
      id: 6,
      tankCode: 'TANK006',
      tankName: '压缩气储罐F',
      tankType: '压缩气储罐',
      specificationModel: 'COMP-4000L',
      volume: 4000,
      currentGasLevel: 85,
      safetyGasLevel: 20,
      minGasLevel: 10,
      maxGasLevel: 90,
      currentPressure: 7.8,
      warningType: '压力异常',
      warningLevel: '一般',
      warningThreshold: 8,
      isEnabled: true,
      warningTime: '2024-01-12 09:20:00',
      warningDuration: 1,
      lastUpdateTime: '2024-01-15 08:30:00',
      expectedRefillTime: '2024-01-25 14:00:00',
      expectedShortageTime: '2024-01-28 16:00:00', // 13天后缺气
      warningRule: '当压力超过8MPa时触发预警'
    },
    {
      id: 7,
      tankCode: 'TANK007',
      tankName: '天然气储罐G',
      tankType: '天然气储罐',
      specificationModel: 'NG-10000L',
      volume: 10000,
      currentGasLevel: 92,
      safetyGasLevel: 15,
      minGasLevel: 8,
      maxGasLevel: 95,
      currentPressure: 5.2,
      warningType: '温度异常',
      warningLevel: '重要',
      warningThreshold: 6,
      isEnabled: true,
      warningTime: '2024-01-11 16:45:00',
      warningDuration: 1,
      lastUpdateTime: '2024-01-15 07:45:00',
      expectedRefillTime: '2024-01-30 09:00:00',
      expectedShortageTime: '2024-02-05 12:00:00', // 21天后缺气
      warningRule: '当温度超过60°C时触发预警'
    },
    {
      id: 8,
      tankCode: 'TANK008',
      tankName: '氧气储罐H',
      tankType: '氧气储罐',
      specificationModel: 'O2-1500L',
      volume: 1500,
      currentGasLevel: 12,
      safetyGasLevel: 30,
      minGasLevel: 8,
      maxGasLevel: 90,
      currentPressure: 4.5,
      warningType: '泄漏预警',
      warningLevel: '紧急',
      warningThreshold: 12,
      isEnabled: true,
      warningTime: '2024-01-15 06:30:00',
      warningDuration: 5,
      lastUpdateTime: '2024-01-15 12:15:00',
      expectedRefillTime: '2024-01-15 20:00:00',
      expectedShortageTime: '2024-01-15 17:30:00', // ä»Šå¤©ä¸‹åˆ5:30缺气
      warningRule: '当检测到气体泄漏时触发预警'
    }
  ]
  // æ ¹æ®æœç´¢æ¡ä»¶è¿‡æ»¤æ•°æ®
  let filteredData = mockData.filter(item => {
    if (searchForm.tankName && !item.tankName.includes(searchForm.tankName)) return false
    if (searchForm.tankType && item.tankType !== searchForm.tankType) return false
    if (searchForm.warningType && item.warningType !== searchForm.warningType) return false
    if (searchForm.warningLevel && item.warningLevel !== searchForm.warningLevel) return false
    return true
  })
  // åˆ†é¡µå¤„理
  const start = (page.current - 1) * page.size
  const end = start + page.size
  const paginatedData = filteredData.slice(start, end)
  return {
    records: paginatedData,
    total: filteredData.length
  }
}
// èŽ·å–åˆ—è¡¨æ•°æ®
const getList = async () => {
  tableLoading.value = true
  try {
    // æ¨¡æ‹Ÿç½‘络延迟
    await new Promise(resolve => setTimeout(resolve, 500))
    const result = generateMockData()
    tableData.value = result.records
    total.value = result.total
    // æ£€æŸ¥ç¼ºæ°”预警
    checkShortageWarnings()
  } catch (error) {
    console.error('获取列表失败:', error)
    ElMessage.error('获取列表失败')
  } finally {
    tableLoading.value = false
  }
}
// æœç´¢
const handleQuery = () => {
  page.current = 1
  getList()
}
// é‡ç½®æœç´¢
const resetQuery = () => {
  Object.keys(searchForm).forEach(key => {
    searchForm[key] = ''
  })
  handleQuery()
}
// åˆ†é¡µå˜åŒ–
const paginationChange = (obj) => {
  page.current = obj.page
  page.size = obj.limit
  getList()
}
// è¡¨æ ¼é€‰æ‹©å˜åŒ–
const handleSelectionChange = (selection) => {
  selectedRows.value = selection
}
// æ–°å¢ž
const handleAdd = () => {
  operationType.value = 'add'
  resetForm()
  dialogFormVisible.value = true
}
// ç¼–辑
const handleEdit = (row) => {
  operationType.value = 'edit'
  Object.assign(form, row)
  dialogFormVisible.value = true
}
// å¤„理预警
const handleProcess = async (row) => {
  try {
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 300))
    ElMessage.success(`正在处理预警:${row.tankName}`)
    getList()
  } catch (error) {
    ElMessage.error('处理预警失败')
  }
}
// åˆ é™¤
const handleDelete = async (row) => {
  try {
    await ElMessageBox.confirm(`确定要删除预警规则:${row.tankName}吗?`, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 300))
    ElMessage.success('删除成功')
    getList()
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('删除失败')
    }
  }
}
// æ‰¹é‡å¤„理
const handleBatchProcess = async () => {
  if (selectedRows.value.length === 0) {
    ElMessage.warning('请选择要处理的预警')
    return
  }
  try {
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 500))
    ElMessage.success(`批量处理了 ${selectedRows.value.length} æ¡é¢„è­¦`)
    getList()
  } catch (error) {
    ElMessage.error('批量处理失败')
  }
}
// å¯¼å‡º
const handleExport = async () => {
  try {
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 800))
    // ç”Ÿæˆå¯¼å‡ºæ•°æ®
    const exportData = generateMockData().records
    const csvContent = generateCSV(exportData)
    // åˆ›å»ºä¸‹è½½é“¾æŽ¥
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = `储气罐预警数据_${new Date().getTime()}.csv`
    link.click()
    window.URL.revokeObjectURL(url)
    ElMessage.success('导出成功')
  } catch (error) {
    ElMessage.error('导出失败')
  }
}
// ç”ŸæˆCSV内容
const generateCSV = (data) => {
  const headers = [
    '储气罐编码', '储气罐名称', '储气罐类型', '规格型号', '容积(m³)',
    '当前气体量(%)', '安全气体量(%)', '最低气体量(%)', '最高气体量(%)',
    '当前压力(MPa)', '预警类型', '预警级别', '预警阈值', '是否启用',
    '预警时间', '预警持续天数', '最后更新时间', '预计充装时间', '预计缺气时间', '预警规则描述'
  ]
  const csvRows = [headers.join(',')]
  data.forEach(item => {
    const row = [
      item.tankCode,
      item.tankName,
      item.tankType,
      item.specificationModel,
      item.volume,
      item.currentGasLevel,
      item.safetyGasLevel,
      item.minGasLevel,
      item.maxGasLevel,
      item.currentPressure,
      item.warningType,
      item.warningLevel,
      item.warningThreshold,
      item.isEnabled ? '是' : '否',
      item.warningTime,
      item.warningDuration,
      item.lastUpdateTime,
      item.expectedRefillTime,
      item.expectedShortageTime,
      item.warningRule
    ]
    csvRows.push(row.join(','))
  })
  return csvRows.join('\n')
}
// å¯ç”¨çŠ¶æ€å˜åŒ–
const handleEnableChange = async (row) => {
  try {
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 200))
    ElMessage.success(`${row.tankName} çš„启用状态已更新`)
  } catch (error) {
    ElMessage.error('状态更新失败')
    // æ¢å¤åŽŸçŠ¶æ€
    row.isEnabled = !row.isEnabled
  }
}
// æäº¤è¡¨å•
const submitForm = async () => {
  try {
    await proxy.$refs.formRef.validate()
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 500))
    if (operationType.value === 'add') {
      ElMessage.success('新增成功')
    } else {
      ElMessage.success('编辑成功')
    }
    closeDialog()
    getList()
  } catch (error) {
    if (!error.errors) {
      ElMessage.error(operationType.value === 'add' ? '新增失败' : '编辑失败')
    }
  }
}
// å…³é—­å¼¹çª—
const closeDialog = () => {
  dialogFormVisible.value = false
  resetForm()
}
// é‡ç½®è¡¨å•
const resetForm = () => {
  Object.keys(form).forEach(key => {
    if (key === 'isEnabled') {
      form[key] = true
    } else if (typeof form[key] === 'number') {
      form[key] = 0
    } else {
      form[key] = ''
    }
  })
  proxy.$refs.formRef?.resetFields()
}
// èŽ·å–æ°”ä½“é‡æ ·å¼ç±»
const getGasLevelClass = (row) => {
  if (row.currentGasLevel < row.minGasLevel) {
    return 'text-danger'
  } else if (row.currentGasLevel > row.maxGasLevel) {
    return 'text-warning'
  }
  return 'text-success'
}
// èŽ·å–é¢„è­¦ç±»åž‹æ ‡ç­¾æ ·å¼
const getWarningTypeTag = (type) => {
  const typeMap = {
    '气体不足': 'danger',
    '压力异常': 'warning',
    '温度异常': 'info',
    '泄漏预警': 'danger'
  }
  return typeMap[type] || 'info'
}
// èŽ·å–é¢„è­¦çº§åˆ«æ ‡ç­¾æ ·å¼
const getWarningLevelTag = (level) => {
  const levelMap = {
    '紧急': 'danger',
    '重要': 'warning',
    '一般': 'info'
  }
  return levelMap[level] || 'info'
}
// å¯åŠ¨å€’è®¡æ—¶å®šæ—¶å™¨
const startCountdownTimer = () => {
  countdownTimer.value = setInterval(() => {
    checkShortageWarnings()
  }, 60000) // æ¯åˆ†é’Ÿæ£€æŸ¥ä¸€æ¬¡
}
// åœæ­¢å€’计时定时器
const stopCountdownTimer = () => {
  if (countdownTimer.value) {
    clearInterval(countdownTimer.value)
    countdownTimer.value = null
  }
}
// é¡µé¢åŠ è½½
onMounted(() => {
  getList()
  startCountdownTimer()
})
// é¡µé¢å¸è½½
onUnmounted(() => {
  stopCountdownTimer()
})
</script>
<style scoped lang="scss">
.app-container {
  padding: 20px;
  .table-operations {
    text-align: right;
    margin-bottom: 20px;
    .el-button {
      margin-top: 20px;
      margin-right: 10px;
    }
  }
  .table_list {
    background: #fff;
    border-radius: 4px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  }
  .text-danger {
    color: #f56c6c;
    font-weight: bold;
  }
  .text-warning {
    color: #e6a23c;
    font-weight: bold;
  }
  .text-success {
    color: #67c23a;
    font-weight: bold;
  }
  .dialog-footer {
    text-align: right;
  }
  // å€’计时样式
  .countdown-timer {
    font-weight: bold;
  }
  .countdown-normal {
    color: #67c23a;
  }
  .countdown-warning {
    color: #e6a23c;
  }
  .countdown-urgent {
    color: #f56c6c;
    animation: blink 1s infinite;
  }
  .countdown-expired {
    color: #f56c6c;
    font-weight: bold;
  }
  @keyframes blink {
    0%, 50% { opacity: 1; }
    51%, 100% { opacity: 0.5; }
  }
  // ç¼ºæ°”预警弹框样式
  .shortage-warning-content {
    text-align: center;
    padding: 20px 0;
    .warning-icon {
      margin-bottom: 20px;
    }
    .warning-message {
      h3 {
        color: #f56c6c;
        margin-bottom: 10px;
      }
      p {
        margin-bottom: 10px;
        color: #606266;
      }
      .warning-details {
        background: #f5f7fa;
        padding: 15px;
        border-radius: 4px;
        text-align: left;
        font-size: 14px;
        line-height: 1.6;
      }
    }
  }
}
</style>
src/views/warehouseManagement/index.vue
@@ -68,6 +68,7 @@
          style="width: 100%; height: calc(100vh - 30em)"
          show-summary
          :summary-method="summarizeChildrenTable"
          :row-class-name="tableRowClassName"
        >
          <el-table-column type="selection" width="55" align="center" />
          <el-table-column
@@ -897,6 +898,14 @@
    }
  });
};
// æ·»åŠ åˆ¤æ–­è¡Œç±»åçš„å‡½æ•°
const tableRowClassName = (row) => {
  if (activeTab.value === 'officialInventory' && row.row.inventoryQuantity < 3) {
    return 'low-inventory-row';
  }
  return '';
};
// å…³é—­å®¡æ ¸å¼¹æ¡†
const cancelReview = () => {
  proxy.$refs.formRef.resetFields();
@@ -908,4 +917,8 @@
:deep(.el-table) {
  margin: 20px 0;
}
:deep(.low-inventory-row) {
  background-color: #ffcccc;
}
</style>
src/views/warehouseManagement/stockWarning/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,1138 @@
<template>
  <div class="app-container">
    <!-- æœç´¢è¡¨å• -->
    <div class="search_form">
      <el-form :model="searchForm" :inline="true">
        <el-form-item label="储气罐名称:">
          <el-input v-model="searchForm.tankName" placeholder="请输入储气罐名称" clearable style="width: 200px" />
        </el-form-item>
        <el-form-item label="储气罐类型:">
          <el-select v-model="searchForm.tankType" placeholder="请选择储气罐类型" clearable style="width: 200px">
            <el-option label="液化气储罐" value="液化气储罐" />
            <el-option label="压缩气储罐" value="压缩气储罐" />
            <el-option label="天然气储罐" value="天然气储罐" />
            <el-option label="氧气储罐" value="氧气储罐" />
          </el-select>
        </el-form-item>
        <el-form-item label="预警类型:">
          <el-select v-model="searchForm.warningType" placeholder="请选择预警类型" clearable style="width: 200px">
            <el-option label="气体不足" value="气体不足" />
            <el-option label="压力异常" value="压力异常" />
            <el-option label="温度异常" value="温度异常" />
            <el-option label="泄漏预警" value="泄漏预警" />
          </el-select>
        </el-form-item>
        <el-form-item label="预警级别:">
          <el-select v-model="searchForm.warningLevel" placeholder="请选择预警级别" clearable style="width: 200px">
            <el-option label="紧急" value="紧急" />
            <el-option label="重要" value="重要" />
            <el-option label="一般" value="一般" />
          </el-select>
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleQuery">搜索</el-button>
          <el-button @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <!-- æ•°æ®è¡¨æ ¼ -->
    <div class="table_list">
      <!-- æ“ä½œæŒ‰é’® -->
      <div class="table-operations">
        <el-button type="primary" @click="handleAdd">新增预警规则</el-button>
        <el-button type="success" @click="handleBatchProcess">批量处理</el-button>
        <el-button @click="handleExport">导出</el-button>
      </div>
      <el-table
        :data="tableData"
        border
        v-loading="tableLoading"
        @selection-change="handleSelectionChange"
        style="width: 100%"
        height="calc(100vh - 280px)"
      >
        <el-table-column align="center" type="selection" width="55" />
        <el-table-column align="center" label="序号" type="index" width="60" />
        <!-- åŸºç¡€ä¿¡æ¯å­—段 -->
        <el-table-column label="储气罐编码" prop="tankCode" width="120" show-overflow-tooltip />
        <el-table-column label="储气罐名称" prop="tankName" width="200" show-overflow-tooltip />
        <el-table-column label="储气罐类型" prop="tankType" width="120" show-overflow-tooltip />
        <el-table-column label="规格型号" prop="specificationModel" width="150" show-overflow-tooltip />
        <el-table-column label="容积(m³)" prop="volume" width="100" show-overflow-tooltip />
        <!-- åº“存相关字段 -->
        <el-table-column label="当前气体量" prop="currentGasLevel" width="120" show-overflow-tooltip>
          <template #default="scope">
            <span :class="getGasLevelClass(scope.row)">{{ scope.row.currentGasLevel }}%</span>
          </template>
        </el-table-column>
        <el-table-column label="安全气体量" prop="safetyGasLevel" width="120" show-overflow-tooltip />
        <el-table-column label="最低气体量" prop="minGasLevel" width="120" show-overflow-tooltip />
        <el-table-column label="最高气体量" prop="maxGasLevel" width="120" show-overflow-tooltip />
        <el-table-column label="当前压力(MPa)" prop="currentPressure" width="140" show-overflow-tooltip />
        <!-- é¢„警规则字段 -->
        <el-table-column label="预警类型" prop="warningType" width="100" show-overflow-tooltip>
          <template #default="scope">
            <el-tag :type="getWarningTypeTag(scope.row.warningType)">
              {{ scope.row.warningType }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="预警级别" prop="warningLevel" width="100" show-overflow-tooltip>
          <template #default="scope">
            <el-tag :type="getWarningLevelTag(scope.row.warningLevel)">
              {{ scope.row.warningLevel }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="预警阈值" prop="warningThreshold" width="100" show-overflow-tooltip />
        <el-table-column label="是否启用" prop="isEnabled" width="100" show-overflow-tooltip>
          <template #default="scope">
            <el-switch v-model="scope.row.isEnabled" @change="handleEnableChange(scope.row)" />
          </template>
        </el-table-column>
        <!-- æ—¶é—´ç›¸å…³å­—段 -->
        <el-table-column label="预警时间" prop="warningTime" width="150" show-overflow-tooltip />
        <el-table-column label="预警持续天数" prop="warningDuration" width="120" show-overflow-tooltip />
        <el-table-column label="最后更新时间" prop="lastUpdateTime" width="150" show-overflow-tooltip />
        <el-table-column label="预计充装时间" prop="expectedRefillTime" width="150" show-overflow-tooltip />
        <el-table-column label="预计缺气时间" prop="expectedShortageTime" width="150" show-overflow-tooltip>
          <template #default="scope">
            <div v-if="scope.row.expectedShortageTime">
              <div v-if="getCountdown(scope.row.expectedShortageTime).isExpired" class="countdown-expired">
                <el-tag type="danger">已缺气</el-tag>
              </div>
              <div v-else class="countdown-timer">
                <span :class="getCountdownClass(scope.row.expectedShortageTime)">
                  {{ getCountdown(scope.row.expectedShortageTime).text }}
                </span>
              </div>
            </div>
            <span v-else>-</span>
          </template>
        </el-table-column>
        <!-- æ“ä½œåˆ— -->
        <el-table-column fixed="right" label="操作" width="200" align="center">
          <template #default="scope">
            <el-button link type="primary" size="small" @click="handleEdit(scope.row)">编辑</el-button>
            <el-button link type="success" size="small" @click="handleProcess(scope.row)">处理</el-button>
            <el-button link type="danger" size="small" @click="handleDelete(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- åˆ†é¡µ -->
      <pagination
        v-show="total > 0"
        :total="total"
        layout="total, sizes, prev, pager, next, jumper"
        :page="page.current"
        :limit="page.size"
        @pagination="paginationChange"
      />
    </div>
    <!-- æ–°å¢ž/编辑预警规则弹窗 -->
    <el-dialog
      v-model="dialogFormVisible"
      :title="operationType === 'add' ? '新增预警规则' : '编辑预警规则'"
      width="50%"
      @close="closeDialog"
    >
      <el-form :model="form" :rules="rules" ref="formRef" label-width="140px">
        <el-row :gutter="20">
          <!-- åŸºç¡€ä¿¡æ¯ -->
          <el-col :span="12">
            <el-form-item label="储气罐编码:" prop="tankCode">
              <el-input v-model="form.tankCode" placeholder="请输入储气罐编码" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="储气罐名称:" prop="tankName">
              <el-input v-model="form.tankName" placeholder="请输入储气罐名称" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="储气罐类型:" prop="tankType">
              <el-select v-model="form.tankType" placeholder="请选择储气罐类型" style="width: 100%">
                <el-option label="液化气储罐" value="液化气储罐" />
                <el-option label="压缩气储罐" value="压缩气储罐" />
                <el-option label="天然气储罐" value="天然气储罐" />
                <el-option label="氧气储罐" value="氧气储罐" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="规格型号:" prop="specificationModel">
              <el-input v-model="form.specificationModel" placeholder="请输入规格型号" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="容积(m³):" prop="volume">
              <el-input-number v-model="form.volume" :min="0" :precision="2" style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="当前气体量(%):" prop="currentGasLevel">
              <el-input-number v-model="form.currentGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- åº“存相关 -->
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="安全气体量(%):" prop="safetyGasLevel">
              <el-input-number v-model="form.safetyGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="最低气体量(%):" prop="minGasLevel">
              <el-input-number v-model="form.minGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="最高气体量(%):" prop="maxGasLevel">
              <el-input-number v-model="form.maxGasLevel" :min="0" :max="100" :precision="1" style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="当前压力(MPa):" prop="currentPressure">
              <el-input-number v-model="form.currentPressure" :min="0" :precision="2" style="width: 100%" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- é¢„警规则 -->
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="预警类型:" prop="warningType">
              <el-select v-model="form.warningType" placeholder="请选择预警类型" style="width: 100%">
                <el-option label="气体不足" value="气体不足" />
                <el-option label="压力异常" value="压力异常" />
                <el-option label="温度异常" value="温度异常" />
                <el-option label="泄漏预警" value="泄漏预警" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="预警级别:" prop="warningLevel">
              <el-select v-model="form.warningLevel" placeholder="请选择预警级别" style="width: 100%">
                <el-option label="紧急" value="紧急" />
                <el-option label="重要" value="重要" />
                <el-option label="一般" value="一般" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="预警阈值:" prop="warningThreshold">
              <el-input-number v-model="form.warningThreshold" :min="0" :precision="2" style="width: 100%" />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="是否启用:" prop="isEnabled">
              <el-switch v-model="form.isEnabled" />
            </el-form-item>
          </el-col>
        </el-row>
        <!-- æ—¶é—´ç›¸å…³ -->
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="预警时间:" prop="warningTime">
              <el-date-picker
                v-model="form.warningTime"
                type="datetime"
                placeholder="请选择预警时间"
                style="width: 100%"
                value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="预计充装时间:" prop="expectedRefillTime">
              <el-date-picker
                v-model="form.expectedRefillTime"
                type="datetime"
                placeholder="请选择预计充装时间"
                style="width: 100%"
                value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="20">
          <el-col :span="12">
            <el-form-item label="预计缺气时间:" prop="expectedShortageTime">
              <el-date-picker
                v-model="form.expectedShortageTime"
                type="datetime"
                placeholder="请选择预计缺气时间"
                style="width: 100%"
                value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="预警规则描述:" prop="warningRule">
              <el-input
                v-model="form.warningRule"
                type="textarea"
                :rows="3"
                placeholder="请输入预警规则描述"
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="closeDialog">取消</el-button>
          <el-button type="primary" @click="submitForm">确认</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- ç¼ºæ°”预警弹框 -->
    <el-dialog
      v-model="shortageWarningVisible"
      title="⚠️ ç¼ºæ°”预警"
      width="400px"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :show-close="false"
    >
      <div class="shortage-warning-content">
        <div class="warning-icon">
          <el-icon size="48" color="#f56c6c"><WarningFilled /></el-icon>
        </div>
        <div class="warning-message">
          <h3>{{ currentWarningTank.tankName }}</h3>
          <p>储气罐已缺气,请及时处理!</p>
          <p class="warning-details">
            å‚¨æ°”罐编码:{{ currentWarningTank.tankCode }}<br>
            å‚¨æ°”罐类型:{{ currentWarningTank.tankType }}<br>
            å½“前气体量:{{ currentWarningTank.currentGasLevel }}%
          </p>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="handleShortageWarning">立即处理</el-button>
          <el-button @click="closeShortageWarning">稍后处理</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- ç¼ºæ°”预警弹框 -->
    <el-dialog
      v-model="shortageWarningVisible"
      title="⚠️ ç¼ºæ°”预警"
      width="400px"
      :close-on-click-modal="false"
      :close-on-press-escape="false"
      :show-close="false"
    >
      <div class="shortage-warning-content">
        <div class="warning-icon">
          <el-icon size="48" color="#f56c6c"><WarningFilled /></el-icon>
        </div>
        <div class="warning-message">
          <h3>{{ currentWarningTank.tankName }}</h3>
          <p>储气罐已缺气,请及时处理!</p>
          <p class="warning-details">
            å‚¨æ°”罐编码:{{ currentWarningTank.tankCode }}<br>
            å‚¨æ°”罐类型:{{ currentWarningTank.tankType }}<br>
            å½“前气体量:{{ currentWarningTank.currentGasLevel }}%
          </p>
        </div>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="handleShortageWarning">立即处理</el-button>
          <el-button @click="closeShortageWarning">稍后处理</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, reactive, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { WarningFilled } from '@element-plus/icons-vue'
import pagination from '@/components/PIMTable/Pagination.vue'
// æ³¨é‡ŠæŽ‰API导入,使用假数据
// import {
//   getStockWarningPage,
//   addStockWarning,
//   updateStockWarning,
//   deleteStockWarning,
//   batchProcessStockWarning,
//   exportStockWarning,
//   toggleStockWarningStatus
// } from '@/api/inventoryManagement/stockWarning.js'
const { proxy } = getCurrentInstance()
// å“åº”式数据
const tableData = ref([])
const tableLoading = ref(false)
const selectedRows = ref([])
const dialogFormVisible = ref(false)
const operationType = ref('add')
const total = ref(0)
// ç¼ºæ°”预警相关
const shortageWarningVisible = ref(false)
const currentWarningTank = ref({})
const countdownTimer = ref(null)
// åˆ†é¡µå‚æ•°
const page = reactive({
  current: 1,
  size: 10
})
// æœç´¢è¡¨å•
const searchForm = reactive({
  tankName: '',
  tankType: '',
  warningType: '',
  warningLevel: ''
})
// è¡¨å•数据
const form = reactive({
  id: null,
  tankCode: '',
  tankName: '',
  tankType: '',
  specificationModel: '',
  volume: 0,
  currentGasLevel: 0,
  safetyGasLevel: 0,
  minGasLevel: 0,
  maxGasLevel: 0,
  currentPressure: 0,
  warningType: '',
  warningLevel: '',
  warningThreshold: 0,
  isEnabled: true,
  warningTime: '',
  warningDuration: 0,
  lastUpdateTime: '',
  expectedRefillTime: '',
  expectedShortageTime: '',
  warningRule: ''
})
// è¡¨å•验证规则
const rules = {
  tankCode: [{ required: true, message: '请输入储气罐编码', trigger: 'blur' }],
  tankName: [{ required: true, message: '请输入储气罐名称', trigger: 'blur' }],
  tankType: [{ required: true, message: '请选择储气罐类型', trigger: 'change' }],
  warningType: [{ required: true, message: '请选择预警类型', trigger: 'change' }],
  warningLevel: [{ required: true, message: '请选择预警级别', trigger: 'change' }],
  warningThreshold: [{ required: true, message: '请输入预警阈值', trigger: 'blur' }]
}
// èŽ·å–å€’è®¡æ—¶ä¿¡æ¯
const getCountdown = (expectedTime) => {
  if (!expectedTime) return { text: '-', isExpired: false }
  const now = new Date().getTime()
  const expected = new Date(expectedTime).getTime()
  const diff = expected - now
  if (diff <= 0) {
    return { text: '已缺气', isExpired: true }
  }
  const days = Math.floor(diff / (1000 * 60 * 60 * 24))
  const hours = Math.floor((diff % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60))
  const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60))
  if (days > 0) {
    return { text: `${days}天${hours}小时`, isExpired: false }
  } else if (hours > 0) {
    return { text: `${hours}小时${minutes}分钟`, isExpired: false }
  } else {
    return { text: `${minutes}分钟`, isExpired: false }
  }
}
// èŽ·å–å€’è®¡æ—¶æ ·å¼ç±»
const getCountdownClass = (expectedTime) => {
  if (!expectedTime) return ''
  const now = new Date().getTime()
  const expected = new Date(expectedTime).getTime()
  const diff = expected - now
  if (diff <= 0) {
    return 'countdown-expired'
  } else if (diff <= 24 * 60 * 60 * 1000) { // 24小时内
    return 'countdown-urgent'
  } else if (diff <= 7 * 24 * 60 * 60 * 1000) { // 7天内
    return 'countdown-warning'
  } else {
    return 'countdown-normal'
  }
}
// æ£€æŸ¥ç¼ºæ°”预警
const checkShortageWarnings = () => {
  tableData.value.forEach(tank => {
    if (tank.expectedShortageTime) {
      const countdown = getCountdown(tank.expectedShortageTime)
      if (countdown.isExpired && !tank.warningShown) {
        // æ ‡è®°å·²æ˜¾ç¤ºé¢„警,避免重复弹框
        tank.warningShown = true
        showShortageWarning(tank)
      }
    }
  })
}
// æ˜¾ç¤ºç¼ºæ°”预警弹框
const showShortageWarning = (tank) => {
  currentWarningTank.value = tank
  shortageWarningVisible.value = true
  // æ’­æ”¾æç¤ºéŸ³ï¼ˆå¯é€‰ï¼‰
  // const audio = new Audio('/path/to/warning-sound.mp3')
  // audio.play()
}
// å¤„理缺气预警
const handleShortageWarning = () => {
  ElMessage.success(`正在处理储气罐 ${currentWarningTank.value.tankName} çš„缺气问题`)
  shortageWarningVisible.value = false
  // è¿™é‡Œå¯ä»¥è°ƒç”¨å¤„理API
}
// å¤„理缺气预警
const closeShortageWarning = () => {
  // ElMessage.success(`正在处理储气罐 ${currentWarningTank.value.tankName} çš„缺气问题`)
  shortageWarningVisible.value = false
  // è¿™é‡Œå¯ä»¥è°ƒç”¨å¤„理API
}
// ç”Ÿæˆå‡æ•°æ®
const generateMockData = () => {
  const mockData = [
    {
      id: 1,
      tankCode: 'TANK001',
      tankName: '液化气储罐A',
      tankType: '液化气储罐',
      specificationModel: 'LPG-5000L',
      volume: 5000,
      currentGasLevel: 15,
      safetyGasLevel: 30,
      minGasLevel: 10,
      maxGasLevel: 95,
      currentPressure: 2.5,
      warningType: '气体不足',
      warningLevel: '紧急',
      warningThreshold: 20,
      isEnabled: true,
      warningTime: '2024-01-15 08:30:00',
      warningDuration: 3,
      lastUpdateTime: '2024-01-15 10:00:00',
      expectedRefillTime: '2024-01-16 14:00:00',
      expectedShortageTime: '2024-01-15 18:30:00', // ä»Šå¤©ä¸‹åˆ6:30缺气
      warningRule: '当气体量低于20%时触发预警'
    },
    {
      id: 2,
      tankCode: 'TANK002',
      tankName: '压缩气储罐B',
      tankType: '压缩气储罐',
      specificationModel: 'COMP-3000L',
      volume: 3000,
      currentGasLevel: 45,
      safetyGasLevel: 25,
      minGasLevel: 15,
      maxGasLevel: 90,
      currentPressure: 8.2,
      warningType: '压力异常',
      warningLevel: '重要',
      warningThreshold: 10,
      isEnabled: true,
      warningTime: '2024-01-14 16:20:00',
      warningDuration: 2,
      lastUpdateTime: '2024-01-15 09:15:00',
      expectedRefillTime: '2024-01-17 09:00:00',
      expectedShortageTime: '2024-01-18 12:00:00', // 3天后缺气
      warningRule: '当压力超过8MPa时触发预警'
    },
    {
      id: 3,
      tankCode: 'TANK003',
      tankName: '天然气储罐C',
      tankType: '天然气储罐',
      specificationModel: 'NG-8000L',
      volume: 8000,
      currentGasLevel: 75,
      safetyGasLevel: 20,
      minGasLevel: 10,
      maxGasLevel: 95,
      currentPressure: 4.8,
      warningType: '温度异常',
      warningLevel: '一般',
      warningThreshold: 5,
      isEnabled: true,
      warningTime: '2024-01-13 11:45:00',
      warningDuration: 1,
      lastUpdateTime: '2024-01-15 08:45:00',
      expectedRefillTime: '2024-01-20 10:00:00',
      expectedShortageTime: '2024-01-22 15:30:00', // 7天后缺气
      warningRule: '当温度超过60°C时触发预警'
    },
    {
      id: 4,
      tankCode: 'TANK004',
      tankName: '氧气储罐D',
      tankType: '氧气储罐',
      specificationModel: 'O2-2000L',
      volume: 2000,
      currentGasLevel: 8,
      safetyGasLevel: 25,
      minGasLevel: 5,
      maxGasLevel: 90,
      currentPressure: 6.5,
      warningType: '泄漏预警',
      warningLevel: '紧急',
      warningThreshold: 15,
      isEnabled: true,
      warningTime: '2024-01-15 07:15:00',
      warningDuration: 4,
      lastUpdateTime: '2024-01-15 11:30:00',
      expectedRefillTime: '2024-01-15 16:00:00',
      expectedShortageTime: '2024-01-15 14:00:00', // ä»Šå¤©ä¸‹åˆ2点缺气
      warningRule: '当检测到气体泄漏时触发预警'
    },
    {
      id: 5,
      tankCode: 'TANK005',
      tankName: '液化气储罐E',
      tankType: '液化气储罐',
      specificationModel: 'LPG-6000L',
      volume: 6000,
      currentGasLevel: 35,
      safetyGasLevel: 30,
      minGasLevel: 15,
      maxGasLevel: 95,
      currentPressure: 3.2,
      warningType: '气体不足',
      warningLevel: '重要',
      warningThreshold: 20,
      isEnabled: false,
      warningTime: '2024-01-14 14:30:00',
      warningDuration: 2,
      lastUpdateTime: '2024-01-15 09:00:00',
      expectedRefillTime: '2024-01-19 08:00:00',
      expectedShortageTime: '2024-01-21 10:00:00', // 6天后缺气
      warningRule: '当气体量低于20%时触发预警'
    },
    {
      id: 6,
      tankCode: 'TANK006',
      tankName: '压缩气储罐F',
      tankType: '压缩气储罐',
      specificationModel: 'COMP-4000L',
      volume: 4000,
      currentGasLevel: 85,
      safetyGasLevel: 20,
      minGasLevel: 10,
      maxGasLevel: 90,
      currentPressure: 7.8,
      warningType: '压力异常',
      warningLevel: '一般',
      warningThreshold: 8,
      isEnabled: true,
      warningTime: '2024-01-12 09:20:00',
      warningDuration: 1,
      lastUpdateTime: '2024-01-15 08:30:00',
      expectedRefillTime: '2024-01-25 14:00:00',
      expectedShortageTime: '2024-01-28 16:00:00', // 13天后缺气
      warningRule: '当压力超过8MPa时触发预警'
    },
    {
      id: 7,
      tankCode: 'TANK007',
      tankName: '天然气储罐G',
      tankType: '天然气储罐',
      specificationModel: 'NG-10000L',
      volume: 10000,
      currentGasLevel: 92,
      safetyGasLevel: 15,
      minGasLevel: 8,
      maxGasLevel: 95,
      currentPressure: 5.2,
      warningType: '温度异常',
      warningLevel: '重要',
      warningThreshold: 6,
      isEnabled: true,
      warningTime: '2024-01-11 16:45:00',
      warningDuration: 1,
      lastUpdateTime: '2024-01-15 07:45:00',
      expectedRefillTime: '2024-01-30 09:00:00',
      expectedShortageTime: '2024-02-05 12:00:00', // 21天后缺气
      warningRule: '当温度超过60°C时触发预警'
    },
    {
      id: 8,
      tankCode: 'TANK008',
      tankName: '氧气储罐H',
      tankType: '氧气储罐',
      specificationModel: 'O2-1500L',
      volume: 1500,
      currentGasLevel: 12,
      safetyGasLevel: 30,
      minGasLevel: 8,
      maxGasLevel: 90,
      currentPressure: 4.5,
      warningType: '泄漏预警',
      warningLevel: '紧急',
      warningThreshold: 12,
      isEnabled: true,
      warningTime: '2024-01-15 06:30:00',
      warningDuration: 5,
      lastUpdateTime: '2024-01-15 12:15:00',
      expectedRefillTime: '2024-01-15 20:00:00',
      expectedShortageTime: '2024-01-15 17:30:00', // ä»Šå¤©ä¸‹åˆ5:30缺气
      warningRule: '当检测到气体泄漏时触发预警'
    }
  ]
  // æ ¹æ®æœç´¢æ¡ä»¶è¿‡æ»¤æ•°æ®
  let filteredData = mockData.filter(item => {
    if (searchForm.tankName && !item.tankName.includes(searchForm.tankName)) return false
    if (searchForm.tankType && item.tankType !== searchForm.tankType) return false
    if (searchForm.warningType && item.warningType !== searchForm.warningType) return false
    if (searchForm.warningLevel && item.warningLevel !== searchForm.warningLevel) return false
    return true
  })
  // åˆ†é¡µå¤„理
  const start = (page.current - 1) * page.size
  const end = start + page.size
  const paginatedData = filteredData.slice(start, end)
  return {
    records: paginatedData,
    total: filteredData.length
  }
}
// èŽ·å–åˆ—è¡¨æ•°æ®
const getList = async () => {
  tableLoading.value = true
  try {
    // æ¨¡æ‹Ÿç½‘络延迟
    await new Promise(resolve => setTimeout(resolve, 500))
    const result = generateMockData()
    tableData.value = result.records
    total.value = result.total
    // æ£€æŸ¥ç¼ºæ°”预警
    checkShortageWarnings()
  } catch (error) {
    console.error('获取列表失败:', error)
    ElMessage.error('获取列表失败')
  } finally {
    tableLoading.value = false
  }
}
// æœç´¢
const handleQuery = () => {
  page.current = 1
  getList()
}
// é‡ç½®æœç´¢
const resetQuery = () => {
  Object.keys(searchForm).forEach(key => {
    searchForm[key] = ''
  })
  handleQuery()
}
// åˆ†é¡µå˜åŒ–
const paginationChange = (obj) => {
  page.current = obj.page
  page.size = obj.limit
  getList()
}
// è¡¨æ ¼é€‰æ‹©å˜åŒ–
const handleSelectionChange = (selection) => {
  selectedRows.value = selection
}
// æ–°å¢ž
const handleAdd = () => {
  operationType.value = 'add'
  resetForm()
  dialogFormVisible.value = true
}
// ç¼–辑
const handleEdit = (row) => {
  operationType.value = 'edit'
  Object.assign(form, row)
  dialogFormVisible.value = true
}
// å¤„理预警
const handleProcess = async (row) => {
  try {
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 300))
    ElMessage.success(`正在处理预警:${row.tankName}`)
    getList()
  } catch (error) {
    ElMessage.error('处理预警失败')
  }
}
// åˆ é™¤
const handleDelete = async (row) => {
  try {
    await ElMessageBox.confirm(`确定要删除预警规则:${row.tankName}吗?`, '提示', {
      confirmButtonText: '确定',
      cancelButtonText: '取消',
      type: 'warning'
    })
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 300))
    ElMessage.success('删除成功')
    getList()
  } catch (error) {
    if (error !== 'cancel') {
      ElMessage.error('删除失败')
    }
  }
}
// æ‰¹é‡å¤„理
const handleBatchProcess = async () => {
  if (selectedRows.value.length === 0) {
    ElMessage.warning('请选择要处理的预警')
    return
  }
  try {
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 500))
    ElMessage.success(`批量处理了 ${selectedRows.value.length} æ¡é¢„è­¦`)
    getList()
  } catch (error) {
    ElMessage.error('批量处理失败')
  }
}
// å¯¼å‡º
const handleExport = async () => {
  try {
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 800))
    // ç”Ÿæˆå¯¼å‡ºæ•°æ®
    const exportData = generateMockData().records
    const csvContent = generateCSV(exportData)
    // åˆ›å»ºä¸‹è½½é“¾æŽ¥
    const blob = new Blob([csvContent], { type: 'text/csv;charset=utf-8;' })
    const url = window.URL.createObjectURL(blob)
    const link = document.createElement('a')
    link.href = url
    link.download = `储气罐预警数据_${new Date().getTime()}.csv`
    link.click()
    window.URL.revokeObjectURL(url)
    ElMessage.success('导出成功')
  } catch (error) {
    ElMessage.error('导出失败')
  }
}
// ç”ŸæˆCSV内容
const generateCSV = (data) => {
  const headers = [
    '储气罐编码', '储气罐名称', '储气罐类型', '规格型号', '容积(m³)',
    '当前气体量(%)', '安全气体量(%)', '最低气体量(%)', '最高气体量(%)',
    '当前压力(MPa)', '预警类型', '预警级别', '预警阈值', '是否启用',
    '预警时间', '预警持续天数', '最后更新时间', '预计充装时间', '预计缺气时间', '预警规则描述'
  ]
  const csvRows = [headers.join(',')]
  data.forEach(item => {
    const row = [
      item.tankCode,
      item.tankName,
      item.tankType,
      item.specificationModel,
      item.volume,
      item.currentGasLevel,
      item.safetyGasLevel,
      item.minGasLevel,
      item.maxGasLevel,
      item.currentPressure,
      item.warningType,
      item.warningLevel,
      item.warningThreshold,
      item.isEnabled ? '是' : '否',
      item.warningTime,
      item.warningDuration,
      item.lastUpdateTime,
      item.expectedRefillTime,
      item.expectedShortageTime,
      item.warningRule
    ]
    csvRows.push(row.join(','))
  })
  return csvRows.join('\n')
}
// å¯ç”¨çŠ¶æ€å˜åŒ–
const handleEnableChange = async (row) => {
  try {
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 200))
    ElMessage.success(`${row.tankName} çš„启用状态已更新`)
  } catch (error) {
    ElMessage.error('状态更新失败')
    // æ¢å¤åŽŸçŠ¶æ€
    row.isEnabled = !row.isEnabled
  }
}
// æäº¤è¡¨å•
const submitForm = async () => {
  try {
    await proxy.$refs.formRef.validate()
    // æ¨¡æ‹ŸAPI调用延迟
    await new Promise(resolve => setTimeout(resolve, 500))
    if (operationType.value === 'add') {
      ElMessage.success('新增成功')
    } else {
      ElMessage.success('编辑成功')
    }
    closeDialog()
    getList()
  } catch (error) {
    if (!error.errors) {
      ElMessage.error(operationType.value === 'add' ? '新增失败' : '编辑失败')
    }
  }
}
// å…³é—­å¼¹çª—
const closeDialog = () => {
  dialogFormVisible.value = false
  resetForm()
}
// é‡ç½®è¡¨å•
const resetForm = () => {
  Object.keys(form).forEach(key => {
    if (key === 'isEnabled') {
      form[key] = true
    } else if (typeof form[key] === 'number') {
      form[key] = 0
    } else {
      form[key] = ''
    }
  })
  proxy.$refs.formRef?.resetFields()
}
// èŽ·å–æ°”ä½“é‡æ ·å¼ç±»
const getGasLevelClass = (row) => {
  if (row.currentGasLevel < row.minGasLevel) {
    return 'text-danger'
  } else if (row.currentGasLevel > row.maxGasLevel) {
    return 'text-warning'
  }
  return 'text-success'
}
// èŽ·å–é¢„è­¦ç±»åž‹æ ‡ç­¾æ ·å¼
const getWarningTypeTag = (type) => {
  const typeMap = {
    '气体不足': 'danger',
    '压力异常': 'warning',
    '温度异常': 'info',
    '泄漏预警': 'danger'
  }
  return typeMap[type] || 'info'
}
// èŽ·å–é¢„è­¦çº§åˆ«æ ‡ç­¾æ ·å¼
const getWarningLevelTag = (level) => {
  const levelMap = {
    '紧急': 'danger',
    '重要': 'warning',
    '一般': 'info'
  }
  return levelMap[level] || 'info'
}
// å¯åŠ¨å€’è®¡æ—¶å®šæ—¶å™¨
const startCountdownTimer = () => {
  countdownTimer.value = setInterval(() => {
    checkShortageWarnings()
  }, 60000) // æ¯åˆ†é’Ÿæ£€æŸ¥ä¸€æ¬¡
}
// åœæ­¢å€’计时定时器
const stopCountdownTimer = () => {
  if (countdownTimer.value) {
    clearInterval(countdownTimer.value)
    countdownTimer.value = null
  }
}
// é¡µé¢åŠ è½½
onMounted(() => {
  getList()
  startCountdownTimer()
})
// é¡µé¢å¸è½½
onUnmounted(() => {
  stopCountdownTimer()
})
</script>
<style scoped lang="scss">
.app-container {
  padding: 20px;
  .table-operations {
    text-align: right;
    margin-bottom: 20px;
    .el-button {
      margin-top: 20px;
      margin-right: 10px;
    }
  }
  .table_list {
    background: #fff;
    border-radius: 4px;
    box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
  }
  .text-danger {
    color: #f56c6c;
    font-weight: bold;
  }
  .text-warning {
    color: #e6a23c;
    font-weight: bold;
  }
  .text-success {
    color: #67c23a;
    font-weight: bold;
  }
  .dialog-footer {
    text-align: right;
  }
  // å€’计时样式
  .countdown-timer {
    font-weight: bold;
  }
  .countdown-normal {
    color: #67c23a;
  }
  .countdown-warning {
    color: #e6a23c;
  }
  .countdown-urgent {
    color: #f56c6c;
    animation: blink 1s infinite;
  }
  .countdown-expired {
    color: #f56c6c;
    font-weight: bold;
  }
  @keyframes blink {
    0%, 50% { opacity: 1; }
    51%, 100% { opacity: 0.5; }
  }
  // ç¼ºæ°”预警弹框样式
  .shortage-warning-content {
    text-align: center;
    padding: 20px 0;
    .warning-icon {
      margin-bottom: 20px;
    }
    .warning-message {
      h3 {
        color: #f56c6c;
        margin-bottom: 10px;
      }
      p {
        margin-bottom: 10px;
        color: #606266;
      }
      .warning-details {
        background: #f5f7fa;
        padding: 15px;
        border-radius: 4px;
        text-align: left;
        font-size: 14px;
        line-height: 1.6;
      }
    }
  }
}
</style>