已修改3个文件
已添加3个文件
3024 ■■■■■ 文件已修改
src/api/payable/index.js 6 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/coalLockManagement/index.vue 725 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/payable/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/warehouseManagement/KeyCoalLocks/index.vue 1138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/warehouseManagement/index.vue 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/warehouseManagement/stockWarning/index.vue 1138 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/payable/index.js
@@ -9,10 +9,10 @@
    })
}
// åˆ†é¡µæŸ¥è¯¢
export function findPayablePage(query) {
export function findPayablePage(data) {
    return request({
        url: '/duePayable/list',
        method: 'get',
        params: query
        method: 'post',
        data: data
    })
}
src/views/coalLockManagement/index.vue
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,725 @@
<template>
  <div class="app-container">
    <el-card class="box-card">
      <!-- æœç´¢åŒºåŸŸ -->
      <el-form :model="queryParams" ref="queryForm" :inline="true" v-show="showSearch" label-width="68px">
        <el-form-item label="煤种名称" prop="coalName">
          <el-input
            v-model="queryParams.coalName"
            placeholder="请输入煤种名称"
            clearable
            size="small"
            @keyup.enter="handleQuery"
          />
        </el-form-item>
        <el-form-item label="锁仓状态" prop="lockStatus">
          <el-select v-model="queryParams.lockStatus" placeholder="请选择锁仓状态" clearable size="small">
            <el-option label="已锁定" value="locked" />
            <el-option label="部分锁定" value="partial" />
            <el-option label="未锁定" value="unlocked" />
          </el-select>
        </el-form-item>
        <el-form-item label="供应商" prop="supplierName">
          <el-input
            v-model="queryParams.supplierName"
            placeholder="请输入供应商名称"
            clearable
            size="small"
            @keyup.enter="handleQuery"
          />
        </el-form-item>
        <el-form-item label="锁仓日期" prop="lockDateRange">
          <el-date-picker
            v-model="queryParams.lockDateRange"
            type="daterange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            size="small"
            format="YYYY-MM-DD"
            value-format="YYYY-MM-DD"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" icon="Search" size="small" @click="handleQuery">搜索</el-button>
          <el-button icon="Refresh" size="small" @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>
      <!-- æ“ä½œæŒ‰é’®åŒºåŸŸ -->
      <el-row :gutter="10" class="mb8">
        <el-col :span="1.5">
          <el-button
            type="primary"
            plain
            icon="Plus"
            size="small"
            @click="handleAdd"
            v-hasPermi="['coalLock:add']"
          >新增锁仓</el-button>
        </el-col>
        <el-col :span="1.5">
          <el-button
            type="success"
            plain
            icon="Edit"
            size="small"
            :disabled="single"
            @click="handleUpdate"
            v-hasPermi="['coalLock:edit']"
          >修改锁仓</el-button>
        </el-col>
        <el-col :span="1.5">
          <el-button
            type="danger"
            plain
            icon="Delete"
            size="small"
            :disabled="multiple"
            @click="handleDelete"
            v-hasPermi="['coalLock:remove']"
          >删除锁仓</el-button>
        </el-col>
        <el-col :span="1.5">
          <el-button
            type="warning"
            plain
            icon="Unlock"
            size="small"
            :disabled="single"
            @click="handleUnlock"
            v-hasPermi="['coalLock:unlock']"
          >解除锁仓</el-button>
        </el-col>
        <el-col :span="1.5">
          <el-button
            type="info"
            plain
            icon="View"
            size="small"
            :disabled="single"
            @click="handleView"
            v-hasPermi="['coalLock:query']"
          >查看详情</el-button>
        </el-col>
        <!-- <el-col :span="1.5">
          <el-button
            type="primary"
            plain
            icon="Download"
            size="small"
            @click="handleExport"
            v-hasPermi="['coalLock:export']"
          >导出</el-button>
        </el-col> -->
        <right-toolbar v-model:showSearch="showSearch" @queryTable="getList"></right-toolbar>
      </el-row>
      <!-- æ•°æ®è¡¨æ ¼ -->
      <el-table v-loading="loading" :data="lockList" @selection-change="handleSelectionChange">
        <el-table-column type="selection" width="55" align="center" />
        <el-table-column label="锁仓编号" align="center" prop="lockCode" width="180" />
        <el-table-column label="煤种名称" align="center" prop="coalName" min-width="120" />
        <el-table-column label="供应商" align="center" prop="supplierName" min-width="120" />
        <el-table-column label="总库存量(吨)" align="center" prop="totalInventory" width="120" />
        <el-table-column label="锁仓数量(吨)" align="center" prop="lockQuantity" width="120" />
        <el-table-column label="可用数量(吨)" align="center" prop="availableQuantity" width="120" />
        <el-table-column label="锁仓状态" align="center" prop="lockStatus" width="100">
          <template #default="scope">
            <el-tag :type="getLockStatusType(scope.row.lockStatus)">
              {{ getLockStatusText(scope.row.lockStatus) }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="锁仓原因" align="center" prop="lockReason" min-width="150" show-overflow-tooltip />
        <el-table-column label="锁仓人" align="center" prop="lockUser" width="100" />
        <el-table-column label="锁仓时间" align="center" prop="lockTime" width="180" />
        <el-table-column label="预计解锁时间" align="center" prop="expectedUnlockTime" width="180" />
        <el-table-column label="操作" align="center" class-name="small-padding fixed-width" width="200">
          <template #default="scope">
            <el-button
              size="small"
              type="text"
              icon="Edit"
              @click="handleUpdate(scope.row)"
              v-hasPermi="['coalLock:edit']"
            >修改</el-button>
            <el-button
              size="small"
              type="text"
              icon="Unlock"
              @click="handleUnlock(scope.row)"
              v-hasPermi="['coalLock:unlock']"
            >解锁</el-button>
            <el-button
              size="small"
              type="text"
              icon="Delete"
              @click="handleDelete(scope.row)"
              v-hasPermi="['coalLock:remove']"
            >删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <!-- åˆ†é¡µç»„ä»¶ -->
      <pagination
        v-show="total > 0"
        :total="total"
        v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize"
        @pagination="getList"
      />
    </el-card>
    <!-- æ·»åŠ æˆ–ä¿®æ”¹é”ä»“å¯¹è¯æ¡† -->
    <el-dialog :title="title" v-model="open" width="800px" append-to-body>
      <el-form ref="lockFormRef" :model="form" :rules="rules" label-width="120px">
        <el-row>
          <el-col :span="12">
            <el-form-item label="煤种名称" prop="coalName">
              <el-select
                v-model="form.coalId"
                placeholder="请选择煤种"
                filterable
                clearable
                @change="handleCoalChange"
                style="width: 100%"
              >
                <el-option
                  v-for="coal in coalOptions"
                  :key="coal.value"
                  :label="coal.label"
                  :value="coal.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="供应商" prop="supplierId">
              <el-select
                v-model="form.supplierId"
                placeholder="请选择供应商"
                filterable
                clearable
                style="width: 100%"
              >
                <el-option
                  v-for="supplier in supplierOptions"
                  :key="supplier.value"
                  :label="supplier.label"
                  :value="supplier.value"
                />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="总库存量(吨)" prop="totalInventory">
              <el-input v-model="form.totalInventory" placeholder="请输入总库存量" disabled />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="锁仓数量(吨)" prop="lockQuantity">
              <el-input
                v-model="form.lockQuantity"
                placeholder="请输入锁仓数量"
                type="number"
                :max="form.totalInventory"
                @input="handleLockQuantityChange"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="可用数量(吨)" prop="availableQuantity">
              <el-input v-model="form.availableQuantity" placeholder="可用数量" disabled />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="锁仓状态" prop="lockStatus">
              <el-select v-model="form.lockStatus" placeholder="请选择锁仓状态" style="width: 100%">
                <el-option label="已锁定" value="locked" />
                <el-option label="部分锁定" value="partial" />
                <el-option label="未锁定" value="unlocked" />
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="12">
            <el-form-item label="锁仓时间" prop="lockTime">
              <el-date-picker
                v-model="form.lockTime"
                type="datetime"
                placeholder="选择锁仓时间"
                style="width: 100%"
                format="YYYY-MM-DD HH:mm:ss"
                value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
          <el-col :span="12">
            <el-form-item label="预计解锁时间" prop="expectedUnlockTime">
              <el-date-picker
                v-model="form.expectedUnlockTime"
                type="datetime"
                placeholder="选择预计解锁时间"
                style="width: 100%"
                format="YYYY-MM-DD HH:mm:ss"
                value-format="YYYY-MM-DD HH:mm:ss"
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="锁仓原因" prop="lockReason">
              <el-input
                v-model="form.lockReason"
                type="textarea"
                placeholder="请输入锁仓原因"
                :rows="3"
                maxlength="500"
                show-word-limit
              />
            </el-form-item>
          </el-col>
        </el-row>
        <el-row>
          <el-col :span="24">
            <el-form-item label="备注" prop="remarks">
              <el-input
                v-model="form.remarks"
                type="textarea"
                placeholder="请输入备注信息"
                :rows="2"
                maxlength="200"
                show-word-limit
              />
            </el-form-item>
          </el-col>
        </el-row>
      </el-form>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="submitForm">ç¡® å®š</el-button>
          <el-button @click="cancel">取 æ¶ˆ</el-button>
        </div>
      </template>
    </el-dialog>
    <!-- æŸ¥çœ‹è¯¦æƒ…对话框 -->
    <el-dialog title="锁仓详情" v-model="viewOpen" width="800px" append-to-body>
      <el-descriptions :column="2" border>
        <el-descriptions-item label="锁仓编号">{{ form.lockCode }}</el-descriptions-item>
        <el-descriptions-item label="煤种名称">{{ form.coalName }}</el-descriptions-item>
        <el-descriptions-item label="供应商">{{ form.supplierName }}</el-descriptions-item>
        <el-descriptions-item label="总库存量">{{ form.totalInventory }}吨</el-descriptions-item>
        <el-descriptions-item label="锁仓数量">{{ form.lockQuantity }}吨</el-descriptions-item>
        <el-descriptions-item label="可用数量">{{ form.availableQuantity }}吨</el-descriptions-item>
        <el-descriptions-item label="锁仓状态">
          <el-tag :type="getLockStatusType(form.lockStatus)">
            {{ getLockStatusText(form.lockStatus) }}
          </el-tag>
        </el-descriptions-item>
        <el-descriptions-item label="锁仓人">{{ form.lockUser }}</el-descriptions-item>
        <el-descriptions-item label="锁仓时间">{{ form.lockTime }}</el-descriptions-item>
        <el-descriptions-item label="预计解锁时间">{{ form.expectedUnlockTime }}</el-descriptions-item>
        <el-descriptions-item label="锁仓原因" :span="2">{{ form.lockReason }}</el-descriptions-item>
        <el-descriptions-item label="备注" :span="2">{{ form.remarks }}</el-descriptions-item>
      </el-descriptions>
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="viewOpen = false">关 é—­</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, reactive, computed, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search, Plus, Edit, Delete, Unlock, View, Download, Refresh } from '@element-plus/icons-vue'
// å“åº”式数据
const loading = ref(false)
const showSearch = ref(true)
const open = ref(false)
const viewOpen = ref(false)
const single = ref(true)
const multiple = ref(true)
const total = ref(0)
const lockList = ref([])
const coalOptions = ref([])
const supplierOptions = ref([])
// æŸ¥è¯¢å‚æ•°
const queryParams = reactive({
  pageNum: 1,
  pageSize: 10,
  coalName: '',
  lockStatus: '',
  supplierName: '',
  lockDateRange: []
})
// è¡¨å•数据
const form = reactive({
  id: undefined,
  lockCode: '',
  coalId: '',
  coalName: '',
  supplierId: '',
  supplierName: '',
  totalInventory: 0,
  lockQuantity: 0,
  availableQuantity: 0,
  lockStatus: 'locked',
  lockReason: '',
  lockUser: '',
  lockTime: '',
  expectedUnlockTime: '',
  remarks: ''
})
// è¡¨å•验证规则
const rules = reactive({
  coalId: [
    { required: true, message: '请选择煤种', trigger: 'change' }
  ],
  supplierId: [
    { required: true, message: '请选择供应商', trigger: 'change' }
  ],
  lockQuantity: [
    { required: true, message: '请输入锁仓数量', trigger: 'blur' },
    { type: 'number', min: 0, message: '锁仓数量不能小于0', trigger: 'blur' }
  ],
  lockStatus: [
    { required: true, message: '请选择锁仓状态', trigger: 'change' }
  ],
  lockReason: [
    { required: true, message: '请输入锁仓原因', trigger: 'blur' }
  ],
  lockTime: [
    { required: true, message: '请选择锁仓时间', trigger: 'change' }
  ]
})
// è®¡ç®—属性
const title = computed(() => {
  return form.id ? '修改锁仓' : '新增锁仓'
})
// è¡¨å•引用
const lockFormRef = ref()
const queryForm = ref()
// åˆå§‹åŒ–数据
onMounted(() => {
  getList()
  initOptions()
})
// åˆå§‹åŒ–选项数据
const initOptions = () => {
  // æ¨¡æ‹Ÿç…¤ç§æ•°æ®
  coalOptions.value = [
    { value: '1', label: '无烟煤' },
    { value: '2', label: '烟煤' },
    { value: '3', label: '褐煤' },
    { value: '4', label: '焦煤' },
    { value: '5', label: '气煤' }
  ]
  // æ¨¡æ‹Ÿä¾›åº”商数据
  supplierOptions.value = [
    { value: '1', label: '山西煤炭集团' },
    { value: '2', label: '内蒙古煤炭公司' },
    { value: '3', label: '陕西煤炭工业' },
    { value: '4', label: '河南煤炭集团' },
    { value: '5', label: '河北煤炭公司' }
  ]
  // æ¨¡æ‹Ÿé”ä»“列表数据
  lockList.value = [
    {
      id: '1',
      lockCode: 'LK20241201001',
      coalId: '1',
      coalName: '无烟煤',
      supplierId: '1',
      supplierName: '山西煤炭集团',
      totalInventory: 1000,
      lockQuantity: 300,
      availableQuantity: 700,
      lockStatus: 'partial',
      lockReason: '生产计划预留',
      lockUser: '张三',
      lockTime: '2024-12-01 09:00:00',
      expectedUnlockTime: '2024-12-31 18:00:00'
    },
    {
      id: '2',
      lockCode: 'LK20241201002',
      coalId: '2',
      coalName: '烟煤',
      supplierId: '2',
      supplierName: '内蒙古煤炭公司',
      totalInventory: 800,
      lockQuantity: 800,
      availableQuantity: 0,
      lockStatus: 'locked',
      lockReason: '质量检测中',
      lockUser: '李四',
      lockTime: '2024-12-01 10:00:00',
      expectedUnlockTime: '2024-12-15 18:00:00'
    },
    {
      id: '3',
      lockCode: 'LK20241201003',
      coalId: '4',
      coalName: '焦煤',
      supplierId: '3',
      supplierName: '陕西煤炭工业',
      totalInventory: 1200,
      lockQuantity: 0,
      availableQuantity: 1200,
      lockStatus: 'unlocked',
      lockReason: '',
      lockUser: '',
      lockTime: '',
      expectedUnlockTime: ''
    }
  ]
  total.value = lockList.value.length
}
// èŽ·å–é”ä»“çŠ¶æ€ç±»åž‹
const getLockStatusType = (status) => {
  const statusMap = {
    'locked': 'danger',
    'partial': 'warning',
    'unlocked': 'success'
  }
  return statusMap[status] || 'info'
}
// èŽ·å–é”ä»“çŠ¶æ€æ–‡æœ¬
const getLockStatusText = (status) => {
  const statusMap = {
    'locked': '已锁定',
    'partial': '部分锁定',
    'unlocked': '未锁定'
  }
  return statusMap[status] || '未知'
}
// ç…¤ç§é€‰æ‹©å˜åŒ–处理
const handleCoalChange = (coalId) => {
  const selectedCoal = coalOptions.value.find(item => item.value === coalId)
  if (selectedCoal) {
    form.coalName = selectedCoal.label
    // æ¨¡æ‹Ÿè®¾ç½®åº“存数据
    form.totalInventory = Math.floor(Math.random() * 1000) + 500
    form.availableQuantity = form.totalInventory - form.lockQuantity
  }
}
// é”ä»“数量变化处理
const handleLockQuantityChange = () => {
  if (form.lockQuantity > form.totalInventory) {
    form.lockQuantity = form.totalInventory
  }
  form.availableQuantity = form.totalInventory - form.lockQuantity
  // æ›´æ–°é”ä»“状态
  if (form.lockQuantity === 0) {
    form.lockStatus = 'unlocked'
  } else if (form.lockQuantity === form.totalInventory) {
    form.lockStatus = 'locked'
  } else {
    form.lockStatus = 'partial'
  }
}
// æŸ¥è¯¢åˆ—表
const getList = () => {
  loading.value = true
  // æ¨¡æ‹ŸAPI调用延迟
  setTimeout(() => {
    loading.value = false
  }, 500)
}
// æœç´¢
const handleQuery = () => {
  queryParams.pageNum = 1
  getList()
}
// é‡ç½®æœç´¢
const resetQuery = () => {
  queryParams.coalName = ''
  queryParams.lockStatus = ''
  queryParams.supplierName = ''
  queryParams.lockDateRange = []
  handleQuery()
}
// é€‰æ‹©å˜åŒ–处理
const handleSelectionChange = (selection) => {
  single.value = selection.length !== 1
  multiple.value = !selection.length
}
// æ–°å¢žé”ä»“
const handleAdd = () => {
  reset()
  open.value = true
}
// ä¿®æ”¹é”ä»“
const handleUpdate = (row) => {
  reset()
  const id = row.id || row
  const lockData = lockList.value.find(item => item.id === id)
  if (lockData) {
    Object.assign(form, lockData)
  }
  open.value = true
}
// æŸ¥çœ‹è¯¦æƒ…
const handleView = (row) => {
  reset()
  const id = row.id || row
  const lockData = lockList.value.find(item => item.id === id)
  if (lockData) {
    Object.assign(form, lockData)
  }
  viewOpen.value = true
}
// åˆ é™¤é”ä»“
const handleDelete = (row) => {
  const ids = row.id || row
  ElMessageBox.confirm('确认删除选中的锁仓记录吗?', '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    ElMessage.success('删除成功')
    getList()
  })
}
// è§£é™¤é”ä»“
const handleUnlock = (row) => {
  const id = row.id || row
  ElMessageBox.confirm('确认解除该煤种的锁仓吗?', '警告', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    const lockData = lockList.value.find(item => item.id === id)
    if (lockData) {
      lockData.lockQuantity = 0
      lockData.availableQuantity = lockData.totalInventory
      lockData.lockStatus = 'unlocked'
      lockData.lockReason = ''
      lockData.lockUser = ''
      lockData.lockTime = ''
      lockData.expectedUnlockTime = ''
    }
    ElMessage.success('解锁成功')
    getList()
  })
}
// å¯¼å‡º
const handleExport = () => {
  ElMessage.success('导出功能开发中...')
}
// æäº¤è¡¨å•
const submitForm = () => {
  lockFormRef.value.validate((valid) => {
    if (valid) {
      if (form.id) {
        // ä¿®æ”¹
        const index = lockList.value.findIndex(item => item.id === form.id)
        if (index !== -1) {
          Object.assign(lockList.value[index], form)
        }
        ElMessage.success('修改成功')
      } else {
        // æ–°å¢ž
        const newLock = {
          ...form,
          id: Date.now().toString(),
          lockCode: `LK${new Date().toISOString().slice(0, 10).replace(/-/g, '')}${String(lockList.value.length + 1).padStart(3, '0')}`,
          lockUser: '当前用户'
        }
        lockList.value.unshift(newLock)
        total.value = lockList.value.length
        ElMessage.success('新增成功')
      }
      open.value = false
      getList()
    }
  })
}
// å–消
const cancel = () => {
  open.value = false
  reset()
}
// é‡ç½®è¡¨å•
const reset = () => {
  Object.assign(form, {
    id: undefined,
    lockCode: '',
    coalId: '',
    coalName: '',
    supplierId: '',
    supplierName: '',
    totalInventory: 0,
    lockQuantity: 0,
    availableQuantity: 0,
    lockStatus: 'locked',
    lockReason: '',
    lockUser: '',
    lockTime: '',
    expectedUnlockTime: '',
    remarks: ''
  })
}
</script>
<style scoped>
.app-container {
  padding: 20px;
}
.box-card {
  margin-bottom: 20px;
}
.mb8 {
  margin-bottom: 8px;
}
.dialog-footer {
  text-align: right;
}
.el-descriptions {
  margin: 20px 0;
}
</style>
src/views/payable/index.vue
@@ -144,7 +144,7 @@
  total: 0,
  // æŸ¥è¯¢å‚æ•°
  queryParams: {
    searchAll: "",
    search: "",
  },
});
const userInfo = ref({});
@@ -206,7 +206,7 @@
    let resp = await findPayablePage(
        {
          current: state.current,
          pageSize: state.current
          size: state.pageSize
          , ...state.queryParams
        })
    tableData.value = resp.data.records
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>