<script lang="tsx" setup>
import { h, nextTick, onMounted, onUpdated, ref, watch } from 'vue';
import { Add28Filled as AddIcon, Delete16Regular as DelICon, CalendarEdit24Regular as EditIcon } from '@vicons/fluent';
import type { TreeOverrideNodeClickBehavior, UploadFileInfo } from 'naive-ui';
import { NButton, NImage, NSpace, NTag, useMessage, useNotification } from 'naive-ui';
import JSMpeg from '@cycjimmy/jsmpeg-player';
import html2canvas from 'html2canvas';
/**
 * api_addAreaNode 树-添加 api_addCameras 摄像头分组 api_base64ToWebURl base64上传 api_delCameras 摄像头-删除 api_deleteAreaNode 区域-删除
 * api_getAreaNode 区域-获取 api_getCameraList 摄像头-获取 api_modifyAreaNode 区域-修改 api_modifyCameras 摄像头-修改
 */
import {
  api_addAreaNode,
  api_addCameras,
  api_base64ToWebURl,
  api_delCameras,
  api_deleteAreaNode,
  api_exportBlobFile,
  api_getAreaNode,
  api_getCameraList,
  api_getCameras,
  api_modifyAreaNode,
  api_modifyCameras
} from '@/api/index';
import type { IArea, IWebCamTreeNode, ItablePagination } from './index';

// import JSMpeg from '@cycjimmy/jsmpeg-player';
// 服务器IP地址
const serviceUrl = import.meta.env.VITE_VIDEO_URL;
// const serviceUrl = 'ws://192.168.101.111:9999';
// 192.168.101.111

const isEdit = ref(false);
const notification = useNotification();
const isEditType = ref(false);
const treeData = ref<IWebCamTreeNode[] | []>([]);
const treeModal = ref(false);
const rootId = ref('');
const treeRootId = ref('');
const areaName = ref('');
const tableData = ref([]);
const curTree = ref({
  id: 100001000000000
});
const message = useMessage();
const webcamtreeModal = ref(false);

const impWebCamModal = ref(false);
const realTimeModal = ref(false);

const devStatus = ref(true);
const showDialogSpin = ref(false);

const tableColumn = [
  {
    type: 'selection',
    disabled(row: RowData) {
      return row.name === 'Edward King 3';
    }
  },
  {
    title: '摄像头名称',
    key: 'cameraName',
    minWidth: 180,
    align: 'center'
  },
  {
    title: '流地址',
    key: 'cameraAddress',
    minWidth: 180,
    align: 'center'
  },
  {
    title: '设备状态',
    key: 'status',
    minWidth: 120,
    align: 'center',
    render: (row: any) => {
      return row.status === 0 ? <NTag bordered={false} type="success">在线</NTag> : <NTag bordered={false} type="error">离线</NTag>;
    }
  },
  {
    title: '预览图',
    key: 'preview',
    minWidth: 160,
    align: 'center',
    render: (row: any) => {
      return h(NImage, {
        width: '70',
        lazy: true,
        height: '30',
        placeholder: "暂无",
        src: row.preview
      });
    }
  },
  {
    title: '操作',
    minWidth: 220,
    key: 'actions',
    align: 'center',
    render(row: any) {
      const o = row.status === 1;
      return (
        <div>
          <n-button
            onClick={() => {
              const { cameraAddress, status } = row;
              devStatus.value = status === 0;
              realTimeMonitoring(cameraAddress);
              const { cameraName } = row;
              videoOpen.value = false;
              formWebCam.value.cameraName = cameraName;
            }}
            type="primary"
            quater
            quaternary
          >
            查看
          </n-button>

          <n-button
            onClick={() => {
              isEdit.value = false;
              const { cameraName, cameraAddress, groupingId, preview, id } = row;
              formWebCam.value = {
                ...formWebCam.value,
                cameraName,
                id,
                cameraAddress,
                groupingId,
                preview
              };
              initVideoPlayer();
              webcamtreeModal.value = true;
            }}
            quater
            quaternary
            type="primary"
          >
            编辑
          </n-button>

          <n-button
            v-if="o"
            onClick={() => {
              const { id } = row;
              delCameras(id);
            }}
            quaternary
            type="error"
          >
            删除
          </n-button>
        </div>
      );
    }
  }
];

const page = ref(1);
const pageSize = ref(10);
// 分页-页码
const pageSizes = [
  {
    label: '10 每页',
    value: 10
  },
  {
    label: '20 每页',
    value: 20
  },
  {
    label: '30 每页',
    value: 30
  },
  {
    label: '40 每页',
    value: 40
  }
];

// 新增摄像头表单
const formWebCam = ref({
  cameraName: null,
  cameraAddress: null,
  groupingId: null,
  preview: '',
  status: ''
});

// 获取区域
const getAreaNode = async () => {
  await api_getAreaNode().then(res => {
    if (res.data.code === 200) {
      treeModal.value = false;
      treeRootId.value = res.data.data.items[0].id;
      const list = res.data.data.items[0].children;
      for (const i of list) {
        // 第一层
        i.suffix = () => {
          return (
            <NSpace>
              {/* 根层 - 增 */}
              {/* tertiary */}
              <div
                circle
                type="primary"
                quaternary
                onClick={_ => {
                  _.stopPropagation();
                  isEditType.value = false;
                  rootId.value = i.id;
                  console.log('第一层', i);
                  treeModal.value = true;
                }}
                style={{ display: 'flex', height: '100%', justifyContent: 'center', alignItems: 'center' }}
              >
                <n-icon color="#2080f0" >
                  <AddIcon />
                </n-icon>
              </div>

              {/* 根层 - 编 */}
              {/* tertiary */}
              <div
                circle
                type="warning"
                quaternary
                onClick={_ => {
                  _.stopPropagation();
                  isEditType.value = true;
                  rootId.value = i.id;
                  areaName.value = i.label;
                  console.log('第一层', i);
                  treeModal.value = true;
                }}
                style={{ display: 'flex', height: '100%', justifyContent: 'center', alignItems: 'center' }}
              >
                <n-icon color="#2080f0" >
                  <EditIcon />
                </n-icon>
              </div>
              {/* 根层 - 删 */}
              {/* #d03050 */}
              <div
                tertiary
                style={{ display: 'flex', height: '100%', justifyContent: 'center', alignItems: 'center' }}
                circle
                type="error"
                quaternary
                onClick={_ => {
                  _.stopPropagation();
                  const { id } = i;
                  delAreaNode(id);
                }}
              >
                <n-icon color="#d03050">
                  <DelICon />
                </n-icon>
              </div>
            </NSpace>
          );
        };

        if (Array.isArray(i.children)) {
          // 第二层
          for (const t of i.children) {
            t.suffix = () => {
              return (
                <NSpace>
                  {/* 二层 - 增 */}
                  <div
                    tertiary
                    circle
                    type="primary"
                    quaternary
                    onClick={_ => {
                      _.stopPropagation();
                      isEditType.value = false;
                      rootId.value = t.id;
                      console.log('第一层', t);
                      treeModal.value = true;
                    }}
                    style={{ display: 'flex', height: '100%', justifyContent: 'center', alignItems: 'center' }}
                  >
                    <n-icon color="#2080f0">
                      <AddIcon />
                    </n-icon>
                  </div>
                  {/* 二层 - 编 */}
                  <div
                    tertiary
                    circle
                    type="warning"
                    quaternary
                    onClick={_ => {
                      isEditType.value = true;
                      _.stopPropagation();

                      rootId.value = t.id;
                      areaName.value = t.label;
                      console.log('第一层', t);
                      treeModal.value = true;
                    }}
                    style={{ display: 'flex', height: '100%', justifyContent: 'center', alignItems: 'center' }}
                  >
                    <n-icon color="#2080f0">
                      <EditIcon />
                    </n-icon>
                  </div>
                  {/* 二层 - 删 */}
                  <div
                    tertiary
                    circle
                    type="error"
                    quaternary
                    onClick={_ => {
                      _.stopPropagation();
                      const { id } = t;
                      delAreaNode(id);
                    }}
                    style={{ display: 'flex', height: '100%', justifyContent: 'center', alignItems: 'center' }}
                  >
                    <n-icon color="#d03050">
                      <DelICon />
                    </n-icon>
                  </div>
                </NSpace>
              );
            };

            if (Array.isArray(t.children)) {
              // eslint-disable-next-line max-depth
              for (const s of t.children) {
                s.suffix = () => {
                  return (
                    <NSpace>
                      {/* 三层 - 编 */}
                      <div
                        tertiary
                        circle
                        type="warning"
                        quaternary
                        onClick={_ => {
                          isEditType.value = true;
                          _.stopPropagation();

                          rootId.value = s.id;
                          areaName.value = s.label;
                          console.log('第一层', t);
                          treeModal.value = true;
                        }}
                        style={{ display: 'flex', height: '100%', justifyContent: 'center', alignItems: 'center' }}
                      >
                        <n-icon color="#2080f0">
                          <EditIcon />
                        </n-icon>
                      </div>
                      {/* 三层 - 删 */}
                      <div
                        quaternary
                        tertiary
                        class="btn"
                        circle
                        type="error"
                        onClick={e => {
                          e.stopPropagation();
                          const { id } = s;
                          delAreaNode(id);
                        }}
                        style={{ display: 'flex', height: '100%', justifyContent: 'center', alignItems: 'center' }}
                      >
                        <n-icon color="#d03050">
                          <DelICon />
                        </n-icon>
                      </div>
                    </NSpace>
                  );
                };
              }
            }
          }
        }
      }
      treeData.value = list as IWebCamTreeNode[];
    }
  });
};

// 删除摄像头
const delCameras = async (id: string) => {
  await api_delCameras(id).then(async res => {
    if (res.data.code === 200) {
      await getCameraList();
      message.success('删除成功!');
    } else {
      message.warning(res.data.msg);
    }
  });
};

const cName = ref('');
const total = ref(0);
const getCameraList = async () => {
  const params: ItablePagination = {
    pageNum: page.value,
    pageSize: pageSize.value,
    resourceNo: curTree.value?.id ? curTree.value?.id : '100001000000000',
    cameraName: cName.value
  };
  await api_getCameraList(params).then(res => {
    if (res.data.code === 200) {
      total.value = res.data.data.total;
      tableData.value = res.data.data.records;
    }
  });
};

interface RowData {
  key: number;
  name: string;
  age: string;
  address: string;
}

watch(page, () => {
  getCameraList();
});

watch(pageSize, () => {
  getCameraList();
});

const override: TreeOverrideNodeClickBehavior = ({ option }) => {
  // 当前 node
  curTree.value = option as { id: number };
  // 树根
  rootId.value = option?.id as string;

  page.value = 1;
  pageSize.value = 10;
  getCameraList();
  if (option.children) {
    return 'toggleExpand';
  }
  return 'default';
};

const generalOptions = ref([]);

// 摄像头对话框- 分组获取
const getCamerasGroup = async () => {
  return await api_getCameras().then(res => {
    if (res.data.code === 200) {
      generalOptions.value = res.data.data;
    }
  });
};

// 摄像头对话框 - 提交
// eslint-disable-next-line consistent-return
const submitCallback = async () => {
  /** cameraName, cameraAddress, groupingId, preview; */
  const { cameraName, cameraAddress, groupingId, preview } = formWebCam.value;

  if (!cameraName) {
    return message.error('摄像头名称必填!');
  }

  if (!cameraAddress) {
    return message.error('摄像头流地址必填!');
  }

  if (!groupingId) {
    return message.error('摄像头分组必选!');
  }

  if (!preview) {
    return message.error('请选择摄像头预览图片!');
  }

  if (isEdit.value) {
    await api_addCameras(formWebCam.value).then(async res => {
      if (res.data.code === 200) {
        message.success('添加成功!');
        webcamtreeModal.value = false;
        await getCameraList();
        console.log('添加摄像头返回数据', res.data.data);
      } else {
        message.error(res.data.msg);
      }
    });
  } else {
    await api_modifyCameras(formWebCam.value).then(async res => {
      if (res.data.code === 200) {
        webcamtreeModal.value = false;
        message.success('修改成功!');
        await getCameraList();
        console.log('添加摄像头返回数据', res.data.data);
      } else {
        message.error(res.data.msg);
      }
    });
  }
};

// 增加区域节点
const addAreaNode = async () => {
  /** parentResourceNo 夫ID */
  const params = {
    parentResourceNo: rootId.value,
    resourceName: areaName.value
  } as any as IArea;

  await api_addAreaNode(params).then(async res => {
    if (res.data.code === 200) {
      message.success('添加成功!');
      await getAreaNode();
      treeModal.value = false;
      areaName.value = '';
    } else {
      message.error('添加失败!');
    }
  });
};

// 删除区域
function delAreaNode(id: string) {
  // const _id = rootId.value;
  console.log('==== 此时 删除 ID', rootId.value);
  api_deleteAreaNode(id).then(async res => {
    if (res.data.code === 200) {
      message.success('删除成功!');
      getAreaNode();
    } else {
      message.error(res.data.msg);
    }
  });
}

// 修改区域
const modifyAreaNode = async () => {
  const params = {
    parentResourceNo: rootId.value,
    resourceName: areaName.value
  } as any as IArea;

  await api_modifyAreaNode(params).then(async res => {
    if (res.data.code === 200) {
      message.success('修改成功!');
      await getAreaNode();
      treeModal.value = false;
    } else {
      message.error(res.data.msg);
    }
  });
};

// 图片上传 - 结束回调
const handleFinish = ({ file, event }: { file: UploadFileInfo; event?: ProgressEvent }) => {
  const res = event?.target && event?.target?.response && JSON.parse(event?.target?.response);

  if (res.code === 200) {
    formWebCam.value.preview = res.data;
    message.success('图片上传成功!');
  }

  return file;
};

// 文件上传 - 结束回调
const handleFinishFile = ({ file, event }: { file: UploadFileInfo; event?: ProgressEvent }) => {
  console.log(JSON.parse(event?.target.response));

  const res = JSON.parse(event?.target.response);

  if (res.code === 200) {
    console.log(res.data);
    formWebCam.value.preview = res.data;
    message.success('文件上传成功!');
    getCameraList();
  }
  // message.success((event?.target as XMLHttpRequest).response);
  // const ext = file.name.split('.')[1];
  // file.name = `更名.${ext}`;
  // file.url = '__HTTPS__://www.mocky.io/v2/5e4bafc63100007100d8b70f';

  return file;
};

const selectWebCaM = ref([]);
const handleCheck = (rowKeys: any) => {
  selectWebCaM.value = rowKeys;
};

// 文件导出
// eslint-disable-next-line consistent-return
const handleExportXLSFFile = async () => {
  /**
   * 1. 接收blob流
   * 2. 本地下载
   */
  if (!selectWebCaM.value.join()) {
    return message.error('请选择表格中的数据后, 导出!');
  }

  await api_exportBlobFile(selectWebCaM.value.join()).then(res => {
    const blob = res.data;
    const url = window.URL.createObjectURL(blob);
    const a = document.createElement('a');
    document.body.appendChild(a);
    a.href = url;
    a.download = '摄像头配置.xlsx';
    a.click();
    window.URL.revokeObjectURL(url);
  });
};

// 模板下载
function downloadFile() {
  console.log('文件下载');
  nextTick(() => {
    const link = document.createElement('a');
    link.href = '/v1/export/download';
    link.download = '文件名.xlsx';
    document.body.appendChild(link);
    link.click();
    document.body.removeChild(link);
  });
}

// 实时监控
// eslint-disable-next-line @typescript-eslint/no-unused-vars
const realTimeMonitoring = (url: string | undefined) => {
  realTimeModal.value = true;
  console.log("实时监控 url ==", url)
  nextTick(() => {
    const rtsp1 = url;
    // eslint-disable-next-line no-new
    try {
      new JSMpeg.Player(
        `${serviceUrl}/rtsp?url=${btoa(rtsp1)}&scale=640:-1&-b:v=1k&brightness=0.2&saturation=1.8`,
        {
          canvas: document.getElementById('canvas-2')
        }
      );
      videoOpen.value = true;

    } catch (e) {
      videoOpen.value = false;
    }
  });
};

// 图片上传前-钩子
function beforeUpload(data: { file: UploadFileInfo; fileList: UploadFileInfo[] }) {
  // if (data.file.file?.type !== 'image/png') {
  //   message.error('仅支持JPEG/JPG/PNG三种图片格式上传');
  //   return false;
  // }

  // if (data.file.file?.type !== 'image/jpg') {
  //   message.error('仅支持JPEG/JPG/PNG三种图片格式上传');
  //   return false;
  // }

  // if (data.file.file?.type !== 'image/jpeg') {
  //   message.error('仅支持JPEG/JPG/PNG三种图片格式上传');
  //   return false;
  // }
  return true;
}

// 文件上传前-钩子
function beforeUploadFile(data: { file: UploadFileInfo; fileList: UploadFileInfo[] }) {
  console.log(data.file.file?.type);

  // if (data.file.file?.type !== 'application/vnd.ms-excel') {
  //   message.error('只能上传 xls/xlsx 格式的文件，请重新上传');
  //   return false;
  // }
  return true;
}

const videoOpen = ref(false);

// 实时监控抓图
const handleRealTimeCaptureImg = () => {
  showDialogSpin.value = true;
  if (!formWebCam.value.cameraAddress) {
    return message.warning('请填写流地址!');
  };
  initVideoPlayer();
  setTimeout(() => {
    nextTick(() => {
      // 2. 将图片放至预览区域
      html2canvas(document.getElementById('canvas-3') as HTMLElement)
        .then(canvas => {
          showDialogSpin.value = false;
          formWebCam.value.preview = canvas.toDataURL('image/png');
          api_base64ToWebURl(canvas.toDataURL('image/png')).then(res => {
            if (res.data.code === 200) {
              formWebCam.value.preview = res.data.data;
            }
          });
        })
        .catch(() => {
          showDialogSpin.value = false;
        });
    });
  }, 3000)
  /**initVideoPlayer()
   * 1. fempeg 视频文件进行截图
   * 2. 将视频文件-保存截图-转成BASE64
   * 3. BASE64上传到服务
   *
   * https://github.com/cycjimmy/jsmpeg-player/issues/31 【GITHUB 抓图黑色方块解决方案】
   */

  /**
   *
   *  1. formWebCam.cameraAddress = 抓此地址
   *  2. 此地址播放
   *  3.
   */
};


const initVideoPlayer = () => {
  nextTick(() => {
    try {
      // 临时测试
      const rtsp1 = formWebCam.value.cameraAddress;
      // eslint-disable-next-line no-new
      new JSMpeg.Player(
        `${serviceUrl}/rtsp?url=${btoa(rtsp1)}&scale=640:-1&-b:v=1k&brightness=0.2&saturation=1.8`,
        {
          canvas: document.getElementById('canvas-3'),
          preserveDrawingBuffer: true
        }
      );
    } catch (e) { }
  })
};

onMounted(() => {
  getAreaNode();
  getCameraList();
  getCamerasGroup();
});

// 展示实时监控
const showRealTimeVideoPlayer = () => {
  nextTick(() => {
    try {
      // 临时测试
      const rtsp1 = 'rtsp://admin:gemho10-7@192.168.0.56:554/h264/ch1/main/av_stream';
      // eslint-disable-next-line no-new
      new JSMpeg.Player(
        `${serviceUrl}/rtsp?url=${btoa(rtsp1)}&scale=640:-1&-b:v=1k&brightness=0.2&saturation=1.8`,
        {
          canvas: document.getElementById('canvas-3'),
          preserveDrawingBuffer: true
        }
      );
    } catch (e) { }
  })
}
</script>

<template>
  <div id="algorithmconfiguration" key="algorithmconfiguration">
    <!-- 临时测试模板 -->
    <div id="canvas-4">
      <canvas id="canvas-3" style="width: 600px; height: 350px"></canvas>
    </div>
    <!-- ================================================= 导入 | S -->
    <NModal v-model:show="impWebCamModal" :mask-closable="false" preset="dialog" title="导入">
      <NForm ref="formRef" style="margin-top: 30px" :model="formWebCam" label-placement="left" label-width="auto"
        require-mark-placement="right-hanging" :style="{
          maxWidth: '640px'
        }" @negative-click="submitCallback">
        <!-- 名称 -->
        <NFormItem label="模板文件" path="inputValue" required>
          <NButton @click="_ => downloadFile()">下载</NButton>
          <br />
          <div style="
              margin-left: 30px;
              color: rgba(79, 79, 79, 0.59);
              font-size: 13px;
              line-height: 19px;
              display: inline-block;
            ">
            * 按模板文件的格式进行填写
          </div>
        </NFormItem>

        <!-- 图片初始化 -->
        <NFormItem label="文件上传" path="selectValue">
          <!-- =============================================================== 新增模块 -->
          <div>
            <!-- <NImage lazy width="100" src="https://07akioni.oss-cn-beijing.aliyuncs.com/07akioni.jpeg" /> -->
            <NSpace>
              <!-- <NButton strong secondary>上传图片</NButton> -->
              <NUpload :max="1" action="/v1/export/upload" :headers="{
                'naive-info': 'hello!'
              }" :data="{
                'naive-data': 'cool! naive!'
              }" @before-upload="beforeUploadFile" @finish="handleFinishFile">
                <NButton strong secondary>上传文件</NButton>
              </NUpload>
            </NSpace>
          </div>
          <!-- =============================================================== 编辑模块 -->
          <!-- <div v-else class="form_imgUpload"> -->
          <!-- <NImage width="100" :src="formWebCam.preview" /> -->
          <!-- <img style="width: 100%; height: 100%" :src="formWebCam.preview" alt="" /> -->
          <!-- </div> -->
        </NFormItem>
      </NForm>
      <!-- <div style="border: 1px solid red; width: 100%; height: 200px"></div> -->
      <!-- <template #footer> -->
      <NSpace justify="end">
        <NButton @click="impWebCamModal = false" type="primary">确定</NButton>
      </NSpace>
      <!-- </template> -->
    </NModal>

    <!-- ================================================= 导入 | E -->
    <NModal v-model:show="realTimeModal" style="width: 650px !important">
      <NCard :title="formWebCam?.value?.cameraName" closable @close="realTimeModal = false">
        <!-- Canvas v-if="videoOpen"  -->
        <div style="width: 600px; height: 350px">
          <canvas id="canvas-2" style="width: 600px; height: 350px"></canvas>
        </div>
        <!-- Skeleton -->
        <!-- <NSkeleton v-else height="350px" width="600px" /> -->
        <!-- 标题 -->
        <template #header>
          <NSpace>
            <span>{{ formWebCam?.cameraName }}</span>
            <span>
              <NTag :bordered="false" v-if="devStatus" type="success">在线</NTag>
              <NTag :bordered="false" v-else type="error">离线</NTag>
            </span>
          </NSpace>
        </template>
      </NCard>
    </NModal>

    <!-- =============================== 摄像头弹出框 | S -->
    <NModal v-model:show="webcamtreeModal">
      <NCard style="width: 600px" :title="isEdit ? '新增摄像头' : '编辑'" closable @close="webcamtreeModal = false">
        <NSpin :show="showDialogSpin" description="正在获取视频截图">
          <NForm ref="formRef" :model="formWebCam" label-placement="left" label-align="left" label-width="auto"
            require-mark-placement="right-hanging" :style="{
              maxWidth: '640px'
            }">
            <!-- 名称 -->
            <NFormItem label="名称" path="inputValue" required style="margin-top: 20px">
              <NInput v-model:value="formWebCam.cameraName" placeholder="填写摄像头名称" />
            </NFormItem>

            <!-- 流地址 -->
            <NFormItem label="地址" path="textareaValue" required>
              <NInput v-model:value="formWebCam.cameraAddress" placeholder="填写摄像头流地址" type="textarea" :autosize="{
                minRows: 3,
                maxRows: 5
              }" />
            </NFormItem>

            <!-- 算法分组 -->
            <NFormItem label="区域" path="selectValue" required>
              <NSelect v-model:value="formWebCam.groupingId" value-field="id" label-field="groupingName"
                placeholder="选择摄像头所在区域" :options="generalOptions" />
            </NFormItem>

            <!-- <NFormItem v-if="formWebCam.preview" label="图片预览" path="selectValue" required> -->
            <!-- <div> -->
            <!-- <div>
                  <NImage width="100" height="50" :src="formWebCam.preview" />
                </div>
                <br /> -->
            <!-- <div> -->
            <!-- <n-alert title="提示" type="info" style="width: 100%;">
                <div>
                  <NImage width="100" height="50" :src="formWebCam.preview" />
                </div>
                获取视频截图白屏黑屏，检查流地址配置！
              </n-alert> -->
            <!-- </div> -->
            <!-- </div> -->
            <!-- </NFormItem> -->

            <NFormItem label="图片初始化" path="selectValue">
              <NSpace justify="space-between" style="width: 100%;">
                <NSpace justify="start">
                  <NUpload :max="1" action="/v1/common/upload" :headers="{
                    'naive-info': 'hello!'
                  }" :data="{
                    'naive-data': 'cool! naive!'
                  }" @before-upload="beforeUpload" @finish="handleFinish">
                    <NButton strong secondary>
                      <template #icon>
                        <icon-ic:round-file-upload class="text-icon" />
                      </template>
                      上传封面
                    </NButton>
                  </NUpload>
                  <NButton v-if="!isEdit" strong secondary @click="handleRealTimeCaptureImg">
                    <template #icon>
                      <icon-ic:round-file-upload class="text-icon" />
                    </template>
                    获取抓图
                  </NButton>
                </NSpace>
                <span>
                  设置摄像头预览的封面图片
                </span>
              </NSpace>

              <!-- </br> -->
              <!-- <n-alert title="提示" type="info" style="width: 100%; margin-top: 20px;">
                <div style="margin: 10px 0">
                  <NImage width="130" height="75" :src="formWebCam.preview"
                    style="border-radius: 0px; box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);" />
                </div>
                获图白屏黑屏后，检查流地址！
              </n-alert> -->
            </NFormItem>

            <!-- 图片初始化 -->
            <!-- <NFormItem :label="' '" path="selectValue"> -->
            <!-- <NSpace>
                <NUpload :max="1" action="/v1/common/upload" :headers="{
                  'naive-info': 'hello!'
                }" :data="{
                  'naive-data': 'cool! naive!'
                }" @before-upload="beforeUpload" @finish="handleFinish">
                  <NButton strong secondary>
                    <template #icon>
                      <icon-ic:round-file-upload class="text-icon" />
                    </template>
                    上传封面
                  </NButton>
                </NUpload>
                <NButton v-if="!isEdit" strong secondary @click="handleRealTimeCaptureImg">
                  <template #icon>
                    <icon-ic:round-file-upload class="text-icon" />
                  </template>
                  获取抓图
                </NButton>
              </NSpace> -->
            <!-- =============================================================== 编辑模块 -->
            <n-alert type="info" style="width: 100%; display: block">
              <div style="margin: 10px 0">
                <NImage v-if="formWebCam.preview" width="130" height="75" :src="formWebCam.preview"
                  style="border-radius: 0px; box-shadow: 0 0 10px rgba(255, 255, 255, 0.6);" />
                <div v-else style="width: 130px; height: 75px;">

                </div>
              </div>
            </n-alert>
            <div style="margin: 10px 0">
              提示 :  获取抓图白屏、黑屏后，检查流地址！
            </div>
            <!-- </NFormItem> -->



          </NForm>
        </NSpin>
        <template #footer>
          <NSpace justify="end">
            <NButton @click="webcamtreeModal = false">取消</NButton>
            <NButton type="primary" @click="submitCallback">确定</NButton>
          </NSpace>
        </template>
      </NCard>
    </NModal>
    <!-- =============================== 摄像头弹出框 | E -->

    <!-- =============================== 新增摄像头区域 Modal | S -->
    <!-- style="width: 50% !important" -->
    <NModal v-model:show="treeModal" class="custom-card" style="width:600px;" preset="card"
      :title="!isEditType ? '添加区域' : '修改区域'" size="huge" :bordered="false">
      <template #header-extra></template>
      <NForm ref="formRef" inline style="width: 50%">
        <NFormItem>
          <!-- <NInputNumber v-model:value="" /> -->
          <NInput v-model:value="areaName" placeholder="填写区域名称 ."></NInput>
        </NFormItem>
        <NFormItem>
          <NButton strong secondary v-if="!isEditType" attr-type="button" @click="() => {
            if (areaName) return addAreaNode();
            message.error('请填写区域名称!');
          }
            ">
            添加
          </NButton>

          <NButton strong secondary v-else attr-type="button" @click="() => {
            if (areaName) modifyAreaNode();
          }
            ">
            确定
          </NButton>
        </NFormItem>
      </NForm>
    </NModal>
    <!-- =============================== 新增摄像头区域 Modal  | E -->

    <NRow gutter="12">
      <!--  =============================== 摄像头分布区域节点  | S -->
      <NCol :span="6">
        <NCard title="所有摄像头" size="small">
          <template #header-extra>
            <NButton strong secondary round @click="() => {
              rootId = treeRootId;
              treeModal = true;
            }
              ">
              <n-icon color="#2080f0">
                <AddIcon />
              </n-icon>
            </NButton>
          </template>
          <!-- ================= 摄像头区域节点数列表 -->
          <NTree accordion :override-default-node-click-behavior="override" show-line block-line :data="treeData"
            key-field="id" default-expand-all></NTree>
        </NCard>
      </NCol>
      <!--  =============================== 摄像头分布区域节点 | E -->

      <!--  =============================== 摄像头分布区域节点 | S -->
      <NCol :span="18">
        <NCard size="medium">
          <template #header>
            <NFlex justify="space-between">
              <NButton type="primary" ghost @click="async () => {
                formWebCam = {
                  cameraName: null,
                  cameraAddress: null,
                  groupingId: null,
                  preview: '',
                  status: '',
                  id: ''
                };
                isEdit = true;
                await getCamerasGroup();
                webcamtreeModal = true;
              }
                ">

                <template #icon>
                  <icon-ic:baseline-plus class="text-icon" />
                </template>
                新增摄像头
              </NButton>


              <!--  -->
              <NSpace>

                <!-- 新增摄像头筛选 | S -->
                <NInput style="width: 200px;" v-model:value="cName" placeholder="摄像头名称" clearable></NInput>

                <NButton type="primary" style="margin-right: 30px" @click="() => getCameraList()">
                  <template #icon>
                    <icon-ic:baseline-search class="text-icon" />
                  </template>

                  查询
                </NButton>
                <!-- 新增摄像头筛选 | E -->

                <NButton tertiary @click="() => {
                  impWebCamModal = true;
                }
                  ">
                  <template #icon>
                    <icon-ic:round-file-upload class="text-icon" />
                  </template>
                  导入
                </NButton>

                <NButton tertiary @click="handleExportXLSFFile">
                  <template #icon>
                    <icon-ic:baseline-file-download class="text-icon" />
                  </template>
                  导出
                </NButton>
              </NSpace>
            </NFlex>


          </template>
          <NDataTable :ellipsis="true" striped bottom-bordered :row-key="row => row.id" :columns="tableColumn"
            :data="tableData" :bordered="true" @update:checked-row-keys="handleCheck" />
          <!-- :pagination="tablePagination" -->

          <div style="display: flex; justify-content: end">
            <NPagination :item-count="total" v-model:page="page" v-model:page-size="pageSize" style="margin-top: 20px"
              :display-order="['quick-jumper', 'pages', 'size-picker']" :page-count="100" show-quick-jumper
              show-size-picker :page-sizes="pageSizes" @on-update:page="next" @on-update:page-size="prev" />
          </div>
        </NCard>
      </NCol>
    </NRow>
  </div>
</template>

<style lang="scss" scoped>
#algorithmconfiguration {
  #canvas-4 {
    position: absolute;
    top: -1500px;
  }

  /* 图片上传 */
  .form_imgUpload {
    border-radius: 6px;
    border: 1px solid rgb(220, 220, 220);
    height: 180px !important;
    width: 100%;
    // background: rgba(242, 243, 255, 0.75);
    display: inline-block;
    text-align: center;
    position: relative;
    top: -1;
    // display: flex;
    // align-items: center;

    &>div {
      display: inline-block !important;
      // position: relative !important;
      z-index: 1000000 !important;
    }
  }

  /* 表单 文字上传描述 */
  .form_imgUpload-title {
    color: rgba(79, 79, 79, 0.59);
    font-size: 13px;
    line-height: 19px;
    text-align: center;
    margin-top: 60px;
  }

  .btn {
    position: relative;
    z-index: 10000000000000 !important;
  }
}
</style>
