<!--设备故障工单（故障维修 orderType=1，参考排水/燃气工单形态）-->
<!--数据源：/api/work-order/*（orderType=1 过滤；equipmentType 为空 = 所有设备）-->
<!--需求 5.2.4.4.1：手动新增字段=设备类型/设备ID/设备位置/设备厂家/维护人员/联系方式/故障时间/故障描述-->
<template>
  <div class="order-container">
    <!-- 顶部搜索区（参考排水/燃气工单） -->
    <el-card class="search-card" shadow="never">
      <div class="search-form">
        <el-form :model="queryParams" ref="queryFormRef" inline>
          <el-form-item label="优先级">
            <el-select v-model="queryParams.orderLevel" placeholder="全部优先级" clearable style="width: 120px">
              <el-option v-for="(v, k) in ORDER_LEVEL_MAP" :key="k" :label="v.text" :value="Number(k)"/>
            </el-select>
          </el-form-item>
          <el-form-item label="状态">
            <el-select v-model="queryParams.orderStatus" placeholder="全部状态" clearable style="width: 120px">
              <el-option v-for="(v, k) in ORDER_STATUS_MAP" :key="k" :label="v.text" :value="Number(k)"/>
            </el-select>
          </el-form-item>
          <el-form-item label="设备编码">
            <el-input v-model="queryParams.deviceCode" placeholder="设备编码" clearable style="width: 150px" @keyup.enter="handleSearch"/>
          </el-form-item>
          <el-form-item label="关键词">
            <el-input v-model="queryParams.keyword" placeholder="工单编号/设备编码/描述" clearable style="width: 200px" @keyup.enter="handleSearch"/>
          </el-form-item>
          <el-form-item>
            <el-button type="primary" @click="handleSearch">查询</el-button>
            <el-button @click="handleReset">重置</el-button>
            <el-button type="primary" plain @click="openAddDialog">➕ 新增故障工单</el-button>
          </el-form-item>
        </el-form>
      </div>
    </el-card>

    <!-- 主容器：左列表 + 右详情（参考排水/燃气工单） -->
    <el-row :gutter="16" class="main-row">
      <!-- 左侧：工单列表 -->
      <el-col :span="8" class="col-fill">
        <el-card class="box-card" shadow="always">
          <template #header>
            <div class="card-header">
              <span>故障工单列表</span>
            </div>
          </template>
          <el-scrollbar class="list-scroll">
            <div class="order-list">
              <div
                v-for="order in tableData"
                :key="order.orderId"
                class="order-item"
                :class="{ 'active': selectedOrderId === order.orderId }"
                @click="handleSelectOrder(order)"
              >
                <div class="order-header">
                  <span class="order-no">{{ order.orderNo }}</span>
                  <el-tag :type="orderStatusType(order.orderStatus)" size="small" effect="light" class="status-badge">{{ orderStatusText(order.orderStatus) }}</el-tag>
                </div>
                <div class="order-body">
                  <div class="order-tags">
                    <el-tag :type="orderLevelType(order.orderLevel)" size="small" effect="plain">{{ orderLevelText(order.orderLevel) }}</el-tag>
                    <el-tag v-if="order.hazardNo" size="small" effect="plain">隐患 {{ order.hazardNo }}</el-tag>
                  </div>
                  <div class="order-desc" v-if="order.orderDesc">{{ order.orderDesc }}</div>
                  <div class="device-code">设备编号：{{ order.deviceCode || '-' }}</div>
                  <div class="create-time">故障时间：{{ timeText(order.createTime) }}</div>
                </div>
              </div>
              <el-empty v-if="tableData.length === 0" description="暂无数据" :image-size="100"/>
            </div>
          </el-scrollbar>
          <div class="pagination-wrapper">
            <el-pagination
              v-model:current-page="pageNum"
              v-model:page-size="pageSize"
              :total="total"
              layout="total, prev, pager, next"
              :page-sizes="[10, 20, 50, 100]"
              @size-change="handleSizeChange"
              @current-change="handlePageChange"
              class="pagination"
            />
          </div>
        </el-card>
      </el-col>

      <!-- 右侧：工单详情 -->
      <el-col :span="16" class="col-fill">
        <el-card v-loading="detailLoading" class="box-card" shadow="always">
          <template #header>
            <div class="card-header">
              <span v-if="selectedOrder && selectedOrder.orderId">工单详情 - {{ selectedOrder.orderNo }}</span>
              <span v-else>请选择工单查看详情</span>
            </div>
          </template>

          <div v-if="selectedOrder && selectedOrder.orderId" class="detail-body">
            <el-tabs v-model="activeTab" class="detail-tabs">
              <!-- 工单信息 -->
              <el-tab-pane label="工单信息" name="info">
                <el-descriptions :column="2" border size="small">
                  <el-descriptions-item label="工单编号">{{ selectedOrder.orderNo }}</el-descriptions-item>
                  <el-descriptions-item label="工单状态">
                    <el-tag :type="orderStatusType(selectedOrder.orderStatus)" size="small">{{ orderStatusText(selectedOrder.orderStatus) }}</el-tag>
                  </el-descriptions-item>
                  <el-descriptions-item label="关联案件编号">{{ selectedOrder.caseNo || '-' }}</el-descriptions-item>
                  <el-descriptions-item label="关联隐患编号">{{ selectedOrder.hazardNo || '-' }}</el-descriptions-item>
                  <el-descriptions-item label="设备编号">{{ selectedOrder.deviceCode || '-' }}</el-descriptions-item>
                  <el-descriptions-item label="工单类型">{{ orderTypeText(selectedOrder.orderType) }}</el-descriptions-item>
                  <el-descriptions-item label="优先级">
                    <el-tag :type="orderLevelType(selectedOrder.orderLevel)" size="small">{{ orderLevelText(selectedOrder.orderLevel) }}</el-tag>
                  </el-descriptions-item>
                  <el-descriptions-item label="接单人">{{ userNames(selectedOrder.receiveUser) || '-' }}</el-descriptions-item>
                  <el-descriptions-item label="问题描述" :span="2">{{ selectedOrder.orderDesc || '-' }}</el-descriptions-item>
                  <el-descriptions-item label="故障时间">{{ timeText(selectedOrder.createTime) }}</el-descriptions-item>
                  <el-descriptions-item label="派单时间">{{ timeText(selectedOrder.dispatchTime) }}</el-descriptions-item>
                  <el-descriptions-item label="计划完成">{{ timeText(selectedOrder.planFinishTime) }}</el-descriptions-item>
                  <el-descriptions-item label="实际完成">{{ timeText(selectedOrder.realFinishTime) }}</el-descriptions-item>
                  <el-descriptions-item label="验收时间">{{ timeText(selectedOrder.verifyTime) }}</el-descriptions-item>
                  <el-descriptions-item label="创建时间">{{ timeText(selectedOrder.createTime) }}</el-descriptions-item>
                  <el-descriptions-item label="更新时间">{{ timeText(selectedOrder.updateTime) }}</el-descriptions-item>
                  <el-descriptions-item label="处置结果" :span="2">{{ selectedOrder.repairResult || '-' }}</el-descriptions-item>
                </el-descriptions>

                <!-- 关联设备信息（需求 5.2.4.4.1 设备维度） -->
                <div v-if="detailDevice" class="device-section">
                  <h4 class="section-title">🔗 关联设备</h4>
                  <el-descriptions :column="2" border size="small">
                    <el-descriptions-item label="设备类型">{{ detailDevice.equipmentTypeName || '-' }}</el-descriptions-item>
                    <el-descriptions-item label="设备编码">{{ detailDevice.equipmentCode || '-' }}</el-descriptions-item>
                    <el-descriptions-item label="安装位置">{{ detailDevice.equipmentLocation || '-' }}</el-descriptions-item>
                    <el-descriptions-item label="管点地址">{{ detailDevice.pointAddress || '-' }}</el-descriptions-item>
                    <el-descriptions-item label="设备厂家">{{ detailDevice.manufacturer || '-' }}</el-descriptions-item>
                    <el-descriptions-item label="所属管线">{{ detailDevice.networkName || '-' }}</el-descriptions-item>
                    <el-descriptions-item label="维护人员">{{ detailDevice.maintainer || '-' }}</el-descriptions-item>
                    <el-descriptions-item label="联系方式">{{ detailDevice.maintainerPhone || '-' }}</el-descriptions-item>
                  </el-descriptions>
                </div>

                <RepairImagePanel :before-images="selectedOrder.maintenanceBeforeImg" :after-images="selectedOrder.maintenanceAfterImg" />

                <!-- 工单操作（参考排水/燃气工单按钮组） -->
                <div class="action-section">
                  <h4 class="section-title">工单操作</h4>
                  <div class="action-buttons">
                    <el-button v-if="canOperate.dispatch(selectedOrder)" type="primary" @click="handleDispatch">下派任务</el-button>
                    <el-button v-if="canOperate.verify(selectedOrder)" type="warning" @click="handleVerify">核查</el-button>
                    <el-button v-if="canOperate.process(selectedOrder)" type="success" @click="handleProcess">处理</el-button>
                    <el-button v-if="canOperate.complete(selectedOrder)" type="danger" @click="handleComplete">提交验收</el-button>
                    <el-button v-if="canOperate.close(selectedOrder)" type="success" @click="handleClose">验收通过</el-button>
                    <el-button v-if="canOperate.cancel(selectedOrder)" type="info" plain @click="handleCancel">取消工单</el-button>
                  </div>
                </div>
              </el-tab-pane>

              <!-- 处理历史 -->
              <el-tab-pane label="处理历史" name="history">
                <div class="timeline-scroll">
                  <el-timeline v-if="currentOrderLogs && currentOrderLogs.length > 0">
                    <el-timeline-item
                      v-for="log in currentOrderLogs"
                      :key="log.logId || log.id"
                      :timestamp="timeText(log.operTime)"
                      placement="top"
                      :type="orderLogType(log.operType)"
                      size="large"
                    >
                      <el-card shadow="hover">
                        <div class="timeline-content">
                          <div class="timestamp">{{ timeText(log.operTime) }}</div>
                          <div class="operator-info">
                            <span class="operator-name">{{ log.operUserName || '-' }}</span>
                            <span class="oper-type">· {{ orderLogText(log.operType) }}</span>
                          </div>
                          <div class="oper-desc">{{ log.operDesc || '-' }}</div>
                        </div>
                      </el-card>
                    </el-timeline-item>
                  </el-timeline>
                  <el-empty v-else description="暂无处理记录" :image-size="100"/>
                </div>
              </el-tab-pane>
            </el-tabs>
          </div>

          <el-empty v-else description="请从左侧选择工单" :image-size="150"/>
        </el-card>
      </el-col>
    </el-row>

    <!-- 新增工单弹窗（需求 5.2.4.4.1：设备类型/设备ID/设备位置/设备厂家/维护人员/联系方式/故障时间/故障描述） -->
    <el-dialog v-model="addVisible" title="➕ 新增故障工单" width="680px" append-to-body destroy-on-close>
      <el-form ref="addFormRef" :model="addForm" :rules="addRules" label-width="100px">
        <el-form-item label="关联设备" prop="deviceId">
          <el-select v-model="addForm.deviceId" filterable remote clearable placeholder="输入设备编码/名称搜索" :remote-method="searchDevice" :loading="deviceLoading" style="width:100%" @change="onDeviceChange">
            <el-option v-for="dev in deviceOptions" :key="dev.equipmentId" :label="`${dev.equipmentName || dev.equipmentCode} (${dev.equipmentCode})`" :value="dev.equipmentId"/>
          </el-select>
        </el-form-item>

        <!-- 设备信息卡：选择设备后自动带出 设备类型/设备ID/设备位置/设备厂家/维护人员/联系方式 -->
        <el-form-item v-if="deviceInfo" label="设备信息">
          <div class="device-info-card">
            <el-descriptions :column="2" border size="small">
              <el-descriptions-item label="设备类型">{{ deviceInfo.equipmentTypeName || '-' }}</el-descriptions-item>
              <el-descriptions-item label="设备ID">{{ deviceInfo.equipmentCode || '-' }}</el-descriptions-item>
              <el-descriptions-item label="设备位置">{{ deviceInfo.equipmentLocation || deviceInfo.pointAddress || '-' }}</el-descriptions-item>
              <el-descriptions-item label="设备厂家">{{ deviceInfo.manufacturer || '-' }}</el-descriptions-item>
              <el-descriptions-item label="维护人员">{{ deviceInfo.maintainer || '-' }}</el-descriptions-item>
              <el-descriptions-item label="联系方式">{{ deviceInfo.maintainerPhone || '-' }}</el-descriptions-item>
            </el-descriptions>
          </div>
        </el-form-item>

        <el-form-item label="设备编码">
          <el-input v-model="addForm.deviceCode" placeholder="未选设备时手动填写" clearable/>
        </el-form-item>
        <el-form-item label="优先级" prop="orderLevel">
          <el-radio-group v-model="addForm.orderLevel">
            <el-radio-button :value="1">紧急</el-radio-button>
            <el-radio-button :value="2">一般</el-radio-button>
            <el-radio-button :value="3">低</el-radio-button>
          </el-radio-group>
        </el-form-item>
        <el-form-item label="故障时间">
          <el-date-picker v-model="addForm.faultTime" type="datetime" placeholder="故障发生时间（默认当前）" value-format="YYYY-MM-DD HH:mm:ss" style="width:100%"/>
        </el-form-item>
        <el-form-item label="计划完成时间">
          <el-date-picker v-model="addForm.planFinishTime" type="datetime" placeholder="请选择计划完成时间" value-format="YYYY-MM-DD HH:mm:ss" style="width:100%"/>
        </el-form-item>
        <el-form-item label="故障描述" prop="orderDesc">
          <el-input v-model="addForm.orderDesc" type="textarea" :rows="4" placeholder="请描述故障现象 / 设备离线信息等" maxlength="500" show-word-limit/>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="addVisible=false">取消</el-button>
        <el-button type="primary" :loading="submitting" @click="submitAdd">提交工单</el-button>
      </template>
    </el-dialog>

    <!-- 派单弹窗（部门树 + 用户多选，参考排水/燃气工单） -->
    <el-dialog v-model="dispatchDialogVisible" title="下派任务 - 选择接单人" width="750px" append-to-body>
      <div style="display: flex; gap: 16px; min-height: 350px;">
        <div style="width: 280px; border-right: 1px solid #e4e7ed; padding-right: 12px;">
          <el-input v-model="deptFilterText" placeholder="筛选部门" clearable size="small" style="margin-bottom: 8px"/>
          <el-tree
            ref="deptTreeRef"
            :data="deptTreeData"
            :props="{ label: 'deptName', children: 'children' }"
            :filter-node-method="filterDeptNode"
            node-key="deptId"
            highlight-current
            @node-click="handleDeptClick"
            style="font-size: 14px"
          />
        </div>
        <div style="flex: 1; min-width: 0;">
          <el-table
            ref="userTableRef"
            :data="userList"
            border size="small"
            max-height="300"
            row-key="userId"
            @selection-change="handleSelectionChange"
            @row-click="handleRowClick"
          >
            <el-table-column type="selection" width="40" align="center" :reserve-selection="true"/>
            <el-table-column prop="userName" label="用户名" width="100"/>
            <el-table-column prop="nickName" label="昵称" width="100"/>
            <el-table-column prop="dept.deptName" label="部门" show-overflow-tooltip/>
          </el-table>
          <div v-if="userList.length === 0" style="text-align: center; color: #909399; padding: 40px 0;">请先在左侧选择部门</div>
        </div>
      </div>
      <el-form label-width="80px" style="margin-top: 16px">
        <el-form-item label="备注"><el-input v-model="dispatchForm.remarks" placeholder="请输入派单备注"/></el-form-item>
      </el-form>
      <template #footer>
        <span style="float: left; line-height: 32px; color: #606266;">
          已选人员：
          <span v-if="selectedUserNames.length > 0" style="color: #409eff; font-weight: bold;">{{ selectedUserNames.join('、') }}</span>
          <span v-else style="color: #909399">未选择</span>
          （{{ dispatchForm.handlerIds.length }}）
        </span>
        <el-button @click="dispatchDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="submitting" @click="submitDispatch">确认</el-button>
      </template>
    </el-dialog>

    <!-- 核查/处理弹窗 -->
    <el-dialog v-model="actionDialogVisible" :title="actionTitle" width="600px" append-to-body>
      <el-form label-width="90px">
        <el-form-item v-if="actionTitle === '处理工单'" label="处理前照片">
          <ImageUpload v-model="processBeforeImages" :limit="9" :isShowTip="true" :upload-url="imageUploadUrl" />
        </el-form-item>
        <el-form-item label="结果说明" required>
          <el-input v-model="actionFormData.solution" type="textarea" :rows="5" :placeholder="actionTitle === '核查工单' ? '请输入核查结论（属实/不属实、现场情况）' : '请输入故障原因、处理结果及处理措施'" maxlength="500" show-word-limit/>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="actionDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="submitting" @click="submitAction">确定</el-button>
      </template>
    </el-dialog>

    <!-- 提交验收弹窗 -->
    <el-dialog v-model="completeDialogVisible" title="提交验收" width="600px" append-to-body>
      <el-form label-width="80px">
        <el-form-item label="维修后照片">
          <ImageUpload v-model="maintenanceAfterImages" :limit="9" :isShowTip="true" :upload-url="imageUploadUrl" />
        </el-form-item>
        <el-form-item label="验收意见">
          <el-input v-model="completeForm.result" type="textarea" :rows="4" placeholder="请填写维修处置结果说明" maxlength="500" show-word-limit/>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="completeDialogVisible = false">取消</el-button>
        <el-button type="primary" :loading="submitting" @click="submitComplete">提交</el-button>
      </template>
    </el-dialog>

    <!-- 验收通过/结案弹窗 -->
    <el-dialog v-model="closeDialogVisible" title="验收通过" width="500px" append-to-body>
      <el-form label-width="80px">
        <el-form-item label="验收结果">
          <el-input v-model="closeForm.result" type="textarea" :rows="4" placeholder="请填写验收结果（结案后关联隐患同步为已整改、设备报警状态重置）" maxlength="500" show-word-limit/>
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="closeDialogVisible = false">取消</el-button>
        <el-button type="success" :loading="submitting" @click="submitClose">确认验收</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, watch, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import RepairImagePanel from '@/components/RepairImagePanel'
import { listWorkOrder, getWorkOrderDetail, addWorkOrder, dispatchWorkOrder, verifyWorkOrder, processWorkOrder, completeWorkOrder, closeWorkOrder, cancelWorkOrder } from '@/api/work/order'
import { getEquipmentFullPage } from '@/api/pipeNetwork/basic'
import { listDept } from '@/api/system/dept'
import { listUser } from '@/api/system/user'
import { handleTree } from '@/utils/ruoyi'
import { ORDER_STATUS_MAP, ORDER_LEVEL_MAP, orderStatusText, orderStatusType, orderTypeText, orderLevelText, orderLevelType, orderLogText, orderLogType, canOperate, timeText } from './workOrderDict'

// ========== 查询 & 列表（orderType=1 故障维修） ==========
const listLoading = ref(false)
const tableData = ref([])
const pageNum = ref(1)
const pageSize = ref(10)
const total = ref(0)
const queryFormRef = ref(null)
const queryParams = reactive({ orderLevel: null, orderStatus: null, deviceCode: '', keyword: '' })

async function handleSearch() {
  listLoading.value = true
  try {
    const params = { orderType: 1 }
    if (queryParams.orderLevel) params.orderLevel = queryParams.orderLevel
    if (queryParams.orderStatus) params.orderStatus = queryParams.orderStatus
    if (queryParams.deviceCode) params.deviceCode = queryParams.deviceCode
    if (queryParams.keyword) params.keyword = queryParams.keyword
    const res = await listWorkOrder(params, pageNum.value, pageSize.value)
    if (res.data) {
      tableData.value = res.data.records || []
      total.value = Number(res.data.total || 0)
    }
  } catch(e) { ElMessage.error('查询失败'); console.error(e) }
  finally { listLoading.value = false }
}

function handleReset() {
  queryFormRef.value && queryFormRef.value.resetFields()
  queryParams.orderLevel = null
  queryParams.orderStatus = null
  queryParams.deviceCode = ''
  queryParams.keyword = ''
  pageNum.value = 1
  selectedOrderId.value = null
  selectedOrder.value = {}
  handleSearch()
}

// ========== 选中工单 & 详情（合并 res.data.order + logs） ==========
const selectedOrderId = ref(null)
const selectedOrder = ref({})
const activeTab = ref('info')
const currentOrderLogs = ref([])
const detailLoading = ref(false)
const detailDevice = ref(null)

async function handleSelectOrder(order) {
  selectedOrderId.value = order.orderId
  selectedOrder.value = { ...order }
  activeTab.value = 'info'
  currentOrderLogs.value = []
  detailDevice.value = null
  await loadOrderDetail(order.orderId)
}

async function loadOrderDetail(orderId) {
  detailLoading.value = true
  try {
    const res = await getWorkOrderDetail(orderId)
    if (res.code === 200 && res.data) {
      selectedOrder.value = { ...selectedOrder.value, ...res.data.order }
      currentOrderLogs.value = res.data.logs || []
      if (res.data.order?.deviceCode) {
        loadDeviceInfo(res.data.order.deviceCode)
      }
    }
  } catch(e) { ElMessage.error('加载工单详情失败'); console.error(e) }
  finally { detailLoading.value = false }
}

async function loadDeviceInfo(codeOrId) {
  try {
    const res = await getEquipmentFullPage(1, 1, { equipmentCode: codeOrId })
    const rows = res.data?.rows || res.data?.records || []
    if (rows.length) { detailDevice.value = rows[0]; return }
    const res2 = await getEquipmentFullPage(1, 1, { equipmentId: codeOrId })
    const rows2 = res2.data?.rows || res2.data?.records || []
    if (rows2.length) detailDevice.value = rows2[0]
  } catch(e) { console.warn('加载设备信息失败', e) }
}

function handleSizeChange() {
  pageNum.value = 1
  selectedOrderId.value = null
  selectedOrder.value = {}
  handleSearch()
}

function handlePageChange() {
  selectedOrderId.value = null
  selectedOrder.value = {}
  handleSearch()
}

// ========== 用户映射（接单人 ID → 姓名） ==========
const userMap = ref({})
function userNames(ids) {
  if (!ids) return ''
  return String(ids).split(',').map(id => userMap.value[id] || id).join('、')
}
async function loadUsers() {
  try {
    const res = await listUser({ pageNum: 1, pageSize: 200 })
    if (res.rows) {
      userMap.value = Object.fromEntries(res.rows.map(u => [u.userId, u.nickName || u.userName]))
    }
  } catch(e) { console.warn('加载用户列表失败', e) }
}

// ========== 新增工单（需求 5.2.4.4.1） ==========
const addVisible = ref(false)
const addFormRef = ref(null)
const addForm = reactive({ deviceId: '', deviceCode: '', orderLevel: 2, faultTime: '', planFinishTime: '', orderDesc: '' })
const addRules = {
  orderLevel: [{ required: true, message: '请选择优先级', trigger: 'change' }],
  orderDesc: [{ required: true, message: '请填写故障描述', trigger: 'blur' }]
}
const deviceOptions = ref([])
const deviceLoading = ref(false)
const deviceInfo = ref(null)
const submitting = ref(false)

function openAddDialog() {
  addForm.deviceId = ''; addForm.deviceCode = ''; addForm.orderLevel = 2
  addForm.faultTime = ''; addForm.planFinishTime = ''; addForm.orderDesc = ''
  deviceOptions.value = []
  deviceInfo.value = null
  addVisible.value = true
}

async function searchDevice(query) {
  if (!query) { deviceOptions.value = []; return }
  deviceLoading.value = true
  try {
    const res = await getEquipmentFullPage(1, 20, { equipmentCode: query })
    // 后端返回 MyBatis-Plus Page（records），兼容 rows 命名
    if (res.data) deviceOptions.value = res.data.records || res.data.rows || []
  } catch(e) { console.warn('设备搜索失败', e) }
  finally { deviceLoading.value = false }
}

// 选中设备后：带出设备信息卡 + 自动填充设备编码
function onDeviceChange(id) {
  deviceInfo.value = null
  if (!id) { addForm.deviceCode = ''; return }
  // equipmentId 可能是数字/字符串，统一转字符串比较
  const dev = deviceOptions.value.find(d => String(d.equipmentId) === String(id))
  if (dev) {
    deviceInfo.value = dev
    addForm.deviceCode = dev.equipmentCode || ''
  }
}

async function submitAdd() {
  await addFormRef.value.validate().catch(() => { throw new Error('校验失败') })
  submitting.value = true
  try {
    const data = { orderType: 1, orderLevel: addForm.orderLevel, orderDesc: addForm.orderDesc }
    if (addForm.deviceId) data.deviceId = addForm.deviceId
    if (addForm.deviceCode) data.deviceCode = addForm.deviceCode
    if (addForm.planFinishTime) data.planFinishTime = addForm.planFinishTime
    // 故障时间：手动指定则作为工单创建时间（列表"故障时间"列展示 createTime）
    if (addForm.faultTime) data.createTime = addForm.faultTime
    const res = await addWorkOrder(data)
    ElMessage.success('工单创建成功')
    addVisible.value = false
    handleSearch()
  } catch(e) { ElMessage.error('创建失败：' + (e.msg || e.message || '请重试')); console.error(e) }
  finally { submitting.value = false }
}

// ========== 派单（部门树 + 用户多选，参考排水/燃气工单） ==========
const dispatchDialogVisible = ref(false)
const dispatchForm = reactive({ handlerIds: [], remarks: '' })
const deptTreeRef = ref(null)
const userTableRef = ref(null)
const deptTreeData = ref([])
const deptFilterText = ref('')
const userList = ref([])
const selectedUserList = ref([])

watch(deptFilterText, (val) => { deptTreeRef.value && deptTreeRef.value.filter(val) })
function filterDeptNode(value, data) {
  if (!value) return true
  return data.deptName.includes(value)
}

async function loadDeptTree() {
  if (deptTreeData.value.length > 0) return
  try {
    const res = await listDept()
    deptTreeData.value = handleTree(res.data || [], 'deptId')
  } catch(e) { console.warn('加载部门失败', e) }
}

async function handleDeptClick(node) {
  try {
    userTableRef.value && userTableRef.value.clearSelection()
    selectedUserList.value = []
    dispatchForm.handlerIds = []
    const res = await listUser({ deptId: node.deptId, pageNum: 1, pageSize: 100 })
    userList.value = res.rows || []
  } catch(e) { console.warn('加载部门用户失败', e) }
}

function handleSelectionChange(selection) {
  selectedUserList.value = selection
  dispatchForm.handlerIds = selection.map(item => item.userId)
}

function handleRowClick(row) {
  userTableRef.value && userTableRef.value.toggleRowSelection(row)
}

const selectedUserNames = computed(() => selectedUserList.value.map(item => item.nickName || item.userName))

function handleDispatch() {
  if (!canOperate.dispatch(selectedOrder.value)) {
    ElMessage.warning('仅可对待派单工单进行派单操作')
    return
  }
  Object.assign(dispatchForm, { handlerIds: [], remarks: '' })
  selectedUserList.value = []
  userList.value = []
  loadDeptTree()
  dispatchDialogVisible.value = true
}

async function submitDispatch() {
  if (!dispatchForm.handlerIds || dispatchForm.handlerIds.length === 0) {
    ElMessage.warning('请选择至少一个接单人')
    return
  }
  submitting.value = true
  try {
    await dispatchWorkOrder({
      orderId: selectedOrder.value.orderId,
      handlerIds: dispatchForm.handlerIds,
      remarks: dispatchForm.remarks
    })
    ElMessage.success('派单成功！已向 ' + dispatchForm.handlerIds.length + ' 人下发任务')
    dispatchDialogVisible.value = false
    refreshAfterAction()
  } catch(e) { ElMessage.error('派单失败：' + (e.msg || e.message || '请重试')); console.error(e) }
  finally { submitting.value = false }
}

// ========== 核查/处理（参考排水/燃气工单） ==========
const actionDialogVisible = ref(false)
const actionTitle = ref('')
const actionFormData = reactive({ solution: '' })
const processBeforeImages = ref('')
const imageUploadUrl = import.meta.env.VITE_APP_BASE_API + '/minio/upload'

function handleVerify() {
  if (!canOperate.verify(selectedOrder.value)) {
    ElMessage.warning('当前工单不允许核查')
    return
  }
  actionTitle.value = '核查工单'
  actionFormData.solution = ''
  processBeforeImages.value = ''
  actionDialogVisible.value = true
}

function handleProcess() {
  if (!canOperate.process(selectedOrder.value)) {
    ElMessage.warning('当前工单不允许处理')
    return
  }

  ElMessageBox.alert(
    '<div style="padding: 10px; color: #666;">' +
    '<strong>维修操作指引：</strong><br/><br/>' +
    '• 在下方表格中可以上传处理前的照片（最多9张）<br/>' +
    '• 请选择本地图片或拍照上传<br/>' +
    '• 填写处理说明后点击"确定"提交<br/>' +
    '</div>',
    '开始维修',
    {
      dangerouslyUseHTMLString: true,
      confirmButtonText: '我已了解',
      center: false
    }
  ).then(() => {
    actionTitle.value = '处理工单'
    actionFormData.solution = ''
    processBeforeImages.value = ''
    actionDialogVisible.value = true
  }).catch(() => {})
}

async function submitAction() {
  if (!actionFormData.solution.trim()) {
    ElMessage.warning('请填写说明')
    return
  }
  submitting.value = true
  try {
    const data = {
      orderId: selectedOrder.value.orderId,
      handleResult: 'solved',
      solution: actionFormData.solution
    }
    if (actionTitle.value === '处理工单' && processBeforeImages.value) {
      data.maintenanceBeforeImg = processBeforeImages.value
    }
    if (actionTitle.value === '核查工单') {
      await verifyWorkOrder(data)
    } else {
      await processWorkOrder(data)
    }
    ElMessage.success(actionTitle.value + '成功')
    actionDialogVisible.value = false
    refreshAfterAction()
  } catch(e) { ElMessage.error('操作失败：' + (e.msg || e.message || '请重试')); console.error(e) }
  finally { submitting.value = false }
}

// ========== 提交验收（后端 completeOrder 要求状态 4） ==========
const completeDialogVisible = ref(false)
const completeForm = reactive({ result: '' })
const maintenanceAfterImages = ref('')

function handleComplete() {
  if (!canOperate.complete(selectedOrder.value)) {
    ElMessage.warning('当前工单不允许提交验收')
    return
  }
  completeForm.result = ''
  maintenanceAfterImages.value = ''
  completeDialogVisible.value = true
}

async function submitComplete() {
  if (!completeForm.result.trim()) {
    ElMessage.warning('请填写验收意见')
    return
  }
  submitting.value = true
  try {
    await completeWorkOrder({
      orderId: selectedOrder.value.orderId,
      result: completeForm.result,
      maintenanceAfterImg: maintenanceAfterImages.value
    })
    ElMessage.success('提交验收成功')
    completeDialogVisible.value = false
    refreshAfterAction()
  } catch(e) { ElMessage.error('提交失败：' + (e.msg || e.message || '请重试')); console.error(e) }
  finally { submitting.value = false }
}

// ========== 验收通过/结案（参考排水/燃气工单） ==========
const closeDialogVisible = ref(false)
const closeForm = reactive({ result: '' })

function handleClose() {
  if (!canOperate.close(selectedOrder.value)) {
    ElMessage.warning('当前工单不允许验收通过')
    return
  }
  closeForm.result = ''
  closeDialogVisible.value = true
}

async function submitClose() {
  if (!closeForm.result.trim()) {
    ElMessage.warning('请填写验收结果')
    return
  }
  submitting.value = true
  try {
    await closeWorkOrder({
      orderId: selectedOrder.value.orderId,
      result: closeForm.result
    })
    ElMessage.success('验收通过，工单已结案')
    closeDialogVisible.value = false
    refreshAfterAction()
  } catch(e) { ElMessage.error('验收失败：' + (e.msg || e.message || '请重试')); console.error(e) }
  finally { submitting.value = false }
}

// ========== 取消工单 ==========
function handleCancel() {
  ElMessageBox.confirm(`确定取消工单「${selectedOrder.value.orderNo}」吗？`, '取消工单', { type: 'warning' })
    .then(async () => {
      try {
        await cancelWorkOrder(selectedOrder.value.orderId)
        ElMessage.success('工单已取消')
        selectedOrderId.value = null
        selectedOrder.value = {}
        handleSearch()
      } catch(e) { ElMessage.error('取消失败：' + (e.msg || e.message || '请重试')); console.error(e) }
    }).catch(() => {})
}

/** 操作完成后刷新列表并重新加载当前选中工单 */
async function refreshAfterAction() {
  await handleSearch()
  const fresh = tableData.value.find(o => o.orderId === selectedOrderId.value)
  if (fresh) {
    await handleSelectOrder(fresh)
  } else {
    selectedOrderId.value = null
    selectedOrder.value = {}
  }
}

onMounted(() => {
  loadUsers()
  handleSearch()
})
</script>

<style scoped lang="scss">
.order-container {
  padding: 0 16px 16px;

  .search-card {
    margin-bottom: 16px;

    :deep(.el-card__body) {
      padding: 16px;
    }
  }

  .search-form {
    .el-form {
      display: flex;
      flex-wrap: wrap;
      align-items: flex-start;
      gap: 12px;

      .el-form-item {
        margin-bottom: 0;
        min-width: 150px;

        &:last-child {
          margin-left: auto;
        }
      }
    }
  }

  .main-row {
    height: calc(100vh - 200px);

    .col-fill {
      height: 100%;
    }
  }

  .box-card {
    height: 100%;
    display: flex;
    flex-direction: column;

    :deep(.el-card__body) {
      flex: 1;
      display: flex;
      flex-direction: column;
      overflow: hidden;
    }
  }

  .card-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
  }

  .list-scroll {
    flex: 1;
    overflow: hidden;
  }

  .order-list {
    padding-right: 4px;
  }

  .order-item {
    padding: 16px;
    margin-bottom: 8px;
    border-radius: 8px;
    cursor: pointer;
    transition: all 0.2s;
    border: 1px solid #e4e7ed;

    &:hover {
      background-color: #f5f7fa;
    }

    &.active {
      background-color: #ecf5ff;
      border-color: #409eff;
    }

    .order-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 8px;

      .order-no {
        font-weight: bold;
        font-size: 14px;
      }

      .status-badge {
        min-width: 60px;
      }
    }

    .order-body {
      font-size: 12px;
      color: #606266;

      .order-tags {
        display: flex;
        gap: 6px;
        margin-bottom: 6px;
      }

      .order-desc {
        margin-top: 4px;
        color: #303133;
        font-size: 13px;
        overflow: hidden;
        text-overflow: ellipsis;
        white-space: nowrap;
      }

      .device-code, .create-time {
        margin-top: 4px;
      }
    }
  }

  .pagination-wrapper {
    padding: 16px 0;
    border-top: 1px solid #e4e7ed;
    margin-top: 8px;

    .pagination {
      display: flex;
      justify-content: flex-end;
    }
  }

  .detail-body {
    flex: 1;
    overflow-y: auto;
  }

  .timeline-scroll {
    max-height: calc(100vh - 340px);
    overflow-y: auto;
    padding-right: 8px;
  }

  .device-section, .image-section, .action-section {
    margin-top: 24px;
    padding-top: 24px;
    border-top: 1px solid #e4e7ed;

    .section-title {
      font-size: 15px;
      font-weight: bold;
      margin-bottom: 16px;
      color: #303133;
    }
  }

  .image-list {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
  }

  .image-group + .image-group {
    margin-top: 16px;
  }

  .image-label {
    display: block;
    margin-bottom: 8px;
    color: #606266;
    font-size: 13px;
  }

  .action-buttons {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;

    .el-button {
      min-width: 100px;
    }
  }

  /* 新增工单：设备信息卡（需求 5.2.4.4.1） */
  .device-info-card {
    width: 100%;
    background: #f8fafc;
    border-radius: 10px;
    padding: 12px;
    border: 1px solid #e4eaf1;

    :deep(.el-descriptions__body) {
      background: #fff;
    }
  }

  .timeline-content {
    .timestamp {
      font-size: 12px;
      color: #909399;
      margin-bottom: 6px;
    }

    .operator-info {
      font-size: 14px;
      margin-bottom: 8px;

      .operator-name {
        font-weight: bold;
        color: #303133;
      }

      .oper-type {
        color: #909399;
      }
    }

    .oper-desc {
      font-size: 14px;
      color: #606266;
    }
  }
}
</style>
