<template>
  <div
    class="content"
    style="height: calc(100vh - 82px); overflow-y: auto"
    v-if="group === '数据'"
  >
    <div class="data-header">
      <div
        class="flex mb-16"
        style="justify-content: space-between; padding-right: 8px"
      >
        <div style="line-height: 32px">数据列表</div>
        <div class="flex">
          <t-tooltip content="批量导入数据图元到画布" placement="top">
            <div @click="onCheckAllChange" class="icon-box">
              <DragDropIcon  :style="{
                  color: data.checkAll ? 'var(--color-primary)' : '',
                }"/>
            </div>
          </t-tooltip>
          <t-tooltip content="开启全局数据模拟" placement="top">
            <div  @click="onChangeMock" class="icon-box">
              <RouterWaveIcon
                :style="{
                  color: data.enableMock ? 'var(--color-primary)' : '',
                }"
              />
            </div>
          </t-tooltip>
          <t-dropdown :minColumnWidth="168">
            <div class="icon-box">
              <AddIcon />
            </div>
            <t-dropdown-menu>
              <t-dropdown-item @click="onShowIot"> 物联网平台 </t-dropdown-item>
              <t-dropdown-item @click="addSql"> SQL数据源 </t-dropdown-item>
              <t-dropdown-item @click="addNetwork('mqtt')"> MQTT </t-dropdown-item>
              <t-dropdown-item @click="addNetwork('websocket')"> Websocket </t-dropdown-item>
              <t-dropdown-item @click="addNetwork('http')"> HTTP </t-dropdown-item>
              <t-dropdown-item @click="addNetwork('SSE')"> SSE </t-dropdown-item>
            </t-dropdown-menu>
          </t-dropdown>
        </div>
      </div>
      <div class="flex">
        <!-- <t-tooltip content="可批量导入数据图元到画布" placement="top">
          <t-checkbox v-model="data.checkAll" @change="onCheckAllChange"
            >批量导入到画布</t-checkbox
          >
        </t-tooltip> -->
        <!-- <t-tooltip content="开启全局数据模拟" placement="top">
          <t-checkbox v-model="data.enableMock" @change="onChangeMock"
            >开启</t-checkbox
          >
        </t-tooltip> -->
        <div class="input-search" style="width: 100%;margin-top: 0px;">
          <div class="btn">
            <search-icon class="hover" />
          </div>
          <t-input
            v-model="dataSearch"
            @change="onSearchData"
            @enter="onSearchData"
            placeholder="搜索我的数据列表"
          />
        </div>
      </div>
    </div>
    <div v-if="data.iotTree?.length">
      <div class="flex mt-16 between" style="height: 32px; line-height: 32px">
        <!-- <div class="flex"> -->
          <!-- <ApplicationIcon class="tree-icon mt-8" /> -->
          <div class="datasource-title">物联网平台</div>
        <!-- </div> -->
        <!-- <div>
          <Edit2Icon  class="mr-12 hover" style="width: 14px;height: 14px;" @click="onShowIot" />
        </div> -->
      </div>
      <!-- <div> -->
      <div
        :draggable="data.checkAll ? true : false"
        @dragstart="onAddShape($event, data.iotTree,'iot')"
        @dragend="onAddShapeEnd"
      >
        <t-tree
          :draggable="false"
          v-model="allChecked"
          style="overflow-y: hidden"
          activeMultiple
          :data="data.iotTree"
          :expand-parent="true"
          :checkable="data.checkAll"
          :checkStrictly="false"
          :filter="dataFilter"
        />
      </div>
      <!-- </div> -->
      <div
        id="dragElem-iot"
        style="position: absolute; left: 0; z-index: -999"
        v-if="data.iotTree.length"
      >
        <div v-for="device in data.iotTree">
          <div
            class="flex mt-4"
            v-for="(prop, i) in device.children"
            v-show="allChecked.includes(prop.value)"
          >
            <div style="width: 100px; text-align: end">{{ prop.label }}：</div>
            <div class="ml-4">{{ prop.mock }}</div>
          </div>
        </div>
      </div>
    </div>
    <div v-if="data.sqls?.length">
      <div class="flex mt-16" style="height: 32px">
        <!-- <DataIcon class="tree-icon" /> -->
        <div class="datasource-title">SQL数据源</div>
      </div>
      <div
        :draggable="data.checkAll ? true : false"
        @dragstart="onAddShape($event, data.sqls,'sql')"
        @dragend="onAddShapeEnd"
      >
      <t-tree
        :draggable="false"
        :key="sqlTreeKey"
        hover
        style="overflow-y: hidden"
        activeMultiple
        :data="data.sqls"
        :expand-parent="true"
        :checkable="data.checkAll"
        :checkStrictly="false"
      >
        <template #operations="{ node }">
          <tepmlate v-if="!node.getParent()">
            <Edit2Icon
              class="mr-12"
              @click="editSql(node.data, node.getIndex())"
            />
            <DeleteIcon class="mr-8" @click="deleteSql(node.getIndex())" />
          </tepmlate>
        </template>
      </t-tree>
      </div>
      <div
        id="dragElem-sql"
        style="position: absolute; left: 0; z-index: -999"
        v-if="data.sqls.length"
      >
        <div v-for="item in data.sqls">
          <div
            class="flex mt-4"
            v-for="(prop, i) in item.children"
            v-show="sqlsCheked.includes(prop.value)"
          >
            <div style="width: 100px; text-align: end">{{ prop.label }}：</div>
            <div class="ml-4">{{ prop.mock }}</div>
          </div>
        </div>
      </div>
    </div>
    <!-- <div v-if="data.networks?.length">
      <div class="flex mt-16 between" style="height: 32px; line-height: 32px">
        <div class="flex">
          <ControlPlatformIcon class="tree-icon mt-8" />
          <div class="ml-8">Mqtt</div>
        </div>
        <div>
        </div>
      </div>
      <div
        :draggable="data.checkAll ? true : false"
        @dragstart="onAddShape($event, data.networks,'network')"
        @dragend="onAddShapeEnd"
      >
      <t-tree
        :draggable="false"
        class="ml-16"
        v-model="networksCheked"
        ref="networkTree"
        :key="networkTreeKey"
        style="overflow-y: hidden"
        activeMultiple
        :data="data.networks"
        :expand-parent="true"
        :checkable="data.checkAll"
        :checkStrictly="false"
      >
        <template #operations="{ node }">
          <template v-if="node.getParent()">
            <Edit2Icon
              class="mr-12"
              @click="showAddData(node.getParent().data, node)"
            />
            <DeleteIcon
              class="mr-8"
              @click="
                deleteData(node.getParent().data, node.getIndex());
                node.remove();
              "
            />
          </template>
          <template v-else>
            <t-dropdown :minColumnWidth="168" :hide-after-item-click="false">
              <AddIcon class="mr-12" />
              <t-dropdown-menu>
                <t-dropdown-item
                  :value="2"
                  :divider="true"
                  @click="showAddData(node.data)"
                >
                  新建属性
                </t-dropdown-item>
                <t-dropdown-item :value="2" @click="importDataset(node.data)">
                  从Excel导入
                </t-dropdown-item>
                <t-dropdown-item :value="4">
                  <a
                    :href="
                      isDownload
                        ? '/v/data.xlsx'
                        : cdn
                        ? cdn + '/v/data.xlsx?r=' + Math.random()
                        : '/data.xlsx'
                    "
                    style="color: var(--td-text-color-primary)"
                    @click.stop
                  >
                    下载Excel示例
                  </a>
                </t-dropdown-item>
              </t-dropdown-menu>
            </t-dropdown>
            <Edit2Icon
              class="mr-12"
              @click="editNetwork(node.data, node.getIndex())"
            />
            <DeleteIcon
              class="mr-8"
              @click="
                deleteNetwork(node.getIndex());
                node.remove();
              "
            />
          </template>
        </template>
      </t-tree>
      </div>
      <div
        id="dragElem-network"
        style="position: absolute; left: 0; z-index: -999"
        v-if="data.networks.length"
      >
        <div v-for="item in data.networks">
          <div
            class="flex mt-4"
            v-for="(prop, i) in item.children"
            v-show="networksCheked.includes(prop.value)"
          >
            <div style="width: 100px; text-align: end">{{ prop.label }}：</div>
            <div class="ml-4">{{ prop.mock }}</div>
          </div>
        </div>
      </div>
    </div> -->
    <div v-if="data.mqtt_networks?.length">
      <div class="flex mt-16 between" style="height: 32px; line-height: 32px">
        <!-- <div class="flex"> -->
          <!-- <ControlPlatformIcon class="tree-icon mt-8" /> -->
          <div class="datasource-title">MQTT</div>
        <!-- </div> -->
        <div>
        </div>
      </div>
      <div
        :draggable="data.checkAll ? true : false"
        @dragstart="onAddShape($event, data.networks,'network')"
        @dragend="onAddShapeEnd"
      >
      <t-tree
        :draggable="false"
        v-model="networksCheked"
        ref="mqttTree"
        :key="mqttTreeKey"
        style="overflow-y: hidden"
        activeMultiple
        :data="data.mqtt_networks"
        :expand-parent="true"
        :checkable="data.checkAll"
        :checkStrictly="false"
      >
        <template #operations="{ node }">
          <template v-if="node.getParent()">
            <Edit2Icon
              class="mr-12"
              @click="showAddData(node.getParent().data, node)"
            />
            <DeleteIcon
              class="mr-8"
              @click="
                deleteData(node.getParent().data, node.getIndex());
                node.remove();
              "
            />
          </template>
          <template v-else>
            <t-dropdown :minColumnWidth="168" :hide-after-item-click="false">
              <AddIcon class="mr-12 hover" />
              <t-dropdown-menu>
                <t-dropdown-item
                  :value="2"
                  :divider="true"
                  @click="showAddData(node.data)"
                >
                  新建属性
                </t-dropdown-item>
                <t-dropdown-item :value="3" :divider="true">
                  在线接口

                  <t-dropdown-menu
                    class="menu-item-input"
                    style="max-width: 216px !important"
                  >
                    <t-dropdown-item
                      :value="3 - 1"
                      style="max-width: 216px !important"
                    >
                      <div
                        class="data-input-box"
                        style="max-width: 216px !important"
                      >
                        <t-input
                          label="地址："
                          style="width: 216px"
                          placeholder="请输入地址"
                          v-model="data.dataset.url"
                          @blur="getDatas(node.data)"
                          @enter="getDatas(node.data)"
                        >
                          <template #suffixIcon>
                            <CloudDownloadIcon
                              @click="getDatas(node.data)"
                              :style="{ cursor: 'pointer' }"
                            />
                          </template>
                        </t-input>
                      </div>
                    </t-dropdown-item>
                  </t-dropdown-menu>
                </t-dropdown-item>
                <t-dropdown-item :value="2" @click="importDataset(node.data)">
                  从Excel导入
                </t-dropdown-item>
                <t-dropdown-item :value="4">
                  <a
                    :href="'/data.xlsx'
                    "
                    style="color: var(--td-text-color-primary)"
                    @click.stop
                  >
                    下载Excel示例
                  </a>
                </t-dropdown-item>
              </t-dropdown-menu>
            </t-dropdown>
            <Edit2Icon
              class="mr-12 hover"
              @click="editNetwork(node.data, node.data.tem_index)"
            />
            <DeleteIcon
              class="mr-8"
              @click="
                deleteNetwork(node.data.tem_index);
                node.remove();
              "
            />
          </template>
        </template>
      </t-tree>
      </div>
      <div
        id="dragElem-network"
        style="position: absolute; left: 0; z-index: -999"
        v-if="data.networks.length"
      >
        <div v-for="item in data.networks">
          <div
            class="flex mt-4"
            v-for="(prop, i) in item.children"
            v-show="networksCheked.includes(prop.value)"
          >
            <div style="width: 100px; text-align: end">{{ prop.label }}：</div>
            <div class="ml-4">{{ prop.mock }}</div>
          </div>
        </div>
      </div>
    </div>
    <div v-if="data.ws_networks?.length">
      <div class="flex mt-16 between" style="height: 32px; line-height: 32px">
        <!-- <div class="flex"> -->
          <!-- <ControlPlatformIcon class="tree-icon mt-8" /> -->
          <div class="datasource-title">Websocket</div>
        <!-- </div> -->
        <div>
        </div>
      </div>
      <div
        :draggable="data.checkAll ? true : false"
        @dragstart="onAddShape($event, data.networks,'network')"
        @dragend="onAddShapeEnd"
      >
      <t-tree
        :draggable="false"
        v-model="networksCheked"
        ref="wsTree"
        :key="wsTreeKey"
        style="overflow-y: hidden"
        activeMultiple
        :data="data.ws_networks"
        :expand-parent="true"
        :checkable="data.checkAll"
        :checkStrictly="false"
      >
        <template #operations="{ node }">
          <template v-if="node.getParent()">
            <Edit2Icon
              class="mr-12"
              @click="showAddData(node.getParent().data, node)"
            />
            <DeleteIcon
              class="mr-8"
              @click="
                deleteData(node.getParent().data, node.getIndex());
                node.remove();
              "
            />
          </template>
          <template v-else>
            <t-dropdown :minColumnWidth="168" :hide-after-item-click="false">
              <AddIcon class="mr-12" />
              <t-dropdown-menu>
                <t-dropdown-item
                  :value="2"
                  :divider="true"
                  @click="showAddData(node.data)"
                >
                  新建属性
                </t-dropdown-item>
                <t-dropdown-item :value="3" :divider="true">
                  在线接口

                  <t-dropdown-menu
                    class="menu-item-input"
                    style="max-width: 216px !important"
                  >
                    <t-dropdown-item
                      :value="3 - 1"
                      style="max-width: 216px !important"
                    >
                      <div
                        class="data-input-box"
                        style="max-width: 216px !important"
                      >
                        <t-input
                          label="地址："
                          style="width: 216px"
                          placeholder="请输入地址"
                          v-model="data.dataset.url"
                          @blur="getDatas(node.data)"
                          @enter="getDatas(node.data)"
                        >
                          <template #suffixIcon>
                            <CloudDownloadIcon
                              @click="getDatas(node.data)"
                              :style="{ cursor: 'pointer' }"
                            />
                          </template>
                        </t-input>
                      </div>
                    </t-dropdown-item>
                  </t-dropdown-menu>
                </t-dropdown-item>
                <t-dropdown-item :value="2" @click="importDataset(node.data)">
                  从Excel导入
                </t-dropdown-item>
                <t-dropdown-item :value="4">
                  <a
                    :href="'/data.xlsx'"
                    style="color: var(--td-text-color-primary)"
                    @click.stop
                  >
                    下载Excel示例
                  </a>
                </t-dropdown-item>
              </t-dropdown-menu>
            </t-dropdown>
            <Edit2Icon
              class="mr-12"
              @click="editNetwork(node.data, node.data.tem_index)"
            />
            <DeleteIcon
              class="mr-8"
              @click="
                deleteNetwork(node.data.tem_index);
                node.remove();
              "
            />
          </template>
        </template>
      </t-tree>
      </div>
      <div
        id="dragElem-network"
        style="position: absolute; left: 0; z-index: -999"
        v-if="data.networks.length"
      >
        <div v-for="item in data.networks">
          <div
            class="flex mt-4"
            v-for="(prop, i) in item.children"
            v-show="networksCheked.includes(prop.value)"
          >
            <div style="width: 100px; text-align: end">{{ prop.label }}：</div>
            <div class="ml-4">{{ prop.mock }}</div>
          </div>
        </div>
      </div>
    </div>
    <div v-if="data.http_networks?.length">
      <div class="flex mt-16 between" style="height: 32px; line-height: 32px">
        <!-- <div class="flex"> -->
          <!-- <ControlPlatformIcon class="tree-icon mt-8" /> -->
          <div class="datasource-title">HTTP</div>
        <!-- </div> -->
        <div>
        </div>
      </div>
      <div
        :draggable="data.checkAll ? true : false"
        @dragstart="onAddShape($event, data.networks,'network')"
        @dragend="onAddShapeEnd"
      >
      <t-tree
        :draggable="false"
        v-model="networksCheked"
        ref="httpTree"
        :key="httpTreeKey"
        style="overflow-y: hidden"
        activeMultiple
        :data="data.http_networks"
        :expand-parent="true"
        :checkable="data.checkAll"
        :checkStrictly="false"
        :filter="dataFilter"
      >
        <template #operations="{ node }">
          <template v-if="node.getParent()">
            <Edit2Icon
              class="mr-12"
              @click="showAddData(node.getParent().data, node)"
            />
            <DeleteIcon
              class="mr-8"
              @click="
                deleteData(node.getParent().data, node.getIndex());
                node.remove();
              "
            />
          </template>
          <template v-else>
            <t-dropdown :minColumnWidth="168" :hide-after-item-click="false">
              <AddIcon class="mr-12" />
              <t-dropdown-menu>
                <t-dropdown-item
                  :value="2"
                  :divider="true"
                  @click="showAddData(node.data)"
                >
                  新建属性
                </t-dropdown-item>
                <t-dropdown-item :value="3" :divider="true">
                  在线接口

                  <t-dropdown-menu
                    class="menu-item-input"
                    style="max-width: 216px !important"
                  >
                    <t-dropdown-item
                      :value="3 - 1"
                      style="max-width: 216px !important"
                    >
                      <div
                        class="data-input-box"
                        style="max-width: 216px !important"
                      >
                        <t-input
                          label="地址："
                          style="width: 216px"
                          placeholder="请输入地址"
                          v-model="data.dataset.url"
                          @blur="getDatas(node.data)"
                          @enter="getDatas(node.data)"
                        >
                          <template #suffixIcon>
                            <CloudDownloadIcon
                              @click="getDatas(node.data)"
                              :style="{ cursor: 'pointer' }"
                            />
                          </template>
                        </t-input>
                      </div>
                    </t-dropdown-item>
                  </t-dropdown-menu>
                </t-dropdown-item>
                <t-dropdown-item :value="2" @click="importDataset(node.data)">
                  从Excel导入
                </t-dropdown-item>
                <t-dropdown-item :value="4">
                  <a
                    :href="'/data.xlsx'"
                    style="color: var(--td-text-color-primary)"
                    @click.stop
                  >
                    下载Excel示例
                  </a>
                </t-dropdown-item>
              </t-dropdown-menu>
            </t-dropdown>
            <Edit2Icon
              class="mr-12"
              @click="editNetwork(node.data, node.data.tem_index)"
            />
            <DeleteIcon
              class="mr-8"
              @click="
                deleteNetwork(node.data.tem_index);
                node.remove();
              "
            />
          </template>
        </template>
      </t-tree>
      </div>
      <div
        id="dragElem-network"
        style="position: absolute; left: 0; z-index: -999"
        v-if="data.networks.length"
      >
        <div v-for="item in data.networks">
          <div
            class="flex mt-4"
            v-for="(prop, i) in item.children"
            v-show="networksCheked.includes(prop.value)"
          >
            <div style="width: 100px; text-align: end">{{ prop.label }}：</div>
            <div class="ml-4">{{ prop.mock }}</div>
          </div>
        </div>
      </div>
    </div>
    <div v-if="data.SSE_networks?.length">
      <div class="flex mt-16 between" style="height: 32px; line-height: 32px">
        <!-- <div class="flex"> -->
          <!-- <ControlPlatformIcon class="tree-icon mt-8" /> -->
          <div class="datasource-title">SSE</div>
        <!-- </div> -->
        <div>
        </div>
      </div>
      <div
        :draggable="data.checkAll ? true : false"
        @dragstart="onAddShape($event, data.networks,'network')"
        @dragend="onAddShapeEnd"
      >
      <t-tree
        :draggable="false"
        v-model="networksCheked"
        ref="SSETree"
        :key="SSETreeKey"
        style="overflow-y: hidden"
        activeMultiple
        :data="data.SSE_networks"
        :expand-parent="true"
        :checkable="data.checkAll"
        :checkStrictly="false"
      >
        <template #operations="{ node }">
          <template v-if="node.getParent()">
            <Edit2Icon
              class="mr-12"
              @click="showAddData(node.getParent().data, node)"
            />
            <DeleteIcon
              class="mr-8"
              @click="
                deleteData(node.getParent().data, node.getIndex());
                node.remove();
              "
            />
          </template>
          <template v-else>
            <t-dropdown :minColumnWidth="168" :hide-after-item-click="false">
              <AddIcon class="mr-12" />
              <t-dropdown-menu>
                <t-dropdown-item
                  :value="2"
                  :divider="true"
                  @click="showAddData(node.data)"
                >
                  新建属性
                </t-dropdown-item>
                <t-dropdown-item :value="3" :divider="true">
                  在线接口

                  <t-dropdown-menu
                    class="menu-item-input"
                    style="max-width: 216px !important"
                  >
                    <t-dropdown-item
                      :value="3 - 1"
                      style="max-width: 216px !important"
                    >
                      <div
                        class="data-input-box"
                        style="max-width: 216px !important"
                      >
                        <t-input
                          label="地址："
                          style="width: 216px"
                          placeholder="请输入地址"
                          v-model="data.dataset.url"
                          @blur="getDatas(node.data)"
                          @enter="getDatas(node.data)"
                        >
                          <template #suffixIcon>
                            <CloudDownloadIcon
                              @click="getDatas(node.data)"
                              :style="{ cursor: 'pointer' }"
                            />
                          </template>
                        </t-input>
                      </div>
                    </t-dropdown-item>
                  </t-dropdown-menu>
                </t-dropdown-item>
                <t-dropdown-item :value="2" @click="importDataset(node.data)">
                  从Excel导入
                </t-dropdown-item>
                <t-dropdown-item :value="4">
                  <a
                    :href="'/data.xlsx'"
                    style="color: var(--td-text-color-primary)"
                    @click.stop
                  >
                    下载Excel示例
                  </a>
                </t-dropdown-item>
              </t-dropdown-menu>
            </t-dropdown>
            <Edit2Icon
              class="mr-12"
              @click="editNetwork(node.data, node.data.tem_index)"
            />
            <DeleteIcon
              class="mr-8"
              @click="
                deleteNetwork(node.data.tem_index);
                node.remove();
              "
            />
          </template>
        </template>
      </t-tree>
      </div>
      <div
        id="dragElem-network"
        style="position: absolute; left: 0; z-index: -999"
        v-if="data.networks.length"
      >
        <div v-for="item in data.networks">
          <div
            class="flex mt-4"
            v-for="(prop, i) in item.children"
            v-show="networksCheked.includes(prop.value)"
          >
            <div style="width: 100px; text-align: end">{{ prop.label }}：</div>
            <div class="ml-4">{{ prop.mock }}</div>
          </div>
        </div>
      </div>
    </div>
    <div
      class="flex column middle nodata"
      v-if="!data.iotTree.length && !data.sqls.length && !data.networks.length"
    >
      <img src="/img/no-data.png" />
      <div class="gray center">暂无数据</div>
      <!-- <div class="mt-20">
        <t-button theme="primary" @click="addNetwork()">
          添加数据源
        </t-button>
      </div> -->
    </div>
  </div>
  <div class="content" v-if="group === '解析'">
    <div class="flex between">
      <div class="title">数据{{ group }}</div>
    </div>
    <div class="mt-8">
      <CodeEditor
        :key="data.randomkey"
        v-model="data.socketCbJs"
        style="min-height: 300px"
        @change="onSocketCbJsChange"
      />
      <div class="data-full-icon hover">
        <Fullscreen2Icon @click="showDataTransformation" />
      </div>
    </div>
    <div class="mt-16">
      参考文档：
      <a
        target="_blank"
        href="https://doc.le5le.com/document/136233394#%E8%A7%A3%E6%9E%90%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F"
      >
        解析自定义格式数据</a
      >
    </div>
  </div>

  <t-dialog
    v-if="addDataDialog.show"
    :visible="true"
    class="data-dialog"
    :header="addDataDialog.header"
    @close="addDataDialog.show = false"
    @confirm="onOkAddData"
  >
    <!-- <div class="form-item mt-16">
        <label>设备</label>
        <t-input v-model="addDataDialog.data.device" placeholder="设备名称" />
      </div> -->
    <div class="form-item mt-16">
      <label>显示名称</label>
      <t-input
        @change="changeDataLabel($event)"
        :value="addDataDialog.data.label"
        placeholder="属性简短描述"
      />
    </div>
    <div class="form-item mt-16">
      <label>属性名</label>
      <t-input
        @change="changeDataID($event)"
        :value="addDataDialog.data.id"
        placeholder="属性名"
      />
    </div>
    <!-- <div class="form-item mt-16">
      <label>类型</label>
      <t-select
        class="w-full"
        :options="typeOptions"
        v-model="addDataDialog.data.type"
        placeholder="字符串"
        @change="addDataDialog.data.value = null"
      />
    </div>
    <div class="form-item mt-16">
      <label
        >值范围
        <t-tooltip content="可用做数据模拟" placement="top">
          <HelpCircleIcon style="font-size: 12px" />
        </t-tooltip>
      </label>
      <div class="w-full">
        <t-input v-model="addDataDialog.data.mock" placeholder="值范围" />
        <h6 class="desc mt-8" style="font-size: 12px">值范围说明</h6>
        <ul class="desc ml-16" style="font-size: 12px">
          <li>
            <label class="inline" style="width: 80px">固定值：</label>
            直接填写，例如：10
          </li>
          <li>
            <label class="inline" style="width: 80px">随机值：</label>
            值1,值2,...。例如：1,2,3,4,5
          </li>
          <li>
            <label class="inline" style="width: 80px">范围数字：</label>
            最小值-最大值。例如：0-1.0 或 0-100
          </li>
          <li>
            <label class="inline" style="width: 80px">随机字符串：</label>
            [长度]。例如：[8]
          </li>
        </ul>
      </div>
    </div> -->
  </t-dialog>
  <t-dialog
    v-if="networkDialog.show"
    :visible="true"
    width="800px"
    class="data-dialog"
    :header="networkDialog.header"
    @close="networkDialog.show = false"
    @confirm="onOkNetwork"
  >
    <template #footer>
      <div class="flex mr-8" style="justify-content: end">
        <!-- <t-checkbox v-model="networkDialog.save" class="mr-12">
          同时保存到我的数据源
        </t-checkbox> -->
        <t-button @click="onOkNetwork">确定</t-button>
      </div>
    </template>
    <div style="max-height: 450px; padding: 8px; overflow-y: auto">
      <Net v-model="networkDialog.network" />
    </div>
  </t-dialog>
  <t-dialog
    v-if="dataTransformationDialog.show"
    :visible="true"
    header="数据监听"
    @confirm="onOkDataTransformation"
    @close="dataTransformationDialog.show = false"
    :width="800"
  >
    <CodeEditor v-model="dataTransformationDialog.data" style="height: 300px" />
    <div class="mt-8">
      参考文档：
      <a
        target="_blank"
        href="https://doc.le5le.com/document/136233394#%E8%A7%A3%E6%9E%90%E8%87%AA%E5%AE%9A%E4%B9%89%E6%95%B0%E6%8D%AE%E6%A0%BC%E5%BC%8F"
      >
        解析自定义格式数据</a
      >
    </div>
  </t-dialog>
  <t-dialog
    v-if="sqlDialog.show"
    :visible="true"
    width="800px"
    class="data-dialog"
    :header="sqlDialog.header"
    @close="sqlDialog.show = false"
    @confirm="onOkSql"
  >
    <div style="max-height: 450px; padding: 8px">
      <div class="form-item mt-8">
        <label>sql数据源</label>
        <t-select v-model="sqlDialog.sql.dbid" placeholder="请选择数据源">
          <t-option
            v-for="sql in sqlList"
            @click="sqlChange(sql)"
            :key="sql.id"
            :value="sql.id"
            :label="sql.name + '(' + sql.dbType + ')'"
          />
        </t-select>
      </div>
      <div class="form-item mt-8">
        <label>sql轮询间隔</label>
        <t-input-number
          theme="column"
          v-model="sqlDialog.sql.interval"
          placeholder="不填，仅初始执行一次"
        />
      </div>
      <div class="form-item mt-8">
        <label>查询方式</label>
        <t-select v-model="sqlDialog.sql.method">
          <t-option key="get" value="get" label="单条" />
          <t-option key="list" value="list" label="列表" />
        </t-select>
      </div>
      <div class="form-item mt-8">
        <label>sql语句</label>
        <CodeEditor
          :json="false"
          :language="'sql'"
          v-model="sqlDialog.sql.sql"
          class="mt-4"
          style="height: 100px"
        />
      </div>
      <div v-if="sqlDialog.sql.method === 'list'" class="form-item mt-8">
        <label>第几页</label>
        <t-input-number
          v-model="sqlDialog.sql.current"
          theme="normal"
          :min="1"
          placeholder="默认1"
        />
      </div>
      <div v-if="sqlDialog.sql.method === 'list'" class="form-item mt-8">
        <label>每页数量</label>
        <t-input-number
          v-model="sqlDialog.sql.pageSize"
          theme="normal"
          placeholder="默认20"
          :min="1"
        />
      </div>
      <div class="form-item mt-8">
        <label>关联属性名</label>
        <t-input v-model="sqlDialog.sql.bindId" placeholder="关联属性名" />
      </div>
      <div class="flex mt-8">
        <!-- <label> -->
        <t-button style="width: 75px" @click="sqlTest">连接测试</t-button>
        <!-- </label> -->
        <p class="ml-8" style="width: 700px">{{ sqlDialog.result }}</p>
      </div>
    </div>
  </t-dialog>
  <t-dialog
    v-if="iotDialog.show"
    :visible="true"
    width="472px"
    class="data-dialog"
    :header="iotDialog.header"
    @close="iotDialog.show = false"
    @confirm="onOkIot"
  >
    <!-- <t-input
      v-model="iotSearch"
      @change="onSearchIot"
      @enter="onSearchIot"
      placeholder="设备属性搜索"
    /> -->
    <div class="input-search" style="padding: 0px 4px">
      <div class="btn" style="left: 14px">
        <img src="/img/icon_search_gray.svg" />
      </div>
      <t-input
        style="height: 32px"
        v-model="iotSearch"
        @change="onSearchIot"
        @enter="onSearchIot"
        placeholder="搜索设备属性"
      />
    </div>
    <div style="height: 320px; margin-top: 8px; overflow-y: scroll">
      <t-tree
        style="overflow-y: hidden"
        activeMultiple
        v-model="checkedIots"
        :data="iots"
        :expand-parent="true"
        :checkable="true"
        :checkStrictly="false"
        allow-fold-node-on-filter
        :filter="iotFilter"
        :scroll="{
          // rowHeight: 34,
          bufferSize: 10,
          threshold: 10,
          type: 'virtual',
        }"
      />
    </div>
  </t-dialog>
</template>

<script lang="ts" setup>
import { reactive, defineComponent, ref, onMounted, toRaw, watch } from 'vue';
import {
  FileImportIcon,
  FileExportIcon,
  DeleteIcon,
  AddIcon,
  AddCircleIcon,
  MinusCircleIcon,
  Edit2Icon,
  FileExcelIcon,
  CloudDownloadIcon,
  SearchIcon,
  Fullscreen2Icon,
  FullscreenExit1Icon,
  HelpCircleIcon,
  CaretDownSmallIcon,
  CaretRightSmallIcon,
  RouterWaveIcon,
  ArrowUpDown3Icon,
  Download1Icon,
  ApplicationIcon,
  DataIcon,
  ControlPlatformIcon,
  DragDropIcon
} from 'tdesign-icons-vue-next';
import { typeOptions } from '@/services/common';
import { MessagePlugin } from 'tdesign-vue-next';
import { Pen, deepClone } from '@meta2d/core';
import { useDot } from '@/services/common';
import { cdn } from '@/services/api';
import { importExcel, saveAsExcel } from '@/services/excel';
import axios from 'axios';
import { transformData } from '@/services/utils';
import { debounce } from '@/services/debouce';
import Net from '@/views/components/Net.vue';
import CodeEditor from '@/views/components/common/CodeEditor.vue';
import { s8 } from '@/services/random';
import { useUser } from '@/services/user';
import {
  getSqlSourceList,
  getDevices,
  getDeviceProperties,
  getMqttUrl,
  doSqlCode,
} from '@/services/iot';

const props = defineProps<{
  group: string;
}>();

const { user } = useUser();

const { dot, setDot } = useDot();

const data = reactive({
  //列表
  datesetBak: {},
  datasetId: '',
  networks: [],
  http_networks:[],
  ws_networks:[],
  mqtt_networks:[],
  SSE_networks:[],
  datasetList: [],
  dataset: {
    name: '',
    id: '',
    url: '',
    devices: [],
  } as any,
  checkAll: false,
  //获取
  networkList: [],
  input: '',
  popupVisible: false,
  networkId: '',

  //监听
  socketCbJs: '',
  full: false,

  dataMocks: [
    // {
    //   name: '',
    //   id: '',
    //   enableMock: true,
    //   mock: 'aaa',
    //   type: 'string',
    //   expend: true,
    //   show: false,
    // },
  ],
  enableMock: false,
  randomkey: s8(),
  sqls: [],
  iotList: [],
  iotTree: [],
});

onMounted(() => {
  meta2d.store.data.networks?.forEach((network:any)=>
  { 
    if(!network.label){
      network.label = network.name;
    }
    if(!network.value){
      network.value = s8();
    }
    network.checkable = false
  });
  data.networks = meta2d.store.data.networks || [];
  data.dataset = (meta2d.store.data as any).dataset || {};
  if( data.networks?.length&&data.dataset?.devices){
    if(!data.networks[0].children?.length){
      data.dataset.devices.forEach((item)=>item.value = item.id);
      data.networks[0].children = deepClone(data.dataset.devices);
    }
  }
  data.socketCbJs = meta2d.store.data.socketCbJs || '';
  // data.dataMocks = meta2d.store.data.dataMocks || [];
  data.enableMock = meta2d.store.data.enableMock || false;
  // getNetworks();
  // getDatasets();
  // getIot();
  data.sqls = meta2d.store.data.sqls || [];
  data.iotList = meta2d.store.data.iot?.list || [];

  data.iotTree = meta2d.store.data.iot?.tree || [];
  getThirdNetwork();
});

const dataSearch = ref('');
const dataFilter = ref(null);
const onSearchData = () => {
  dataFilter.value = dataSearch.value ? (node) => { return node.data.label?.indexOf(dataSearch.value) >= 0|| node.data.value?.indexOf(dataSearch.value) >= 0 }: null;
};

const getThirdNetwork = (key?:string)=>{
  if(!meta2d.store.data.networks?.length){
    return;
  }
  meta2d.store.data.networks.forEach((item:any,index)=>{
    item.tem_index = index;
  });
  if(!key||key==='http'){
    data.http_networks = meta2d.store.data.networks.filter((item)=>item.protocol==='http') || [];  
  }
  if(!key||key==='websocket'){
    data.ws_networks = meta2d.store.data.networks.filter((item)=>item.protocol==='websocket') || [];
  }
  if(!key||key==='mqtt'){
    data.mqtt_networks = meta2d.store.data.networks.filter((item)=>item.protocol==='mqtt') || [];
  }
  if(!key||key==='SSE'){
    data.SSE_networks = meta2d.store.data.networks.filter((item)=>item.protocol==='SSE') || [];
  }
}

const iotDialog = ref({
  show: false,
  header: '添加物联网平台',
});

const onOkIot = () => {
  let _iots = [];
  iots.value.forEach((item) => {
    if (checkedIots.value.includes(item.value)) {
      _iots.push(deepClone(item));
    } else {
      if (item.children?.length) {
        const child = item.children.filter((child) =>
          checkedIots.value.includes(child.value)
        );
        if (child.length) {
          _iots.push({
            label: item.label,
            value: item.value,
            deviceId: item.deviceId, //item.id
            token: item.token,
            children: deepClone(child),
          });
        }
      }
    }
  });
  data.iotTree = _iots;
  if (!meta2d.store.data.iot) {
    meta2d.store.data.iot = {};
  }
  meta2d.store.data.iot.tree = _iots;
  iotDialog.value.show = false;
};

const onShowIot = async () => {
  await getIotTree();
  getCheckedIots();
  iotDialog.value.show = true;
};

const iots = ref([]);

const getIotTree = async () => {
  if (iots.value.length) {
    return;
  }
  let ret = await getDevices();
  const type = ret.type;
  const list = ret.list;
  for (let i = 0; i < list.length; i++) {
    const item = list[i];
    item.label = item.name;
    item.value = item.id;

    item.deviceId = item.id; //item.id
    item.token = item.token;
    // item.children = true;
    // item.checkable = false;
    let properties = await getDeviceProperties(item.id);
    item.children = properties.map((prop: any) => {
      return {
        label: prop.name,
        value: type?prop.key:item.deviceId + '#' + prop.key,
        _label: item.name + '#' + prop.name,
        token: item.token,
        class: 'iot',
      };
    });
    if (!item.children.length) {
      item.checkable = false;
    }
  }
  // setTimeout(()=>{
  iots.value = deepClone(list);
  // },3000);
};

const getCheckedIots = ()=>{
  let arr = [];
  meta2d.store.data?.iot?.tree.forEach((item)=>{
    arr.push(...item.children?.map((_item)=>_item.value));
  });
  checkedIots.value = arr;
}

const iotSearch = ref('');
const iotFilter = ref(null);
const onSearchIot = () => {
  iotFilter.value = iotSearch.value
    ? (node) =>
        node.data.label.indexOf(iotSearch.value) >= 0 ||
        node.data.value.indexOf(iotSearch.value) >= 0
    : null;
};

const checkedIots = ref([]);

const onShowSql = async () => {
  addSql();
};
const iotLoad = async (node) => {
  let properties = await getDeviceProperties(node.value);
  return properties.map((item: any) => {
    item.label = item.name;
    item.value = node.data.deviceId + '#' + item.key;
    item._label = node.data.name + '#' + item.name;
    // item.sn = item.sn;
    item.token = node.data.token;
    return item;
  });
};

const doBind = (node) => {
};

const iotMqtt = ref({});
const iotProtocol = ref('');
const getIot = async () => {
  let canmqtt: any = await getMqttUrl();
  if (canmqtt && canmqtt.host) {
    iotMqtt.value = canmqtt;
  }

  if (meta2d.store.data.iot) {
    iotProtocol.value = meta2d.store.data.iot.protocol;
  }
};

const selectIot = (protocol: any) => {
  if (iotProtocol.value === protocol) {
    meta2d.store.data.iot = {};
    iotProtocol.value = '';
  } else {
    if (protocol === 'mqtt') {
      meta2d.store.data.iot = {
        protocol: protocol,
        ...iotMqtt.value,
      };
    } else {
      meta2d.store.data.iot = {
        protocol: protocol,
        // host: iotMqtt.value.host
      };
    }
    iotProtocol.value = protocol;
  }
  meta2d.connectNetwork();
};

const addSql = async () => {
  sqlList.value = await getSqlSourceList();
  sqlDialog.header = '添加sql数据源';
  sqlDialog.show = true;
  sqlDialog.edit = false;
  sqlDialog.sql = {
    interval: undefined,
    sql: '-- eg:SELECT * FROM "directory"',
  };
  sqlDialog.result = '';
};

const editSql = (sql: any, index: number) => {
  sqlDialog.header = '编辑sql数据源';
  sqlDialog.show = true;
  sqlDialog.edit = true;
  sqlDialog.index = index;
  sqlDialog.sql = deepClone(sql);
};

const deleteSql = (index: number) => {
  data.sqls.splice(index, 1);
  (meta2d.store.data as any).sqls = data.sqls;
  sqlTreeKey.value = s8();
  setDot(true);
};
const sqlTreeKey = ref(s8());
const onOkSql = async () => {
  if (!sqlDialog.sql.dbid) {
    MessagePlugin.error('请选择数据源');
    return;
  }
  if (!sqlDialog.sql.sql) {
    MessagePlugin.error('请填写sql语句');
    return;
  }
  if (!sqlDialog.sql.interval) {
    sqlDialog.sql.interval = undefined;
  }
  if (!sqlDialog.sql.bindId) {
    MessagePlugin.error('关联属性名必填');
    return;
  }
  sqlDialog.sql.label = sqlDialog.sql.bindId;
  sqlDialog.sql.value = sqlDialog.sql.bindId;
  // let sql = sqlDialog.value.sql+' LIMIT '+(sqlDialog.value.pageSize||20)+(sqlDialog.value.current>1?(' OFFSET '+(sqlDialog.value.current-1)*sqlDialog.value.pageSize):'');

  if (!sqlDialog.sql.children) {
    await sqlTest();
    sqlTreeKey.value = s8();
  }
  if (!sqlDialog.edit) {
    data.sqls.push(sqlDialog.sql);
    // meta2d.store.data.sqls = data.sqls;
  } else {
    data.sqls[sqlDialog.index] = sqlDialog.sql;
  }
  meta2d.store.data.sqls = toRaw(data.sqls);
  sqlTreeKey.value = s8();
  // data.sqls = deepClone(data.sqls);
  meta2d.connectNetwork();
  sqlDialog.show = false;
};

const sqlDialog = reactive<any>({
  show: false,
  edit: false,
  index: -1,
  header: '添加sql数据源',
  sql: {
    interval: undefined,
    sql: '',
  },
});
const sqlList = ref([]);

const sqlChange = (sql: any) => {
  sqlDialog.sql.dbid = sql.id;
  sqlDialog.sql.dbType = sql.dbType;
  sqlDialog.sql.name = sql.name;
};

const sqlTest = async () => {
  let ret: any = await doSqlCode(sqlDialog.sql);
  if (ret.error) {
    MessagePlugin.error('连接错误：' + ret.error);
    sqlDialog.result = '连接错误：' + ret.error;
  } else {
    if (sqlDialog.sql.method === 'list') {
      sqlDialog.result = '连接成功：[' + JSON.stringify(ret[0]) + ',...]';
      // sqlDialog.sql.columns = ret[0];
      const columnsKeys = Object.keys(ret[0]);
      const children = new Array(ret.length).fill(0).map((item, index) => {
        return {
          label: index + 1 + '',
          value: sqlDialog.sql.bindId + '#' + index,
          _label: sqlDialog.sql.bindId + '#' + index + 1,
          class: 'sql',
          children: columnsKeys.map((key) => {
            return {
              label: key,
              value: sqlDialog.sql.bindId + '#' + index + '#' + key,
              _label: sqlDialog.sql.bindId + '#' + (index + 1) + '#' + key,
              class: 'sql',
            };
          }),
        };
      });
      sqlDialog.sql.class = 'sql';
      sqlDialog.sql.children = children;
    } else {
      sqlDialog.result = '连接成功：' + JSON.stringify(ret);
      // sqlDialog.sql.columns = ret;
      const children = [];
      for (let key in ret) {
        children.push({
          label: key,
          value: sqlDialog.sql.bindId + '#' + key,
          _label: sqlDialog.sql.bindId + '#' + key,
          class: 'sql',
        });
      }
      sqlDialog.sql.class = 'sql';
      sqlDialog.sql.children = children;
    }
  }
};

const addDataDialog = reactive<any>({});

const showAddData = (network: any, node?: any) => {
  addDataDialog.network = network;
  const row = node?.data;
  const index = node?.getIndex();
  addDataDialog.node = node;
  if (row) {
    addDataDialog.header = '编辑数据';
    addDataDialog.data = JSON.parse(JSON.stringify(row));
    addDataDialog.index = index;
  } else {
    addDataDialog.header = '添加数据';
    addDataDialog.data = { type: 'string', expend: true };
  }

  addDataDialog.show = true;
};

const deleteData = (network: any, index: number) => {
  network.children.splice(index, 1);
  meta2d.store.data.networks = toRaw(data.networks);
  // data.dataset.devices.splice(row, 1);
  // (meta2d.store.data as any).dataset = data.dataset;
  setDot(true);
};

const clearData = () => {
  data.datasetId = undefined;
  data.dataset.id = undefined;
  data.dataset.name = undefined;
  data.dataset.url = undefined;
  data.dataset.devices = [];
  setDot(true);
};

const changeDataLabel = (value) => {
  if (!value) {
    MessagePlugin.error('显示名称不能为空！');
    return;
  }
  let item = data.dataset.devices?.filter((item) => item.label === value);
  if (item && item.length) {
    MessagePlugin.error('显示名称重复！');
    return;
  }
  addDataDialog.data.label = value;
};

const changeDataID = (value) => {
  if (!value) {
    MessagePlugin.error('属性名不能为空！');
    return;
  }
  let item = data.dataset.devices?.filter((item) => item.id === value);
  if (item && item.length) {
    MessagePlugin.error('属性名重复！');
    return;
  }
  addDataDialog.data.id = value;
};

const onOkAddData = () => {
  if (!addDataDialog.data.label) {
    MessagePlugin.error('请填写名称');
    return;
  }
  if (!addDataDialog.data.id) {
    MessagePlugin.error('请填写数据ID');
    return;
  }
  if (!addDataDialog.network.children) {
    addDataDialog.network.children = [];
  }
  addDataDialog.data.value = addDataDialog.data.id;
  if (addDataDialog.header === '添加数据') {
    addDataDialog.network.children.push(addDataDialog.data);
    if(addDataDialog.network.protocol === 'http'){
      httpTree.value.appendTo(addDataDialog.network.value, addDataDialog.data);
    }else if(addDataDialog.network.protocol === 'websocket'){
      wsTree.value.appendTo(addDataDialog.network.value, addDataDialog.data);
    }else if(addDataDialog.network.protocol === 'mqtt'){
      mqttTree.value.appendTo(addDataDialog.network.value, addDataDialog.data);
    }else if(addDataDialog.network.protocol === 'SSE'){
      SSETree.value.appendTo(addDataDialog.network.value, addDataDialog.data);
    }
  } else {
    // addDataDialog.network.children[addDataDialog.index] = addDataDialog.data;
    let beforeId =  addDataDialog.network.children[addDataDialog.index].id;
    
    addDataDialog.network.children.splice(
      addDataDialog.index,
      1,
      addDataDialog.data
    );
    if(beforeId !== addDataDialog.data.id){
      addDataDialog.node?.insertAfter(deepClone(addDataDialog.data));
      addDataDialog.node?.remove();
    }else{
      addDataDialog.node?.setData(deepClone(addDataDialog.data));
    }
    // mqttTreeKey.value = s8();
    // wsTreeKey.value = s8();
    // httpTreeKey.value = s8();
    // networkTree.value.setItem(addDataDialog.network.value, {children:deepClone(addDataDialog.network.children)});
    // addDataDialog.node?.setData(deepClone(addDataDialog.data));
    //更新所有绑定该id的pen label
    // let binds = meta2d.store.bind[addDataDialog.data.id];
    // if (binds) {
    //   binds.forEach((item) => {
    //     const pen: Pen = meta2d.findOne(item.id);
    //     pen.realTimes &&
    //       pen.realTimes.forEach((_realTime) => {
    //         if (_realTime.key === item.key) {
    //           _realTime.bind.label = addDataDialog.data.label;
    //         }
    //       });
    //   });
    // }
  }
  // (meta2d.store.data as any).dataset = data.dataset;
  meta2d.store.data.networks = toRaw(data.networks);
  addDataDialog.show = false;
};

const importDataset = async (network) => {
  let columns: any = [
    {
      header: '设备',
      key: 'device',
    },
    {
      header: '显示名称',
      key: 'label',
    },
    {
      header: '属性名',
      key: 'id',
    },
    {
      header: '类型',
      key: 'type',
    },
    {
      header: '值范围',
      key: 'mock',
    },
  ];
  const _data: any = await importExcel(columns);
  _data.forEach((item) => {
    if (item.device) {
      item.label = item.device + '-' + item.label;
      delete item.device;
    }
    item.value = item.id;
  });
  if (!network.children) {
    network.children = [];
  }
  mergeDataset(network.children, _data);
  if(network.protocol === 'http'){
    httpTree.value.appendTo(network.value, network.children);
  }else if(network.protocol === 'websocket'){
    wsTree.value.appendTo(network.value, network.children);
  }else if(network.protocol === 'mqtt'){
    mqttTree.value.appendTo(network.value, network.children);
  }else if(network.protocol === 'SSE'){
    SSETree.value.appendTo(network.value, network.children);
  }
  // networkTree.value.appendTo(network.value, network.children);
  // (meta2d.store.data as any).dataset = data.dataset;
};

const downloadAsExcel = () => {
  if (!(data.dataset.devices && data.dataset.devices.length)) {
    MessagePlugin.error('属性列表不能为空！');
    return;
  }
  const name = meta2d.store.data.name;
  const columns: any[] = [
    {
      key: 'label',
      header: '显示名称',
    },
    {
      key: 'id',
      header: '属性名',
    },
    {
      key: 'type',
      header: '类型',
    },
    {
      key: 'mock',
      header: '值范围',
    },
  ];
  saveAsExcel(name, columns, data.dataset.devices);
};

const downloadAsJson = () => {
  if (!(data.dataset.devices && data.dataset.devices.length)) {
    MessagePlugin.error('属性列表不能为空！');
    return;
  }
  import('file-saver').then(({ saveAs }) => {
    saveAs(
      new Blob([JSON.stringify(data.dataset)], {
        type: 'text/plain;charset=utf-8',
      }),
      `${data.dataset.name || '未命名'}.json`
    );
  });
};

const onOkDataset = async (saveas = false) => {
  // if (!dataDialog.dataset.name) {
  //   MessagePlugin.error('名称不能为空');
  //   return;
  // }
  if (!(data.dataset.devices && data.dataset.devices.length)) {
    MessagePlugin.error('属性列表不能为空');
    return;
  }
  const dataset = JSON.parse(JSON.stringify(data.dataset));
  let _data = dataset;
  _data.type = 'dataset';
  if (!_data.name) {
    _data.name = meta2d.store.data.name;
  }
  _data = transformData(dataset, 'toNetwork');
  // 保存到我的数据源
  if (saveas || !dataset.id) {
    delete dataset.id;
    delete dataset._id;
    dataset.type = 'dataset';
    const ret: any = await axios.post(`/api/data/datasource/add`, _data);
    if (!ret) {
      return;
    }
    ret.id = ret.id || ret._id;
    data.datasetId = ret.id;
    dataset.id = ret.id;
    data.dataset.id = ret.id;
    data.datasetList.push(dataset);
  } else {
    const ret: any = await axios.post(`/api/data/datasource/update`, _data);
    if (!ret) {
      return;
    }
    data.datasetList.forEach((item: any, index: number) => {
      if (
        item.id === dataset.id ||
        (item._id === dataset._id && dataset._id != undefined)
      ) {
        data.datasetList.splice(index, 1, dataset);
      }
    });
  }
  delete dataset.devices;
  // @ts-ignore
  // meta2d.store.data.dataset = dataset;

  // setDot(true);

  data.editDataset = false;
  delete data.datesetBak;
};

const mergeDataset = (arr1: any, arr2: any[]) => {
  if (!(arr2 && arr2.length)) {
    return;
  }
  if (!arr1) {
    arr1 = [];
  }
  arr2.forEach((item) => {
    let index = arr1.findIndex((elem) => elem.id === item.id);
    if (index >= 0) {
      Object.assign(arr1[index], item);
    } else {
      arr1.push(item);
    }
  });
};

const getDatas = async (network) => {
  // return;
  if (!data.dataset.url) {
    return;
  }
  const ret = await axios.get(data.dataset.url);
  let flattenRet = flattenTree(ret);
  if (flattenRet?.length) {
    flattenRet.forEach((item) => {
      if(!item.value){
        item.value = item.id;
      }
    });
    if (!network.children) {
      network.children = [];
    }
    // mergeDataset(data.dataset, flattenRet);
    // (meta2d.store.data as any).dataset = data.dataset;
    mergeDataset(network.children, flattenRet);
    if(network.protocol === 'http'){
      httpTree.value.appendTo(network.value, network.children);
    }else if(network.protocol === 'websocket'){
      wsTree.value.appendTo(network.value, network.children);
    }else if(network.protocol === 'mqtt'){
      mqttTree.value.appendTo(network.value, network.children);
    }else if(network.protocol === 'SSE'){
      SSETree.value.appendTo(network.value, network.children);
    }
  }
};

//展开树
const flattenTree = (root) => {
  if (!root) return []; // 空树返回空数组

  const result = []; // 存储展开后的数组

  // 递归遍历树
  function dfs(node) {
    result.push({
      id: node.id,
      label: node.label || node.name,
      device: node.device || node.id,
      type: node.type,
      mock: node.mock,
      // children: node.children,
    }); // 将当前节点值添加到结果数组
    // 遍历当前节点的子节点
    if (node.children) {
      for (let child of node.children) {
        dfs(child); // 递归调用DFS
      }
    }
  }
  root.forEach((item) => {
    dfs(item);
  });
  // dfs(root); // 从根节点开始遍历

  return result;
};

const onSelDataset = async (datasetId = false) => {
  if (datasetId) {
    const dataset = data.datasetList.find((item: any) => {
      return item.id === datasetId;
    });

    if (!dataset) {
      return;
    }

    if (dataset.url) {
      const ret = await axios.get(dataset.url);
      if (ret) {
        dataset.devices = ret;
      }
    } else {
      const ret = await axios.post(`/api/data/datasource/get`, {
        id: dataset.id,
      });
      if (ret?.data) {
        Object.assign(dataset, { ...ret.data });
      }
    }
    mergeDataset(data.dataset, dataset.devices);

    (meta2d.store.data as any).dataset = data.dataset;
    // dataDialog.dataset = dataset;

    // if (!init) {
    //   const d = JSON.parse(JSON.stringify(dataset));
    //   delete d.devices;
    //   // @ts-ignore
    //   meta2d.store.data.dataset = d;

    //   setDot(true);
    // }
  }
};

// 请求我的数据模型
const getDatasets = async (name?: string) => {
  if (!user.id) {
    MessagePlugin.error('请先登录');
    return;
  }
  const body: any = {
    type: 'dataset',
    projection: 'id,data,name,type',
  };
  if (name) {
    body.name = name;
  }
  const ret: any = await axios.post(`/api/data/datasource/list`, body, {
    params: {
      current: 1,
      pageSize: 10,
    },
  });
  if (ret?.list) {
    const list = [];
    let found = false;
    for (const item of ret.list) {
      item.id = item.id || item._id;
      list.push(transformData(item, 'toMetaNetwork'));
      if (data.dataset?.id === item.id) {
        found = true;
      }
    }
    if (data.dataset?.id && !found) {
      list.push(data.dataset);
    }

    data.datasetList = list;
  }
};

const onDelDataset = async (item: any, i: number) => {
  const ret: any = await axios.post(`/api/data/datasource/delete`, {
    id: item.id,
  });
  if (
    (meta2d.store.data as any).dataset &&
    (meta2d.store.data as any).dataset.id === item.id
  ) {
    //@ts-ignore
    meta2d.store.data.dataset = {};
    data.dataset = {};
    data.datasetId = undefined;
  }
  if (ret) {
    data.datasetList.splice(i, 1);
  }
};

const search = ref('');
const onSearch = () => {
  // if (!search.value) {
  //   return;
  // }
  data.dataset.devices.forEach((item) => {
    if (
      item.label.indexOf(search.value) !== -1 ||
      item.id.indexOf(search.value) !== -1
    ) {
      item.show = true;
    } else {
      item.show = false;
    }
  });
};

const onInputNetwork = (e) => {
  debounce(getNetworks, 300, e);
};

const onSelectNetWork = (value) => {
  if (!value) {
    return;
  }
  const network: any = data.networks.find((elem: any) => value === elem.id);
  if (!network) {
    const item = data.networkList.find((elem: any) => value === elem.id);
    data.networks.push(item);
    meta2d.store.data.networks = toRaw(data.networks);
    meta2d.connectNetwork();
    setDot(true);
  }
  // data.input = null;
  data.popupVisible = false;
};

// 请求我的实时数据
const getNetworks = async (e?) => {
  const ret: any = await axios.post(
    `/api/data/datasource/list`,
    {
      // q: {
      name: e,
      // },
      type: 'subscribe',
      projection: 'id,data,name,type',
    },
    {
      params: {
        current: 1,
        pageSize: 10,
      },
    }
  );
  if (ret?.list) {
    const list = [];
    for (const item of ret.list) {
      item.id = item.id || item._id;
      list.push(transformData(item, 'toMetaNetwork'));
    }
    data.networkList = list;
  }
};

const onDelNetWork = async (item: any, i: number) => {
  const ret: any = await axios.post(`/api/data/datasource/delete`, {
    id: item.id || item._id,
  });
  if (ret) {
    data.networkList.splice(i, 1);
  }
};

const networkTree = ref();
const networkTreeKey = ref(s8());
const mqttTree = ref();
const mqttTreeKey = ref(s8());
const wsTree = ref();
const wsTreeKey = ref(s8());
const httpTree = ref();
const httpTreeKey = ref(s8());
const SSETree = ref();
const SSETreeKey = ref(s8());

const deleteNetwork = (index: number) => {
  data.networks.splice(index, 1);
  meta2d.store.data.networks = toRaw(data.networks);
  getThirdNetwork('xxx');
  meta2d.connectNetwork();
  setDot(true);
};

const networkDialog = reactive<any>({
  save: true,
});
const editNetwork = (network: any, index: number) => {
  networkDialog.network = JSON.parse(JSON.stringify(data.networks[index]));
  networkDialog.editNetwork = 2;
  networkDialog.editNetworkIndex = index;
  networkDialog.header = `编辑${networkDialog.network.protocol}数据源`;
  networkDialog.show = true;
};

const addNetwork = (protocol:string) => {
  networkDialog.network = {
    name: '',
    type: 'subscribe',
    protocol,
    url: '',
    // options: {
    //   clientId: '',
    //   username: '',
    //   password: '',
    //   customClientId: false,
    // },
  };
  if(protocol === 'mqtt'){
    networkDialog.network.options = {
      clientId: '',
      username: '',
      password: '',
      customClientId: false,
    };
  }else if(protocol === 'websocket'){
    networkDialog.network.options = {protocols:''}
  }
  networkDialog.editNetwork = 1;
  networkDialog.header = `添加${protocol}数据源`;
  networkDialog.show = true;
};

const onOkNetwork = async () => {
  const _data = transformData(networkDialog.network, 'toNetwork');
  networkDialog.network.label = networkDialog.network.name;
  // networkDialog.network.value = networkDialog.network.url;
  networkDialog.network.value = s8();
  networkDialog.network.checkable = false;
  if (networkDialog.editNetwork === 1) {
    if (
      ['mqtt', 'websocket', 'http'].includes(networkDialog.network.protocol) &&
      !networkDialog.network.url
    ) {
      MessagePlugin.error('URL地址不能为空！');
      return;
    }
    if (!networkDialog.network.name) {
      MessagePlugin.error('名称不能为空！');
      return;
    }
    // if (networkDialog.save) {
    //   const ret: any = await axios.post(`/api/data/datasource/add`, _data);
    //   if (!ret) {
    //     return;
    //   }
    //   ret.id = ret.id || ret._id;
    //   networkDialog.network.id = ret.id;
    // }
    data.networks.push(networkDialog.network);
    // getThirdNetwork(networkDialog.network.protocol);
    // data.networkList.push(networkDialog.network);
    // networkTree.value?.appendTo('', networkDialog.network);
  } else if (networkDialog.editNetwork === 2) {
    // if (networkDialog.save) {
    //   const ret: any = await axios.post(`/api/data/datasource/update`, _data);
    //   if (!ret) {
    //     return;
    //   }
    // }
    //替换
    let index = networkDialog.editNetworkIndex;
    if (index !== undefined) {
      data.networks.splice(index, 1, networkDialog.network);
      // getThirdNetwork(networkDialog.network.protocol);
      // networkTreeKey.value = s8();
      if(networkDialog.network.protocol==='http'){
        httpTreeKey.value = s8();
      }else if(networkDialog.network.protocol==='websocket'){
        wsTreeKey.value = s8();
      }else if(networkDialog.network.protocol==='mqtt'){
        mqttTreeKey.value = s8();
      }else if(networkDialog.network.protocol==='SSE'){
        SSETreeKey.value = s8();
      }
      // networkTree.value.setItem(networkDialog.network.value,networkDialog.network);
    }
  }
  networkDialog.show = false;
  networkDialog.editNetwork = 0;
  meta2d.store.data.networks = toRaw(data.networks);
  getThirdNetwork(networkDialog.network.protocol);
  meta2d.connectNetwork();
  setDot(true);
};

const dataTransformationDialog = reactive<any>({
  show: false,
  data: '',
});

const showDataTransformation = () => {
  dataTransformationDialog.data = meta2d.store.data.socketCbJs;
  dataTransformationDialog.show = true;
};

const onOkDataTransformation = () => {
  meta2d.store.data.socketCbJs = dataTransformationDialog.data;
  data.randomkey = s8();
  data.socketCbJs = dataTransformationDialog.data;
  meta2d.listenSocket();
  dataTransformationDialog.show = false;
};

let timer: any = 0;

const onSocketCbJsChange = (e) => {
  clearTimeout(timer);
  timer = setTimeout(() => {
    meta2d.store.data.socketCbJs = data.socketCbJs;
    meta2d.listenSocket();
  }, 3000);
};

const onChangeMock = () => {
  // @ts-ignore
  data.enableMock = !data.enableMock;
  meta2d.store.data.enableMock = data.enableMock;
  if (data.enableMock) {
    meta2d.startDataMock();
  } else {
    meta2d.stopDataMock();
  }
};

const onCheckAllChange = (e) => {
  if(data.checkAll){
    allChecked.value = [];
    networksCheked.value = [];
    sqlsCheked.value = [];
    console.log("进入",allChecked.value,networksCheked.value, sqlsCheked.value)
  }
  data.checkAll =!data.checkAll;
  console.log("data.checkAll",data.checkAll);
  
  // if (!e) {
  //   data.dataset?.devices?.forEach((item) => {
  //     item.checked = false;
  //   });
  // }
};

const allChecked = ref([]);
const networksCheked = ref([]);
const sqlsCheked = ref([]);
const onAddShape = (e, _data,type) => {
  e.stopPropagation();
  let data: any;
  console.log("_data",_data);

  if (Array.isArray(_data)) {
    const dragElem = document.getElementById(`dragElem-${type}`);
    let width = dragElem.offsetWidth;
    e.dataTransfer.setDragImage(dragElem, width / 2, 10);
    const checked = [];
    if(type === 'iot'){
      _data.forEach((item) => {
        item.children?.forEach((_item) => {
          if (allChecked.value.includes(_item.value)) {
            checked.push(_item);
          }
        });
      });
    }else if(type === 'network'){
      _data.forEach((item) => {
        item.children?.forEach((_item) => {
          if (networksCheked.value.includes(_item.value)) {
            checked.push(_item);
          }
        });
      });
    }else if(type === 'sql'){
      _data.forEach((item) => {
        item.children?.forEach((_item) => {
          if (sqlsCheked.value.includes(_item.value)) {
            checked.push(_item);
          }
        });
      });
    }
    // const checked = _data.filter((item) => item.checked);
    if (!checked.length) {
      MessagePlugin.error('请先选择数据');
      return;
    }
    data = [];
    checked.forEach((item) => {
      let bind:any = {
        class: 'iot',
        id: item.value,
        label: item._label,
        token: item.token,
      };
      if(type === 'network'){
        bind = {
          id: item.id||item.value,
          label: item.label,
        }
      }else if(type === 'sql'){
        //TODO
        bind = {
          id: item.id||item.value,
          label: item.label,
        }
      }
      if (globalThis.style1) {
        data.push(
          ...[
            {
              text: item.label,
              width: 150,
              height: 20,
              name: 'text',
              dataset: true,
              textAlign: 'right',
            },
            {
              text: item.mock || 0,
              width: 58,
              height: 28,
              name: 'rectangle',
              dataset: true,
              // textAlign: 'left',
              color: '#478BFFFF',
              textColor: '#A9C9FFFF',
              background: '#478BFF1F',
              fontWeight: 'bold',
              borderRadius: 0.1,
              lineWidth: 1,
              realTimes: [
                {
                  label: '文字',
                  key: 'text',
                  type: 'string',
                  bind: deepClone(item),
                },
              ],
            },
          ]
        );
      } else {
        data.push(
          ...[
            {
              text: item.label + ':',
              width: 150,
              height: 28,
              name: 'text',
              dataset: true,
              textAlign: 'right',
            },
            {
              text: item.mock,
              width: 58,
              height: 20,
              name: 'text',
              dataset: true,
              textAlign: 'left',
              realTimes: [
                {
                  label: '文字',
                  key: 'text',
                  type: 'string',
                  bind: bind,
                },
              ],
            },
          ]
        );
      }
    });
  } else {
    if (globalThis.style1) {
      data = [
        {
          text: _data.label,
          width: 150,
          height: 28,
          name: 'text',
          dataset: true,
          textAlign: 'right',
        },
        {
          text: _data.mock || 0,
          width: 58,
          height: 28,
          name: 'rectangle',
          dataset: true,
          // textAlign: 'left',
          color: '#478BFFFF',
          textColor: '#A9C9FFFF',
          background: '#478BFF1F',
          fontWeight: 'bold',
          borderRadius: 0.1,
          lineWidth: 1,
          realTimes: [
            {
              label: '文字',
              key: 'text',
              type: 'string',
              bind: deepClone(_data),
            },
          ],
        },
      ];
    } else {
      data = [
        {
          text: _data.label + ':',
          width: 150,
          height: 20,
          name: 'text',
          dataset: true,
          textAlign: 'right',
        },
        {
          text: _data.mock,
          width: 58,
          height: 20,
          name: 'text',
          dataset: true,
          textAlign: 'left',
          realTimes: [
            {
              label: '文字',
              key: 'text',
              type: 'string',
              bind: deepClone(_data),
            },
          ],
        },
      ];
    }
  }
  meta2d.canvas.addCaches = deepClone(data);
};

const onAddShapeEnd = () => {
  setTimeout(() => {
    meta2d.initBinds();
  }, 1000);
};

let lastIndex = -1;

const onCheckChange = (e, i) => {
  if (lastIndex > -1) {
    if (e.shiftKey) {
      let start = Math.min(i, lastIndex);
      let end = Math.max(i, lastIndex);
      data.dataset?.devices?.forEach((item, index) => {
        if (index >= start && index <= end) {
          item.checked = true;
        }
      });
      e.stopPropagation();
      e.preventDefault();
    }
  }
  lastIndex = i;
};

const checkChange = (e, device, i) => {
  data.checkAll && (device.checked = !device.checked);
  if (lastIndex > -1) {
    if (e.shiftKey) {
      let start = Math.min(i, lastIndex);
      let end = Math.max(i, lastIndex);
      data.dataset?.devices?.forEach((item, index) => {
        if (index >= start && index <= end) {
          item.checked = true;
        }
      });
    }
  }
  lastIndex = i;
};

const onAddmock = (item: any) => {
  if (data.dataMocks.find((elem) => elem.id === item.id)) {
    return;
  }
  item.name = item.label;
  data.dataMocks.push(deepClone(item));
  (meta2d.store.data as any).dataMocks = data.dataMocks;
  meta2d.startDataMock();
};

const onAddAllMock = () => {
  if (!data.dataset.devices) {
    return;
  }
  data.dataset.devices.forEach((item) => {
    if (data.dataMocks.find((elem) => elem.id === item.id)) {
      return;
    }
    item.name = item.label;
    data.dataMocks.push(deepClone(item));
  });
  (meta2d.store.data as any).dataMocks = data.dataMocks;
  meta2d.startDataMock();
};

const deleteMock = (index: number) => {
  data.dataMocks.splice(index, 1);
  (meta2d.store.data as any).dataMocks = data.dataMocks;
  setDot(true);
};
</script>
<style lang="postcss" scoped>
/* :deep(.data-input-box){
  position: absolute;
    left: 193px;
    width: 501px;
    top: 80px;
} */
.content {
  background: var(--color-background-active);
  padding: 0px 16px;
  .data-header{
    position: sticky;
    top:0;
    background: var(--color-background-active);
    z-index: 2;
    padding-top: 16px;
  }
  .tree-icon {
    width: 14px;
    height: 14px;
  }

  .datasource-title{
    color: #6e7e99;
  }

  .prop-title {
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
  }

  :deep(.t-collapse) {
    border: none;
  }

  :deep(.t-collapse-panel__header) {
    border: none;
    font-size: 12px;
    font-weight: 400;
    padding: 8px 0px;
    background: var(--color-background-active);
  }
  :deep(.t-collapse-panel__body) {
    border: none;
  }
  :deep(.t-collapse-panel__content) {
    background-color: var(--color-background-active);
    color: var(--color);
    padding: 8px 0px;
  }

  .btn-select {
    height: 32px;
    line-height: 32px;
    color: #fff;
    border: 1px solid var(--color-border);
    border-radius: 4px;
    padding: 0px 8px;
    background-color: var(--color-background-input);
    cursor: pointer;
  }

  .btn-select-active {
    background-color: var(--color-primary);
  }

  .input-search {
    flex-shrink: 0;
    color: #878f9c;
    padding: 0px;
    margin-top: 10px;

    .btn {
      background: #fff0;
      left: 12px;

      img {
        background-color: #fff0;
        margin-top: 9px;
      }
    }

    :deep(.t-select) {
      .t-input {
        padding-left: 8px !important;
      }
    }
  }

  .select-search {
    .t-input {
      padding-left: 8px !important;

      .t-icon {
        font-size: 12px;
      }
    }
  }

  .title {
    height: 32px;
    line-height: 32px;
  }

  .title-span {
    display: inline-block;
    margin-left: 4px;
    max-width: 108px;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
  }

  .data-list {
    /* padding: 12px 6px; */
    /* background: var(--color-background-active); */
    max-height: calc(100vh - 200px);
    margin-bottom: 24px;
    overflow-y: auto;

    .data-title {
      /* padding: 4px; */
    }

    .data-body {
      margin-bottom: 8px;
    }

    .data-title-hover {
      &:hover {
        background: var(--color-background-input);
        border-radius: 4px;
      }
    }

    width: 234px;

    & > div {
      width: 218px;
    }
  }

  .data-mock-list {
    height: auto;
    max-height: calc(100vh - 220px);
  }

  .icon-box {
    width: 24px;
    height: 24px;
    margin: 4px;
    text-align: center;
    line-height: 24px;
    border-radius: 4px;

    &:hover {
      background: var(--td-brand-color-light);
    }

    .t-icon {
      width: 14px;
      height: 14px;
    }
  }

  .icon-item-box {
    height: 30px;
    line-height: 30px;
    margin: 1px;
  }

  .nodata {
    padding-top: 50px;

    img {
      width: 80px;
    }

    .gray {
      margin-top: 8px;
    }

    .t-button {
      height: 24px;
      padding-left: 8px;
      padding-right: 8px;
    }
  }

  .form-line {
    margin-left: 12px;
    width: 11px;
    /* height: 120px; */
    /* border-bottom: 1px solid var(--color-background-input); */
    /* border-left: 1px solid var(--color-background-input); */
  }

  .form-data-item {
    margin-left: 4px;
    margin-top: 4px;

    /* margin-right: 12px; */
    label {
      /* color: #ffffff80; */
      height: 24px;
      line-height: 24px;
      width: 60px;
    }

    & > div {
      width: 118px;
      height: 24px;
      line-height: 24px;
      /* background: var(--color-background-input); */
      border-radius: 4px;
      /* color: #e3e8f459; */
      padding-left: 8px;
      padding-right: 8px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }

  .form-mock-item {
    & > div {
      padding: 0px;

      :deep(.t-input) {
        height: 24px !important;
        border: 0px;
      }
    }
  }

  .form-swicth-item {
    margin-left: 4px;

    label {
      /* color: #ffffff80; */
      height: 24px;
      width: 56px;
    }
  }

  .data-code {
    width: 218px;

    .code-editor {
      height: 126px;
    }
  }

  .data-code-full {
    position: absolute;
    /* right: calc(50% - 250px); */
    width: 100%;
    height: 100vh;
    background: var(--td-mask-active);
    right: 0px;
    top: 0px;

    .code-editor {
      width: 800px;
      margin: 0 auto;
      height: 80%;
      margin-top: 16vh;
    }

    .data-full-icon {
      .t-icon {
        margin-right: calc(50% - 384px);
      }
    }
  }

  .data-full-icon {
    margin-top: -20px;
    /* z-index: 10000; */
    position: relative;
    display: flex;
    justify-content: flex-end;
    width: 100%;

    .t-icon {
      margin-right: 16px;
      cursor: pointer;
      height: 16px;
      width: 16px;
    }
  }

  ul {
    list-style-type: none;
  }
}

:deep(.t-tree) {
  .t-icon {
      width: 14px;
      height: 14px;
    }
  .t-tree__label {
    font-size: 12px;
    color: #bdc7db;
  }
  .t-tree__item[data-level='0'] {
    .t-tree__operations{
     visibility: hidden;
    }
    &:hover{
      .t-tree__operations{
        visibility: visible;
      }
    }
  }
  
  .t-tree__item[data-level='1'] {
    padding: 0 0 0 16px;
    .t-checkbox__label {
      max-width: 148px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
    .t-tree__operations{
      display: none;
    }

    &:hover{
      .t-checkbox__label {
        max-width: 94px;
      }
      .t-tree__operations{
        display: block;
      }
    }
  }
  .t-tree__item[data-level='2'] {
    padding: 0 0 0 16px;
    .t-checkbox__label {
      max-width: 50px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
    }
  }
  /* .t-tree__item{
    .t-tree__operations{
      display: none;
    }
  }

  .t-tree__item:hover{
    .t-tree__operations{
      display: block;
    }
  } */
  .t-tree__item .t-icon {
    color: #bdc7db;
  }
  .t-tree__label.t-is-checked {
    background: none;
  }
}

:deep(.t-tree--checkable){
  .t-tree__item[data-level='1'] {
    padding: 0 0 0 0px;
  }
}
</style>
<style lang="postcss">
.menu-item-a {
  &:hover {
    color: var(--td-brand-color);
  }
}

.network-option {
  height: 100%;
  padding: 0px;
}
</style>
