<script setup>
import { nextTick, onBeforeUnmount, onMounted, ref, getCurrentInstance, watch } from 'vue'
import { getConfigKey } from '@/api/system/config'
import { ArrowDown, Folder, Refresh, Search } from '@element-plus/icons-vue'

const mapEl = ref(null)

let map = null

const districtPanelOpen = ref(false)
const districtScope = ref(null)
const districtFilterText = ref('')
const districtTreeRef = ref(null)

const editingEnabled = ref(false)
const surveyFirstEnabled = ref(true)
const parcelQuery = ref('')
const helpCount = ref(446)
const referenceFileInputRef = ref(null)
const layerPanelOpen = ref(false)
const layerVillageBoundaryEnabled = ref(true)
const layerGroupBoundaryEnabled = ref(false)
const layerAltitudeEnabled = ref(true)
const layerParcelEnabled = ref(true)
const layerUploadEnabled = ref(true)
const layerAnalysisParcelEnabled = ref(false)
const taskPanelOpen = ref(false)
const taskKeyword = ref('')
const taskStatus = ref('approved')
const feedbackPanelOpen = ref(false)
const feedbackKeyword = ref('')
const parcelAttrPanelOpen = ref(false)
const helpPanelOpen = ref(false)
const helpStatus = ref('unhandled')
const helpType = ref('')
const helpKeyword = ref('')
const helpList = ref([
  {
    id: '430381110247210007',
    name: '丁建强',
    status: 'unhandled',
    time: '2025-12-19 16:00:39',
    desc: '电话更改'
  },
  {
    id: '4303811107208240023',
    name: '王建南',
    status: 'unhandled',
    time: '2025-11-19 16:12:08',
    desc: '减少人员'
  },
  {
    id: '4303811107218020030',
    name: '傅新德',
    status: 'unhandled',
    time: '2025-11-19 11:54:48',
    desc: '姓名的“傅”应该可以是“付”字,请退回'
  },
  {
    id: '4303811107218060047',
    name: '邓国云',
    status: 'unhandled',
    time: '2025-11-19 11:41:09',
    desc: '面积登记错误,彭罗秀的需要转让给邓国云'
  },
  {
    id: '4303811107218060051',
    name: '彭罗秀',
    status: 'unhandled',
    time: '2025-11-19 10:55:26',
    desc: '请核对承包方身份证号码'
  }
])
const helpStatusOptions = [
  { label: '未处理', value: 'unhandled' },
  { label: '已处理', value: 'handled' }
]
const helpTypeOptions = [
  { label: '帮助类型', value: '' },
  { label: '电话更改', value: 'phone' },
  { label: '人员变更', value: 'member' },
  { label: '面积核对', value: 'area' }
]
const parcelAttrForm = ref({
  parcelName: '',
  parcelCode: '',
  ownershipType: 'collective',
  landCategory: 'other_collective',
  useType: 'paddy',
  landGrade: 'grade_1',
  landPurpose: 'planting',
  basicFarmland: 'yes',
  contractArea: '',
  measuredArea: '',
  eastTo: '',
  westTo: '',
  southTo: '',
  northTo: '',
  boundaryPersonName: '',
  contractorName: '',
  remark: ''
})
const ownershipTypeOptions = [
  { label: '集体土地所有权', value: 'collective' },
  { label: '国有土地所有权', value: 'state' }
]
const landCategoryOptions = [
  { label: '其它集体土地', value: 'other_collective' },
  { label: '耕地', value: 'cultivated' },
  { label: '林地', value: 'forest' }
]
const useTypeOptions = [
  { label: '水田', value: 'paddy' },
  { label: '旱地', value: 'dry' }
]
const landGradeOptions = [
  { label: '一等地', value: 'grade_1' },
  { label: '二等地', value: 'grade_2' },
  { label: '三等地', value: 'grade_3' }
]
const landPurposeOptions = [
  { label: '种植业', value: 'planting' },
  { label: '养殖业', value: 'breeding' }
]
const yesNoOptions = [
  { label: '是', value: 'yes' },
  { label: '否', value: 'no' }
]
const taskList = ref([
  {
    id: '430381110226120019',
    titlePrefix: '[1/2]',
    title: '王桂花',
    members: 1,
    parcels: 4,
    area: 2.34,
    reporter: '陈菊珍',
    reportTime: '2025-06-23 15:41:29',
    desc: '修改户主信息,转让所得(或共同承包)1块地'
  },
  {
    id: '430381110226120046',
    titlePrefix: '[2/2]',
    title: '陈国福',
    members: 5,
    parcels: 10,
    area: 4.67,
    reporter: '陈国福',
    reportTime: '2025-05-14 14:54:51',
    desc: '新增3名家庭成员,修改户主信息,新增9块地,转让所得(或共同承包)1块地'
  }
])

const { proxy } = getCurrentInstance()

const districtTreeData = [
  {
    id: '106',
    label: '106安天镇',
    children: []
  },
  {
    id: '107',
    label: '107翻江镇',
    children: []
  },
  {
    id: '110',
    label: '110月山镇',
    children: [
      {
        id: '202',
        label: '202蔡虫山村',
        status: 'error',
        children: []
      },
      { id: '210', label: '210白龙村', status: 'error', children: [] },
      { id: '215', label: '215马龙村', status: 'error', children: [] },
      { id: '216', label: '216田心村', status: 'error', children: [] },
      { id: '218', label: '218龙洞村', status: 'error', children: [] },
      {
        id: '226',
        label: '226红日村',
        status: 'error',
        children: [
          {
            id: '226-0001',
            label: '[0001] 防止其它名称段误覆盖',
            status: 'pending',
            children: []
          },
          { id: '226-03', label: '[03] 六房台组', status: 'pending', children: [] },
          { id: '226-06', label: '[06] 潘家冲组', status: 'pending', children: [] },
          { id: '226-07', label: '[07] 石头冲组', status: 'pending', children: [] },
          { id: '226-11', label: '[11] 新塘冲组', status: 'pending', children: [] },
          {
            id: '226-12',
            label: '[12] 杨龙塘组',
            status: 'pending',
            children: [
              { id: '226-12-0001', label: '[0001] 彭建华', status: 'done', children: [] },
              { id: '226-12-0002', label: '[0002] 冯江荣', status: 'done', children: [] },
              { id: '226-12-0003', label: '[0003] 冯春林', status: 'done', children: [] },
              { id: '226-12-0004', label: '[0004] 刘罗军', status: 'done', children: [] },
              { id: '226-12-0005', label: '[0005] 刘如意', status: 'done', children: [] },
              { id: '226-12-0007', label: '[0007] 冯江华', status: 'done', children: [] }
            ]
          }
        ]
      }
    ]
  }
]

const districtTreeProps = {
  children: 'children',
  label: 'label'
}

function toggleDistrictPanel() {
  districtPanelOpen.value = !districtPanelOpen.value
}

function toggleLayerPanel() {
  layerPanelOpen.value = !layerPanelOpen.value
}

function toggleTaskPanel() {
  feedbackPanelOpen.value = false
  parcelAttrPanelOpen.value = false
  helpPanelOpen.value = false
  taskPanelOpen.value = !taskPanelOpen.value
}

function toggleFeedbackPanel() {
  taskPanelOpen.value = false
  parcelAttrPanelOpen.value = false
  helpPanelOpen.value = false
  feedbackPanelOpen.value = !feedbackPanelOpen.value
}

function toggleParcelAttrPanel() {
  taskPanelOpen.value = false
  feedbackPanelOpen.value = false
  helpPanelOpen.value = false
  parcelAttrPanelOpen.value = !parcelAttrPanelOpen.value
}

function toggleHelpPanel() {
  taskPanelOpen.value = false
  feedbackPanelOpen.value = false
  parcelAttrPanelOpen.value = false
  helpPanelOpen.value = !helpPanelOpen.value
}

function getNodeTextClass(data) {
  if (data?.status === 'done') return 'text-green-600'
  if (data?.status === 'error') return 'text-fuchsia-600'
  if (data?.status === 'missing') return 'text-blue-600'
  if (data?.status === 'pending') return 'text-amber-600'
  if (data?.status === 'undone') return 'text-red-600'
  return 'text-gray-700'
}

function filterDistrictNode(value, data) {
  if (!value) return true
  return String(data?.label || '').includes(value)
}

watch(districtFilterText, (value) => {
  districtTreeRef.value?.filter?.(value)
})

function waitForTdtApi(timeoutMs = 15000) {
  return new Promise((resolve, reject) => {
    const start = Date.now()
    const timer = window.setInterval(() => {
      if (window?.T?.Map) {
        window.clearInterval(timer)
        resolve()
        return
      }
      if (Date.now() - start > timeoutMs) {
        window.clearInterval(timer)
        reject(new Error('tianditu api load timeout'))
      }
    }, 50)
  })
}

function loadScriptOnce(id, src) {
  if (window?.T?.Map) return Promise.resolve()

  const existing = document.getElementById(id)
  if (existing) return waitForTdtApi()

  return new Promise((resolve, reject) => {
    const script = document.createElement('script')
    script.id = id
    script.src = src
    script.async = true
    script.onload = () => resolve()
    script.onerror = () => reject(new Error('tianditu api load error'))
    document.head.appendChild(script)
  }).then(() => waitForTdtApi())
}

async function resolveTk() {
  const tkFromEnv = import.meta.env?.VITE_TDT_TOKEN
  if (tkFromEnv && tkFromEnv.trim()) return tkFromEnv.trim()

  const keys = [
    'tdt.tk',
    'tdt.token',
    'tianditu.tk',
    'tianditu.token',
    'sys.tdt.tk',
    'sys.tdt.token',
    'sys.tianditu.tk',
    'sys.tianditu.token',
    'map.tdt.tk',
    'map.tianditu.tk'
  ]

  for (const key of keys) {
    try {
      const res = await getConfigKey(key)
      const value = typeof res?.msg === 'string' ? res.msg.trim() : ''
      if (value) return value
    } catch {}
  }

  return ''
}

function setSatelliteMapType(T) {
  const mapTypes = [
    window.TMAP_SATELLITE_MAP,
    window.TMAP_HYBRID_MAP,
    T?.MAP_TYPE_SATELLITE,
    T?.MAP_TYPE_HYBRID,
    T?.SATELLITE_MAP,
    T?.HYBRID_MAP
  ].filter(Boolean)

  for (const type of mapTypes) {
    try {
      map?.setMapType?.(type)
      return
    } catch {}
  }
}

function clickAction(label) {
  proxy?.$modal?.msg?.(label)
}

function refreshTasks() {
  proxy?.$modal?.msg?.('刷新任务列表')
}

function confirmTaskChanges() {
  proxy?.$modal?.msg?.('确认修改')
}

function refreshFeedback() {
  proxy?.$modal?.msg?.('刷新公示反馈')
}

function searchFeedback() {
  proxy?.$modal?.msg?.(`搜索公示反馈：${feedbackKeyword.value || ''}`)
}

function saveParcelAttr() {
  proxy?.$modal?.msg?.('保存地块属性')
}

function updateParcelAttr() {
  proxy?.$modal?.msg?.('修改地块')
}

function deleteParcelAttr() {
  proxy?.$modal?.msg?.('删除地块')
}

function setParcelContractor() {
  proxy?.$modal?.msg?.('设置承包方')
}

function refreshParcelLayer() {
  proxy?.$modal?.msg?.('刷新地块图层')
}

function refreshParcelContractorNames() {
  proxy?.$modal?.msg?.('刷新地块承包方名称')
}

function refreshDataAndSetContractor() {
  proxy?.$modal?.msg?.('刷新数据设置承包方')
}

function locateHelpHousehold(item) {
  proxy?.$modal?.msg?.(`定位农户：${item?.name || ''}`)
}

function locateHelpParcel(item) {
  proxy?.$modal?.msg?.(`定位地块：${item?.name || ''}`)
}

function helpReturn(item) {
  proxy?.$modal?.msg?.(`退回：${item?.name || ''}`)
}

function helpInternalReject(item) {
  proxy?.$modal?.msg?.(`内业驳回：${item?.name || ''}`)
}

function searchParcel() {
  const value = parcelQuery.value?.trim()
  if (!value) return
  clickAction(`搜索：${value}`)
}

function chooseReferenceFile() {
  referenceFileInputRef.value?.click?.()
}

function handleReferenceFileChange(e) {
  const file = e?.target?.files?.[0]
  if (!file) return
  proxy?.$modal?.msg?.(`已选择文件：${file.name}`)
  e.target.value = ''
}

async function initTdtMap() {
  const tk = await resolveTk()
  const src = `https://api.tianditu.gov.cn/api?v=4.0${tk ? `&tk=${encodeURIComponent(tk)}` : ''}`
  await loadScriptOnce('tdt-jsapi-v4', src)
  await nextTick()

  const T = window.T
  if (!T?.Map || !mapEl.value) return

  const center = new T.LngLat(112.938814, 28.228209)
  map = new T.Map(mapEl.value)
  setSatelliteMapType(T)
  map.centerAndZoom(center, 12)
  map.enableScrollWheelZoom?.()
  map.addOverLay(new T.Marker(center))
}

onMounted(() => {
  initTdtMap()
})

onBeforeUnmount(() => {
  try {
    map?.clearOverLays?.()
    map?.destroy?.()
  } catch {}
  map = null
})
</script>

<template>
  <div class="tdt-page">
    <div
      class="h-10 w-full flex items-center gap-2 bg-white/95 backdrop-blur px-5 border-b border-gray-200 overflow-x-auto shadow-sm transition-shadow"
    >
      <el-tooltip
        placement="bottom-start"
        effect="light"
        popper-class="map-tooltip"
        :show-after="150"
        :hide-after="0"
      >
        <template #content>
          <div class="text-sm text-gray-700">
            <div class="mb-2">承包方名称颜色 对应 内业处理状态 说明：</div>
            <div class="space-y-1">
              <div class="flex items-center gap-2">
                <span class="h-2 w-2 rounded-full bg-green-600"></span>
                <span>已完成</span>
              </div>
              <div class="flex items-center gap-2">
                <span class="h-2 w-2 rounded-full bg-fuchsia-600"></span>
                <span>未完成资料有误</span>
              </div>
              <div class="flex items-center gap-2">
                <span class="h-2 w-2 rounded-full bg-blue-600"></span>
                <span>未完成资料缺失</span>
              </div>
              <div class="flex items-center gap-2">
                <span class="h-2 w-2 rounded-full bg-amber-600"></span>
                <span>未完成待验收</span>
              </div>
              <div class="flex items-center gap-2">
                <span class="h-2 w-2 rounded-full bg-red-600"></span>
                <span>未完成</span>
              </div>
            </div>
          </div>
        </template>
        <el-button class="toolbar-item" size="small" text bg @click="toggleDistrictPanel">行政区树</el-button>
      </el-tooltip>
      <div class="h-5 w-px bg-gray-200"></div>
      <el-tooltip
        placement="bottom-start"
        effect="light"
        popper-class="map-tooltip"
        :show-after="150"
        :hide-after="0"
      >
        <template #content>
          <div class="text-sm text-gray-700">
            <div class="mb-2">村名颜色 对应 网签处理状态 说明：</div>
            <div class="space-y-1">
              <div class="flex items-center gap-2">
                <span class="h-2 w-2 rounded-full bg-green-600"></span>
                <span>入网签平台完成</span>
              </div>
              <div class="flex items-center gap-2">
                <span class="h-2 w-2 rounded-full bg-blue-600"></span>
                <span>入网签平台中</span>
              </div>
              <div class="flex items-center gap-2">
                <span class="h-2 w-2 rounded-full bg-amber-600"></span>
                <span>公示中</span>
              </div>
              <div class="flex items-center gap-2">
                <span class="h-2 w-2 rounded-full bg-red-600"></span>
                <span>摸底中</span>
              </div>
            </div>
          </div>
        </template>
        <el-button class="toolbar-item" size="small" text bg @click="chooseReferenceFile">加载参考数据</el-button>
      </el-tooltip>
      <input
        ref="referenceFileInputRef"
        class="hidden"
        type="file"
        @change="handleReferenceFileChange"
      />
      <div class="h-5 w-px bg-gray-200"></div>
      <el-button class="toolbar-item" size="small" text bg @click="toggleLayerPanel">
        图层管理
        <el-icon class="ml-1 transition-transform" :class="layerPanelOpen ? 'rotate-180' : ''">
          <ArrowDown />
        </el-icon>
      </el-button>

      <div class="ml-2 h-5 w-px bg-gray-200"></div>

      <div class="flex items-center gap-2">
        <el-switch v-model="editingEnabled" />
        <span class="text-sm text-gray-600 select-none">
          {{ editingEnabled ? '开启编辑' : '关闭编辑' }}
        </span>
      </div>

      <div class="h-5 w-px bg-gray-200"></div>

      <div class="flex items-center gap-2">
        <el-switch v-model="surveyFirstEnabled" />
        <span class="text-sm text-gray-600 select-none">标识调查初开启</span>
      </div>

      <div class="h-5 w-px bg-gray-200"></div>

      <el-input
        v-model="parcelQuery"
        size="small"
        clearable
        placeholder="输入地块编码或图斑"
        class="!w-64"
        @keyup.enter="searchParcel"
      />

      <div class="flex-1"></div>

      <el-button class="toolbar-item" size="small" text bg @click="toggleTaskPanel">变更任务</el-button>
      <el-button class="toolbar-item" size="small" text bg @click="toggleFeedbackPanel">公示反馈</el-button>
      <el-button class="toolbar-item" size="small" text bg @click="toggleParcelAttrPanel">地块属性</el-button>
      <div class="h-5 w-px bg-gray-200"></div>
      <el-badge :value="helpCount" :max="999">
        <el-button class="toolbar-item" size="small" text bg @click="toggleHelpPanel">帮助清单</el-button>
      </el-badge>
    </div>
    <div v-show="helpPanelOpen" class="help-panel">
      <el-card shadow="always" class="help-card">
        <div class="help-toolbar">
          <el-select v-model="helpStatus" size="small" class="!w-28">
            <el-option v-for="opt in helpStatusOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
          </el-select>
          <el-select v-model="helpType" size="small" class="!w-28">
            <el-option v-for="opt in helpTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
          </el-select>
          <el-input v-model="helpKeyword" size="small" clearable placeholder="名称或编码" class="flex-1">
            <template #suffix>
              <el-icon class="text-gray-500"><Search /></el-icon>
            </template>
          </el-input>
        </div>
        <div class="help-body">
          <el-scrollbar class="h-full">
            <div class="p-3 space-y-3">
              <div v-for="(item, idx) in helpList" :key="item.id" class="help-item">
                <div class="flex items-start justify-between gap-3">
                  <div class="min-w-0">
                    <div class="text-sm text-gray-800">
                      <span class="mr-1">{{ idx + 1 }}.</span>
                      <span class="font-medium">{{ item.name }}</span>
                      <span class="text-gray-500">[{{ item.id }}]</span>
                    </div>
                    <div class="mt-2 flex flex-wrap gap-2">
                      <el-button type="success" size="small" @click="locateHelpHousehold(item)">定位农户</el-button>
                      <el-button type="success" size="small" @click="locateHelpParcel(item)">定位地块</el-button>
                    </div>
                    <div class="mt-2 flex flex-wrap items-center gap-2 text-xs">
                      <span class="text-gray-700">退回审批</span>
                      <el-button type="primary" size="small" @click="helpReturn(item)">退回</el-button>
                      <el-button type="warning" size="small" @click="helpInternalReject(item)">内业驳回</el-button>
                      <span class="ml-auto text-gray-600">{{ item.time }}</span>
                    </div>
                    <div class="mt-2 text-sm text-gray-700 leading-5">
                      {{ item.desc }}
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </el-scrollbar>
        </div>
        <div class="help-footer">
          <el-pagination
            small
            background
            layout="prev, pager, next, jumper, total"
            :total="helpCount"
            :page-size="10"
          />
        </div>
      </el-card>
    </div>
    <div v-show="parcelAttrPanelOpen" class="parcel-attr-panel">
      <el-card shadow="always" class="parcel-attr-card">
        <div class="parcel-attr-toolbar">
          <div class="parcel-attr-title">地块属性</div>
        </div>
        <div class="parcel-attr-body">
          <el-scrollbar class="h-full">
            <div class="p-3">
              <el-form :model="parcelAttrForm" label-width="92px" class="parcel-attr-form">
                <el-form-item label="地块名称">
                  <el-input v-model="parcelAttrForm.parcelName" size="small" />
                </el-form-item>
                <el-form-item label="地块代码">
                  <el-input v-model="parcelAttrForm.parcelCode" size="small" />
                </el-form-item>
                <el-form-item label="所有权性质">
                  <el-select v-model="parcelAttrForm.ownershipType" size="small" class="w-full">
                    <el-option v-for="opt in ownershipTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
                  </el-select>
                </el-form-item>
                <el-form-item label="地块类别">
                  <el-select v-model="parcelAttrForm.landCategory" size="small" class="w-full">
                    <el-option v-for="opt in landCategoryOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
                  </el-select>
                </el-form-item>
                <el-form-item label="利用类型">
                  <el-select v-model="parcelAttrForm.useType" size="small" class="w-full">
                    <el-option v-for="opt in useTypeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
                  </el-select>
                </el-form-item>
                <el-form-item label="地方等级">
                  <el-select v-model="parcelAttrForm.landGrade" size="small" class="w-full">
                    <el-option v-for="opt in landGradeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
                  </el-select>
                </el-form-item>
                <el-form-item label="土地用途">
                  <el-select v-model="parcelAttrForm.landPurpose" size="small" class="w-full">
                    <el-option v-for="opt in landPurposeOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
                  </el-select>
                </el-form-item>
                <el-form-item label="基本农田">
                  <el-select v-model="parcelAttrForm.basicFarmland" size="small" class="w-full">
                    <el-option v-for="opt in yesNoOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
                  </el-select>
                </el-form-item>
                <el-form-item label="合同面积">
                  <el-input v-model="parcelAttrForm.contractArea" size="small" />
                </el-form-item>
                <el-form-item label="实测面积亩">
                  <el-input v-model="parcelAttrForm.measuredArea" size="small" />
                </el-form-item>
                <el-form-item label="地块东至">
                  <el-input v-model="parcelAttrForm.eastTo" size="small" />
                </el-form-item>
                <el-form-item label="地块西至">
                  <el-input v-model="parcelAttrForm.westTo" size="small" />
                </el-form-item>
                <el-form-item label="地块南至">
                  <el-input v-model="parcelAttrForm.southTo" size="small" />
                </el-form-item>
                <el-form-item label="地块北至">
                  <el-input v-model="parcelAttrForm.northTo" size="small" />
                </el-form-item>
                <el-form-item label="指界人姓名">
                  <el-input v-model="parcelAttrForm.boundaryPersonName" size="small" />
                </el-form-item>
                <el-form-item label="承包方名称">
                  <el-input v-model="parcelAttrForm.contractorName" size="small" />
                </el-form-item>
                <el-form-item label="备注信息">
                  <el-input v-model="parcelAttrForm.remark" size="small" />
                </el-form-item>
              </el-form>
            </div>
          </el-scrollbar>
        </div>
        <div class="parcel-attr-footer">
          <div class="flex items-center gap-2 flex-wrap">
            <el-button type="primary" size="small" @click="updateParcelAttr">修改地块</el-button>
            <el-button type="primary" size="small" @click="saveParcelAttr">保存</el-button>
            <el-button type="primary" size="small" @click="deleteParcelAttr">删除地块</el-button>
            <el-button type="primary" size="small" @click="setParcelContractor">设置承包方</el-button>
          </div>
          <div class="mt-2 flex items-center gap-2 flex-wrap">
            <el-button type="warning" size="small" @click="refreshParcelLayer">刷新地块图层</el-button>
            <el-button type="warning" size="small" @click="refreshParcelContractorNames">刷新地块承包方名称</el-button>
            <el-button type="warning" size="small" @click="refreshDataAndSetContractor">刷新数据设置承包方</el-button>
          </div>
        </div>
      </el-card>
    </div>
    <div v-show="feedbackPanelOpen" class="feedback-panel">
      <el-card shadow="always" class="feedback-card">
        <div class="feedback-toolbar">
          <el-button size="small" class="feedback-icon-btn" @click="refreshFeedback">
            <el-icon><Refresh /></el-icon>
          </el-button>
          <el-input
            v-model="feedbackKeyword"
            size="small"
            clearable
            placeholder="请输入姓名或身份证号"
            class="flex-1"
            @keyup.enter="searchFeedback"
          />
          <el-button size="small" class="feedback-icon-btn" @click="searchFeedback">
            <el-icon><Search /></el-icon>
          </el-button>
        </div>
        <div class="feedback-body"></div>
      </el-card>
    </div>
    <div v-show="taskPanelOpen" class="task-panel">
      <el-card shadow="always" class="task-card">
        <div class="task-header">
          <div class="flex items-center gap-2">
            <span class="text-sm font-medium text-gray-800">变更任务</span>
            <span class="text-xs text-gray-500">月山镇红日村杨龙坑组</span>
          </div>
          <el-button type="primary" size="small" @click="confirmTaskChanges">确认修改</el-button>
        </div>
        <div class="task-toolbar">
          <el-input
            v-model="taskKeyword"
            size="small"
            clearable
            placeholder="请输入姓名或身份证号"
            class="flex-1"
          />
          <el-button size="small" class="task-icon-btn" @click="clickAction('搜索')">
            <el-icon><Search /></el-icon>
          </el-button>
          <el-button size="small" class="task-icon-btn" @click="refreshTasks">
            <el-icon><Refresh /></el-icon>
          </el-button>
          <el-select v-model="taskStatus" size="small" class="!w-24">
            <el-option label="已审核" value="approved" />
            <el-option label="待处理" value="pending" />
          </el-select>
        </div>
        <div class="task-body">
          <el-scrollbar class="h-full">
            <div class="p-3 space-y-3">
              <div v-for="item in taskList" :key="item.id" class="task-item">
                <div class="flex items-center justify-between gap-3">
                  <div class="min-w-0 flex items-center gap-2">
                    <span class="text-red-600 text-sm">{{ item.titlePrefix }}</span>
                    <span class="text-red-600 text-sm truncate">{{ item.title }} {{ item.id }}</span>
                  </div>
                  <div class="task-warn">!</div>
                </div>
                <div class="grid grid-cols-3 gap-2 text-xs text-gray-600">
                  <div class="flex items-center justify-between rounded border border-gray-200 px-2 py-1">
                    <span>成员数</span>
                    <span class="text-gray-800">{{ item.members }}</span>
                  </div>
                  <div class="flex items-center justify-between rounded border border-gray-200 px-2 py-1">
                    <span>地块数</span>
                    <span class="text-gray-800">{{ item.parcels }}</span>
                  </div>
                  <div class="flex items-center justify-between rounded border border-gray-200 px-2 py-1">
                    <span>确权面积</span>
                    <span class="text-gray-800">{{ item.area }}</span>
                  </div>
                </div>
                <div class="flex items-center justify-between text-xs">
                  <span class="text-fuchsia-600">上报人：{{ item.reporter }}</span>
                  <span class="text-fuchsia-600">上报时间：{{ item.reportTime }}</span>
                </div>
                <div class="flex flex-wrap gap-2">
                  <el-button type="primary" size="small" @click="clickAction('变更记录列表')">变更记录列表</el-button>
                  <el-button type="primary" size="small" @click="clickAction('详情')">详情</el-button>
                  <el-button type="primary" size="small" @click="clickAction('附件')">附件</el-button>
                  <el-button type="primary" size="small" @click="clickAction('设置处理状态')">设置处理状态</el-button>
                </div>
                <div class="text-xs text-gray-700 leading-5">
                  {{ item.desc }}
                </div>
                <div class="pt-2">
                  <el-button type="primary" size="small" @click="confirmTaskChanges">确认修改</el-button>
                </div>
              </div>
            </div>
          </el-scrollbar>
        </div>
        <div class="task-footer">
          <el-pagination
            small
            background
            layout="prev, pager, next, total"
            :total="taskList.length"
            :page-size="10"
          />
        </div>
      </el-card>
    </div>
    <div v-show="layerPanelOpen" class="layer-panel">
      <el-card shadow="always" class="layer-card">
        <div class="p-3 space-y-3">
          <div class="flex items-center justify-between gap-6">
            <span class="text-sm text-gray-700 select-none">村界线</span>
            <el-switch v-model="layerVillageBoundaryEnabled" size="small" />
          </div>
          <div class="flex items-center justify-between gap-6">
            <span class="text-sm text-gray-700 select-none">组界线</span>
            <el-switch v-model="layerGroupBoundaryEnabled" size="small" />
          </div>
          <div class="flex items-center justify-between gap-6">
            <span class="text-sm text-gray-700 select-none">高亮图层</span>
            <el-switch v-model="layerAltitudeEnabled" size="small" />
          </div>
          <div class="flex items-center justify-between gap-6">
            <span class="text-sm text-gray-700 select-none">地块图层</span>
            <el-switch v-model="layerParcelEnabled" size="small" />
          </div>
          <div class="flex items-center justify-between gap-6">
            <span class="text-sm text-gray-700 select-none">上传图层</span>
            <el-switch v-model="layerUploadEnabled" size="small" />
          </div>
          <div class="flex items-center justify-between gap-6">
            <span class="text-sm text-gray-700 select-none">分析地块图层</span>
            <el-switch v-model="layerAnalysisParcelEnabled" size="small" />
          </div>
        </div>
      </el-card>
    </div>
    <div v-show="districtPanelOpen" class="district-panel">
      <el-card shadow="always" class="district-card">
        <div class="p-2 pb-0">
          <el-select
            v-model="districtScope"
            size="small"
            clearable
            placeholder="选中的节点中搜索"
            class="w-full"
          >
            <el-option label="当前节点" value="current" />
            <el-option label="全部" value="all" />
          </el-select>
          <div class="mt-2">
            <el-input
              v-model="districtFilterText"
              size="small"
              clearable
              placeholder="搜索"
            />
          </div>
        </div>
        <div class="p-2 pt-2">
          <el-scrollbar height="560px">
            <el-tree
              ref="districtTreeRef"
              :data="districtTreeData"
              node-key="id"
              :props="districtTreeProps"
              :filter-node-method="filterDistrictNode"
              :default-expand-all="true"
              highlight-current
              :expand-on-click-node="false"
            >
              <template #default="{ data }">
                <span class="flex items-center gap-2">
                  <el-icon class="text-gray-500">
                    <Folder />
                  </el-icon>
                  <span :class="getNodeTextClass(data)">{{ data.label }}</span>
                </span>
              </template>
            </el-tree>
          </el-scrollbar>
        </div>
      </el-card>
    </div>
    <div ref="mapEl" class="tdt-map"></div>
  </div>
</template>

<style scoped lang="scss">
.tdt-page {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.tdt-map {
  width: 100%;
  flex: 1;
}

:deep(.toolbar-item.el-button) {
  transition: background-color 150ms ease, color 150ms ease, transform 150ms ease;
}

:deep(.toolbar-item.el-button:hover) {
  transform: translateY(-1px);
}

.district-panel {
  position: absolute;
  top: 40px;
  left: 20px;
  z-index: 999;
  width: 360px;
}

.layer-panel {
  position: absolute;
  top: 40px;
  left: 160px;
  z-index: 999;
  width: 240px;
}

.task-panel {
  position: absolute;
  top: 40px;
  right: 20px;
  bottom: 12px;
  z-index: 999;
  width: 440px;
}

.help-panel {
  position: absolute;
  top: 40px;
  right: 20px;
  bottom: 12px;
  z-index: 999;
  width: 520px;
}

:deep(.help-card.el-card) {
  height: 100%;
  border-radius: 2px;
}

:deep(.help-card .el-card__body) {
  padding: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.help-toolbar {
  padding: 10px 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid #e5e7eb;
  background: #fff;
}

.help-body {
  flex: 1;
  min-height: 0;
  background: #fff;
}

.help-footer {
  padding: 10px 12px;
  border-top: 1px solid #e5e7eb;
  background: #fff;
}

.help-item {
  border: 1px solid #e5e7eb;
  border-radius: 2px;
  background: #fff;
  padding: 12px;
}

.parcel-attr-panel {
  position: absolute;
  top: 40px;
  right: 20px;
  bottom: 12px;
  z-index: 999;
  width: 440px;
}

:deep(.parcel-attr-card.el-card) {
  height: 100%;
  border-radius: 2px;
}

:deep(.parcel-attr-card .el-card__body) {
  padding: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.parcel-attr-toolbar {
  height: 40px;
  padding: 0 12px;
  display: flex;
  align-items: center;
  border-bottom: 1px solid #e5e7eb;
  background: #fff;
}

.parcel-attr-title {
  font-size: 14px;
  color: #111827;
  font-weight: 600;
}

.parcel-attr-body {
  flex: 1;
  min-height: 0;
  background: #fff;
}

.parcel-attr-footer {
  padding: 10px 12px;
  border-top: 1px solid #e5e7eb;
  background: #fff;
}

:deep(.parcel-attr-form .el-form-item) {
  margin-bottom: 10px;
}

:deep(.parcel-attr-form .el-form-item__label) {
  color: #111827;
}

:deep(.feedback-card.el-card) {
  height: 100%;
  border-radius: 2px;
}

:deep(.feedback-card .el-card__body) {
  padding: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.feedback-panel {
  position: absolute;
  top: 40px;
  right: 20px;
  bottom: 12px;
  z-index: 999;
  width: 440px;
}

.feedback-toolbar {
  padding: 10px 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid #e5e7eb;
  background: #fff;
}

.feedback-icon-btn {
  padding: 0 8px;
}

.feedback-body {
  flex: 1;
  min-height: 0;
  background: #fff;
}

:deep(.task-card.el-card) {
  height: 100%;
  border-radius: 2px;
}

:deep(.task-card .el-card__body) {
  padding: 0;
  height: 100%;
  display: flex;
  flex-direction: column;
}

.task-header {
  height: 40px;
  padding: 0 12px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  border-bottom: 1px solid #e5e7eb;
  background: #fff;
}

.task-toolbar {
  padding: 10px 12px;
  display: flex;
  align-items: center;
  gap: 8px;
  border-bottom: 1px solid #e5e7eb;
  background: #fff;
}

.task-body {
  flex: 1;
  min-height: 0;
  background: #fff;
}

.task-footer {
  padding: 10px 12px;
  border-top: 1px solid #e5e7eb;
  background: #fff;
}

.task-item {
  border: 1px solid #e5e7eb;
  border-radius: 2px;
  background: #fff;
  padding: 12px;
}

.task-warn {
  width: 18px;
  height: 18px;
  border-radius: 999px;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 12px;
  line-height: 1;
  color: #fff;
  background: #ef4444;
  flex: none;
}

.task-icon-btn {
  padding: 0 8px;
}

:deep(.layer-card.el-card) {
  border-radius: 2px;
}

:deep(.layer-card .el-card__body) {
  padding: 0;
}

:deep(.district-card.el-card) {
  border-radius: 2px;
}

:deep(.district-card .el-card__body) {
  padding: 0;
}

:global(.map-tooltip) {
  background: #fff !important;
  border: 1px solid #e5e7eb !important;
  color: #374151 !important;
  box-shadow: 0 12px 32px rgba(0, 0, 0, 0.18) !important;
}

:global(.map-tooltip .el-popper__arrow::before) {
  background: #fff !important;
  border: 1px solid #e5e7eb !important;
}
</style>
