<template>
  <div class="content">
    <div class="leftTree fleft">
      <div class="head">
        <div class="title">设备分组</div>
        <div class="nodeEdit" @click="addNode(null)">新增</div>
      </div>
      <div class="Search">
        <input type="text" class="txt" v-model="searchTxt" placeholder="输入分组名称" />
      </div>

      <div class="treeContent">
        <el-tree :default-expand-all="true" :data="treeData" :props="defaultProps" accordion
          @node-click="handleNodeClick" :highlight-current="true">
          <template #default="{ node, data }">
            <div class="custom-tree-node">
              <span :class="data.parentId != null ? '' : 'treeBold'">{{ node.label }}</span>

              <div class="iconContent">
                <Edit class="icon" @click.stop="editNode(node)" />
                <Plus class="icon" @click.stop="addNode(node)" />
                <Delete class="icon red" @click.stop="delNode(node)" />
              </div>
            </div>
          </template>
        </el-tree>
      </div>
    </div>

    <div class="main fleft">
      <div class="toolBar">
        <div class="btnAdd" @click="showDevice">
          <Plus class="icon" style="width: 14px; height: 14px" />
          添加设备
        </div>
        <div class="rightSearch">
          <div class="searchContent">
            <div class="center H100">
              <input type="text" class="serchTxt" v-model="GjSearchForm.deviceName" @input="InputSearch()" />
              <Search class="icon" style="width: 16px; height: 16px" />
            </div>
          </div>

          <div class="gjSearch" @click="ToggleGjSearch()">高级筛选</div>
        </div>
      </div>

      <div class="searchBar" :class="Status.isGjSearch ? '' : 'displayNone'">
        <div style="margin-top: 20px">
          <el-form class="demo-form-inline" :inline="true" :model="GjSearchForm" label-width="auto" style="width: 100%">
            <el-form-item label="设备类型">
              <el-select v-model="GjSearchForm.deviceType" placeholder="请选择">
                <el-option v-for="item in deviceTypes" :key="item.value" :label="item.typeName" :value="item.value" />
              </el-select>
            </el-form-item>

            <el-form-item label="通信方式">
              <el-select v-model="GjSearchForm.netMode" placeholder="请选择">
                <el-option label="4G" :value="0" />
                <el-option label="蓝牙" :value="1" />
              </el-select>
            </el-form-item>
            <el-form-item>
              <div class="btnSearch" @click="getDeviceList">查询</div>
              <div class="btnReset" @click="ResetQuery()">重置</div>
            </el-form-item>
          </el-form>
        </div>
      </div>

      <div class="grid">
        <el-card shadow="hover">
          <div class="gridTool">
            <div class="button-row">
              <el-button type="success" @click="showCheckGroup('check')" plain>移动</el-button>

              <el-button type="danger" plain @click="groupDelDevice()">删除</el-button>
            </div>
          </div>
          <el-table ref="grid" height="calc(100vh - 320px)" v-loading="Status.loading" border :data="deviceList"
            @selection-change="RowSelectionChange">
            <el-table-column type="selection" width="50" align="center" />
            <el-table-column label="设备名称" align="center" prop="deviceName" />

            <el-table-column prop="devicePic" label="设备图片">
              <template #default="scope">
                <el-popover placement="right" trigger="click">
                  <template #reference>
                    <img :src="scope.row.devicePic"
                      style="width: 40px; height: 40px; cursor: pointer; object-fit: contain"
                      class="hover:opacity-80 transition-opacity" />
                  </template>
                  <img :src="scope.row.devicePic" style="max-width: 600px; max-height: 600px; object-fit: contain" />
                </el-popover>
              </template>
            </el-table-column>

            <el-table-column prop="typeName" label="设备类型" />
            <el-table-column prop="bindingStatus" label="绑定状态">
              <template #default="scope">
                <el-tag :type="scope.row.bindingStatus === 1 ? 'success' : 'info'">
                  {{ scope.row.bindingStatus === 1 ? '已绑定' : '未绑定' }}
                </el-tag>
              </template>
            </el-table-column>

            <el-table-column label="操作" fixed="right" width="280" class-name="small-padding fixed-width">
              <template #default="scope">
                <div class="center">
                  <el-button link type="primary" @click="showCheckGroup('item', scope.row)">移动</el-button>
                  <el-button link type="danger" @click="groupDelDevice(scope.row)">删除</el-button>
                </div>
              </template>
            </el-table-column>
          </el-table>
          <pagination v-show="pagin.total > 0" v-model:page="GjSearchForm.pageNum" v-model:limit="GjSearchForm.pageSize"
            :total="pagin.total" @pagination="getDeviceList" />
        </el-card>
      </div>
    </div>

    <div class="clear"></div>

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

    <!-- 选择分组的弹窗 -->
    <el-dialog v-model="Status.dialogGroupVisible" title="选择分组" width="500" :draggable="true">
      <el-tree :data="treeData" :props="defaultProps" accordion default-expand-all>
        <template #default="{ node, data }">
          <div class="custom-tree-node" @click.stop="CheckGroup(data)">
            <span :class="data.parentId != null ? '' : 'treeBold'">{{ node.label }}</span>
            <span>选择</span>
          </div>
        </template>
      </el-tree>
      <div style="text-align: right;">
        
        <el-button  @click="CancelCheckGroup()"> 取消 </el-button>
        <el-button type="primary" @click="OkCheckGroup()"> 确定 </el-button>
      </div>

    </el-dialog>

    <!-- 选择设备的穿梭框 -->
    <el-dialog v-model="Status.dialogDeviceVisible" title="选择设备" width="630" :draggable="true">
      <el-transfer :titles="['所有设备', '已选择设备']" v-model="transfer.value" :data="transfer.data" :filterable="true" />

      <div class="center" style="margin-top: 10px">
        <el-button type="primary" @click="OKCheckDevice()"> 确定 </el-button>
        <el-button type="info" @click="hideDevice()"> 取消 </el-button>
      </div>
    </el-dialog>

    <!-- 添加节点的弹出框 -->
    <el-dialog :width="350" :draggable="true" v-model="Status.dialogEditNode"
      :title="cEdit.id ? '修改分组' : cEdit.pNode ? '新增子节点' : '新增根节点'" center>
      <div>
        <el-form class="demo-form-inline" :inline="true" :model="cEdit" label-width="auto" style="width: 100%">
          <el-form-item label="分组名称"> <el-input v-model="cEdit.groupName" placeholder="请输入" /> </el-form-item>
          <div style="text-indent: 68px; color: #f56c6c; margin-top: -15px">{{ cEdit.groupName ? '' : '请输入分组名称' }}</div>
        </el-form>
      </div>
      <template #footer>
        <div class="dialog-footer">
          <el-button v-show="Status.confirm.showCancel" @click="Status.dialogEditNode = false">取消</el-button>
          <el-button type="primary" @click="saveNode()"> 确定 </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup lang="ts">
import api from '@/api/equipmentManagement/devicegroup/index';
import common from '@/utils/common';

interface Device {
  deviceName: string;
  devicePic: string;
  typeName: string;
  bindingStatus: string;
}

var searchTxt = ref(''); //左侧树筛选文本
var treeDataOrin = ref([]); //树控件的数据源
var grid = ref(null);

var cEdit = ref({ id: '', groupName: '', pNode: null, editNode: null }); //当前正在编辑的节点数据

var checkNode = { val: '' }; //记录被选中的节点

//全局状态控制
var Status = reactive({
  isEditTreeNode: false, //是否编辑节点
  isGjSearch: false, //是否显示高级筛选
  loading: false,
  confirm: {
    Visible: false,
    title: '',
    text: '',
    cancelCallback: '',
    OkCallback: '',
    showCancel: true
  },
  dialogGroupVisible: false, //是否显示选择分组的弹窗
  dialogDeviceVisible: false, //是否显示选择设备的弹窗
  dialogEditNode: false //是否显示添加节点的弹窗
});
//页码控件数据
var pagin = reactive({
  total: 0
});
//右边的筛选条件
var GjSearchForm = reactive({
  deviceName: '',
  deviceType: '',
  netMode: '',
  pageNum: 1,
  pageSize: 10
});
//设备列表
var deviceList = ref<Device[]>();
//所有设备类型
var deviceTypes = reactive([]);

//穿梭框的数据和值
var transfer = reactive({
  value: [],
  data: []
});

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

  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
  };

  Status.confirm = Cfg;
};

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

  Status.confirm = Cfg;
};

var showloading = function () {
  // window.loadingIndex = ElLoading.service({ fullscreen: true })

  Status.loading = true;
};

var closeLoading = function () {
  // if (window.loadingIndex) {
  //   window.loadingIndex.close();
  // }

  Status.loading = false;
};
var hideloading = closeLoading;

function ResetQuery() {
  GjSearchForm.deviceType = '';
  GjSearchForm.netMode = '';
  getDeviceList()

}
//查询某个节点的设备
const getDeviceList = () => {
  // 无论是否有 checkNode.val，都返回 Promise
  return new Promise((resolve, reject) => {
    if (!checkNode.val && checkNode.val !== '') { // 排除全部设备的空字符串
      pagin.total = 0;
      deviceList.value = [];
      hideloading(); // 确保 loading 关闭
      resolve();
      return;
    }
    showloading();
    let para = {
      nodeCode: checkNode.val || '', // 空ID对应全部设备
      pageIndex: GjSearchForm.pageNum,
      pageSize: GjSearchForm.pageSize,
      communicationMode: GjSearchForm.netMode,
      deviceType: GjSearchForm.deviceType,
      deviceName: GjSearchForm.deviceName
    };
    api.getNodeDevice(para).then((res: any) => {
      console.log(res, 'ressss');
      deviceList.value = res.rows;
      pagin.total = res.total;
      resolve();
    }).catch((ex) => {
      console.log('出现了异常', ex);
      reject(ex); // 抛出错误
    }).finally(() => {
      hideloading();
    });
  });
};
//树控件节点点击事件
var handleNodeClick = (node) => {
  if (checkNode.val == node.id) {
    return;
  }
  console.log('节点数据：', node.id);
  checkNode.val = node.id;
  getDeviceList();
};

const ALL_DEVICE_NODE = {
  id: '',
  groupName: '全部设备',
  parentId: null,
  children: [],
  isAll: true
};
//树控件筛选后显示的数据源
var treeData = computed(() => {
  let arr = api.treeNodeSearch(treeDataOrin.value, searchTxt.value, 'groupName', 'children');
  let newArr = [JSON.parse(JSON.stringify(ALL_DEVICE_NODE))];
  if (arr.length) {
    newArr = newArr.concat(arr);
  }
  if (newArr.length && !checkNode.val) {
    checkNode.val = newArr[0].id; // 空ID
    Promise.resolve(getDeviceList()).finally(() => {
    });
  }
  return newArr;
});

//显示/隐藏高级筛选
var ToggleGjSearch = function () {
  Status.isGjSearch = !Status.isGjSearch;
};

//编辑节点
var editNode = (node) => {
  console.log('编辑节点：', node.data.value);
  cEdit.value.id = node.data.id;
  cEdit.value.groupName = node.data.groupName;
  Status.isEditTreeNode = true;
  cEdit.value.editNode = node;
  cEdit.value.pNode = null;
  Status.dialogEditNode = true;
  //
};

//完成编辑
var completeEdit = (node) => {
  let now = common.DateFormat(new Date(), 'yyyy-MM-dd HH:mm:ss');

  let newNode = {
    'createDept': node.data.createDept, //创建部门
    'createBy': node.data.createBy, //创建者
    'createTime': now, //创建时间
    'updateBy': node.data.updateBy, //更新者
    'updateTime': now, //更新时间
    'params': {
      'additionalProp1': '',
      'additionalProp2': '',
      'additionalProp3': ''
    },
    'id': node.data.id, //主键ID
    'groupName': cEdit.value.groupName, //分组名称
    'status': 1, //状态：0-禁用，1-正常
    'parentId': node.data.parentId, //父分组ID
    'fullPath': node.data.fullPath, //完整分组路径
    'isDeleted': 0 //删除标记：0-未删除，1-已删除
  };

  showloading();
  api
    .updateTreeName(treeDataOrin.value, newNode, cEdit.value.groupName)
    .then((res) => {
      if (res.code == 200) {
        alert('操作成功');
        RefreshTree();
        Status.dialogEditNode = false;
      } else {
        alert(res.msg);
      }
    })
    .finally(() => {
      hideloading();
    });
  Status.isEditTreeNode = false;
};

//放弃编辑
var cancelEdit = (node) => {
  cEdit.value.id = '';
  cEdit.value.groupName = '';
  cEdit.value.pNode = null;
  cEdit.value.editNode = null;
  Status.isEditTreeNode = false;
};

//删除节点
var delNode = (node) => {
  if (node.data.children && node.data.children.length > 0) {
    alert('节点包含子节点,不允许删除');
    return;
  }
  confirm(
    '您确认删除’' + node.data.groupName + '’节点吗',
    () => {
      hideConfirm();

      api.delTreeNode(treeDataOrin.value, node.data.id).then((res) => {
        if (res.code == 200) {
          alert('操作成功');
          RefreshTree();
        } else {
          alert(res.msg);
        }
      });
    },
    () => {
      hideConfirm();
    }
  );
};

//增加节点
var addNode = (node) => {
  let title = '';
  if (node) {
    console.log('给节点新增子节点：', node.data.id);
    title = '添加子节点';
  } else {
    console.log('新增初级节点');
    title = '添加根节点';
  }
  cEdit.value.pNode = node;
  cEdit.value.editNode = null;
  cEdit.value.id = '';
  cEdit.value.groupName = '';
  Status.dialogEditNode = true;
};

var saveNode = () => {
  if (!cEdit.value.groupName) {
    return;
  }
  let val = new Date().getTime();
  // let newNode = { value: val, txt: '' };
  let now = common.DateFormat(new Date(), 'yyyy-MM-dd HH:mm:ss');

  showloading();
  if (cEdit.value.id) {
    //编辑
    completeEdit(cEdit.value.editNode);
  } else {
    //新增
    let newNode = {
      'createDept': 0, //创建部门
      'createBy': 0, //创建者
      'createTime': now, //创建时间
      'updateBy': 0, //更新者
      'updateTime': now, //更新时间
      'params': {
        'additionalProp1': '',
        'additionalProp2': '',
        'additionalProp3': ''
      },
      'id': null, //主键ID
      'groupName': cEdit.value.groupName, //分组名称
      'status': 1, //状态：0-禁用，1-正常
      'parentId': cEdit.value.pNode ? cEdit.value.pNode.data.id : null, //父分组ID
      'fullPath': val, //完整分组路径
      'isDeleted': 0 //删除标记：0-未删除，1-已删除
    };
    api
      .addTreeNode(treeDataOrin.value, newNode, cEdit.value.pNode ? cEdit.value.pNode.data.id : null)
      .then((res) => {
        if (res.code == 200) {
          alert('操作成功');
          RefreshTree();
          Status.dialogEditNode = false;
        } else {
          alert(res.msg);
        }
      })
      .catch((ex) => {
        console.log('ex=', ex);
      })
      .finally(() => {
        hideloading();
      });
  }
};

//树控件的自定义属性
var defaultProps = {
  children: 'children',
  label: 'groupName',
  parentId: 'parentId'
};

var RowSelectionChange = (tr) => {
  console.log('行选中变化', tr);
  getSelectionRows();
};

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

var RefreshTree = function () {
  api.getTreeData(searchTxt.value).then((res) => {
    console.log(res, 'reddddd');
    treeDataOrin.value = res;
  });
};

//从分组中删除设备
var groupDelDevice = (row) => {
  let rows = []; //
  if (!row) {
    rows = getSelectionRows();
  } else {
    rows = [row];
  }
  if (rows.length == 0) {
    alert('请选择要删除的设备');
    return;
  }

  confirm(
    '此操作不可逆,您确认要进行吗?',
    () => {
      showloading();
      let ids = rows.map((r) => r.deviceId).join(',');
      api
        .groupDelDevice(checkNode.val, ids)
        .then((res) => {
          if (res.code == 200) {
            alert('操作成功');
            getDeviceList();
          } else {
            alert(res.msg);
          }
        })
        .finally(() => {
          hideloading();
        });
    },
    null,
    '警告'
  );
};

var showDevice = () => {
  if (!checkNode.val) {
    alert('请先选择分组');
    return;
  }
  Status.dialogDeviceVisible = true;
  //获取所有
  let promise1 = api.getNodeDevice({
    pageIndex: 1,
    pageSize: 9999,
    nodeCode: ''
  });
  //获取已选中的
  let promise2 = api.getNodeDevice({
    pageIndex: 1,
    pageSize: 9999,
    nodeCode: checkNode.val
  });

  cGroupAndDevice.deviceIds = [];
  transfer.value = [];

  Promise.allSettled([promise1, promise2]).then((res) => {
    if (res[0].status == 'fulfilled') {
      let res1 = res[0].value;

      if (res1.code == 200) {
        let arr = res1.rows.map((item) => ({
          key: item.deviceId,
          label: item.deviceName //,
        }));
        ;
        transfer.data = arr;
      }
    }

    if (res[1].status == 'fulfilled') {
      let res2 = res[1].value;
      if (res2.code == 200) {
        let vals = res2.rows.map((item) => item.deviceId);

        transfer.value = vals;
      }
    }
  });
};

//确认选择这些设备
var OKCheckDevice = () => {
  let arr = transfer.value.map((item) => ({
    deviceId: item
  }));
  if (arr.length == 0) {
    alert('未选择任何设备');
    return;
  }
  hideDevice();
  cGroupAndDevice.deviceIds = arr;
  cGroupAndDevice.groupid = checkNode.val;
  deviceMoveGroup(cGroupAndDevice.groupid, cGroupAndDevice.deviceIds);
};

//隐藏选择设备
var hideDevice = () => {
  Status.dialogDeviceVisible = false;
};

var cGroupAndDevice = {
  groupid: '',
  deviceIds: []
};
//显示选择分组
var showCheckGroup = (type, row) => {
  let rows = [row];
  if (type == 'check') {
    rows = getSelectionRows();
  }

  if (rows.length == 0) {
    alert('请选择要移动的设备');
    return;
  }
  cGroupAndDevice.deviceIds = rows;
  Status.dialogGroupVisible = true;

  cGroupAndDevice.groupid = '';
};
//选中了某个分组
var CheckGroup = (item) => {
  cGroupAndDevice.groupid = item.id;
};

//确定选中某个分组
var OkCheckGroup = () => {
  if (!cGroupAndDevice.groupid) {
    alert('请先选择分组');
    return;
  }
  CancelCheckGroup();
  deviceMoveGroup(cGroupAndDevice.groupid, cGroupAndDevice.deviceIds);
};
//隐藏选择分组
var CancelCheckGroup = () => {
  Status.dialogGroupVisible = false;
};
//将设备移动至分组
var deviceMoveGroup = (groupid, row) => {
  let rows = []; //
  if (!row) {
    rows = getSelectionRows();
  } else {
    if (Array.isArray(row)) {
      rows = row;
    } else {
      rows = [row];
    }
  }
  if (rows.length == 0) {
    alert('请选择要移动的设备');
    return;
  }

  // confirm("此操作不可逆,您确认要进行吗?", () => {
  showloading();
  let ids = rows.map((r) => r.deviceId).join(',');
  api
    .deviceMoveGroup(groupid, ids)
    .then((res) => {
      if (res.code == 200) {
        alert('操作成功');
        getDeviceList();
      } else {
        alert(res.msg);
      }
    })
    .finally(() => {
      hideloading();
    });
  // }, null, "警告");
};

let timer;
function InputSearch() {
  clearTimeout(timer);
  // 等待 500ms 无输入后执行查询
  timer = setTimeout(() => {
    getDeviceList();
  }, 500);
}

onMounted(() => {
  RefreshTree();
  api.getDeviceTypeAll().then((res) => {
    if (res.code == 200) {
      deviceTypes = res.data.map((item) => ({
        value: item.deviceTypeId,
        typeName: item.typeName
      }));
    }
  });
});
</script>

<style lang="scss" scoped>
.main .searchBar .btnReset {
  width: 76px;
  height: 32px;
  border-radius: 4px;
  background-color: #00000000;
  color: #027cfb;
  text-align: center;
  font-family: Microsoft YaHei;
  font-size: 14px;
  font-weight: 400;
  line-height: 32px;
  letter-spacing: 0px;
  border: 1px solid rgb(2, 124, 251);
  cursor: pointer;
}

.main .searchBar .btnSearch {
  /* 组合 454 */
  width: 76px;
  height: 32px;
  border-radius: 4px;
  background-color: #027cfb;
  color: #ffffff;
  text-align: center;
  font-family: Microsoft YaHei;
  font-size: 14px;
  font-weight: 400;
  line-height: 32px;
  letter-spacing: 0px;
  border: none;
  margin-right: 15px;
  cursor: pointer;
}

.main .searchBar {
  width: 100%;
  height: 50px;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-content: center;
  justify-content: space-between;
  align-items: center;
}

.main .toolBar .rightSearch {
  width: 295px;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-content: center;
  justify-content: space-between;
  align-items: center;
}

.main .toolBar .gjSearch {
  /* 矩形 155 */
  width: 85px;
  height: 32px;
  box-sizing: border-box;
  border: 1px solid rgba(2, 124, 251, 1);
  border-radius: 4px;
  color: rgba(2, 124, 251, 1);
  cursor: pointer;
  font-family: Noto Sans SC;
  font-size: 14px;
  font-weight: 400;
  line-height: 32px;
  letter-spacing: 0px;
  text-align: center;
}

.main .toolBar .searchContent {
  width: 200px;
  height: 32px;
  border: 1px solid rgba(189, 198, 215, 1);
  border-radius: 4px;
}

.main .toolBar .serchTxt {
  border: none;
  width: 175px;
  height: 100%;
}

.main .toolBar .btnAdd {
  background-color: #027cfb;
  color: #ffffff;
  width: 105px;
  height: 32px;
  text-align: center;
  font-family: Microsoft YaHei;
  font-size: 14px;
  font-weight: 400;
  line-height: 32px;
  letter-spacing: 0px;
  cursor: pointer;
}

.main .toolBar {
  width: 100%;
  height: 35px;
  overflow: hidden;
  box-sizing: border-box;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-content: center;
  justify-content: space-between;
  align-items: flex-start;
  border-bottom: 1px solid rgba(235, 238, 248, 1);
}

.nodeInput {
  height: 30px;
  line-height: 30px;
  border: 1px solid rgb(189, 198, 215);
  border-radius: 4px;
  box-sizing: border-box;
}

.red {
  color: #ff0000;
}

.green {
  color: #0ed50e;
}

.custom-tree-node {
  width: 100%;
  height: 40px;
  line-height: 40px;
  display: flex;
  flex-direction: row;
  align-content: center;
  flex-wrap: nowrap;
  justify-content: space-between;
  align-items: center;
}

.custom-tree-node.active {
  background: #80bcf966 !important;
  color: #ffffff;
}

.custom-tree-node .iconContent {
  width: 60px;
  height: 100%;

  box-sizing: border-box;
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-content: center;
  justify-content: space-evenly;
  align-items: center;
}

.custom-tree-node .iconContent .icon {
  width: 15px;
  height: 15px;
  visibility: hidden;
}

.custom-tree-node-Edit .iconContent .icon {
  visibility: visible !important;
}

.custom-tree-node:hover .iconContent .icon {
  visibility: visible;
}

.leftTree .treeBold {
  font-weight: 700;
}

.leftTree .treeContent::-webkit-scrollbar {
  display: none;
}

.leftTree .treeContent {
  margin-top: 10px;
  height: calc(100% - 95px);
  overflow: scroll;
  box-sizing: border-box;
}

.leftTree .Search .txt::placeholder {
  color: rgba(189, 198, 215, 1);

  font-family: Microsoft YaHei;
  font-size: 14px;
  font-weight: 400;
  letter-spacing: 0px;
  text-align: left;
}

.leftTree .Search .txt {
  width: 100%;
  height: 100%;
  border: none;
  background-color: #00000000;
  text-indent: 5px;
  line-height: 36px;
  color: rgb(96, 98, 102);
}

.leftTree .Search {
  width: 100%;
  margin-top: 10px;
  height: 36px;
  border: 1px solid rgba(189, 198, 215, 1);
  border-radius: 4px;
  box-sizing: border-box;
}

.leftTree .head .nodeEdit {
  color: rgba(2, 124, 251, 1);
  cursor: pointer;
  font-family: Microsoft YaHei;
  font-size: 14px;
  font-weight: 400;
  line-height: 18px;
  letter-spacing: 0px;
  text-align: left;
}

.leftTree .head .title {
  color: rgba(56, 64, 79, 1);

  font-family: Microsoft YaHei;
  font-size: 14px;
  font-weight: 700;
  line-height: 18px;
  letter-spacing: 0px;
  text-align: left;
}

.leftTree .head {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
  align-content: center;
  justify-content: space-between;
  align-items: center;
  width: 100%;
  height: 40px;
  border-bottom: 1px solid rgba(235, 238, 248, 1);
}

.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;
}

input:focus {
  outline: none;
}

.H100 {
  height: 100%;
}

.content {
  width: 100%;
  min-height: calc(100vh - 84px);
  height: calc(100vh - 84px);
  background-color: #ffffff;
  font-size: 16px;
  box-sizing: border-box;
  padding: 8px 20px;
  font-family: 'Microsoft YaHei';
}

.leftTree {
  width: 18%;
  height: 100%;
  border-radius: 4px;
  box-shadow: 0px 0px 6px 0px rgba(0, 34, 96, 0.1);
  background: rgba(255, 255, 255, 1);
  margin-right: 15px;
  box-sizing: border-box;
  padding: 12px 13px;
}

.main {
  width: calc(82% - 15px);
  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;
}

.moveDev {
  margin-right: 10px;
  color: rgba(2, 124, 251, 1);

  font-family: Noto Sans SC;
  font-size: 12px;
  font-weight: 400;
  letter-spacing: 0px;
}

.delDev {
  color: rgba(224, 52, 52, 1);

  font-family: Noto Sans SC;
  font-size: 12px;
  font-weight: 400;

  letter-spacing: 0px;
}

.gridTool {
  padding-bottom: 10px;
}

:deep .el-tree-node__content {
  height: auto !important;
}

:deep .is-link,
.is-link {
  cursor: pointer;
}
</style>
