diff --git a/ui/dv/AiDvMap.vue b/ui/dv/AiDvMap.vue
index d7edfbc0..decb9f83 100644
--- a/ui/dv/AiDvMap.vue
+++ b/ui/dv/AiDvMap.vue
@@ -1,13 +1,6 @@
 
   
 
 
@@ -20,14 +13,12 @@ export default {
   props: {
     geoJson: String,
     data: Array,
-    area: String
+    ops: Object
   },
   data() {
     return {
-      dialog: false,
       chart: null,
-      detail: {},
-      dialogPos: {}
+      geo: null
     }
   },
   directives: {
@@ -62,10 +53,11 @@ export default {
     this.$load(this.$refs.dvMap).then(() => this.initChart())
   },
   watch: {
-    dialog(v) {
-      if (!v) {
-        this.detail = []
-        this.dialogPos = {}
+    data: {
+      deep: true, handler(v) {
+        this.chart.setOption({
+          geo: [{data: v}]
+        })
       }
     }
   },
@@ -78,11 +70,43 @@ export default {
     initChart() {
       const {echarts} = window
       this.chart = echarts.init(this.$refs.dvMap)
-      this.getData(this.geoJson).then(res => {
-        if (res?.data) {
-          echarts.registerMap('customMap', res.data)
+      this.chart.showLoading({
+        text: "数据加载中...", textColor: "#fff",
+        maskColor: 'rgba(0, 0, 0, 0.2)'
+      })
+      Promise.all([
+        this.getData(this.geoJson).then(res => this.geo = res?.data),
+        // waitFor(this.data)
+      ]).then(() => {
+        if (!!this.geo) {
+          echarts.registerMap('customMap', this.geo)
           const option = {
             geo: [
+              // 重影
+              ...Array(3).fill(1).map((e, i) => {
+                return {
+                  type: "map",
+                  map: "customMap",
+                  zlevel: -1,
+                  aspectScale: 1,
+                  zoom: 0.65,
+                  layoutCenter: ["50%", `${51 + i}%`],
+                  layoutSize: "180%",
+                  roam: false,
+                  silent: true,
+                  itemStyle: {
+                    normal: {
+                      borderWidth: 1,
+                      // borderColor:"rgba(17, 149, 216,0.6)",
+                      borderColor: `rgba(2, 198, 220, ${0.6 - i * 0.2})`,
+                      shadowColor: `rgba(2, 198, 220, ${0.6 - i * 0.2})`,
+                      shadowOffsetY: 5,
+                      shadowBlur: 15,
+                      areaColor: "transparent",
+                    },
+                  },
+                }
+              }),
               {
                 map: "customMap",
                 aspectScale: 1,
@@ -121,34 +145,11 @@ export default {
                   borderWidth: 2,
                   areaColor: "#02bcff29",
                   shadowBlur: 120,
-                }
+                },
+                data: this.data
               },
-              // 重影
-              ...Array(3).fill(1).map((e, i) => {
-                return {
-                  type: "map",
-                  map: "customMap",
-                  zlevel: -1,
-                  aspectScale: 1,
-                  zoom: 0.65,
-                  layoutCenter: ["50%", `${51 + i}%`],
-                  layoutSize: "180%",
-                  roam: false,
-                  silent: true,
-                  itemStyle: {
-                    normal: {
-                      borderWidth: 1,
-                      // borderColor:"rgba(17, 149, 216,0.6)",
-                      borderColor: `rgba(2, 198, 220, ${0.6 - i * 0.2})`,
-                      shadowColor: `rgba(2, 198, 220, ${0.6 - i * 0.2})`,
-                      shadowOffsetY: 5,
-                      shadowBlur: 15,
-                      areaColor: "transparent",
-                    },
-                  },
-                }
-              })
             ],
+            ...this.ops
             // geo3D: {
             //   map: "customMap",
             //   shading: 'color',
@@ -178,38 +179,15 @@ export default {
             // },
           }
           this.chart.setOption(option)
-          this.chart.on('click', evt => {
-            const {name, event: {offsetX, offsetY}} = evt
-            this.dialog = true
-            this.detail = []
-            const item = this.data.find(e => e.name.includes(name))
-            for (const k in item) {
-              if ('name' != k) {
-                this.detail.push({
-                  label: k, value: item[k], color: {
-                    高风险纠纷: "#FF6868",
-                    中风险纠纷: "#FFAB68",
-                    低风险纠纷: "#7FE89E",
-                  }[k]
-                })
-              }
-            }
-            this.dialogPos = {left: offsetX + 'px', top: offsetY + 'px'}
-          })
-          this.chart.on('globalout', () => {
-            this.dialog = false
-          })
+          this.chart.on('click', evt => this.$emit("click", {...evt, info: this.geo.features.find(e => e.properties?.name == evt.name)?.properties}))
+          this.chart.on('globalout', () => this.$emit("globalout"))
         }
-      })
+        return 1
+      }).finally(() => this.chart.hideLoading())
     },
     getData(url = `https://geo.datav.aliyun.com/areas_v3/bound/geojson?code=${this.user.info.areaId?.substring(0, 6)}`) {
       return http.post(`/app/appdvcpconfig/apiForward?url=${encodeURIComponent(url)}`)
     },
-    dotStyle(color) {
-      return {
-        background: color,
-      }
-    }
   }
 }
 
@@ -229,43 +207,5 @@ export default {
     width: 100%;
     height: 100%;
   }
-
-  .dialog {
-    position: absolute;
-    transform: translate(-50%, -120%);
-    z-index: 20240327926;
-    padding: 16px 16px 24px;
-    background-color: rgba(9, 48, 69, 0.8);
-    backdrop-filter: blur(5px);
-    color: #fff;
-    font-size: 14px;
-    min-width: 200px;
-    border: 1px solid #02C6DC;
-
-    &:after {
-      position: absolute;
-      bottom: 0;
-      left: 50%;
-      transform: translate(-50%, 50%) rotate(-135deg);
-      content: " ";
-      width: 10px;
-      height: 10px;
-      background: inherit;
-      border: inherit;
-      clip-path: polygon(0 0, 100% 0, 0 100%);
-    }
-
-    .dot {
-      width: 14px;
-      height: 14px;
-      border-radius: 50%;
-      margin-right: 8px;
-      border: 3px solid rgba(9, 48, 69, .4);
-    }
-
-    .label {
-      color: #9BB7D4;
-    }
-  }
 }
 
diff --git a/ui/dv/AiLinkageMap.vue b/ui/dv/AiLinkageMap.vue
index 62858d79..3ccc03ea 100644
--- a/ui/dv/AiLinkageMap.vue
+++ b/ui/dv/AiLinkageMap.vue
@@ -12,23 +12,85 @@ export default {
   },
   data() {
     return {
-      mapData: [],
-      areaId: "530300000000"
+      geoData: [],
+      mapOptions: {
+        visualMap: {
+          left: "right",
+          type: "piecewise",
+          splitNumber: 8,
+          min: 0,
+          max: 800,
+          inRange: {
+            color: ["#0CDEE9", "#0BD0DA", "#0BC1D5", "#0BACC1", "#0993AE", "#076C88", "#064E6B", "#054261"].reverse()
+          },
+          outOfRange: {
+            color: "#25EDF4"
+          },
+          textStyle: {
+            color: "#fff"
+          },
+          calculable: true
+        }
+      },
+      dialog: false,
+      detail: [],
+      dialogPos: {},
+      compData: null
+    }
+  },
+  watch: {
+    dialog(v) {
+      if (!v) {
+        this.detail = []
+        this.dialogPos = {}
+      }
     }
   },
   computed: {
-    sta: v => v.config.summaryConfigs || []
+    sta: v => v.config.summaryConfigs || [],
+    mapData: v => v.geoData.map(e => ({name: e.name.replace(/([市县区])/g, ""), value: parseInt(e.低风险纠纷) + parseInt(e.中风险纠纷) + parseInt(e.高风险纠纷)}))
   },
   methods: {
-    getData() {
-      new DvCompData(this.config, this.instance).getData({type: this.areaId}).then(res => {
+    getData(type = "530300000000") {
+      return this.compData.getData({type}).then(res => {
         const json = JSON.parse(res.param)
-        this.mapData = json.map
+        this.geoData = json.map
         this.config.summaryConfigs = json.sta?.map((e, i) => ({pos: ["rt", "lb", 'lt', 'rb'][i % 4], display: "summary20", ...e})) || []
       })
+    },
+    handleMapClick(evt) {
+      const {name, event: {offsetX, offsetY}, info: {code} = {}} = evt
+      this.dialog = true
+      this.detail = []
+      const item = this.geoData.find(e => e.name.includes(name))
+      this.$refs.map.chart.showLoading({
+        text: "数据加载中...", textColor: "#fff",
+        maskColor: 'rgba(0, 0, 0, 0)'
+      })
+      this.getData(String(code).padEnd(12, '0')).finally(() => {
+        this.$refs.map.chart.hideLoading()
+      })
+      for (const k in item) {
+        if ('name' != k) {
+          this.detail.push({
+            label: k, value: item[k], color: {
+              高风险纠纷: "#FF6868",
+              中风险纠纷: "#FFAB68",
+              低风险纠纷: "#7FE89E",
+            }[k]
+          })
+        }
+      }
+      this.dialogPos = {left: offsetX + 'px', top: offsetY + 'px'}
+    },
+    dotStyle(color) {
+      return {
+        background: color,
+      }
     }
   },
   created() {
+    this.compData = new DvCompData(this.config, this.instance)
     this.getData()
   }
 }
@@ -36,9 +98,15 @@ export default {
 
 
   
 
 
@@ -74,5 +142,42 @@ export default {
     }
   }
 
+  .dialog {
+    position: absolute;
+    transform: translate(-50%, -120%);
+    z-index: 20240327926;
+    padding: 16px 16px 24px;
+    background-color: rgba(9, 48, 69, 0.8);
+    backdrop-filter: blur(5px);
+    color: #fff;
+    font-size: 14px;
+    min-width: 200px;
+    border: 1px solid #02C6DC;
+
+    &:after {
+      position: absolute;
+      bottom: 0;
+      left: 50%;
+      transform: translate(-50%, 50%) rotate(-135deg);
+      content: " ";
+      width: 10px;
+      height: 10px;
+      background: inherit;
+      border: inherit;
+      clip-path: polygon(0 0, 100% 0, 0 100%);
+    }
+
+    .dot {
+      width: 14px;
+      height: 14px;
+      border-radius: 50%;
+      margin-right: 8px;
+      border: 3px solid rgba(9, 48, 69, .4);
+    }
+
+    .label {
+      color: #9BB7D4;
+    }
+  }
 }