Pārlūkot izejas kodu

预警配置样式

CzRger 8 mēneši atpakaļ
vecāks
revīzija
1110b81bb4

+ 1 - 1
.env.development

@@ -2,4 +2,4 @@
 NODE_ENV = development
 
 # 标题
-VITE_TITLE = 海上预警
+VITE_TITLE = 海上船舶异常行为预警模型

+ 1 - 1
.env.production

@@ -2,4 +2,4 @@
 NODE_ENV = production
 
 # 标题
-VITE_TITLE = 海上预警
+VITE_TITLE = 海上船舶异常行为预警模型

BIN
src/assets/images/web/head-bg.png


BIN
src/assets/images/web/tools-config.png


BIN
src/assets/images/web/tools-search.png


BIN
src/assets/images/web/tools-ship.png


BIN
src/assets/images/web/tools-warning.png


BIN
src/assets/images/web/window-bg.png


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 3 - 6
src/assets/svg/arrow_1.svg


Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 7 - 4
src/assets/svg/arrow_2.svg


+ 5 - 0
src/assets/svg/arrow_3.svg

@@ -0,0 +1,5 @@
+<svg width="16" height="17" viewBox="0 0 16 17" xmlns="http://www.w3.org/2000/svg">
+<g id="icon/&#231;&#174;&#173;&#229;&#164;&#180;">
+<path id="&#232;&#183;&#175;&#229;&#190;&#132;" d="M4 12.729C4 13.5531 4.94076 14.0234 5.6 13.529L10.9333 9.52901C11.4667 9.12901 11.4667 8.32901 10.9333 7.92901L5.6 3.92901C4.94076 3.43458 4 3.90496 4 4.72901L4 12.729Z"/>
+</g>
+</svg>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 5 - 0
src/assets/svg/arrow_4.svg


+ 8 - 0
src/assets/svg/circle_1.svg

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 26.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 28 28" style="enable-background:new 0 0 28 28;" xml:space="preserve">
+<path class="st0" d="M27.6,14c0-0.9-0.6-1.6-1.4-1.8C25.3,6.2,20.1,1.5,13.8,1.5C6.9,1.5,1.3,7.1,1.3,14c0,6.9,5.6,12.5,12.5,12.5
+	c6.3,0,11.5-4.7,12.4-10.8C27,15.6,27.6,14.9,27.6,14z M13.8,25.5C7.5,25.5,2.3,20.3,2.3,14S7.5,2.5,13.8,2.5
+	c5.8,0,10.6,4.3,11.4,9.8C24.5,12.6,24,13.2,24,14s0.5,1.4,1.1,1.7C24.4,21.2,19.6,25.5,13.8,25.5z"/>
+</svg>

+ 8 - 0
src/assets/svg/line_1.svg

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 26.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 28 28" style="enable-background:new 0 0 28 28;" xml:space="preserve">
+<path class="st0" d="M24.5,4.8c-0.9,0-1.6,0.7-1.6,1.6c0,0.4,0.1,0.7,0.3,1l-6.3,9.1l-6-4.1l-6.8,7.7C4,20,3.7,19.9,3.5,19.9
+	c-0.9,0-1.6,0.7-1.6,1.6s0.7,1.6,1.6,1.6s1.6-0.7,1.6-1.6c0-0.3-0.1-0.5-0.2-0.8l6.2-7l6.1,4.2l6.9-10c0.1,0,0.3,0.1,0.5,0.1
+	c0.9,0,1.6-0.7,1.6-1.6S25.4,4.8,24.5,4.8z"/>
+</svg>

Failā izmaiņas netiks attēlotas, jo tās ir par lielu
+ 4 - 0
src/assets/svg/point_1.svg


+ 12 - 0
src/assets/svg/poly_1.svg

@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 26.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 28 28" style="enable-background:new 0 0 28 28;" xml:space="preserve">
+<path class="st0" d="M26.2,11.9c0-0.9-0.7-1.6-1.6-1.6c-0.1,0-0.2,0-0.3,0l-8.6-6.2c0,0,0,0,0,0c0-0.9-0.7-1.6-1.6-1.6
+	c-0.9,0-1.6,0.7-1.6,1.6c0,0,0,0,0,0l-8.6,6.3c-0.1,0-0.3-0.1-0.4-0.1c-0.9,0-1.6,0.7-1.6,1.6c0,0.8,0.6,1.5,1.3,1.6l3.1,9.6
+	C6.1,23.4,6,23.7,6,24c0,0.9,0.7,1.6,1.6,1.6c0.5,0,0.9-0.2,1.2-0.5h10.4c0.3,0.3,0.7,0.5,1.2,0.5c0.9,0,1.6-0.7,1.6-1.6
+	c0-0.3-0.1-0.6-0.2-0.8l3.1-9.7C25.7,13.2,26.2,12.6,26.2,11.9z M9.3,24C9.3,24,9.3,24,9.3,24c0-1-0.7-1.7-1.6-1.7
+	c-0.2,0-0.4,0-0.6,0.1l-2.9-9.1c0.5-0.3,0.9-0.8,0.9-1.5c0-0.4-0.1-0.7-0.3-1l8.1-5.9c0.3,0.4,0.8,0.6,1.3,0.6c0.5,0,1-0.2,1.3-0.6
+	l8,5.8c-0.3,0.3-0.4,0.7-0.4,1.1c0,0.7,0.5,1.3,1.1,1.5l-2.9,9c-0.2-0.1-0.4-0.1-0.6-0.1c-0.9,0-1.6,0.7-1.6,1.6c0,0,0,0.1,0,0.1
+	H9.3z"/>
+</svg>

+ 8 - 0
src/assets/svg/rectangle_1.svg

@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!-- Generator: Adobe Illustrator 26.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="图层_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 28 28" style="enable-background:new 0 0 28 28;" xml:space="preserve">
+<path class="st0" d="M24.8,23.5V4.7c0-0.6-0.4-1-1-1h-20c-0.6,0-1,0.4-1,1v20c0,0.6,0.4,1,1,1h18.4c0.3,0.4,0.8,0.6,1.3,0.6
+	c0.9,0,1.7-0.8,1.7-1.7C25.2,24.2,25.1,23.8,24.8,23.5z M3.8,24.7v-20l0,0V4.2v0.5h20V23c-0.1,0-0.2,0-0.3,0c-0.9,0-1.7,0.8-1.7,1.7
+	v0.1h-18V24.7z"/>
+</svg>

+ 14 - 24
src/components/easyMap/component/form-draw/index.vue

@@ -125,21 +125,7 @@
                 />
                 <CusFormColumn
                   required
-                  label-width="94px"
                   :span="12"
-                  label="边线类型:"
-                  link="select"
-                  v-model:param="config.polyBorderType"
-                  static
-                  @change="onConfigChange"
-                >
-                  <el-option label="—————" :value="0"/>
-                  <el-option label="— — — —" :value="1"/>
-                  <el-option label="- - - - - - - -" :value="2"/>
-                </CusFormColumn>
-                <CusFormColumn
-                  required
-                  :span="24"
                   label="填充颜色:"
                   v-model:param="config.polyColor"
                   :clearable="false"
@@ -544,20 +530,24 @@ export default defineComponent({
       ref_formCom.value?.setDefault(obj)
     }
     const drawSmallSuccess = () => {
-      const obj = {
-        smallWkt: state.config.smallWkt
+      if (state.config.isSmall) {
+        const obj = {
+          smallWkt: state.config.smallWkt
+        }
+        ref_formCom.value?.setSmall(obj)
       }
-      ref_formCom.value?.setSmall(obj)
     }
     const drawHcqSuccess = () => {
-      const obj = {
-        hcqWkt: state.config.hcqWkt,
-        hcqAuto: state.config.hcqAuto,
-        hcqAutoRadius: state.config.hcqAutoRadius,
-        hcqPolyColor: state.config.hcqPolyColor,
-        hcqPolyBorderColor: state.config.hcqPolyBorderColor
+      if (state.config.isHcq) {
+        const obj = {
+          hcqWkt: state.config.hcqWkt,
+          hcqAuto: state.config.hcqAuto,
+          hcqAutoRadius: state.config.hcqAutoRadius,
+          hcqPolyColor: state.config.hcqPolyColor,
+          hcqPolyBorderColor: state.config.hcqPolyBorderColor
+        }
+        ref_formCom.value?.setHcq(obj)
       }
-      ref_formCom.value?.setHcq(obj)
     }
     const initDrawDefault = () => {
       state.staticLayer?.getSource()?.clear()

+ 2 - 0
src/plugins/initProperties.ts

@@ -2,12 +2,14 @@ import {App, nextTick, reactive} from 'vue'
 import * as api from '@/api/index'
 import * as util from '@/utils/util'
 import * as permissions from '@/utils/permissions'
+import * as easyMap from '@/utils/easyMap'
 import {delay} from "@/utils/util";
 
 export default async (app: App) => {
     app.config.globalProperties.$api = await api.default
     app.config.globalProperties.$util = util
     app.config.globalProperties.$permissions = permissions
+    app.config.globalProperties.$easyMap = easyMap
     app.config.globalProperties.$loading = reactive({
         value: false,
         show(){

+ 4 - 0
src/stores/app.ts

@@ -5,6 +5,7 @@ export const useAppStore = defineStore('app', {
   state: () => ({
     token: localStorage.getItem('__token'),
     userInfo: null,
+    zIndex: 1,
   }),
   getters: {
   },
@@ -15,5 +16,8 @@ export const useAppStore = defineStore('app', {
       // @ts-ignore
       window.location.replace(`${import.meta.env.BASE_URL}`);
     },
+    getZIndex() {
+      return this.zIndex + 1
+    }
   },
 })

+ 23 - 2
src/style/cus.scss

@@ -283,7 +283,7 @@
   font-size: 14px;
   font-family: PingFang SC-Regular, PingFang SC;
   font-weight: 400;
-  color: var(--cus-main-color);
+  color: #2E81FF;
   display: flex;
   align-items: center;
   position: relative;
@@ -295,7 +295,28 @@
     left: 0;
     width: 2px;
     height: 14px;
-    background-color: var(--cus-main-color);
+    background-color: #2E81FF;
+  }
+}
+.__cus-title_2 {
+  width: 100%;
+  height: 32px;
+  font-size: 14px;
+  font-family: PingFang SC-Regular, PingFang SC;
+  font-weight: 400;
+  color: #68c3ff;
+  display: flex;
+  align-items: center;
+  position: relative;
+  padding-left: 10px;
+  box-sizing: border-box;
+  &:before {
+    content: '';
+    position: absolute;
+    left: 0;
+    width: 2px;
+    height: 14px;
+    background-color: #68c3ff;
   }
 }
 

+ 156 - 0
src/views/web/components/drag-window.vue

@@ -0,0 +1,156 @@
+<template>
+  <VueDragResize
+      ref="ref_drag"
+      :isActive="false"
+      :z="state.zIndex"
+      :layout="layout"
+      :isResizable="isResizable"
+      :parentLimitation="true"
+      @resizing="resize"
+      @dragging="resize"
+      @mousedown="setZ"
+  >
+    <div class="drag-window">
+      <div class="head">
+        <div class="head-bg">
+          <img class="img-bg" src="@/assets/images/web/window-bg.png"/>
+          <div class="color-bg"/>
+        </div>
+        <div class="head-content">
+          <div class="line"/>
+          <div class="title">
+            {{title}}
+            <slot name="title"/>
+          </div>
+          <div class="buttons">
+            <slot name="buttons"/>
+            <SvgIcon v-if="expend !== false" class="expend-button __hover" :class="{active: state.notExpend}" @click="state.notExpend = !state.notExpend" name="arrow_4" color="#ffffff" size="16"/>
+            <SvgIcon v-if="close !== false" class="__hover" @click="$emit('onClose')"  name="close_3" color="#ffffff" size="14"/>
+          </div>
+        </div>
+      </div>
+      <div class="content" :class="{'not-expend': expend !== false && state.notExpend}">
+        <slot/>
+      </div>
+    </div>
+  </VueDragResize>
+</template>
+
+<script setup lang="ts">
+import {computed, getCurrentInstance, nextTick, reactive} from "vue";
+import VueDragResize from '@/components/vue-drag-resize/index.vue'
+import {useAppStore} from "@/stores";
+
+const {proxy} = getCurrentInstance()
+const emit = defineEmits(['update:layout'])
+const appStore = useAppStore()
+const props = defineProps({
+  title: {default: ''},
+  layout: {required: false},
+  isResizable: {default: false},
+  close: {default: false},
+  expend: {default: false},
+})
+const state: any = reactive({
+  zIndex: appStore.getZIndex(),
+  notExpend: false
+})
+const resize = (layout) => {
+  nextTick(() => {
+    let c = layout
+    if (props.expend !== false) {
+      c = Object.assign(c, {
+        height: 'auto'
+      })
+    }
+    emit('update:layout', c)
+  })
+}
+const setZ = () => {
+  state.zIndex = appStore.getZIndex()
+}
+</script>
+<style scoped lang="scss">
+.drag-window {
+  display: flex;
+  flex-direction: column;
+  .head {
+    position: relative;
+    width: 100%;
+    height: 40px;
+    display: flex;
+    .head-bg {
+      width: 100%;
+      position: relative;
+      z-index: 1;
+      opacity: 0.8;
+      overflow: hidden;
+      .img-bg {
+        user-select: none;
+        width: 372px;
+        height: 100%;
+        position: absolute;
+        top: 0;
+        left: 0;
+        z-index: 2;
+      }
+      .color-bg {
+        width: calc(100% - 20px);
+        height: 100%;
+        background-color: rgba(11, 68, 197);
+        position: absolute;
+        top: 0;
+        right: 0;
+        z-index: 1;
+      }
+    }
+    .head-content {
+      width: 100%;
+      height: 100%;
+      position: absolute;
+      z-index: 2;
+      display: flex;
+      align-items: center;
+      .line {
+        width: 3px;
+        height: 16px;
+        background: #68C3FF;
+        margin-left: 10px;
+      }
+      .title {
+        margin-left: 10px;
+        font-size: 16px;
+        font-family: PingFang SC-Medium, PingFang SC;
+        font-weight: 500;
+        color: #FFFFFF;
+        display: flex;
+        line-height: 1;
+        align-items: center;
+      }
+      .buttons {
+        margin-left: auto;
+        margin-right: 10px;
+        display: flex;
+        align-items: center;
+        .expend-button {
+          margin-right: 8px;
+          transition: all .2s;
+          &.active {
+            transform: rotate(180deg) !important;
+          }
+        }
+      }
+    }
+  }
+  .content {
+    width: 100%;
+    height: calc(100% - 40px);
+    background-color: rgba(7, 44, 145, 0.9);
+    overflow: hidden;
+    transition: height .2s;
+    &.not-expend {
+      height: 0;
+    }
+  }
+}
+</style>

+ 79 - 16
src/views/web/index.vue

@@ -1,21 +1,56 @@
 <template>
   <div class="layout">
-    <div class="layout-head">{{titleCpt}}</div>
+    <div class="layout-head">
+      <div class="layout-head-title">{{titleCpt}}</div>
+    </div>
     <div class="layout-content">
       <div class="content-map">
         <EasyMapComponent
           class="map"
           @easyMapLoad="mapLoad"
           layout="info"
+          @mapClose="val => val.source === 'formDraw' ? refreshArea() : undefined"
         />
       </div>
       <div class="content-tools">
-        <div class="content-tools-item">搜索</div>
-        <div class="content-tools-item __hover" @click="state.tools.showConfig = true">规则</div>
-        <div class="content-tools-item">预警</div>
-        <div class="content-tools-item">船舶</div>
+        <el-tooltip
+          effect="light"
+          content="搜索"
+          placement="right"
+        >
+          <div class="tools-item __hover">
+            <img src="@/assets/images/web/tools-search.png"/>
+          </div>
+        </el-tooltip>
+        <el-tooltip
+          effect="light"
+          content="预警配置"
+          placement="right"
+        >
+          <div class="tools-item __hover" @click="state.tools.showConfig = !state.tools.showConfig">
+            <img src="@/assets/images/web/tools-config.png"/>
+          </div>
+        </el-tooltip>
+        <el-tooltip
+          effect="light"
+          content="预警列表"
+          placement="right"
+        >
+          <div class="tools-item __hover">
+            <img src="@/assets/images/web/tools-warning.png"/>
+          </div>
+        </el-tooltip>
+        <el-tooltip
+          effect="light"
+          content="船舶档案"
+          placement="right"
+        >
+          <div class="tools-item __hover">
+            <img src="@/assets/images/web/tools-ship.png"/>
+          </div>
+        </el-tooltip>
       </div>
-      <ConfigCom class="content-config" v-model:show="state.tools.showConfig" />
+      <ConfigCom v-model:show="state.tools.showConfig" :mapFunc="state.mapFunc"/>
     </div>
   </div>
 </template>
@@ -27,6 +62,7 @@ import ConfigCom from './tools/config.vue'
 const {proxy} = getCurrentInstance()
 const state: any = reactive({
   map: null,
+  mapFunc: null,
   tools: {
     showConfig: true
   }
@@ -36,6 +72,10 @@ const titleCpt = computed(() => {
 })
 const mapLoad = (map, mapFunc) => {
   state.map = map
+  state.mapFunc = mapFunc
+}
+const refreshArea = () => {
+  console.log(123)
 }
 </script>
 
@@ -47,8 +87,19 @@ const mapLoad = (map, mapFunc) => {
   flex-direction: column;
   .layout-head {
     width: 100%;
-    height: 40px;
-    background-color: #2E81FF;
+    height: 60px;
+    background-image: url("@/assets/images/web/head-bg.png");
+    background-repeat: no-repeat;
+    background-size: 100% 100%;
+    display: flex;
+    align-items: center;
+    .layout-head-title {
+      margin-left: 40px;
+      font-family: Microsoft YaHei;
+      font-weight: bold;
+      font-size: 30px;
+      color: #FFFFFF;
+    }
   }
   .layout-content {
     flex: 1;
@@ -63,17 +114,29 @@ const mapLoad = (map, mapFunc) => {
     .content-tools {
       top: 10px;
       left: 10px;
-      padding: 10px;
-      border: 1px solid;
       display: flex;
       flex-direction: column;
+      align-items: center;
       gap: 10px;
-    }
-    .content-config {
-      border: 1px solid;
-      top: 10px;
-      left: 100px;
-      height: calc(100% - 20px);
+      width: 44px;
+      background-color: rgba(255,255,255,0.4);
+      border-radius: 8px;
+      padding: 10px 0;
+      .tools-item {
+        width: 32px;
+        height: 32px;
+        display: flex;
+        align-items: center;
+        justify-content: center;
+        border-radius: 8px;
+        &:hover {
+          background: linear-gradient(180deg, #b2ccfb 100%, #7ba2e5 100%);
+        }
+        >img {
+          width: 20px;
+          height: 20px;
+        }
+      }
     }
   }
 }

+ 122 - 0
src/views/web/tools/area-form.vue

@@ -0,0 +1,122 @@
+<template>
+  <div class="draw-form">
+    <CusForm labelWidth="90px" ref="ref_form" :formView="isView">
+      <CusFormColumn
+        :span="24"
+        required
+        label="区域名称"
+        v-model:param="form.p1"
+        :maxLength="20"/>
+      <CusFormColumn
+        class="__textarea-content"
+        :span="24"
+        required
+        label="区域坐标"
+        type="textarea"
+        :rows="4"
+        v-model:param="form.wkt"
+        :disabled="true"
+        defaultErrorMsg="请绘制区域"
+        :rules="[
+          {
+            handle: (val) => $easyMap.validWkt.Polygon(val),
+            message: '区域WKT坐标格式错误'
+          },
+          {
+            handle: (val) => $easyMap.validWkt.PolygonKinks(val),
+            message: '区域坐标不可自相交'
+          },
+        ]"
+      />
+      <div class="__draw-handle" v-if="!isView">
+        <div class="__draw __hover" @click="$emit('drawDefault')">标绘</div>
+        <div class="__clear __hover" @click="form.wkt = ''">清空</div>
+      </div>
+    </CusForm>
+  </div>
+</template>
+
+<script lang="ts">
+import {
+  defineComponent,
+  computed,
+  onMounted,
+  ref,
+  reactive,
+  watch,
+  getCurrentInstance,
+  ComponentInternalInstance,
+  toRefs,
+  nextTick
+} from 'vue'
+import {useRouter, useRoute} from 'vue-router'
+import {ElMessage, ElMessageBox} from "element-plus";
+
+export default defineComponent({
+  name: '',
+  components: {},
+  props: {
+    transfer: {},
+    loading: {},
+    isView: {}
+  },
+  emits: ['pass', 'drawDefault', 'drawHcq', 'drawSmall', 'update:loading', 'wkt', 'hcqWkt', 'smallWkt'],
+  setup(props, {emit}) {
+    const that = (getCurrentInstance() as ComponentInternalInstance).appContext.config.globalProperties
+    const state = reactive({
+      form: <any>{},
+      fileList: []
+    })
+    const ref_form = ref()
+    watch(() => props.transfer, (n) => {
+      state.form = JSON.parse(JSON.stringify(n))
+    }, {immediate: true})
+    watch(() => state.form.wkt, (n) => {
+      emit('wkt', n)
+    })
+    const setDefault = (val) => {
+      state.form.wkt = val.wkt
+      state.form.polyColor = val.polyColor
+      state.form.polyBorderColor = val.polyBorderColor
+      state.form.polyBorderWidth = val.polyBorderWidth
+      state.form.polyBorderType = val.polyBorderType
+    }
+    const onSubmit = () => {
+      ref_form.value.submit().then(() => {
+        ElMessageBox.confirm("是否提交?", "提示", {
+          confirmButtonText: "确定",
+          cancelButtonText: "取消",
+          type: "warning",
+        }).then(() => {
+          emit('update:loading', true)
+          setTimeout(() => {
+            console.log('比对表单')
+            console.log(props.transfer)
+            console.log(state.form)
+            ElMessage.success('保存成功')
+            emit('pass')
+            emit('update:loading', false)
+          }, 2000)
+        }).catch(() => {})
+      }).catch((e) => {
+        ElMessage({
+          message: e[0].message,
+          grouping: true,
+          type: 'warning',
+        })
+      })
+    }
+    onMounted(() => {
+    })
+    return {
+      ...toRefs(state),
+      ref_form,
+      setDefault,
+      onSubmit,
+    }
+  },
+})
+</script>
+
+<style scoped lang="scss">
+</style>

+ 227 - 31
src/views/web/tools/config.vue

@@ -1,51 +1,114 @@
 <template>
-  <div class="config" v-if="show" v-loading="state.loading">
-    <el-button @click="$emit('update:show', false)">关闭</el-button>
-    <div style="display: flex">
-      <div style="width: 60px">过滤</div><el-input v-model="state.text"/>
-    </div>
-    <div class="tabs" style="display: flex;gap: 20px;">
-      <el-button @click="state.tab = 1">规则</el-button>
-      <el-button @click="state.tab = 2">区域</el-button>
-    </div>
-    <template v-if="state.tab == 1">
-      <el-button @click="expendRules">{{rulesExpandAllCpt ? '收起' : '展开'}}全部</el-button>
-      <el-tree
-        ref="ref_rulesTree"
-        :data="state.rulesList"
-        :props="ruleProps"
-        node-key="id"
+  <DragWindow
+    v-if="show"
+    @onClose="$emit('update:show', false)"
+    title="预警配置"
+    v-model:layout="state.layout"
+    close
+    expend
+  >
+    <div class="config" v-if="show" v-loading="state.loading">
+      <div class="tabs">
+        <div class="tabs-item __hover" :class="{active: state.tab == 1}" @click="state.tab = 1">预警规则</div>
+        <div class="tabs-item __hover" :class="{active: state.tab == 2}" @click="state.tab = 2">预警区域</div>
+      </div>
+      <CusForm
+        labelWidth="60px"
+        class="search-form"
+        @handleEnter="onSearch()"
       >
-        <template #default="{ node, data }">
+        <CusFormColumn
+          :span="20"
+          labelWidth="0px"
+          v-model:param="state.text"
+        />
+        <el-col :span="2">
+          <div class="search-btn" @click="onSearch()">
+            <el-icon color="#FFFFFF">
+              <Search />
+            </el-icon>
+          </div>
+        </el-col>
+        <el-col :span="2">
+          <div class="search-btn" @click="state.text = '', onSearch()">
+            <el-icon color="#FFFFFF">
+              <Refresh />
+            </el-icon>
+          </div>
+        </el-col>
+      </CusForm>
+      <template v-if="state.tab == 1">
+        <div class="__cus-title_2">
+          全部规则(0)
+          <div class="expend-tree __hover" @click="expendRules">{{rulesExpandAllCpt ? '收起' : '展开'}}全部</div>
+        </div>
+        <el-tree
+          class="tree"
+          ref="ref_rulesTree"
+          :data="state.rulesList"
+          :props="ruleProps"
+          node-key="id"
+        >
+          <template #default="{ node, data }">
         <span class="custom-tree-node">
           <span>{{ node.label }}</span>
           <span v-if="node.level > 1">
-            <el-button @click.stop="$util._console(node)">编辑</el-button>
-            <el-button @click.stop="$util._console(node)">查看</el-button>
+            <SvgIcon name="edit" size="12" class="__hover" @click.stop="onAddRule(data)"/>
+            <SvgIcon name="detail_1" size="12" class="__hover" @click.stop="onAddRule(data)"/>
+            <el-switch v-model="data.active" size="small"/>
           </span>
           <span v-else>
-            <el-button @click.stop="onAddRule(data)">新增</el-button>
+            <SvgIcon name="add" size="12" class="__hover" @click.stop="onAddRule(data)"/>
           </span>
         </span>
-        </template>
-      </el-tree>
-    </template>
-    <template v-else-if="state.tab == 2">
-
-    </template>
-    <ruleDetail v-model:show="state.ruleDetail.show" :transfer="state.ruleDetail.transfer"/>
-  </div>
+          </template>
+        </el-tree>
+      </template>
+      <template v-else-if="state.tab == 2">
+        <div class="__cus-title_2">
+          全部区域(0)
+          <div class="expend-tree __hover" @click="onAddArea">新增区域</div>
+        </div>
+        <el-tree
+          class="tree"
+          :data="state.areaList"
+          :props="areaProps"
+          node-key="id"
+        >
+          <template #default="{ node, data }">
+            <span class="custom-tree-node">
+              <span>{{ data.name }}</span>
+              <span>
+                <SvgIcon name="edit" size="12" class="__hover" @click.stop="onEditArea(data)"/>
+              </span>
+            </span>
+          </template>
+        </el-tree>
+      </template>
+      <ruleDetail v-model:show="state.ruleDetail.show" :transfer="state.ruleDetail.transfer"/>
+    </div>
+  </DragWindow>
 </template>
 
 <script setup lang="ts">
-import {computed, getCurrentInstance, onMounted, reactive, ref, watch} from "vue";
+import {computed, getCurrentInstance, markRaw, onMounted, reactive, ref, watch} from "vue";
 import ruleDetail from "./rule-detail.vue";
+import areaForm from "./area-form.vue";
+import DragWindow from '../components/drag-window.vue'
+import { Search, Refresh } from "@element-plus/icons-vue";
 
 const {proxy} = getCurrentInstance()
 const props = defineProps({
   show: {},
+  mapFunc: {}
 })
 const state: any = reactive({
+  layout: {
+    width: 400,
+    height: '90%',
+    left: 70,
+    top: 10
+  },
   tab: 1,
   loading: false,
   text: '',
@@ -53,11 +116,20 @@ const state: any = reactive({
   ruleDetail: {
     transfer: {},
     show: false
-  }
+  },
+  areaList: [
+    {
+      id: 'area-1',
+      name: '区域-1',
+    }
+  ]
 })
 const ruleProps = {
   children: 'children'
 }
+const areaProps = {
+  children: 'children'
+}
 const ref_rulesTree = ref()
 watch(() => props.show, (n) => {
   if (n) {
@@ -100,6 +172,45 @@ const onAddRule = (row) => {
   }
   state.ruleDetail.show = true
 }
+const onAddArea = (row) => {
+  const config = {
+    featureType: 'Polygon',
+    wkt: '',
+    polyColor: 'rgba(231,18,18,0.53)', // Polygon的填充色,默认蓝色
+    polyBorderColor: 'rgba(231,18,18,0.53)', // Polygon的边框颜色,默认蓝色
+    polyBorderWidth: 2, // Polygon的边框宽度,默认1
+  }
+  props.mapFunc.formDrawEdit({
+    config: config,
+    form: {
+      com: markRaw(areaForm),
+      detail: config
+    }
+  })
+}
+const onEditArea = (row) => {
+  const config = {
+    featureType: 'Polygon',
+    wkt: 'POLYGON((110.10212241843107 19.31790648240469,111.12312792246837 18.750781049337483,110.25884201127086 17.952069610196993,110.10212241843107 19.31790648240469))',
+    polyColor: 'rgba(231,18,18,0.53)', // Polygon的填充色,默认蓝色
+    polyBorderColor: 'rgba(231,18,18,0.53)', // Polygon的边框颜色,默认蓝色
+    polyBorderWidth: 2, // Polygon的边框宽度,默认1
+  }
+  props.mapFunc.formDrawEdit({
+    config: config,
+    form: {
+      com: markRaw(areaForm),
+      detail: config
+    }
+  })
+}
+const onSearch = () => {
+  if (state.tab == 1) {
+
+  } else {
+
+  }
+}
 onMounted(() => {
   initData()
 })
@@ -107,6 +218,91 @@ onMounted(() => {
 
 <style lang="scss" scoped>
 .config {
-  width: 300px;
+  height: 790px;
+  padding: 12px 10px;
+  .tabs {
+    display: flex;
+    font-weight: 500;
+    font-size: 14px;
+    color: #ffffff;
+    gap: 15px;
+    .active {
+      color: #1cfeff;
+      border-bottom: 2px solid #1cfeff;
+    }
+  }
+  :deep(.search-form) {
+    margin-top: 16px;
+    margin-bottom: 10px;
+    .el-col {
+      display: flex;
+      align-items: center;
+    }
+    .el-form-item {
+      margin-bottom: 0;
+      flex: 1;
+      .el-form-item__label {
+        padding: unset;
+        margin: 0 5px;
+        font-weight: 400;
+        font-size: 14px;
+        color: #ffffff;
+      }
+      .el-input__wrapper {
+        height: 28px;
+        background-color: unset;
+        box-shadow: unset;
+        border: 1px solid #1a56d4;
+      }
+    }
+    .search-btn {
+      width: 28px;
+      height: 28px;
+      background: #0062e9;
+      border-radius: 4px 4px 4px 4px;
+      margin-left: 5px;
+      margin-top: 3px;
+      cursor: pointer;
+      text-align: center;
+      line-height: 33px;
+    }
+  }
+  .expend-tree {
+    padding: 2px 6px;
+    font-size: 10px;
+    font-weight: 400;
+    color: #FFFFFF;
+    border: 1px solid #0062e9;
+    border-radius: 4px;
+    margin-left: 16px;
+  }
+  :deep(.tree) {
+    background-color: unset;
+    .custom-tree-node {
+      flex: 1;
+      display: flex;
+      align-items: center;
+      justify-content: space-between;
+      font-family: PingFang SC, PingFang SC;
+      font-weight: 500;
+      font-size: 14px;
+      color: #ffffff;
+      .svg-icon {
+        margin-right: 6px;
+      }
+    }
+
+    .el-tree-node__content:hover {
+      background-color: #044fb787;
+    }
+
+    .el-tree-node:focus > .el-tree-node__content {
+      background-color: #044fb787;
+    }
+
+    .el-checkbox__inner {
+      background-color: unset;
+    }
+  }
 }
 </style>