<template>
  <div class="content" v-loading="Status.fullLoading">
    <div class="percent100" v-show="!Status.showEdit && !Status.showDevice">
      <div class="topTool">
        <div class="button-row">
          <el-button type="primary" @click.stop="ShowEdit(null)"
            ><el-icon><Plus /></el-icon>新增</el-button
          >
          <el-button type="primary" @click.stop="Export()" plain
            ><el-icon><Download /></el-icon>导出</el-button
          >
          <el-button type="danger" plain @click.stop="DropFence(null)"
            ><el-icon><Delete /></el-icon>删除</el-button
          >
        </div>
        <div>
          <el-form :inline="true" :model="queryParams" class="demo-form-inline" @submit.native.prevent>
            <el-form-item label="" style="margin-right: 15px">
              <el-input :suffix-icon="'Search'" v-model="queryParams.name" placeholder="名称" clearable @input="handleQuery" />
            </el-form-item>

            <el-form-item style="margin-right: 0px">
              <el-button type="primary" @click.stop="showSearch">高级筛选</el-button>
            </el-form-item>
          </el-form>
        </div>
      </div>
      <div class="demo-collapse" v-show="Status.showSearch.length > 0">
        <el-collapse accordion v-model="Status.showSearch">
          <el-collapse-item name="1">
            <el-form ref="queryFormRef" :model="queryParams" :inline="true" class="queryFormRef">
              <el-form-item label="围栏类型" prop="areaType">
                <el-select v-model="queryParams.areaType" placeholder="请选择" clearable>
                  <el-option :key="0" :label="'多边形'" :value="0" />
                  <el-option :key="1" :label="'圆形'" :value="1" />
                </el-select>
              </el-form-item>
              <el-form-item label="是否激活" prop="isActive">
                <el-select v-model="queryParams.isActive" clearable placeholder="请选择">
                  <el-option :key="1" :label="'是'" :value="1" />
                  <el-option :key="0" :label="'否'" :value="0" />
                </el-select>
              </el-form-item>
              <el-form-item label="描述" prop="description">
                <el-input v-model="queryParams.description" placeholder="请输入设备名称" clearable />
              </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>
          </el-collapse-item>
        </el-collapse>
      </div>

      <el-table
        ref="grid"
        v-loading="Status.loading"
        border
        :data="List"
        :height="Status.showSearch.length > 0 ? 'calc(100vh - 355px)' : 'calc(100vh - 255px)'"
      >
        <el-table-column type="selection" width="50" align="center" />
        <el-table-column label="围栏名称" align="center" prop="name" />

        <el-table-column label="围栏类型" align="center" prop="areaType">
          <template #default="scope">
            <div>{{ scope.row.areaType == '1' ? '圆形' : '多边形' }}</div>
          </template>
        </el-table-column>
        <el-table-column label="半径(米)" align="center" prop="radius"> </el-table-column>
        <el-table-column label="是否激活" align="center" prop="isActive">
          <template #default="scope">
            <div>{{ scope.row.isActive == '1' ? '是' : '否' }}</div>
          </template>
        </el-table-column>
        <el-table-column label="描述" align="center" prop="description"> </el-table-column>

        <el-table-column label="操作" fixed="right" width="180" class-name="small-padding fixed-width">
          <template #default="scope">
            <el-button link type="primary" @click="ShowEdit(scope.row)">编辑</el-button>
            <el-button link type="primary" @click="ShowDevice(scope.row)">终端管理</el-button>
            <el-button link type="danger" @click="DropFence(scope.row)">删除</el-button>
          </template>
        </el-table-column>
      </el-table>
      <pagination
        v-show="pagin.total > 0"
        v-model:page="queryParams.pageNum"
        v-model:limit="queryParams.pageSize"
        :total="pagin.total"
        @pagination="getList"
      />
    </div>

    <!-- 围栏编辑弹出层 -->
    <div class="editLayer percent100 popLayer" v-show="Status.showEdit" :title="'编辑围栏'">
      <div class="abClose" @click="CloseEdit">
        <el-icon><Close /></el-icon>
      </div>
      <div>
        <el-form :inline="true" :model="cEdit" label-width="auto">
          <el-form-item label="服务id">
            <el-select v-model="cEdit.sid" placeholder="请选择" :disabled="cEdit.id !== null">
              <el-option v-for="(item, index) in services" :key="item.sid" :label="item.sname" :value="item.sid" />
            </el-select>
          </el-form-item>
          <el-form-item label="围栏名称">
            <el-input v-model="cEdit.name" />
          </el-form-item>
          <el-form-item label="围栏类型">
            <el-select v-model="cEdit.areaType" placeholder="请选择" @change="areaTypeChange()">
              <el-option :key="0" :label="'多边形'" :value="0" />
              <el-option :key="1" :label="'圆形'" :value="1" />
            </el-select>
          </el-form-item>

          <el-form-item label="半径(米)">
            <el-input v-model="cEdit.radius" @keydown="refreshOverLayer" :disabled="cEdit.areaType !== 1" />
          </el-form-item>

          <el-form-item label="是否激活">
            <el-select v-model="cEdit.isActive" placeholder="请选择">
              <el-option :key="1" :label="'是'" :value="1" />
              <el-option :key="0" :label="'否'" :value="0" />
            </el-select>
          </el-form-item>

          <el-form-item label="备注">
            <el-input v-model="cEdit.description" />
          </el-form-item>
        </el-form>
      </div>
      <div>
        <el-button type="primary" @click.stop="AddPoint()"
          ><el-icon><Plus /></el-icon>添加点</el-button
        >

        <el-button type="danger" @click.stop="ClearPoint()">
          <el-icon><Delete /></el-icon>清空</el-button
        >
      </div>
      <div class="map" id="map"></div>
      <div class="center footerBtn" style="margin-top: 20px">
        <el-button type="primary" @click="SaveFormData"> 确定 </el-button>
        <el-button type="danger" plain @click="CloseEdit"> 关闭 </el-button>
      </div>
    </div>

    <!-- 终端维护的弹窗 -->
    <div class="percent100 deviceLayer popLayer" v-show="Status.showDevice">
      <div class="abClose" @click="CloseDevice">
        <el-icon><Close /></el-icon>
      </div>

        

      <div class="gridContent">
        <div class="button-row">
          <el-button type="primary" @click="showCheckDevice" class="fleft"
            ><el-icon><Plus /></el-icon>添加</el-button
          >
          <el-button type="danger" @click="DropDevice(null)" class="fleft"
            ><el-icon><Delete /></el-icon>删除</el-button
          >
          <div class="fright">
          <el-form :inline="true">
            <el-form-item label="" prop="checkedKey">
              <el-input v-model="searchFilter.nocheckKey"  placeholder="imei查询" clearable @keyup.enter="SearchDevice" />
            </el-form-item>
            <!-- <el-form-item>
              <el-button type="primary" icon="Search" @click="SearchDevice">搜索</el-button>
            </el-form-item> -->
          </el-form>
        </div>
        <div class="clear"></div>
        </div>

        <el-table ref="gridDevice" v-loading="Status.deviceLoading" border :data="DeviceList" @selection-change="ZDSelectionChange">
          <el-table-column type="selection" width="55" align="center" />
            <!-- <el-table-column label="deviceId" align="center" prop="deviceId" />
            <el-table-column label="id" align="center" prop="id" /> -->
            <el-table-column label="设备类型" align="center" prop="typeName" />
            <el-table-column label="设备名称" align="center" prop="deviceName" />
            <el-table-column label="IMEI" align="center" prop="deviceImei" />
            <el-table-column label="Mac" align="center" prop="deviceMac" />
            <el-table-column label="蓝牙名称" align="center" prop="bluetoothName" />
            <!-- <el-table-column label="高德服务id" align="center" prop="sid" /> -->
            <el-table-column label="高德终端id" align="center" prop="tid" />
            <el-table-column label="高德轨迹id" align="center" prop="trid" />

          <el-table-column label="操作" fixed="right" width="180" class-name="small-padding fixed-width">
            <template #default="scope">
              <el-icon color="#FF0000" @click="DropDevice(scope.row)"><Delete /></el-icon>
            </template>
          </el-table-column>
        </el-table>
        <pagination
          v-show="devicePage.total > 0"
          v-model:page="devicePage.pageNum"
          v-model:limit="devicePage.pageSize"
          :total="devicePage.total"
          @pagination="getList"
        />
      </div>
      <div class="center footerBtn" style="margin-top: 20px">
        <el-button type="danger" plain @click="CloseDevice"> 关闭 </el-button>
      </div>
    </div>

    <el-dialog :title="'选择终端'" :draggable="true" footer-class="dilogFooter" v-model="Status.showCheckDevice" width="65%" append-to-body>
      <div class="deviceContent">
        <div class="filter">
          <el-form :inline="true">
            <el-form-item label="关键字" prop="checkedKey">
              <el-input v-model="searchFilter.checkedKey" placeholder="imei查询" clearable @keyup.enter="searchZD" />
            </el-form-item>
            <el-form-item>
              <el-button type="primary" icon="Search" @click="searchZD">搜索</el-button>
            </el-form-item>
          </el-form>
        </div>

        <div class="checked">
          <el-table
            v-loading="Status.showCheckDeviceLoading"
            border
            :data="checkedDevices"
            @selection-change="handleSelectionChange"
            ref="multipleTableRef"
            row-key="id"
          >
            <el-table-column type="selection" width="55" align="center" />
            <!-- <el-table-column label="deviceId" align="center" prop="deviceId" />
            <el-table-column label="id" align="center" prop="id" /> -->
            <el-table-column label="设备类型" align="center" prop="typeName" />
            <el-table-column label="设备名称" align="center" prop="deviceName" />
            <el-table-column label="IMEI" align="center" prop="deviceImei" />
            <el-table-column label="Mac" align="center" prop="deviceMac" />
            <el-table-column label="蓝牙名称" align="center" prop="bluetoothName" />
            <!-- <el-table-column label="高德服务id" align="center" prop="sid" /> -->
            <el-table-column label="高德终端id" align="center" prop="tid" />
            <el-table-column label="高德轨迹id" align="center" prop="trid" />
          </el-table>

          <pagination
            :total="checkedPageParams.total"
            v-model:page="checkedPageParams.pageNum"
            v-model:limit="checkedPageParams.pageSize"
            @pagination="searchZD"
          />
        </div>
      </div>
      <template #footer>
        <div class="center footerBtn" style="margin-top: 20px">
          <el-button type="primary" @click="SaveChecked"> 确定 </el-button>
          <el-button type="danger" plain @click="CloseCheckDevice"> 关闭 </el-button>
        </div>
      </template>
    </el-dialog>

    <!-- 提示框 -->
    <el-dialog :width="300" :draggable="true" v-model="Status.confirm.Visible" :title="Status.confirm.title" center>
      <span :class="Status.confirm.isWarn" v-html="Status.confirm.text"> </span>
      <template #footer>
        <div class="dialog-footer">
          <el-button type="primary" @click="Status.confirm.OkCallback"> 确定 </el-button>
          <el-button v-show="Status.confirm.showCancel" @click="Status.confirm.cancelCallback">取消</el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import api from '@/api/FenceManager/fence';
import common from '@/utils/common';
import map from '@/api/FenceManager/mapOpt';
import { listService } from '@/api/system/service/api';
const { proxy } = getCurrentInstance() as ComponentInternalInstance;

import { getDevice } from '@/api/system/service/api';

const mapApiKey = import.meta.env.VITE_AMAP_KEY;

var grid = ref(null);

//全局状态控制
var Status = reactive({
  fullLoading: false, //是否显示全屏loading
  loading: false, //是否显示表格区域loading
  confirm: {
    //弹出框的配置
    Visible: false,
    title: '',
    text: '',
    cancelCallback: null,
    OkCallback: null,
    showCancel: true,
    isWarn: false //是否警告色
  },
  showSearch: [], //是否显示高级查询
  showEdit: false, //是否显示编辑弹窗
  showDevice: false, //是否显示终端维护
  deviceLoading: false, //终端查询的loading

  showCheckDevice: false, //是否显示选择终端
  showCheckDeviceLoading: false
});
//查询的条件
var queryParams = reactive({
  name: '',
  areaType: null,
  isActive: null,
  description: '',
  pageNum: 1,
  pageSize: 10
});
var cEdit = reactive({
  id: null,
  name: '',
  description: '',
  areaType: null,
  coordinates: [],
  radius: undefined,
  isActive: null,
  sid: null,
  gfid: null
});
var checkGf = reactive({
  //当前正在操作的数据
  sid: null,
  gfid: null
});
//页码控件数据
var pagin = reactive({
  total: 0
});
var devicePage = reactive({
  total: 0,
  pageNum: 1,
  pageSize: 10
});

var checkedPageParams = reactive({
  pageNum: 1,
  pageSize: 20,
  total: 0
});

//列表数据
var List = ref<any[]>(null);

var services = ref<any[]>(null);

var DeviceList = ref<any[]>(null);

const checkZd = ref<any>([]);

var checkedDevices = ref([]);
const searchFilter = ref({
  nocheckKey: '',
  checkedKey: ''
});

const ids = ref<any>([]);

//显示终端
function ShowDevice(item) {
  Status.showDevice = true;
  checkGf = item;
  SearchDevice();
}
//选择终端

function ZDSelectionChange(selection: any[]) {
  checkZd.value = selection;
}
//查询已选择的终端
function SearchDevice() {
  Status.deviceLoading = true;

  let searchMap = () => {
    let json = {
      key: mapApiKey,
      sid: checkGf.sid,
      gfid: checkGf.gfid
    };
    let formData = [];
    if (json) {
      let keys = Object.keys(json);
      for (let index = 0; index < keys.length; index++) {
        let key = keys[index];
        let encodedKey = encodeURIComponent(key);
        let encodedValue = encodeURIComponent(json[key]);
        formData.push(`${encodedKey}=${encodedValue}`);
      }
    }

    let queryString = formData.join('&'); // 拼接成 key1=value1&key2=value2

    request({
      url: 'https://tsapi.amap.com/v1/track/geofence/terminal/list?' + queryString,
      method: 'GET',
      data: ''
    })
      .then((res) => {
        if (res && res.errcode === 10000) {
          DeviceList.value = res.data.results;
          devicePage.total = res.data.count;
        }
      })
      .finally(() => {
        Status.deviceLoading = false;
      });
  };

  let searchSys = () => {
    let json = {
      fenceId: checkGf.gfid,
      sid: checkGf.sid,
      isTid: true,
       pageNum: devicePage.pageNum,
      pageSize: devicePage.pageSize,
      deviceImei: searchFilter.value.nocheckKey
    };
    api
      .pageTerminal(json)
      .then((res) => {
        if (res && res.code === 200) {
          DeviceList.value = res.rows;
          devicePage.total = res.total;
          return;
        }

        DeviceList.value = [];
        devicePage.total = 0;
      })
      .finally(() => {
        Status.deviceLoading = false;
      });
  };

  searchSys();
}

//关闭终端
function CloseDevice() {
  Status.showDevice = false;
}
//显示选择终端
function showCheckDevice() {
  Status.showCheckDevice = true;
  searchZD();
}

//查询待选择的终端
function searchZD() {
  return new Promise((resolve, reject) => {
    let json = {
      fenceId: checkGf.gfid,
      sid: checkGf.sid,
      isTid: false,
      pageNum: checkedPageParams.pageNum,
      pageSize: checkedPageParams.pageSize,
      deviceImei: searchFilter.value.checkedKey
    };

    api
      .pageTerminal(json)
      .then((res) => {
        if (res.code === 200) {
          checkedDevices.value = res.rows;
          checkedPageParams.total = res.total;
          resolve(res);
          return;
        }
        resolve(null);
      })
      .catch((ex) => {
        resolve(null);
      })
      .finally(() => {
        Status.showCheckDeviceLoading = false;
      });
  });

  // return new Promise((resolve, reject) => {
  //   let para = {
  //     deviceStatus: 1,
  //     isTid: true,
  //     sid: cEdit.sid,
  //     pageNum: checkedPageParams.pageNum,
  //     pageSize: checkedPageParams.pageSize,
  //     deviceImei: searchFilter.value.checkedKey
  //   };
  //   checkedPageParams.total = 0;
  //   Status.showCheckDeviceLoading = true;
  //   getDevice(para)
  //     .then((res) => {
  //       console.log('查询已选择设备成功');
  //       if (res.code === 200) {
  //         checkedDevices.value = res.rows;
  //         checkedPageParams.total = res.total;
  //         resolve(res);
  //         return;
  //       }
  //       resolve(null);
  //     })
  //     .catch((ex) => {
  //       resolve(null);
  //     })
  //     .finally(() => {
  //       Status.showCheckDeviceLoading = false;
  //     });
  // });
}
//关闭选择终端
function CloseCheckDevice() {
  Status.showCheckDevice = false;
}
//保存选择的终端
function SaveChecked() {
  if (ids.value.length === 0) {
    alert('请选择终端');
    return;
  }
  if (ids.value.length > 100) {
    alert('最多只能选100条数据');
    return;
  }
  let tids = ids.value
    .map((v) => {
      return v.tid;
    })
    .join(',');

  let deviceIds = ids.value.map((v) => {
    return v.deviceId;
  });
  let mapAdd = () => {
    //先从高德添加数据，成功后再提交后台
    return new Promise((resolve, reject) => {
      let url = 'https://tsapi.amap.com/v1/track/geofence/terminal/bind';
      let method = 'POST';
      let data = {
        key: mapApiKey,
        sid: checkGf.sid,
        gfid: checkGf.gfid,
        tids: tids
      };

      request({ url: url, method: method, data: data })
        .then((res) => {
          if (res && res.errcode === 10000) {
            resolve(res);
            return;
            // alert('操作成功');
            //
          } else {
            alert(res.errmsg);
            reject(res);
          }
        })
        .catch((ex) => {
          reject(ex);
        });
    });
  };

  mapAdd()
    .then((res) => {
      let json = {
        sid: checkGf.sid,
        fenceId: checkGf.gfid,
        deviceIds: deviceIds
      };
      api
        .addTerminal(json)
        .then((result) => {
          //高德添加成功了，提交到后台
          if (result && result.code === 200) {
            alert('操作成功');
          } else {
            alert('在高德保存成功，系统保存失败,失败数据:' + JSON.stringify(json));
          }
        })
        .finally(() => {
          SearchDevice();
        });
    })
    .then((ex) => {});
}

//删除终端
function DropDevice(row) {
  let arr = [];
  if (row) {
    arr = [row];
  } else {
    arr = checkZd.value;
  }
  if (arr.length === 0) {
    alert('请选择要删除的数据');
    return;
  }
  if (arr.length > 100) {
    alert('最多只能选择100条数据');
    return;
  }

  let tids = arr
    .map((v) => {
      return v.tid;
    })
    .join(',');

  let deviceIds = arr.map((v) => {
    return v.deviceId;
  });

  let mapDrop = () => {
    //从高德删除
    return new Promise((resolve, reject) => {
      let url = 'https://tsapi.amap.com/v1/track/geofence/terminal/unbind';

      let data = {
        key: mapApiKey,
        sid: checkGf.sid,
        gfid: checkGf.gfid,
        tids: tids
      };
      request({
        url: url,
        method: 'POST',
        data: data
      })
        .then((res) => {
          if (res && res.errcode === 10000) {
            resolve(res);
            return;
          } else {
            alert(res.errmsg);
            reject(res);
          }
        })
        .catch((ex) => {
          alert(JSON.stringify(ex));
          reject(ex);
        });
    });
  };
  //先从高德删除，再从系统删除
  let execDrop = () => {
    mapDrop().then((res) => {
      let json = {
        sid: checkGf.sid,
        fenceId: checkGf.gfid,
        deviceIds: deviceIds
      };
      api
        .delTerminal(json)
        .then((result) => {
          //从系统删除
          if (result && result.code === 200) {
            alert('操作成功');

            return;
          }
          alert('<div class="red">从高德删除成功，但从系统删除失败了,失败数据:' + JSON.stringify(json) + '</div>');
        })
        .finally(() => {
          SearchDevice();
        });
    });
  };

  confirm('<div class="red">删除后不可恢复，您确认删除所选数据吗？</div>', execDrop, null, '提示');
}

const handleSelectionChange = (selection: any[]) => {
  ids.value = selection;
};

//查询所有服务
function getServices() {
  listService({ pageNum: 1, pageSize: 9999 }).then((res) => {
    if (res.code === 200) {
      services.value = res.rows;
    }
  });
}
//显示隐藏高级查询
function showSearch() {
  if (Status.showSearch.length > 0) {
    Status.showSearch = [];
  } else {
    Status.showSearch = ['1'];
  }
}

function ShowEdit(item) {
  Status.showEdit = true;
  if (item) {
    let keys = Object.keys(item);
    keys.forEach((key) => {
      if (key !== 'coordinates') {
        cEdit[key] = item[key];
      }
    });
    if (item.coordinates) {
      cEdit.coordinates = JSON.parse(item.coordinates);
    }
  } else {
    cEdit.id = null;
    cEdit.name = '';
    cEdit.description = '';
    cEdit.areaType = null;
    cEdit.coordinates = [];
    cEdit.radius = null;
    cEdit.isActive = null;
    cEdit.sid = null;
    cEdit.gfid = null;
  }
  getServices();
  map.clearOverLays();
  setTimeout(() => {
    map
      .initMap()
      .then((res) => {
        console.log('地图初始化成功', res);
        if (cEdit.coordinates.length > 0) {
          refreshOverLayer();
          for (let i = 0; i < cEdit.coordinates.length; i++) {
            let point = cEdit.coordinates[i];
            AddPoint(point, i);
          }

          map.setFitView();
        }
      })
      .catch(() => {
        alert('地图初始化没有成功');
      });
  }, 500);
}

function CloseEdit() {
  Status.showEdit = false;
  let defCfg = {
    id: null,
    name: '',
    description: '',
    areaType: null,
    coordinates: [],
    radius: null,
    isActive: null,
    sid: null,
    gfid: null
  };
  let keys = Object.keys(defCfg);
  keys.forEach((key) => {
    cEdit[key] = defCfg[key];
  });
}
//响应查询
var queryTime = null;
function handleQuery() {
  clearTimeout(queryTime);
  queryTime = setTimeout(getList, 300);
}

//重置查询条件
function resetQuery() {
  let cfg = {
    name: '',
    areaType: null,
    isActive: null,
    description: ''
  };
  let keys = Object.keys(cfg);
  keys.forEach((k) => {
    queryParams[k] = cfg[k];
  });
  handleQuery();
}

//--------------------------------------
//修改围栏类型时，清空所有坐标
function areaTypeChange() {
  cEdit.coordinates = [];
  cEdit.radius = undefined;
  map.clearOverLays();
}
//圆大小改变时，更新半径字段
function circleDragEnd(radius) {
  cEdit.radius = radius;
}

//修改半径后主动更新图形
let time = null;
function refreshOverLayer() {
  clearTimeout(time);
  time = setTimeout(() => {
    if (cEdit.areaType == 1) {
      map.DrawCicle(cEdit.coordinates, cEdit.radius, circleDragEnd);
    } else {
      map.DrawPoy(cEdit.coordinates);
    }
  }, 200);
}
//清空所有点
function ClearPoint() {
  confirm(
    '您确认清除所有标记吗?',
    () => {
      cEdit.coordinates = [];
      map.clearOverLays();
    },
    null,
    '提示'
  );
}
//添加一个点
function AddPoint(point, i) {
  if (cEdit.areaType == null && !point) {
    alert('请选择围栏类型');
    return;
  }
  if (!point && cEdit.areaType == 1 && cEdit.coordinates.length > 0) {
    alert('圆形围栏只有一个中心坐标点');
    return;
  }

  if (!point && cEdit.areaType == 1 && !cEdit.radius) {
    cEdit.radius = 1000;
  }

  let index = i !== undefined ? i : cEdit.coordinates.length;
  let dragEnd = (evt, lay) => {
    map.removePoy();

    cEdit.coordinates[index].lng = evt.lnglat.lng;
    cEdit.coordinates[index].lat = evt.lnglat.lat;
    refreshOverLayer();
  };
  let pointClick = (evt, lay) => {
    confirm(
      '您确认删除该点吗?',
      () => {
        cEdit.coordinates.splice(index, 1);
        map.removeOverLay(lay);
        refreshOverLayer();
      },
      null,
      null
    );
  };

  map.AddPoint(point, index + 1, dragEnd, pointClick).then((res) => {
    let lon = res.lng;
    let lat = res.lat;

    if (!point) {
      cEdit.coordinates.push({ lng: lon, lat: lat });
    }
    refreshOverLayer();
  });
}
//调用高德的接口添加/修改围栏
function updateGeoFence() {
  const legalChars = cEdit.name.match(/[\u4e00-\u9fa5a-zA-Z0-9_\-]/g) || [];

  let geoFenceName = legalChars.join('').slice(0, 128);

  let json = {
    key: mapApiKey,
    sid: cEdit.sid,
    name: geoFenceName,
    desc: geoFenceName
  };
  if (cEdit.gfid && cEdit.id) {
    //修改围栏
    json.gfid = cEdit.gfid;
  }
  let url = '';
  if (cEdit.areaType == 0) {
    //多边形新增/修改

    json.points = cEdit.coordinates
      .map((v) => {
        return v.lng + ',' + v.lat;
      })
      .join(';');
    if (!cEdit.id) {
      url = 'https://tsapi.amap.com/v1/track/geofence/add/polygon';
    } else {
      url = 'https://tsapi.amap.com/v1/track/geofence/update/polygon';
    }
  } else if (cEdit.areaType == 1) {
    //圆形新增/修改
    json.center = cEdit.coordinates[0].lng + ',' + cEdit.coordinates[0].lat;
    json.radius = parseFloat(cEdit.radius);
    if (!cEdit.id) {
      url = 'https://tsapi.amap.com/v1/track/geofence/add/circle';
    } else {
      url = 'https://tsapi.amap.com/v1/track/geofence/update/circle';
    }
  }

  return request({
    url: url,
    method: 'POST',
    data: json
  });
}

function dropGeoFence(arr) {
  let ids = arr.filter((v) => {
    return v.gfid;
  });
  let defaultSucc = Promise.resolve({ errcode: 10000, msg: '操作成功' });
  if (ids.length === 0) {
    return defaultSucc;
  }

  let sids = [];

  arr.filter((v) => {
    let f = sids.find((sid) => {
      return sid === v.sid;
    });
    if (!f && v.sid) {
      sids.push(v.sid);
    }
  });

  let task = (sid, gfids) => {
    if (!gfids || !sid) {
      return defaultSucc;
    }

    let json = {
      key: mapApiKey,
      sid: sid,
      gfids: gfids
    };

    const url = 'https://tsapi.amap.com/v1/track/geofence/delete';
    return request({
      url: url,
      method: 'POST',
      data: json
    });
  };

  let promises = [];
  for (let i = 0; i < sids.length; i++) {
    const serviceId = sids[i];
    const gfids = arr
      .filter((v) => {
        return v.sid === serviceId && v.gfid;
      })
      .map((v) => {
        return v.gfid;
      })
      .join(',');

    if (serviceId && gfids) {
      promises.push(task(serviceId, gfids));
    }
  }

  if (promises.length) {
    return Promise.allSettled(promises)
      .then((res) => {
        let succIds = [];
        for (let i = 0; i < promises.length; i++) {
          if (res[i].status === 'fulfilled') {
            let result = res[i].value;
            if (result.errcode === 10000) {
              succIds = succIds.concat(result.data.gfids);
            }
          }
        }
        if (succIds.length > 0) {
          return Promise.resolve({ errcode: 10000, data: succIds });
        } else {
          return Promise.resolve({ errcode: 10000, errmsg: 'UNKNOWN_ERROR' });
        }
      })
      .catch((ex) => {
        console.log('出现异常', ex);
      });
  } else {
    return defaultSucc;
  }
}

function request(cfg) {
  return new Promise((resolve, reject) => {
    let json = cfg.data;
    let url = cfg.url;
    let method = cfg.method;

    let formData = [];
    if (json) {
      let keys = Object.keys(json);
      for (let index = 0; index < keys.length; index++) {
        let key = keys[index];
        let encodedKey = encodeURIComponent(key);
        let encodedValue = encodeURIComponent(json[key]);
        formData.push(`${encodedKey}=${encodedValue}`);
      }
    }

    let queryString = formData.join('&'); // 拼接成 key1=value1&key2=value2
    let xhr = new XMLHttpRequest();
    xhr.open(method, url, true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded;charset=UTF-8');
    xhr.responseType = 'json';
    xhr.onreadystatechange = function () {
      // readyState=4 表示请求完成，status=200 表示响应成功
      if (xhr.readyState === XMLHttpRequest.DONE) {
        if (xhr.status >= 200 && xhr.status < 300) {
          // 成功：返回响应数据
          resolve(xhr.response);
        } else {
          // 失败：返回状态码和错误信息
          reject(new Error(`请求失败：状态码 ${xhr.status}，信息：${xhr.statusText}`));
        }
      }
    };

    // 6. 监听网络错误（如断网、跨域、服务器不可达）
    xhr.onerror = function () {
      reject(new Error('网络错误：请求无法完成'));
    };

    // 7. 监听超时（可选，建议设置）
    xhr.ontimeout = function () {
      reject(new Error('请求超时：超过指定时间未响应'));
    };

    // 8. 设置超时时间（毫秒）
    xhr.timeout = 20000; // 20秒超时

    try {
      // 9. 发送请求：将 JSON 对象转为字符串
      xhr.send(queryString);
    } catch (error) {
      // 捕获数据序列化错误
      reject(error);
    }
  });
}

//保存数据
function SaveFormData() {
  let err = [];
  if (!cEdit.sid) {
    err.push('请选择服务id');
  }
  if (!cEdit.name) {
    err.push('请填写围栏名称');
  }
  if (cEdit.areaType === null) {
    err.push('请选择围栏类型');
  } else {
    if (cEdit.areaType == 0 && cEdit.coordinates.length < 3) {
      err.push('多边形的围栏至少需要3个点');
    }
    if (cEdit.areaType == 1 && cEdit.coordinates.length == 0) {
      err.push('圆形的围栏至少需要1个点');
    }
  }

  if (err.length) {
    alert(err.join('<br/>'));
    return;
  }
  let promise = Promise.resolve({ code: 200, msg: '操作成功' });
  Status.fullLoading = true;
  let json = Object.assign({}, cEdit);
  json.coordinates = JSON.stringify(json.coordinates);

  promise = updateGeoFence()
    .then((res) => {
      if (res.errcode === 10000) {
        if (cEdit.id !== null) {
          //编辑
          return api.updateFence(json);
        } else {
          //新增
          json.gfid = res.data.gfid;
          return api.AddFence(json);
        }
      }
      return Promise.resolve({ code: 500, msg: res.errmsg });
    })
    .catch((ex) => {
      return { code: ex.code, msg: ex.message };
    });

  promise
    .then((res) => {
      if (res.code == 200) {
        getList();
        CloseEdit();
      }
      alert(res.msg);
    })
    .finally(() => {
      Status.fullLoading = false;
    });
}
//删除围栏
function DropFence(item) {
  let arr = [];
  if (item) {
    arr = [item];
  } else {
    arr = getSelectionRows(grid);
  }
  if (arr.length == 0) {
    alert('请选择要删除的数据');
    return;
  }

  let execDelete = () => {
    //先从高德删除围栏，再从后台删除
    dropGeoFence(arr).then((res) => {
      if (res.errcode === 10000) {
        let dropIds = res.data;
        if (!dropIds) {
          alert('从高德地图删除围栏失败');
          return;
        }
        let ids = [];

        arr.filter((v) => {
          if (!v.gfid || !v.sid) {
            ids.push(v.id);
            return true;
          }
          if (dropIds) {
            let f = dropIds.find((gfid) => {
              return gfid === v.gfid;
            });
            if (f) {
              ids.push(v.id);
            }
          } else {
            ids.push(v.id);
          }

          return true;
        });
        if (!ids.length) {
          alert('操作没有成功');
          return;
        }
        ids = ids.join(',');
        api.DelFence(ids).then((res) => {
          if (res.code == 200) {
            handleQuery();
          }
          alert(res.msg);
        });
      } else {
        alert(res.errmsg);
      }
    });
  };

  confirm('删除后不可恢复,您确认?', execDelete, null, '提示');
}

function getList() {
  Status.loading = true;
  api
    .getList(queryParams)
    .then((res) => {
      List.value = res.rows;
      pagin.total = res.total;
    })
    .finally(() => {
      Status.loading = false;
    });
}

function Export() {
  let json = {};
  proxy?.download('/api/equipment/geoFence/export', json, `电子围栏列表_${new Date().getTime()}.xlsx`, 'post').finally(() => {});
}

//获取已选中的行
var getSelectionRows = (gridInstance) => {
  if (gridInstance.value) {
    // 检查ref是否已正确引用组件实例
    var selectedRows = gridInstance.value.getSelectionRows(); // 获取选中行数据数组
    return selectedRows;
  }
  return [];
};

window.confirm = function (text, OK, cancel, title, isWarn = false) {
  let Cfg = {
    Visible: true,
    title: title ? title : '提示',
    text: text ? text : '此操作不可逆，您确定这样做吗？',
    OkCallback: () => {
      Status.confirm.Visible = false;
      if (OK) {
        OK();
      }
    },
    showCancel: true,
    cancelCallback: () => {
      Status.confirm.Visible = false;
      if (cancel) {
        cancel();
      }
    },
    isWarn: isWarn
  };

  Status.confirm = Cfg;
};

window.alert = function (text, OK, title) {
  let Cfg = {
    Visible: true,
    title: title ? title : '提示',
    text: text ? text : '不符合规则',
    OkCallback: () => {
      Status.confirm.Visible = false;
      if (OK) {
        OK();
      }
    },
    showCancel: false,
    cancelCallback: null,
    isWarn: false
  };

  Status.confirm = Cfg;
};

var hideConfirm = function () {
  let Cfg = {
    Visible: false,
    title: '提示',
    text: '',
    cancelCallback: null,
    OkCallback: null,
    showCancel: false,
    isWarn: false
  };

  Status.confirm = Cfg;
};

onMounted(() => {
  getList();
});
</script>

<style lang="scss" scoped>
.fleft {
  float: left;
}

.fright {
  float: right;
}

.clear {
  clear: both;
}

.center {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-content: center;
  align-items: center;
  justify-content: center;
}

.displayNone {
  display: none !important;
}

.content {
  width: 100%;
  min-height: calc(100vh - 84px);
  height: calc(100vh - 84px);
  background: rgba(247, 248, 252, 1);
  font-size: 16px;
  box-sizing: border-box;
  padding: 8px 20px;
  font-family: 'Microsoft YaHei';
}

.topTool {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-content: center;
  justify-content: space-between;
  align-items: flex-start;
  width: 100%;
  border-bottom: 1px solid #e1e2e5f2;
  margin-bottom: 15px;
}
.percent100 {
  width: 100%;
  height: 100%;
  border-radius: 4px;
  box-shadow: 0px 0px 6px 0px rgba(0, 34, 96, 0.1);
  background: rgba(255, 255, 255, 1);
  box-sizing: border-box;
  padding: 15px;
}

:deep .el-collapse-item__header {
  display: none !important;
}
:deep .el-collapse,
:deep .el-collapse-item__wrap {
  border: none !important;
}

.map {
  width: 100%;
  height: calc(100% - 200px);
  box-sizing: border-box;
  border: 1px solid #ccc;
  border-radius: 8px;
  margin-top: 10px;
}

.point,
:deep .point {
  background-image: url(http://wdxm.ztzhtech.com:8111/Script/Home/img/welComeImg/mapLocation.png);
  width: 30px;
  height: 48px;
  background-repeat: no-repeat;
  background-color: #00000000;
  background-size: cover;
}

.point amap-overlay-text-container,
:deep .point .amap-overlay-text-container {
  color: #ffffff;
  font-size: 17px;
  border: none;
  text-align: center;
  line-height: 30px;
  background: #00000000;
}

.point:hover,
:deep .point:hover {
  filter: hue-rotate(169deg);
}
:deep .el-dialog__body,
.el-dialog__body {
  position: relative;
}
:deep .el-dialog__body .footerBtn,
.el-dialog__body .footerBtn {
  //  position: absolute;
  //  bottom: 0px;
  //  width: 100%;
  //  left: 0px;
}

.deviceLayer .gridContent {
  width: 100%;
  height: calc(100% - 50px);
}
.button-row {
  margin-top: 10px;
  width:auto;
  height: 36px;
  box-sizing: border-box;
}

.popLayer {
  position: relative;
}

.popLayer .abClose {
  position: absolute;
  top: 15px;
  right: 15px;
  z-index: 9;
  cursor: pointer;
}

.red,
:deep .red {
  color: #ff0000;
}
</style>
