From 3d6ff15899256f33cd100d95237f613c023d50df Mon Sep 17 00:00:00 2001
From: MrShi <1878285526@qq.com>
Date: 星期一, 08 十二月 2025 09:54:09 +0800
Subject: [PATCH] 优化

---
 server/system_service/src/main/java/com/doumee/core/utils/Constants.java                                                        |    2 
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchCustomerServiceImpl.java                   |    4 
 admin/src/views/business/deviceBroadcast.vue                                                                                    |  125 +++
 server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/DistanceCalculator.java                                         |    2 
 server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketchCustomer.java                                 |    3 
 admin/whyc_admin/template/member.xlsx                                                                                           |    0 
 server/visits/dmvisit_admin/src/main/resources/bootstrap.yml                                                                    |    2 
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceServiceImpl.java                             |  184 ++++++
 server/visits/dmvisit_service/pom.xml                                                                                           |    5 
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/ext/HkSyncService.java                                  |    1 
 server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/service/HKService.java                                      |   12 
 server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/DeviceCloudController.java                                     |    7 
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/JkSketchService.java                                    |    3 
 admin/whyc_admin/avatar/woman.png                                                                                               |    0 
 server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/vo/CabinetInfoVO.java                                       |    2 
 admin/.env.development                                                                                                          |    6 
 server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkCabinet.java                                        |    3 
 admin/src/views/business/jkSketch.vue                                                                                           |   17 
 admin/whyc_admin/template/traintime.xlsx                                                                                        |    0 
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkCabinetServiceImpl.java                          |    2 
 admin/src/views/business/deviceBroadcastChannel.vue                                                                             |  103 +++
 admin/whyc_admin/template/oil.xlsx                                                                                              |    0 
 server/system_gateway/src/main/resources/bootstrap.yml                                                                          |    2 
 admin/public/template/member.xlsx                                                                                               |    0 
 server/visits/dmvisit_service/src/main/java/com/doumee/dao/admin/request/SketchCateModel.java                                   |   36 +
 server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java                                        |  147 +++++
 server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/Clustering.java                                                 |   85 ++
 server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/Empower.java                                          |    1 
 server/system_service/src/main/java/com/doumee/core/utils/HttpsUtil.java                                                        |   79 ++
 admin/whyc_admin/favicon.ico                                                                                                    |    0 
 admin/whyc_admin/template/cars.xlsx                                                                                             |    0 
 /dev/null                                                                                                                       |  110 ---
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/DeviceService.java                                      |    8 
 server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/model/param/request/ISAPIBroadcastAddPlanSchemeRequest.java |   87 +++
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchServiceImpl.java                           |  341 +++++++++++
 admin/src/components/business/OperaDeviceBroadcastWindow.vue                                                                    |   89 +++
 server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/HkSyncCloudController.java                                     |   14 
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/hksync/HkSyncBaseServiceImpl.java                  |    5 
 server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/model/HKTools.java                                          |    1 
 server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/Device.java                                           |   10 
 admin/src/api/business/device.js                                                                                                |   20 
 server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/TspSolver.java                                                  |   45 
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/hksync/HkSyncDeviceServiceImpl.java                |  147 +++++
 43 files changed, 1,513 insertions(+), 197 deletions(-)

diff --git a/admin/.env.development b/admin/.env.development
index c574b58..6ffc081 100644
--- a/admin/.env.development
+++ b/admin/.env.development
@@ -3,9 +3,15 @@
 
 # VUE_APP_API_URL  = 'https://atwl.ahzyssl.com/zhyq_interface'
 
+<<<<<<< HEAD
 # VUE_APP_API_URL  = 'http://192.168.1.45:10010'
 
 VUE_APP_API_URL  = 'http://192.168.0.7/system_gateway'
+=======
+VUE_APP_API_URL  = 'http://localhost:10010'
+
+#VUE_APP_API_URL  = 'http://192.168.0.7/system_gateway'
+>>>>>>> ce3b9c67f6b2ee83d7edf593d06221d909e9afda
 
 # VUE_APP_API_URL  = 'http://localhost:10010'
 
diff --git a/admin/public/template/member.xlsx b/admin/public/template/member.xlsx
index 1e0a152..577efa0 100644
--- a/admin/public/template/member.xlsx
+++ b/admin/public/template/member.xlsx
Binary files differ
diff --git a/admin/src/api/business/device.js b/admin/src/api/business/device.js
index 7259c4a..d5274bb 100644
--- a/admin/src/api/business/device.js
+++ b/admin/src/api/business/device.js
@@ -25,6 +25,9 @@
 export function updateById (data) {
   return request.post('/visitsAdmin/cloudService/business/device/updateById', data)
 }
+export function create (data) {
+  return request.post('/visitsAdmin/cloudService/business/device/create', data)
+}
 
 // 淇敼鏄惁闂ㄧ鍏ュ彛
 export function updateEntranceById (data) {
@@ -34,3 +37,20 @@
 export function setLedContent (data) {
   return request.post('/visitsAdmin/cloudService/business/hksync/setLedContent', data)
 }
+export function sendBobao (data) {
+  return request.post('/visitsAdmin/cloudService/business/hksync/sendBobao', data)
+}
+
+// 鍒犻櫎
+export function deleteById (id) {
+  return request.get(`/visitsAdmin/cloudService/business/device/delete/${id}`)
+}
+
+// 鎵归噺鍒犻櫎
+export function deleteByIdInBatch (ids) {
+  return request.get('/visitsAdmin/cloudService/business/device/delete/batch', {
+    params: {
+      ids
+    }
+  })
+}
diff --git a/admin/src/components/business/OperaDeviceBroadcastWindow.vue b/admin/src/components/business/OperaDeviceBroadcastWindow.vue
new file mode 100644
index 0000000..c7a4027
--- /dev/null
+++ b/admin/src/components/business/OperaDeviceBroadcastWindow.vue
@@ -0,0 +1,89 @@
+<template>
+    <GlobalWindow
+        :title="title"
+        :visible.sync="visible"
+        :confirm-working="isWorking"
+        @confirm="confirm"
+    >
+        <el-form :model="form" ref="form" :rules="rules">
+          <el-form-item label="璁惧鍚嶇О" prop="name">
+            <el-input v-model="form.name" placeholder="璇疯緭鍏ュ悕绉�" v-trim/>
+          </el-form-item>
+          <el-form-item label="璁惧鍞竴鐮�" prop="hkId">
+            <el-input v-model="form.hkId" placeholder="璇疯緭鍏ヨ澶囧敮涓�鐮�" v-trim/>
+          </el-form-item>
+          <el-form-item label="璁惧搴忓垪鍙�" prop="no">
+            <el-input v-model="form.no" placeholder="璇疯緭鍏ュ簭鍒楀彿" v-trim/>
+          </el-form-item>
+          <el-form-item label="杩炴帴IP" prop="ip">
+            <el-input v-model="form.ip" placeholder="璇疯緭鍏ヨ澶囪繛鎺P鍦板潃" v-trim/>
+          </el-form-item>
+          <el-form-item label="杩炴帴绔彛" prop="port">
+            <el-input v-model="form.port" placeholder="璇疯緭鍏ヨ繛鎺ョ鍙�" v-trim/>
+          </el-form-item>
+          <el-form-item label="杩炴帴璐﹀彿" prop="doorId">
+            <el-input v-model="form.doorId" placeholder="璇疯緭鍏ヨ澶囪繛鎺ヨ处鍙�" v-trim/>
+          </el-form-item>
+          <el-form-item label="杩炴帴瀵嗙爜" prop="doorName">
+            <el-input v-model="form.doorName" type="password"  maxlength="30" show-password></el-input>
+          </el-form-item>
+          <el-form-item label="鎵�鍦ㄤ綅缃�" prop="regionPathName">
+            <el-input v-model="form.regionPathName" placeholder="璇疯緭鍏ユ墍鍦ㄤ綅缃�" v-trim/>
+          </el-form-item>
+        </el-form>
+    </GlobalWindow>
+</template>
+
+<script>
+import BaseOpera from '@/components/base/BaseOpera'
+import GlobalWindow from '@/components/common/GlobalWindow'
+export default {
+  name: 'OperaDeviceBroadcastWindow',
+  extends: BaseOpera,
+  components: { GlobalWindow },
+  data () {
+    return {
+      // 琛ㄥ崟鏁版嵁
+      form: {
+        id: null,
+        hkId: '',
+        name: '',
+        regionPathName: '',
+        no: '',
+        type: 4,
+        ip: '',
+        port: '',
+        doorId: '',
+        doorName:''
+      },
+      // 楠岃瘉瑙勫垯
+      rules: {
+        name: [
+          { required: true, message: '璇疯緭鍏ヨ澶囧悕绉�' }
+        ],
+        ip: [
+          { required: true, message: '璇疯緭鍏ヨ澶囪繛鎺P鍦板潃' }
+        ],
+        port: [
+          { required: true, message: '璇疯緭鍏ヨ澶囪繛鎺ョ鍙e彿' }
+        ],
+        doorId: [
+          { required: true, message: '璇疯緭鍏ヨ澶囪繛鎺ヨ处鍙�' }
+        ],
+        doorName: [
+          { required: true, message: '璇疯緭鍏ヨ澶囪繛鎺ュ瘑鐮�' }
+        ],
+        hkId: [
+          { required: true, message: '璇疯緭鍏ヨ澶囧敮涓�鐮�' }
+        ]
+      }
+    }
+  },
+  created () {
+    this.config({
+      api: '/business/device',
+      'field.id': 'id'
+    })
+  }
+}
+</script>
diff --git a/admin/src/views/business/deviceBroadcast.vue b/admin/src/views/business/deviceBroadcast.vue
index c10e474..baf4669 100644
--- a/admin/src/views/business/deviceBroadcast.vue
+++ b/admin/src/views/business/deviceBroadcast.vue
@@ -12,22 +12,49 @@
         </el-form>
         <!-- 琛ㄦ牸鍜屽垎椤� -->
         <template v-slot:table-wrap>
-            <ul class="toolbar">
-                <li><el-button type="primary" @click="synchronousData">鍚屾</el-button></li>
-            </ul>
+          <ul class="toolbar" v-permissions="['business:device:create', 'business:device:delete']">
+            <li><el-button type="primary" :loading="isWorking.delete" @click="synchronousData">鍚屾</el-button></li>
+            <li><el-button type="primary" @click="$refs.operaDeviceWindow.open('鏂板缓骞挎挱')" icon="el-icon-plus" v-permissions="['business:device:create']">鏂板缓</el-button></li>
+            <li><el-button @click="deleteByIdInBatch" icon="el-icon-delete" v-permissions="['business:device:delete']">鍒犻櫎</el-button></li>
+          </ul>
             <el-table
                 :height="tableHeightNew"
                 v-loading="isWorking.search"
                 :data="tableData.list"
                 stripe
             >
+              <el-table-column type="selection" width="55"></el-table-column>
               <el-table-column label="搴忓彿"  width="55" fixed><template slot-scope="scope" >{{scope.$index+1}}</template></el-table-column>
-                <el-table-column prop="name" label="鍚嶇О"></el-table-column>
-                <el-table-column prop="hkId" label="骞挎挱鐐瑰敮涓�鏍囪瘑" min-width="200"></el-table-column>
-                <el-table-column prop="channelInfo" label="骞挎挱鐐圭被鍨�"></el-table-column>
-                <el-table-column prop="channelNo" label="閫氶亾鍙�"></el-table-column>
-                <el-table-column prop="regionName" label="鍖哄煙鍚嶇О"></el-table-column>
-                <el-table-column prop="hkDate" label="鍚屾鏃堕棿"></el-table-column>
+              <el-table-column prop="name" label="鍚嶇О"></el-table-column>
+              <el-table-column prop="hkId" label="鍞竴鏍囪瘑"  ></el-table-column>
+              <el-table-column prop="regionPathName" label="鎵�鍦ㄤ綅缃�"></el-table-column>
+              <el-table-column prop="no" label="搴忓垪鍙�"  ></el-table-column>
+              <el-table-column prop="ip" label="IP鍦板潃"  ></el-table-column>
+              <el-table-column prop="port" label="绔彛"  ></el-table-column>
+              <el-table-column prop="doorId" label="璐﹀彿"></el-table-column>
+              <el-table-column prop="doorName" label="瀵嗙爜" align="center">
+                <template slot-scope="{row}">
+                  <span :class=" 'blue'">{{row.showPwd?row.doorName:'******'}}</span>
+                  <el-button  style="margin-left: 10px" v-if="row.doorName!=null"
+                              @click.native.p.prevent="showPassward(row)" type="text">
+                   <i class="el-icon-view" :class="row.showPwd?'red':'blue'" :title="row.showPwd?'闅愯棌':'鏄剧ず'"></i>
+                  </el-button>
+                </template>
+              </el-table-column>
+              <el-table-column prop="editDate" label="鏈�杩戞洿鏂版椂闂�"></el-table-column>
+              <el-table-column
+                  v-if="containPermissions(['business:devicerole:update', 'business:devicerole:delete'])"
+                  label="鎿嶄綔"
+                  align="center"
+                  min-width="120"
+                  fixed="right"
+              >
+                  <template slot-scope="{row}">
+                    <el-button type="text" @click="$refs.operaDeviceWindow.open('缂栬緫骞挎挱', row)" icon="el-icon-edit" v-permissions="['business:device:update']">缂栬緫</el-button>
+                    <el-button type="text" @click="send(row)" icon="el-icon-edit"  v-permissions="['business:device:update']">鍙戦�佹挱鎶�</el-button>
+                    <el-button type="text" class="red" @click="deleteById(row)" icon="el-icon-delete" v-permissions="['business:device:delete']">鍒犻櫎</el-button>
+                  </template>
+                </el-table-column>
             </el-table>
             <pagination
                 @size-change="handleSizeChange"
@@ -36,8 +63,26 @@
             >
             </pagination>
         </template>
+      <el-dialog
+          :visible.sync="visibleSend"
+          style="z-index: 100000"
+          append-to-body
+          width="50%"
+          height="50%"
+          :title="'鍙戦�佹挱鎶�-'+ form.name"
+      >
+        <el-form :model="form" ref="form" >
+          <el-form-item label="鎾姤鍐呭" prop="name" required>
+            <el-input v-model="form.sendInfo" type="textarea" placeholder="璇疯緭鍏ユ挱鎶ュ唴瀹�" v-trim/>
+          </el-form-item>
+        </el-form>
+        <template  v-slot:footer  >
+          <el-button @click="sendBobao()" type="primary" :loading="isWorkSending">纭</el-button>
+          <el-button @click="sendClose()">杩斿洖</el-button>
+        </template>
+      </el-dialog>
         <!-- 鏂板缓/淇敼 -->
-<!--        <OperaDeviceWindow ref="operaDeviceWindow" @success="handlePageChange"/>-->
+    <OperaDeviceBroadcastWindow ref="operaDeviceWindow" @success="handlePageChange"/>
     </TableLayout>
 </template>
 
@@ -45,12 +90,12 @@
 import BaseTable from '@/components/base/BaseTable'
 import TableLayout from '@/layouts/TableLayout'
 import Pagination from '@/components/common/Pagination'
-import OperaDeviceWindow from '@/components/business/OperaDeviceWindow'
-import { syncDevices, updateEntranceById } from '@/api/business/device'
+import OperaDeviceBroadcastWindow from '@/components/business/OperaDeviceBroadcastWindow'
+import { syncDevices } from '@/api/business/device'
 export default {
   name: 'Device',
   extends: BaseTable,
-  components: { TableLayout, Pagination, OperaDeviceWindow },
+  components: { TableLayout, Pagination, OperaDeviceBroadcastWindow },
   data () {
     return {
       // 鎼滅储
@@ -59,8 +104,16 @@
         regionPathName: '',
         isEntrance: '',
         online: '',
-        type: 3
+        type: 4
       },
+      isWorkSending: false,
+      form: {
+        sendInfo: '',
+        id: '',
+        hkId: '',
+        name: ''
+      },
+      visibleSend: false,
       options: []
     }
   },
@@ -74,23 +127,53 @@
     this.search()
   },
   methods: {
-    changeManufature(e, row) {
-      updateEntranceById({
-        id: row.id,
-        isEntrance: e
-      })
+    showPassward (row) {
+      if (!row.showPwd) {
+        this.$set(row, 'showPwd', true)
+      } else {
+        this.$set(row, 'showPwd', false)
+      }
+    },
+    sendBobao () {
+      if (!this.form.sendInfo) {
+        return
+      }
+      this.$dialog.actionConfirm('纭杩涜骞挎挱鎾姤鍚楋紵', '鎿嶄綔纭鎻愰啋')
+        .then(() => {
+          this.isWorkSending = true
+          this.api.sendBobao(this.form)
+            .then(res => {
+              this.$tip.apiSuccess(res || '鎾姤璇锋眰鎴愬姛')
+              this.sendClose()
+            })
+            .catch(e => {
+            })
+            .finally(() => {
+              this.isWorkSending = false
+            })
+        })
+        .catch(() => {})
+    },
+    send (row) {
+      this.visibleSend = true
+      this.form = { sendInfo: '', id: row.id, hkId: row.hkId, name: row.name }
+    },
+    sendClose () {
+      this.visibleSend = false
+      this.isWorkSending = false
+      this.form = { sendInfo: '', id: '', hkId: '', name: '' }
     },
     synchronousData () {
       this.$dialog.actionConfirm('鎿嶄綔纭鎻愰啋', '鎮ㄧ‘璁ゅ悓姝ュ叏閮ㄤ俊鎭悧锛�')
         .then(() => {
           this.isWorking.delete = true
-          syncDevices({type: 3})
+          syncDevices({ type: 4 })
             .then(res => {
               this.$tip.apiSuccess(res || '鍚屾鎴愬姛')
               this.search()
             })
             .catch(e => {
-             //  this.$tip.apiFailed(e)
+              //  this.$tip.apiFailed(e)
             })
             .finally(() => {
               this.isWorking.delete = false
diff --git a/admin/src/views/business/deviceBroadcastChannel.vue b/admin/src/views/business/deviceBroadcastChannel.vue
new file mode 100644
index 0000000..c10e474
--- /dev/null
+++ b/admin/src/views/business/deviceBroadcastChannel.vue
@@ -0,0 +1,103 @@
+<template>
+    <TableLayout :permissions="['business:device:query']">
+        <!-- 鎼滅储琛ㄥ崟 -->
+        <el-form ref="searchForm"  slot="search-form" :model="searchForm" label-width="100px" inline>
+            <el-form-item title="鍚嶇О" prop="name">
+                <el-input v-model="searchForm.name" placeholder="璇疯緭鍏ュ悕绉�" @keypress.enter.native="search"></el-input>
+            </el-form-item>
+            <section>
+                <el-button type="primary" @click="search">鎼滅储</el-button>
+                <el-button @click="reset">閲嶇疆</el-button>
+            </section>
+        </el-form>
+        <!-- 琛ㄦ牸鍜屽垎椤� -->
+        <template v-slot:table-wrap>
+            <ul class="toolbar">
+                <li><el-button type="primary" @click="synchronousData">鍚屾</el-button></li>
+            </ul>
+            <el-table
+                :height="tableHeightNew"
+                v-loading="isWorking.search"
+                :data="tableData.list"
+                stripe
+            >
+              <el-table-column label="搴忓彿"  width="55" fixed><template slot-scope="scope" >{{scope.$index+1}}</template></el-table-column>
+                <el-table-column prop="name" label="鍚嶇О"></el-table-column>
+                <el-table-column prop="hkId" label="骞挎挱鐐瑰敮涓�鏍囪瘑" min-width="200"></el-table-column>
+                <el-table-column prop="channelInfo" label="骞挎挱鐐圭被鍨�"></el-table-column>
+                <el-table-column prop="channelNo" label="閫氶亾鍙�"></el-table-column>
+                <el-table-column prop="regionName" label="鍖哄煙鍚嶇О"></el-table-column>
+                <el-table-column prop="hkDate" label="鍚屾鏃堕棿"></el-table-column>
+            </el-table>
+            <pagination
+                @size-change="handleSizeChange"
+                @current-change="handlePageChange"
+                :pagination="tableData.pagination"
+            >
+            </pagination>
+        </template>
+        <!-- 鏂板缓/淇敼 -->
+<!--        <OperaDeviceWindow ref="operaDeviceWindow" @success="handlePageChange"/>-->
+    </TableLayout>
+</template>
+
+<script>
+import BaseTable from '@/components/base/BaseTable'
+import TableLayout from '@/layouts/TableLayout'
+import Pagination from '@/components/common/Pagination'
+import OperaDeviceWindow from '@/components/business/OperaDeviceWindow'
+import { syncDevices, updateEntranceById } from '@/api/business/device'
+export default {
+  name: 'Device',
+  extends: BaseTable,
+  components: { TableLayout, Pagination, OperaDeviceWindow },
+  data () {
+    return {
+      // 鎼滅储
+      searchForm: {
+        doorName: '',
+        regionPathName: '',
+        isEntrance: '',
+        online: '',
+        type: 3
+      },
+      options: []
+    }
+  },
+  created () {
+    this.config({
+      module: '璁惧淇℃伅琛�',
+      api: '/business/device',
+      'field.id': 'id',
+      'field.main': 'id'
+    })
+    this.search()
+  },
+  methods: {
+    changeManufature(e, row) {
+      updateEntranceById({
+        id: row.id,
+        isEntrance: e
+      })
+    },
+    synchronousData () {
+      this.$dialog.actionConfirm('鎿嶄綔纭鎻愰啋', '鎮ㄧ‘璁ゅ悓姝ュ叏閮ㄤ俊鎭悧锛�')
+        .then(() => {
+          this.isWorking.delete = true
+          syncDevices({type: 3})
+            .then(res => {
+              this.$tip.apiSuccess(res || '鍚屾鎴愬姛')
+              this.search()
+            })
+            .catch(e => {
+             //  this.$tip.apiFailed(e)
+            })
+            .finally(() => {
+              this.isWorking.delete = false
+            })
+        })
+        .catch(() => {})
+    }
+  }
+}
+</script>
diff --git a/admin/src/views/business/jkSketch.vue b/admin/src/views/business/jkSketch.vue
index 6cb865b..ff2f105 100644
--- a/admin/src/views/business/jkSketch.vue
+++ b/admin/src/views/business/jkSketch.vue
@@ -5,6 +5,12 @@
       <el-form-item label="閫佽揣鏃ユ湡" prop="dateInfo">
         <el-date-picker v-model="searchForm.dateInfo" value-format="yyyy-MM-dd" placeholder="璇疯緭鍏ユ棩鏈�" @change="search"/>
       </el-form-item>
+      <el-form-item label="鎵�灞炰富绾胯矾" prop="categoryId">
+        <el-select v-model="searchForm.categoryId" clearable filterable placeholder="璇烽�夋嫨鎵�灞炰富绾胯矾"  @change="search">
+          <el-option v-for="item in categoryList" :key="item.id" :label="item.name" :value="item.id">
+          </el-option>
+        </el-select>
+      </el-form-item>
       <el-form-item label="鐘舵��" prop="status" >
         <el-select v-model="searchForm.status" placeholder="璇烽�夋嫨" clearable @change="search">
           <el-option label="鏈紭鍖�" value="0"></el-option>
@@ -91,6 +97,7 @@
 import OperaJkSketchLineListWindow from '@/components/business/OperaJkSketchLineListWindow'
 import OperaJkSketchResultWindow from '@/components/business/OperaJkSketchResultWindow'
 import OperaJkSketchImportWindow from '@/components/business/OperaJkSketchImportWindow'
+import {fetchCateList} from "@/api/business/category";
 export default {
   name: 'JkSketch',
   extends: BaseTable,
@@ -100,12 +107,14 @@
       // 鎼滅储
       searchForm: {
         status: '',
+        categoryId: '',
         dateInfo: ''
       },
       isWorking: {
         export1: false,
         export2: false
-      }
+      },
+      categoryList: []
     }
   },
   created () {
@@ -121,8 +130,14 @@
     const day = now.getDate();
     this.searchForm.dateInfo = `${year}-${month}-${day}`
     this.search()
+    this.loadCategory()
   },
   methods: {
+    loadCategory () {
+      fetchCateList({ type: 4 }).then(res => {
+        this.categoryList = res || []
+      })
+    },
     exportExcel1 () {
       if (!this.searchForm.dateInfo) {
         this.$message.error('璇烽�夋嫨鎸囧畾鏃ユ湡杩涜璇ュ鍑烘搷浣滐紒')
diff --git a/admin/whyc_admin/avatar/woman.png b/admin/whyc_admin/avatar/woman.png
new file mode 100644
index 0000000..eef8695
--- /dev/null
+++ b/admin/whyc_admin/avatar/woman.png
Binary files differ
diff --git a/admin/whyc_admin/favicon.ico b/admin/whyc_admin/favicon.ico
new file mode 100644
index 0000000..ec96d02
--- /dev/null
+++ b/admin/whyc_admin/favicon.ico
Binary files differ
diff --git a/admin/whyc_admin/template/cars.xlsx b/admin/whyc_admin/template/cars.xlsx
new file mode 100644
index 0000000..1b3c485
--- /dev/null
+++ b/admin/whyc_admin/template/cars.xlsx
Binary files differ
diff --git a/admin/whyc_admin/template/member.xlsx b/admin/whyc_admin/template/member.xlsx
new file mode 100644
index 0000000..577efa0
--- /dev/null
+++ b/admin/whyc_admin/template/member.xlsx
Binary files differ
diff --git a/admin/whyc_admin/template/oil.xlsx b/admin/whyc_admin/template/oil.xlsx
new file mode 100644
index 0000000..f4edb8a
--- /dev/null
+++ b/admin/whyc_admin/template/oil.xlsx
Binary files differ
diff --git a/admin/whyc_admin/template/traintime.xlsx b/admin/whyc_admin/template/traintime.xlsx
new file mode 100644
index 0000000..60a8379
--- /dev/null
+++ b/admin/whyc_admin/template/traintime.xlsx
Binary files differ
diff --git a/server/system_gateway/src/main/resources/bootstrap.yml b/server/system_gateway/src/main/resources/bootstrap.yml
index 3d2cb09..02ca26f 100644
--- a/server/system_gateway/src/main/resources/bootstrap.yml
+++ b/server/system_gateway/src/main/resources/bootstrap.yml
@@ -1,6 +1,6 @@
 spring:
   profiles:
-    active: pro
+    active: dev
   application:
     name: system_gateway
   # 瀹夊叏閰嶇疆
diff --git a/server/system_service/src/main/java/com/doumee/core/utils/Constants.java b/server/system_service/src/main/java/com/doumee/core/utils/Constants.java
index 3c92e2c..c867e07 100644
--- a/server/system_service/src/main/java/com/doumee/core/utils/Constants.java
+++ b/server/system_service/src/main/java/com/doumee/core/utils/Constants.java
@@ -57,6 +57,8 @@
     public static final String SIGN_IN_QRCODE ="SIGN_IN_QRCODE" ;
     public static final String SIGN_IN_ATTENTION ="SIGN_IN_ATTENTION" ;
     public static final String SIGN_IN_QRCODE_PREFIX ="SIGN_IN_QRCODE_PREFIX" ;
+    public static final String JK_PLAN_MAX_CLUSTER ="JK_PLAN_MAX_CLUSTER" ;
+    public static final String JK_PLAN_DISTANCE_CLUSTER ="JK_PLAN_DISTANCE_CLUSTER" ;
 
     /**
      * 鎿嶄綔绫诲瀷锛岀敤浜庡仛鎺ュ彛楠岃瘉鍒嗙粍
diff --git a/server/system_service/src/main/java/com/doumee/core/utils/HttpsUtil.java b/server/system_service/src/main/java/com/doumee/core/utils/HttpsUtil.java
index e7845db..244f654 100644
--- a/server/system_service/src/main/java/com/doumee/core/utils/HttpsUtil.java
+++ b/server/system_service/src/main/java/com/doumee/core/utils/HttpsUtil.java
@@ -1,17 +1,35 @@
 package com.doumee.core.utils;
 
+import lombok.extern.slf4j.Slf4j;
+import org.apache.http.HttpEntity;
+import org.apache.http.ParseException;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.UsernamePasswordCredentials;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.CredentialsProvider;
+import org.apache.http.client.config.RequestConfig;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpDelete;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.client.methods.HttpRequestBase;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
 import org.springframework.http.HttpMethod;
 
 import javax.net.ssl.*;
 import java.io.*;
 import java.net.HttpURLConnection;
+import java.net.URI;
 import java.net.URL;
 import java.security.KeyManagementException;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
-
+@Slf4j
 public class HttpsUtil {
 
     public static String get(String url,boolean ignoreSSL) {
@@ -28,6 +46,65 @@
             return connectionHttp(url, "POST", data, "application/json");
         }
     }
+    private static final int CONNECT_TIMEOUT =10000;// 璁剧疆杩炴帴寤虹珛鐨勮秴鏃舵椂闂翠负10s
+    private static final int SOCKET_TIMEOUT = 10000;//socket璇诲啓瓒呮椂鏃堕棿(鍗曚綅姣)
+
+    private static void setRequestConfig(HttpRequestBase httpRequestBase) {
+        RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(CONNECT_TIMEOUT)
+                .setConnectTimeout(CONNECT_TIMEOUT).setSocketTimeout(SOCKET_TIMEOUT).build();
+        httpRequestBase.setConfig(requestConfig);
+    }
+
+    public static String doPostHk(String host,int port,String UserName,String Password,String url, String Input) {
+        try {
+            CloseableHttpResponse responseBody = null;
+            HttpPost httpPost = new HttpPost("http://"+host+":"+port+url);
+            setRequestConfig(httpPost);
+            httpPost.setEntity(new StringEntity(Input, "UTF-8"));
+            CredentialsProvider credsProvider = new BasicCredentialsProvider();
+            credsProvider.setCredentials(new AuthScope(host, port),
+                    new UsernamePasswordCredentials(UserName, Password));
+            CloseableHttpClient httpClient = HttpClients.custom().setDefaultCredentialsProvider(credsProvider).build();
+
+            String response = "";
+
+            // 鐢卞鎴风鎵ц(鍙戦��)Post璇锋眰
+            responseBody = httpClient.execute(httpPost);
+            // 浠庡搷搴旀ā鍨嬩腑鑾峰彇鍝嶅簲瀹炰綋
+            HttpEntity responseEntity = responseBody.getEntity();
+            log.error("doPostHk鍝嶅簲鐘舵�佷负:" + responseBody.getStatusLine());
+            if (responseBody.getStatusLine().getStatusCode() == 302){
+                String redirectLocation = responseBody.getHeaders("Location")[0].getValue();
+                log.error("doPostHkRedirected to: " + redirectLocation);
+                // 鍦ㄨ繖閲岋紝浣犲彲浠ュ彂閫佷竴涓柊鐨勮姹傚埌redirectLocation
+                httpPost.setURI(URI.create(redirectLocation));
+                CloseableHttpResponse responseBody2 = httpClient.execute(httpPost);
+                log.error("doPostHk閲嶅畾鍚戝悗鍝嶅簲鐘舵�佷负:" + responseBody2.getStatusLine());
+                HttpEntity responseEntity2 = responseBody2.getEntity();
+                log.error("doPostHk閲嶅畾鍚戝悗鍝嶅簲鍐呭闀垮害涓�:" + responseEntity2.getContentLength());
+                response = EntityUtils.toString(responseEntity2);
+                log.error("doPostHk閲嶅畾鍚戝悗鍝嶅簲鍐呭涓�:\n" + response);
+                responseBody2.close();
+                return response;
+            }else {
+                if (responseEntity != null) {
+                    log.error("doPostHk鍝嶅簲鍐呭闀垮害涓�:" + responseEntity.getContentLength());
+                    response = EntityUtils.toString(responseEntity);
+                    log.error("doPostHk鍝嶅簲鍐呭涓�:\n" + response);
+                    return response;
+                }
+            }
+            if (httpClient != null) {
+                httpClient.close();
+            }
+            if (responseBody != null) {
+                responseBody.close();
+            }
+        } catch (Exception e) {
+            log.error("doPostHk鍙戣捣璇锋眰寮傚父:\n" + e.getMessage());
+        }
+        return null;
+    }
 
     public static String connection(String url,String method,String data,String contentType,boolean ignoreSSL){
         HttpsURLConnection connection = null;
diff --git a/server/visits/dmvisit_admin/src/main/java/com/doumee/api/business/DeviceController.java b/server/visits/dmvisit_admin/src/main/java/com/doumee/api/business/DeviceController.java
deleted file mode 100644
index 237c964..0000000
--- a/server/visits/dmvisit_admin/src/main/java/com/doumee/api/business/DeviceController.java
+++ /dev/null
@@ -1,110 +0,0 @@
-package com.doumee.api.business;
-
-import com.doumee.core.annotation.excel.ExcelExporter;
-import com.doumee.core.annotation.pr.PreventRepeat;
-import com.doumee.service.business.third.model.ApiResponse;
-import com.doumee.service.business.third.model.PageWrap;
-import com.doumee.service.business.third.model.PageData;
-import com.doumee.core.utils.Constants;
-import com.doumee.dao.business.model.Device;
-import com.doumee.service.business.DeviceService;
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import org.apache.shiro.authz.annotation.RequiresPermissions;    
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.web.bind.annotation.*;
-import javax.servlet.http.HttpServletResponse;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import com.doumee.api.BaseController;
-/**
- * @author 姹熻箘韫�
- * @date 2023/11/30 15:33
- */
-@Api(tags = "璁惧淇℃伅琛�")
-@RestController
-@RequestMapping("/business/device")
-public class DeviceController extends BaseController {
-
-    @Autowired
-    private DeviceService deviceService;
-
-    @PreventRepeat
-    @ApiOperation("鏂板缓")
-    @PostMapping("/create")
-    @RequiresPermissions("business:device:create")
-    public ApiResponse create(@RequestBody Device device) {
-        return ApiResponse.success(deviceService.create(device));
-    }
-
-    @ApiOperation("鏍规嵁ID鍒犻櫎")
-    @GetMapping("/delete/{id}")
-    @RequiresPermissions("business:device:delete")
-    public ApiResponse deleteById(@PathVariable Integer id) {
-        deviceService.deleteById(id);
-        return ApiResponse.success(null);
-    }
-    @ApiOperation("淇敼鏄惁闂ㄧ鍏ュ彛")
-    @PostMapping("/updateEntranceById")
-    @RequiresPermissions("business:company:update")
-    public ApiResponse updateStatusById(@RequestBody Device param) {
-        Device d = new Device();
-        d.setId(param.getId());
-        d.setEditDate(new Date());
-        d.setIsEntrance(Constants.formatIntegerNum(param.getIsEntrance()));
-        deviceService.updateById(d);
-        return ApiResponse.success(null);
-    }
-
-    @ApiOperation("鎵归噺鍒犻櫎")
-    @GetMapping("/delete/batch")
-    @RequiresPermissions("business:device:delete")
-    public ApiResponse deleteByIdInBatch(@RequestParam String ids) {
-        String [] idArray = ids.split(",");
-        List<Integer> idList = new ArrayList<>();
-        for (String id : idArray) {
-            idList.add(Integer.valueOf(id));
-        }
-        deviceService.deleteByIdInBatch(idList);
-        return ApiResponse.success(null);
-    }
-
-    @ApiOperation("鏍规嵁ID淇敼")
-    @PostMapping("/updateById")
-    @RequiresPermissions("business:device:update")
-    public ApiResponse updateById(@RequestBody Device device) {
-        deviceService.updateById(device);
-        return ApiResponse.success(null);
-    }
-
-    @ApiOperation("鍒嗛〉鏌ヨ")
-    @PostMapping("/page")
-    @RequiresPermissions("business:device:query")
-    public ApiResponse<PageData<Device>> findPage (@RequestBody PageWrap<Device> pageWrap) {
-        return ApiResponse.success(deviceService.findPage(pageWrap));
-    }
-
-    @ApiOperation("瀵煎嚭Excel")
-    @PostMapping("/exportExcel")
-    @RequiresPermissions("business:device:exportExcel")
-    public void exportExcel (@RequestBody PageWrap<Device> pageWrap, HttpServletResponse response) {
-        ExcelExporter.build(Device.class).export(deviceService.findPage(pageWrap).getRecords(), "璁惧淇℃伅琛�", response);
-    }
-
-    @ApiOperation("鏍规嵁ID鏌ヨ")
-    @GetMapping("/{id}")
-    @RequiresPermissions("business:device:query")
-    public ApiResponse findById(@PathVariable Integer id) {
-        return ApiResponse.success(deviceService.findById(id));
-    }
-
-    @ApiOperation("鑾峰彇闂ㄧ闆嗗悎-鎻愪緵缁欓棬绂佺粍")
-    @PostMapping("/getList")
-    @RequiresPermissions("business:device:query")
-    public ApiResponse findList(@RequestBody Device device) {
-        return ApiResponse.success(deviceService.findIdAndNameList(device));
-    }
-}
diff --git a/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/DeviceCloudController.java b/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/DeviceCloudController.java
index 1930129..a65ace5 100644
--- a/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/DeviceCloudController.java
+++ b/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/DeviceCloudController.java
@@ -36,6 +36,7 @@
     @PostMapping("/create")
     @CloudRequiredPermission("business:device:create")
     public ApiResponse create(@RequestBody Device device,@RequestHeader(Constants.HEADER_USER_TOKEN) String token){
+        device.setLoginUserInfo(this.getLoginUser(token));
         return ApiResponse.success(deviceService.create(device));
     }
 
@@ -43,7 +44,7 @@
     @GetMapping("/delete/{id}")
     @CloudRequiredPermission("business:device:delete")
     public ApiResponse deleteById(@PathVariable Integer id,@RequestHeader(Constants.HEADER_USER_TOKEN) String token){
-        deviceService.deleteById(id);
+        deviceService.deleteById(id,this.getLoginUser(token));
         return ApiResponse.success(null);
     }
     @ApiOperation("淇敼鏄惁闂ㄧ鍏ュ彛")
@@ -67,7 +68,7 @@
         for (String id : idArray) {
             idList.add(Integer.valueOf(id));
         }
-        deviceService.deleteByIdInBatch(idList);
+        deviceService.deleteByIdInBatch(idList,this.getLoginUser(token));
         return ApiResponse.success(null);
     }
 
@@ -75,6 +76,8 @@
     @PostMapping("/updateById")
     @CloudRequiredPermission("business:device:update")
     public ApiResponse updateById(@RequestBody Device device,@RequestHeader(Constants.HEADER_USER_TOKEN) String token){
+
+        device.setLoginUserInfo(this.getLoginUser(token));
         deviceService.updateById(device);
         return ApiResponse.success(null);
     }
diff --git a/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/HkSyncCloudController.java b/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/HkSyncCloudController.java
index 1d9c9fd..4edb06e 100644
--- a/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/HkSyncCloudController.java
+++ b/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/HkSyncCloudController.java
@@ -118,6 +118,9 @@
         }else if(Constants.equalsInteger(param.getType(),Constants.THREE)){
             //鍚屾骞挎挱
             result = hkSyncDeviceService.syncHkBroadcast(param);
+        }else if(Constants.equalsInteger(param.getType(),Constants.FOUR)){
+            //鍚屾骞挎挱
+            result = hkSyncDeviceService.syncHkBroadcastDevice(param);
         }
         return ApiResponse.success(result);
     }
@@ -351,5 +354,16 @@
         deviceService.setLedContent(body);
         return ApiResponse.success(null);
     }
+    @ApiOperation("銆愭捣搴枫�戝箍鎾挱鎶�")
+    @PostMapping("/sendBobao")
+    public ApiResponse<String> setBroadcaseBobao(@RequestBody Device body  , HttpServletResponse response) {
+        return ApiResponse.success( deviceService.setBroadcaseBobaoHttp(body));
+    }
+    @ApiOperation("銆愭捣搴枫�戝箍鎾挱鎶�")
+    @PostMapping("/sendBobaoOpenapi")
+    public ApiResponse<List<Map<String,Object>>> sendBobaoOpenapi(@RequestBody Device body  , HttpServletResponse response) {
+        deviceService.setBroadcaseBobao(body);
+        return ApiResponse.success(null);
+    }
 
 }
diff --git a/server/visits/dmvisit_admin/src/main/resources/bootstrap.yml b/server/visits/dmvisit_admin/src/main/resources/bootstrap.yml
index 2df12af..9dc10e9 100644
--- a/server/visits/dmvisit_admin/src/main/resources/bootstrap.yml
+++ b/server/visits/dmvisit_admin/src/main/resources/bootstrap.yml
@@ -1,6 +1,6 @@
 spring:
   profiles:
-    active: pro
+    active: dev
   application:
     name: visitsAdmin
     # 瀹夊叏閰嶇疆
diff --git a/server/visits/dmvisit_service/pom.xml b/server/visits/dmvisit_service/pom.xml
index 923a209..0d421a2 100644
--- a/server/visits/dmvisit_service/pom.xml
+++ b/server/visits/dmvisit_service/pom.xml
@@ -40,6 +40,11 @@
             <scope>compile</scope>
         </dependency>
         <dependency>
+            <groupId>org.apache.commons</groupId>
+            <artifactId>commons-math3</artifactId>
+            <version>3.6.1</version>
+        </dependency>
+        <dependency>
             <groupId>com.doumee</groupId>
             <artifactId>emaysms</artifactId>
             <version>1.0.0-SNAPSHOT</version>
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/model/HKTools.java b/server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/model/HKTools.java
index d6d1024..4dcda60 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/model/HKTools.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/model/HKTools.java
@@ -467,7 +467,6 @@
 		return result;
 	}
 
-
 	public static String startDoPostStringArtemis(String[] pathStr,Map<String, String> querys,Map<String, String> header,String body){
 		Map<String, String> path = getPath(pathStr[0]);
 		header.put("tagId","frs");
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/model/param/request/ISAPIBroadcastAddPlanSchemeRequest.java b/server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/model/param/request/ISAPIBroadcastAddPlanSchemeRequest.java
new file mode 100644
index 0000000..1ff34ee
--- /dev/null
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/model/param/request/ISAPIBroadcastAddPlanSchemeRequest.java
@@ -0,0 +1,87 @@
+package com.doumee.core.haikang.model.param.request;
+
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+public class ISAPIBroadcastAddPlanSchemeRequest {
+
+    /**
+    {
+        "terminalInfoList": [
+        {
+            "terminalID": 1,
+                "audioOutID": [
+            2
+            ],
+            "audioOutIndexList": [
+            1
+            ]
+        }
+    ],
+        "broadcastPlanSchemeList": [
+        {
+            "planSchemeID": "plan1",
+                "enabled": true,
+                "sourceID": "fdb4465d7aa5495884845127a8bbbe3c",
+                "weklyScheduleInfo": {
+            "startTime": "1970-01-01",
+                    "stopTime": "1970-01-01",
+                    "weeklyScheduleList": [
+            {
+                "dayOfWeek": 1,
+                    "scheduleList": [
+                {
+                    "planSchemeExecID": 0,
+                        "beginTime": "00:00:00",
+                        "endTime": "00:00:00",
+                        "playNowTime": "00:00:00",
+                        "operation": {
+                    "audioSource": "customAudio",
+                            "customAudioID": [
+                    2
+                                    ],
+                    "URLIDs": [
+                    1
+                                    ],
+                    "speechSynthesisContent": "test",
+                            "audioLevel": 0,
+                            "TTSLanguageType": "english",
+                            "voiceType": "male",
+                            "audioVolume": 1
+                }
+                }
+                        ]
+            }
+                ]
+        },
+            "dailyScheduleInfo": {
+            "startTime": "1970-01-01",
+                    "stopTime": "1970-01-01",
+                    "dailyScheduleList": [
+            {
+                "beginTime": "00:00:00",
+                    "endTime": "00:00:00",
+                    "playNowTime": "00:00:00",
+                    "operation": {
+                "audioSource": "customAudio",
+                        "customAudioID": [
+                2
+                            ],
+                "URLIDs": [
+                1
+                            ],
+                "speechSynthesisContent": "test",
+                        "audioLevel": 0,
+                        "TTSLanguageType": "english",
+                        "audioVolume": 1
+            }
+            }
+                ]
+        }
+        }
+    ]
+    }
+    */
+}
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/service/HKService.java b/server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/service/HKService.java
index ebb020f..0ed4fb4 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/service/HKService.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/core/haikang/service/HKService.java
@@ -1424,17 +1424,17 @@
      *鍒嗛〉鑾峰彇骞挎挱鐐癸紙鍒嗛〉锛�
      * @return
      */
-    public  static  BaseResponse<BaseListPageResponse<FetchAudioChannelInfoResponse>>   fetchAudioDevice(FetchAudioChannelRequest param){
-        log.info("銆愭捣搴疯幏鍙栧垎椤佃幏鍙栧箍鎾偣銆�================寮�濮�===="+JSONObject.toJSONString(param));
+    public  static  BaseResponse<BaseListPageResponse<FetchAudioDeviceInfoResponse>>   fetchAudioDevice(FetchAudioDeviceRequest param){
+        log.info("銆愭捣搴疯幏鍙栧垎椤佃幏鍙栧箍鎾澶囥��================寮�濮�===="+JSONObject.toJSONString(param));
         try {
             String res = HKTools.fetchAudioDevice(JSONObject.toJSONString(param));
             TypeReference typeReference =
-                    new TypeReference< BaseResponse<BaseListPageResponse<FetchAudioChannelInfoResponse>> >(){};
-            BaseResponse<BaseListPageResponse<FetchAudioChannelInfoResponse>>   result = JSONObject.parseObject(res, typeReference.getType());
-            logResult(result,"娴峰悍鑾峰彇鍒嗛〉鑾峰彇骞挎挱鐐�");
+                    new TypeReference< BaseResponse<BaseListPageResponse<FetchAudioDeviceInfoResponse>> >(){};
+            BaseResponse<BaseListPageResponse<FetchAudioDeviceInfoResponse>>   result = JSONObject.parseObject(res, typeReference.getType());
+            logResult(result,"娴峰悍鑾峰彇鍒嗛〉鑾峰彇骞挎挱璁惧");
             return  result;
         }catch (Exception e){
-            log.error("銆愭捣搴疯幏鍙栧垎椤佃幏鍙栧箍鎾偣銆�================澶辫触====锛歕n"+ e.getMessage());
+            log.error("銆愭捣搴疯幏鍙栧垎椤佃幏鍙栧箍鎾澶囥��================澶辫触====锛歕n"+ e.getMessage());
         }
         return  null;
     }
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java b/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java
new file mode 100644
index 0000000..8915a9b
--- /dev/null
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/ClusterCustomKMeans.java
@@ -0,0 +1,147 @@
+package com.doumee.core.tsp;
+
+import java.math.BigDecimal;
+import java.util.*;
+
+import com.doumee.core.utils.Constants;
+import com.doumee.dao.admin.request.SketchCateModel;
+import com.doumee.dao.business.model.JkSketchCustomer;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.math3.ml.clustering.*;
+import org.apache.commons.math3.ml.distance.EuclideanDistance;
+/**
+ *
+ * @author xjx
+ *
+ */
+@Slf4j
+public class ClusterCustomKMeans{
+    //娆у紡璺濈
+
+        public  List<SketchCateModel> clusterPoints(List<JkSketchCustomer> customers, int k, int d){
+            List<SketchCateModel> list = new ArrayList<>();
+            if(customers.size() <= k){
+                int index =0;
+                for (JkSketchCustomer c : customers) {
+                    SketchCateModel sketchCateModel = new SketchCateModel();
+                    sketchCateModel.setId(index);
+                    List<JkSketchCustomer> cList = new ArrayList<>();
+                    cList.add(c);
+                    sketchCateModel.setTotalNum(c.getTotalNum());
+                    sketchCateModel.setCustomerList(cList);
+                    sketchCateModel.setStartPoint(c);
+                    sketchCateModel.setTotalCustomer(1);
+                    list.add(sketchCateModel);
+                    log.error("Cluster " + index + "members锛�"+1+"/200 "+" 瀹㈡埛锛�"+   c.getName());
+                    index ++;
+                }
+                return list;
+            }
+            List<DoublePointNew> points = new ArrayList<>();
+            for (int i = 0; i < customers.size(); i++) {
+                DoublePointNew p = new DoublePointNew(new double[]{customers.get(i).getLatitude().doubleValue(), customers.get(i).getLongitude().doubleValue()});
+                p.setCustomer(customers.get(i));
+                points.add(p); // 绀轰緥鐐�1
+            }
+            KMeansPlusPlusClusterer<DoublePointNew> clusterer = new KMeansPlusPlusClusterer<>(k, d, new EuclideanDistance());
+            List<CentroidCluster<DoublePointNew>> clusters = clusterer.cluster(points);
+
+            int index  = 0;
+            int maxMembersPerCluster = 200; // 璁剧疆姣忎釜绨囩殑鏈�澶ф垚鍛樻暟
+            List<CentroidCluster<DoublePointNew>> allList = new ArrayList<>();
+            for (CentroidCluster<DoublePointNew> cluster : clusters) {
+                if(cluster.getPoints() ==null || cluster.getPoints().size() ==0){
+                    log.error("Cluster " + clusters.indexOf(cluster) + "members锛�"+cluster.getPoints().size()+"/200  鏃犳暟鎹�");
+                    continue;
+                }
+                log.error("Cluster " + clusters.indexOf(cluster) + "members锛�"+cluster.getPoints().size()+"/200 "+"涓績鐐癸細"+ Arrays.toString(cluster.getCenter().getPoint())+"涓績鐐癸細"+ cluster.getPoints().get(0).getCustomer().getName());
+                if (cluster.getPoints().size() > maxMembersPerCluster) {
+                    // 杩欓噷鍙互閲嶆柊杩愯鑱氱被绠楁硶鎴栬�呮墜鍔ㄨ皟鏁寸皣鐨勫垎閰嶇瓥鐣�
+                    log.error("Cluster " + clusters.indexOf(cluster) + " exceeds maximum members锛�" + cluster.getPoints().size() + "/200, re-clustering needed.");
+                    // 鍙互鑰冭檻鍐嶆璋冪敤KMeansPlusPlusClusterer鎴栧叾瀹冮�昏緫鏉ュ鐞嗚秴闄愭儏鍐点��
+                }
+                allList.add(cluster);
+            }
+            for (CentroidCluster<DoublePointNew> cluster : allList) {
+//                System.out.println("Cluster " + clusters.indexOf(cluster) + "members锛�"+cluster.getPoints().size()+"/200 ");
+                if (cluster.getPoints().size() > maxMembersPerCluster) {
+                    // 杩欓噷鍙互閲嶆柊杩愯鑱氱被绠楁硶鎴栬�呮墜鍔ㄨ皟鏁寸皣鐨勫垎閰嶇瓥鐣�
+//                    System.out.println("Cluster " + clusters.indexOf(cluster) + " exceeds maximum members锛�"+cluster.getPoints().size()+"/200, re-clustering needed.");
+                    // 鍙互鑰冭檻鍐嶆璋冪敤KMeansPlusPlusClusterer鎴栧叾瀹冮�昏緫鏉ュ鐞嗚秴闄愭儏鍐点��
+                }
+                SketchCateModel sketchCateModel = new SketchCateModel();
+                sketchCateModel.setId(index);
+                List<JkSketchCustomer> cList = new ArrayList<>();
+                for(DoublePointNew doublePointNew:cluster.getPoints()){
+                    cList.add(doublePointNew.getCustomer());
+                    sketchCateModel.setTotalNum(Constants.formatBigdecimal(sketchCateModel.getTotalNum()).add(Constants.formatBigdecimal(doublePointNew.getCustomer().getTotalNum())));
+                }
+                sortPointByCenterPoint(cluster,cList);
+                sketchCateModel.setCustomerList(cList);
+                sketchCateModel.setStartPoint(cList.get(0));
+                sketchCateModel.setTotalCustomer(cList.size());
+                list.add(sketchCateModel);
+            }
+            return list;
+        }
+
+    private void sortPointByCenterPoint(CentroidCluster<DoublePointNew> cluster, List<JkSketchCustomer> cList) {
+        double clat = Constants.formatBigdecimal(cList.get(0).getLatitude()).doubleValue();
+        double clong = Constants.formatBigdecimal(cList.get(0).getLongitude()).doubleValue();
+        if(cluster!=null || cluster.getCenter() != null || cluster.getCenter().getPoint() != null && cluster.getCenter().getPoint().length>=2){
+            clong = cluster.getCenter().getPoint()[1];
+            clat = cluster.getCenter().getPoint()[0];
+        }
+        for(JkSketchCustomer c : cList){
+            double latDiff = Constants.formatBigdecimal(c.getLatitude()).doubleValue() - clat;
+            double lonDiff = Constants.formatBigdecimal(c.getLongitude()).doubleValue() - clong;
+            c.setDistanceCenter(Math.sqrt(latDiff * latDiff + lonDiff * lonDiff)); // 娆ф皬璺濈
+        }
+        Collections.sort(cList, (p1, p2) -> Double.compare(p1.getDistanceCenter(), p2.getDistanceCenter()));
+    }
+
+    public  class  DoublePointNew extends  DoublePoint{
+        private JkSketchCustomer customer;
+
+        public DoublePointNew(double[] point) {
+            super(point);
+        }
+
+        public JkSketchCustomer getCustomer() {
+            return customer;
+        }
+
+        public void setCustomer(JkSketchCustomer customer) {
+            this.customer = customer;
+        }
+
+    }
+    public static void main(String[] args) {
+        List<JkSketchCustomer> points = new ArrayList<>();
+        for (int i = 0; i <10; i++) {
+            JkSketchCustomer a = new JkSketchCustomer();
+            a.setLatitude(new BigDecimal(30.19d ));
+            a.setLongitude(new BigDecimal(117.40 ));
+            a.setName("瀹㈡埛"+i);
+            points.add(a);
+        }
+        for (int i = 0; i <10; i++) {
+            JkSketchCustomer a = new JkSketchCustomer();
+            a.setLatitude(new BigDecimal(31.19d ));
+            a.setLongitude(new BigDecimal(118.40 ));
+            a.setName("瀹㈡埛"+i);
+            points.add(a);
+        }
+         for (int i = 10; i <3000; i++) {
+            JkSketchCustomer a = new JkSketchCustomer();
+            a.setLatitude(new BigDecimal(31.19d-(0.1d)*Math.random()));
+            a.setLongitude(new BigDecimal(118.40-(0.2d)*Math.random()));
+            a.setName("瀹㈡埛"+i);
+            points.add(a);
+        }
+
+        double threshold = 1000; // 璁剧疆璺濈闃堝�硷紝瓒呰繃杩欎釜璺濈灏变笉灞炰簬鍚屼竴鑱氱被銆�
+        (new ClusterCustomKMeans()).clusterPoints(points, 100,1);
+    }
+
+}
\ No newline at end of file
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/Clustering.java b/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/Clustering.java
new file mode 100644
index 0000000..56f2a15
--- /dev/null
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/Clustering.java
@@ -0,0 +1,85 @@
+package com.doumee.core.tsp;
+
+/**
+ * 鑱氱被鍒嗙粍
+ */
+import com.doumee.core.utils.Constants;
+import com.doumee.dao.admin.request.SketchCateModel;
+import com.doumee.dao.business.model.JkSketchCustomer;
+import com.doumee.service.business.impl.JkSketchServiceImpl;
+
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Clustering {
+    public static  List<SketchCateModel>  clusterPoints(List<JkSketchCustomer> points, double threshold) {
+
+        List<SketchCateModel> clusters = new ArrayList<>();
+        boolean[] visited = new boolean[points.size()];
+        int index =0;
+        for (int i = 0; i < points.size(); i++) {
+            if (!visited[i]) {
+                List<JkSketchCustomer> cluster = new ArrayList<>();
+                dfs(points, visited, cluster, i, threshold);
+                SketchCateModel sketchCateModel = new SketchCateModel();
+                sketchCateModel.setCustomerList(cluster);
+                sketchCateModel.setId(index);
+                sketchCateModel.setStartPoint(cluster.get(0));
+                for (JkSketchCustomer c : cluster){
+                    sketchCateModel.setTotalNum(Constants.formatBigdecimal(sketchCateModel.getTotalNum()).add(Constants.formatBigdecimal(c.getTotalNum())));
+                }
+                sketchCateModel.setTotalCustomer(cluster.size());
+                clusters.add(sketchCateModel);
+            }
+        }
+        // 鎵撳嵃姣忎釜鑱氱被鐨勭偣
+        for (int i = 0; i < clusters.size(); i++) {
+            System.out.println("Cluster " + (i + 1) + ": " + clusters.get(i).getStartPoint().getName()+ ": " + clusters.get(i).getCustomerList().size());
+        }
+        return  clusters;
+    }
+    public static double distanceTo(JkSketchCustomer self, JkSketchCustomer other) {
+        List<DistanceMapParam> distanceMapParamList  =JkSketchServiceImpl.getListFromJsonStr(self.getDistanceJson());
+        DistanceMapParam param = JkSketchServiceImpl.getParamByCustomerIds( other.getId(),distanceMapParamList);
+        if(param!=null && param.getDistance()!=0){//濡傛灉涔嬪墠宸茬粡鑾峰彇杩�
+          return (param.getDistance());
+        }
+        return DistanceCalculator.calculateDistance(Constants.formatBigdecimal(self.getLatitude()).doubleValue()
+                ,Constants.formatBigdecimal(self.getLongitude()).doubleValue()
+                ,Constants.formatBigdecimal(other.getLatitude()).doubleValue()
+                ,Constants.formatBigdecimal(other.getLongitude()).doubleValue());
+    }
+    private static void dfs(List<JkSketchCustomer> points, boolean[] visited, List<JkSketchCustomer> cluster, int startIndex, double threshold) {
+        visited[startIndex] = true;
+        cluster.add(points.get(startIndex));
+        JkSketchCustomer startPoint = points.get(startIndex);
+
+        for (int i = 0; i < points.size(); i++) {
+            if (!visited[i]) {
+                double distance = distanceTo(startPoint,points.get(i));
+                if (distance <= threshold) {
+                    dfs(points, visited, cluster, i, threshold); // 閫掑綊娣诲姞鍒拌仛绫讳腑
+                }
+            }
+        }
+    }
+
+    /**
+     * 117掳40鈥诧綖118掳44鈥层�佸寳绾�30掳19鈥诧綖31掳34鈥�
+     * @param args
+     */
+    public static void main(String[] args) {
+        List<JkSketchCustomer> points = new ArrayList<>();
+        for (int i = 0; i <3000; i++) {
+            JkSketchCustomer a = new JkSketchCustomer();
+            a.setLatitude(new BigDecimal(30.19d+(30.54d-30.19d)*Math.random()));
+            a.setLongitude(new BigDecimal(117.40+(117.74d-117.40d)*Math.random()));
+            a.setName("瀹㈡埛"+i);
+            points.add(a);
+        }
+
+        double threshold = 1000; // 璁剧疆璺濈闃堝�硷紝瓒呰繃杩欎釜璺濈灏变笉灞炰簬鍚屼竴鑱氱被銆�
+        clusterPoints(points, threshold);
+    }
+}
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/DistanceCalculator.java b/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/DistanceCalculator.java
index 054a7e0..17a6b87 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/DistanceCalculator.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/DistanceCalculator.java
@@ -167,6 +167,6 @@
                         Math.sin(dLon / 2) * Math.sin(dLon / 2);
         double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
 
-        return  (long) (EARTH_RADIUS * c );
+        return  (long) (EARTH_RADIUS * c * 1000);
     }
 }
\ No newline at end of file
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/TspSolver.java b/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/TspSolver.java
index 2aa6bef..9e3c01d 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/TspSolver.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/core/tsp/TspSolver.java
@@ -25,7 +25,7 @@
         data.initDataList();//鏋勯�犳暟鎹�
 
         long start =System.currentTimeMillis();
-        System.out.println("=============start=========="+start);
+       log.error("=============start=========="+start);
         //鍒涘缓姹傝В鍣╩anager瀵硅薄锛屽垵濮嬪寲姹傝В鍣ㄦ暟鎹�
         RoutingIndexManager manager =  new RoutingIndexManager(data.distanceMatrix.length, data.vehicleNumber, data.depot);
 
@@ -71,15 +71,15 @@
         // 鎵撳嵃璺嚎
         printSolution(data, routing, manager, solution);
         long end =System.currentTimeMillis();
-        System.out.println("=============end=========="+end);
+       log.error("=============end=========="+end);
 
-        System.out.println("=============鑰楁椂=========="+(end -start)+"锛坢s锛�"+(end -start)/1000 +"s"+(end -start)/60/1000 +"m");
+       log.error("=============鑰楁椂=========="+(end -start)+"锛坢s锛�"+(end -start)/1000 +"s"+(end -start)/60/1000 +"m");
     */}
     public static void startSearch(DataModel data) {
         // 鍒濆鍖栨暟鎹ā鍨�
         Loader.loadNativeLibraries();
         long start =System.currentTimeMillis();
-        System.out.println("=============start=========="+start);
+       log.error("寮�濮嬭鍒�=============start=========="+start);
         //鍒涘缓姹傝В鍣╩anager瀵硅薄锛屽垵濮嬪寲姹傝В鍣ㄦ暟鎹�
         RoutingIndexManager manager =  new RoutingIndexManager(data.distanceMatrix.length, data.vehicleNumber, data.depot);
 
@@ -87,7 +87,7 @@
         RoutingModel routing = new RoutingModel(manager);
 
         // 娉ㄥ唽鍥炶皟鍑芥暟
-       /* final int transitCallbackIndex =
+       final int transitCallbackIndex =
                 routing.registerTransitCallback((long fromIndex, long toIndex) -> {
                     int fromNode = manager.indexToNode(fromIndex);
                     int toNode = manager.indexToNode(toIndex);
@@ -96,15 +96,16 @@
 
         // 瀹氫箟鍥炶皟鍑芥暟鑷虫瘡鏉¤矾绾�
         routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
-        routing.addDimension(transitCallbackIndex, 0, 30000000,
+  /*      routing.addDimension(transitCallbackIndex, 0, 30000000,
                 true,
                 "Distance");
         RoutingDimension distanceDimension = routing.getMutableDimension("Distance");
-        distanceDimension.setGlobalSpanCostCoefficient(100);*/
+        distanceDimension.setGlobalSpanCostCoefficient(100); */
         // 娉ㄥ唽鍥炶皟鍑芥暟
         final int transitCallbackIndex1 =
                 routing.registerTransitCallback((long fromIndex, long toIndex) -> {
-                    return 1;
+                    int fromNode = manager.indexToNode(fromIndex);
+                    return data.customerDemands[fromNode];
                 });
         for (int d = 0; d < data.vehicleMaxNodes.length; d++) {
             // 澧炲姞璺濈缁村害绾︽潫
@@ -121,33 +122,25 @@
         });
         routing.addDimensionWithVehicleCapacity(demandCallbackIndex, 0, data.vehicleCapacities, true, "Capacity");
 
-/*
-        // 娣诲姞瀹归噺闄愬埗
-        final int demandCallbackIndex1 = routing.registerUnaryTransitCallback((long fromIndex) -> {
-            return 1;
-        });
-        routing.addDimensionWithVehicleCapacity(demandCallbackIndex1, 0, data.vehicleMaxNodes, true, "Capacity");
-*/
-
         Solver solver = routing.solver();
         //璁剧疆鎼滅储鏂规硶(
         RoutingSearchParameters searchParameters =
                 main.defaultRoutingSearchParameters()
                         .toBuilder()
-                        .setTimeLimit(Duration.newBuilder().setSeconds(60*60).build())//鏈�涔�1灏忔椂
+                        .setTimeLimit(Duration.newBuilder().setSeconds(60*60*6).build())//鏈�涔�1灏忔椂
                         .setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
                         .build();
 
         // 鎵ц绠楁硶
         Assignment solution = routing.solveWithParameters(searchParameters);
         if(solution ==null){
+            log.error("瑙勫垝缁撴潫=============鏈壘鍒版渶浼樿矾绾匡紒" );
             throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"鏈壘鍒版渶浼樿矾绾匡紒");
         }
         // 鎵撳嵃璺嚎
         resultSolution(data, routing, manager, solution);
         long end =System.currentTimeMillis();
-        System.out.println("=============end=========="+end);
-        System.out.println("=============鑰楁椂=========="+(end -start)+"锛坢s锛�"+(end -start)/1000 +"s"+(end -start)/60/1000 +"m");
+         log.error("瑙勫垝缁撴潫=============鑰楁椂=========="+(end -start)+"锛坢s锛�"+(end -start)/1000 +"s"+(end -start)/60/1000 +"m");
     }
     static void resultSolution( DataModel data, RoutingModel routing, RoutingIndexManager manager, Assignment solution) {
         long maxRouteDistance = 0;
@@ -223,6 +216,7 @@
 
         //姣忎竴涓偣鐨勫晢鍝佺殑鏁伴噺
         public   long[] demands;
+        public   long[] customerDemands;
         //杞﹁締鏈�澶у杞�
         public   long[] vehicleCapacities ;
         public   long[] vehicleMaxNodes ;
@@ -236,17 +230,19 @@
            this.solutions = solutions;
        }
 
-       public  void initDataInfo(int vehicleNumber1, long[] demands1, long[] vehicleCapacities1, long[][] distanceMatrix1,long[] vehicleMaxNodes){
+       public  void initDataInfo(int vehicleNumber1, long[] demands1,long[] demands2, long[] vehicleCapacities1, long[][] distanceMatrix1,long[] vehicleMaxNodes){
             this.demands = demands1;
+            this.customerDemands = demands2;
             this.vehicleNumber = vehicleNumber1;
             this.vehicleCapacities=vehicleCapacities1;
             this.distanceMatrix=distanceMatrix1;
             this.vehicleMaxNodes =vehicleMaxNodes;
         }
         public   void initDataList(){
-            lenght = 20;
+            lenght = 10;
             vehicleNumber = 5;
             demands = new long[lenght];
+            customerDemands = new long[lenght];
             vehicleCapacities =new long[vehicleNumber];
             vehicleMaxNodes =new long[vehicleNumber];
             distanceMatrix =  new long[lenght][lenght];
@@ -254,15 +250,16 @@
             for (int i = 0; i <vehicleNumber ; i++) {
                 long tem = (long) (Math.random() * 1000 + 20000);
                 vehicleCapacities[i] = tem;
-                vehicleMaxNodes[i] =5;
+                vehicleMaxNodes[i] =50;
                 total0+=tem;
                 System.out.print(tem+" ,");
             }
-            System.out.println( "\ntotal Capacity:"+total0+"=====================");
+           log.error( "\ntotal Capacity:"+total0+"=====================");
             long total = 0;
             for (int i = 0; i <lenght ; i++) {
                 long tem =  (int)(Math.random()*100+100);
                 demands[i] =tem;
+                customerDemands[i] =1;
                 total+=tem;
                 System.out.print(tem+" ,");
                 for (int j = 0; j <lenght ; j++) {
@@ -276,7 +273,7 @@
                 }
             }
 
-            System.out.println( "\ntotal Demands:"+total+"=====================");
+           log.error( "\ntotal Demands:"+total+"=====================");
         }
        /* public final long[][] distanceMatrix = {
                 {0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662},
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/admin/request/SketchCateModel.java b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/admin/request/SketchCateModel.java
new file mode 100644
index 0000000..729ba4b
--- /dev/null
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/admin/request/SketchCateModel.java
@@ -0,0 +1,36 @@
+package com.doumee.dao.admin.request;
+
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.doumee.core.annotation.excel.ExcelColumn;
+import com.doumee.core.tsp.DistanceMapParam;
+import com.doumee.dao.business.model.JkSketchCustomer;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 鍛樺伐淇℃伅瀵煎叆琛�
+ * @author 姹熻箘韫�
+ * @date 2024/01/16 10:03
+ */
+@Data
+@ApiModel("绾胯矾瑙勫垝鑱氱被鍒嗙粍闆嗗悎")
+public class SketchCateModel {
+
+    private int id;
+    private JkSketchCustomer startPoint;
+    //涓績鐐圭含搴�
+    private BigDecimal latitude;
+    //涓績鐐圭粡搴�
+    private BigDecimal longitude;
+    @ApiModelProperty(value = "閫佽揣閲�", example = "1")
+    private BigDecimal totalNum;
+    @ApiModelProperty(value = "鎬诲鎴锋暟", example = "1")
+    private int totalCustomer;
+    //鐐归泦鍚�
+    private  List<JkSketchCustomer> customerList;
+
+}
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/Device.java b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/Device.java
index 2896604..b95469d 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/Device.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/Device.java
@@ -1,5 +1,6 @@
 package com.doumee.dao.business.model;
 
+import com.baomidou.mybatisplus.annotation.TableField;
 import com.doumee.core.annotation.excel.ExcelColumn;
 import com.doumee.service.business.third.model.LoginUserModel;
 import io.swagger.annotations.ApiModel;
@@ -70,8 +71,8 @@
     @ExcelColumn(name="鎺掑簭鐮�")
     private Integer sortnum;
 
-    @ApiModelProperty(value = "绫诲瀷 0闂ㄧ 1杞﹀簱 2LED 3骞挎挱", example = "1")
-    @ExcelColumn(name="绫诲瀷 0闂ㄧ 1杞﹀簱 2LED 3骞挎挱")
+    @ApiModelProperty(value = "绫诲瀷 0闂ㄧ 1杞﹀簱 2LED 3骞挎挱鐐� 4骞挎挱璁惧", example = "1")
+    @ExcelColumn(name="绫诲瀷 0闂ㄧ 1杞﹀簱 2LED 3骞挎挱鐐� 4骞挎挱璁惧")
     private Integer type;
     @ApiModelProperty(value = "鏄惁鍥尯鍑哄叆鍙� 0涓嶆槸 1鏄�", example = "1")
     @ExcelColumn(name="鏄惁鍥尯鍑哄叆鍙� 0涓嶆槸 1鏄�")
@@ -155,8 +156,9 @@
     private String doorName;
 
 
-
-
+    @ApiModelProperty(value = "鎾姤鍐呭")
+    @TableField(exist = false)
+    private String sendInfo;
 
 
 
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/Empower.java b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/Empower.java
index 77f4b74..52671f0 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/Empower.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/Empower.java
@@ -59,7 +59,6 @@
     @ApiModelProperty(value = "瀵煎叆澶囨敞")
     private String importInfo;
 
-
     @ApiModelProperty(value = "涓嬪彂浜哄憳", example = "1")
     private Integer sendUserId;
     @ApiModelProperty(value = "涓嬪彂娆℃暟", example = "1")
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkCabinet.java b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkCabinet.java
index aad438a..f8d889a 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkCabinet.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkCabinet.java
@@ -148,6 +148,9 @@
     @ExcelColumn(name="璧峰缂栫爜")
     private Integer noIndex;
 
+    @ApiModelProperty(value = "閰掔簿妫�娴嬪紑鍚細0=寮�鍚紱1=鍏抽棴", example = "1")
+    private Integer alcoholStatus;
+
     @ApiModelProperty(value = "缁忕含搴︿俊鎭� 鍙傛暟鍊硷細缁忓害,绾害")
     @TableField(exist = false)
     private String jwd;
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketchCustomer.java b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketchCustomer.java
index 8894d2e..8b990bf 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketchCustomer.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketchCustomer.java
@@ -143,6 +143,9 @@
     //@ExcelColumn(name="鐘舵�� 0姝e父 绂佺敤")
     @TableField(exist = false)
     private String  endSteps;
+    @ApiModelProperty(value = "璺濈涓績鐐硅窛绂�", example = "1")
+    @TableField(exist = false)
+    private double  distanceCenter;
     @ApiModelProperty(value = "鍚岀彮缁勯棿瀹㈡埛浣嶇疆璺濈鏁扮粍锛孾{a:12,b:100},{a:13,b:200},...],a锛氬鎴风紪鐮侊紝b锛氫笌瀹㈡埛a涔嬮棿鐨勮窛绂�")
     @TableField(exist = false)
     private List<DistanceMapParam> distanceMapParamList;
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/vo/CabinetInfoVO.java b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/vo/CabinetInfoVO.java
index 591b025..dca9101 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/vo/CabinetInfoVO.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/vo/CabinetInfoVO.java
@@ -64,6 +64,8 @@
     @ApiModelProperty(value = "婵�娲绘枃浠跺湴鍧�")
     private String activateFileUrl;
 
+    @ApiModelProperty(value = "閰掔簿妫�娴嬪紑鍚細0=寮�鍚紱1=鍏抽棴", example = "1")
+    private Integer alcoholStatus;
 
     @ApiModelProperty(value = "杞挱鍥惧湴鍧�", example = "1")
     private List<String> bannerList;
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/DeviceService.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/DeviceService.java
index b447ed3..ceced8e 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/DeviceService.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/DeviceService.java
@@ -1,6 +1,7 @@
 package com.doumee.service.business;
 
 import com.doumee.core.haikang.model.param.request.TransparentChannelSingleRequest;
+import com.doumee.service.business.third.model.LoginUserInfo;
 import com.doumee.service.business.third.model.PageData;
 import com.doumee.service.business.third.model.PageWrap;
 import com.doumee.dao.business.model.Device;
@@ -26,7 +27,7 @@
      *
      * @param id 涓婚敭
      */
-    void deleteById(Integer id);
+    void deleteById(Integer id, LoginUserInfo userInfo);
 
     /**
      * 鍒犻櫎
@@ -40,7 +41,7 @@
      *
      * @param ids 涓婚敭闆�
      */
-    void deleteByIdInBatch(List<Integer> ids);
+    void deleteByIdInBatch(List<Integer> ids, LoginUserInfo userInfo);
 
     /**
      * 涓婚敭鏇存柊
@@ -105,4 +106,7 @@
 
     void setLedContent(TransparentChannelSingleRequest body);
     void allLedDefualtContent();
+
+    void setBroadcaseBobao(Device body);
+    String setBroadcaseBobaoHttp(Device body);
 }
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/JkSketchService.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/JkSketchService.java
index 7d062df..32500c3 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/JkSketchService.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/JkSketchService.java
@@ -108,6 +108,7 @@
 
     List<JkSketch> importBatch(MultipartFile file, String dateInfo, LoginUserInfo loginUser);
 
+    void startUpdateLineAsyncOld(JkSketch model);
     void startUpdateLineAsync(JkSketch model);
 
     void distanceCustomer(Category model );
@@ -119,7 +120,7 @@
     void startEditSketchLineAsync(JkSketch model);
 
     void startInitOriginDistanceBatch(JkSketch list);
-
+    void startEditSketchLineAsyncOld(JkSketch model);
 
     /**
      * 杞﹁締绾胯矾  - 鐢典俊浣跨敤
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/ext/HkSyncService.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/ext/HkSyncService.java
index c30d332..c7b3189 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/ext/HkSyncService.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/ext/HkSyncService.java
@@ -97,6 +97,7 @@
     String syncHkLed(Device param);
 
     String syncHkBroadcast(Device param);
+    String syncHkBroadcastDevice(Device param);
     String dealVisitEventIccm(EventVisitIccmRequest param, HttpServletResponse response);
 
     String dealPlatformStatusEvent(EventPlatformRequest param, HttpServletResponse response);
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceServiceImpl.java
index b8c1545..0415313 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/DeviceServiceImpl.java
@@ -1,12 +1,20 @@
 package com.doumee.service.business.impl;
 
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 import com.doumee.biz.system.SystemDictDataBiz;
 import com.doumee.core.constants.ResponseStatus;
 import com.doumee.core.exception.BusinessException;
+import com.doumee.core.haikang.model.HKConstants;
+import com.doumee.core.haikang.model.param.BaseResponse;
+import com.doumee.core.haikang.model.param.request.CustomBroadcastRequest;
 import com.doumee.core.haikang.model.param.request.TransparentChannelSingleRequest;
+import com.doumee.core.haikang.service.HKService;
+import com.doumee.core.utils.HttpsUtil;
 import com.doumee.dao.business.*;
 import com.doumee.dao.business.model.*;
+import com.doumee.service.business.third.model.LoginUserInfo;
 import com.doumee.service.business.third.model.PageData;
 import com.doumee.service.business.third.model.PageWrap;
 import com.doumee.core.utils.Constants;
@@ -49,14 +57,24 @@
 
 
     @Override
-    public Integer create(Device device) {
-        deviceMapper.insert(device);
-        return device.getId();
+    public Integer create(Device model) {
+        model.setCreator(model.getLoginUserInfo().getId()+"");
+        model.setEdirot(model.getCreator());
+        model.setIsdeleted(Constants.ZERO);
+        model.setEditDate(new Date());
+        model.setCreateDate(model.getEditDate());
+        deviceMapper.insert(model);
+        return model.getId();
     }
 
     @Override
-    public void deleteById(Integer id) {
-        deviceMapper.deleteById(id);
+    public void deleteById(Integer id, LoginUserInfo userInfo) {
+        Device update = new Device();
+        update.setEdirot(userInfo.getId()+"");
+        update.setEditDate(new Date());
+        update.setIsdeleted(Constants.ONE);
+        update.setId(id);
+        deviceMapper.updateById(update);
     }
 
     @Override
@@ -66,15 +84,19 @@
     }
 
     @Override
-    public void deleteByIdInBatch(List<Integer> ids) {
+    public void deleteByIdInBatch(List<Integer> ids, LoginUserInfo userInfo) {
         if (CollectionUtils.isEmpty(ids)) {
             return;
         }
-        deviceMapper.deleteBatchIds(ids);
+        for(Integer id :ids){
+            deleteById(id,userInfo);
+        }
     }
 
     @Override
     public void updateById(Device device) {
+        device.setEdirot(device.getLoginUserInfo().getId()+"");
+        device.setEditDate(new Date());
         deviceMapper.updateById(device);
     }
 
@@ -232,6 +254,154 @@
     }
 
     @Override
+    public void setBroadcaseBobao(Device model){
+        List<String> ids = new ArrayList<>();
+        ids.add(model.getHkId());
+        CustomBroadcastRequest request = new CustomBroadcastRequest();
+        request.setAudioPointIndexCode(ids);
+        request.setPlayDuration(15);//鍗曚綅绉�
+        request.setBroadCastMode("tts");
+        request.setPriority(1);
+        request.setState(1);//鎾斁/鍋滄鏍囪瘑 1-鎾斁锛�0-鍋滄
+        request.setPlayTtsContent(model.getSendInfo());
+        BaseResponse response =  HKService.customBroadcast(request);
+        if(response == null || !StringUtils.equals(response.getCode(), HKConstants.RESPONSE_SUCCEE)){
+          throw  new BusinessException(ResponseStatus.SERVER_ERROR.getCode(),"鍙戦�佸け璐ワ細"+ JSONObject.toJSONString(response));
+        }
+    }
+    @Override
+    public String setBroadcaseBobaoHttp(Device param){
+       /* Device model = deviceMapper.selectById(param.getId());
+        if(model ==null && Constants.equalsInteger(param.getType(),Constants.FOUR)){
+            throw  new BusinessException(ResponseStatus.DATA_EMPTY);
+        }
+        String input = "";
+        JSONObject objext = new JSONObject();
+
+        //閲嶆柊涓嬪彂璁″垝
+        JSONObject jsonObject = new JSONObject();
+        //绗竴灞�
+        JSONArray firstJsonArray = new JSONArray();
+        JSONObject downJson = new JSONObject();
+        downJson.put("terminalID",1);
+        //涓嶅~榛樿瀵规墍鏈夐�氶亾涓嬪彂
+        JSONArray audioJsonArray = new JSONArray();
+        audioJsonArray.add(1);
+        downJson.put("audioOutID",audioJsonArray);
+        firstJsonArray.add(downJson);
+        jsonObject.put("TerminalInfoList",firstJsonArray);
+        //绗竴灞傛暟缁�
+        JSONArray allJsonArray = new JSONArray();
+        //鏁扮粍涓璞�
+        for (WaterTimingBroadcastDO waterTimingBroadcastDO : searchList) {
+            JSONObject downArrayData = new JSONObject();
+            downArrayData.put("audioOutID",audioJsonArray);
+            downArrayData.put("enabled",true);
+            downArrayData.put("planSchemeID",waterTimingBroadcastDO.getName());
+            JSONObject executeJson = new JSONObject();
+            executeJson.put("startTime", getDateStringByZones(waterTimingBroadcastDO.getStartDate()));
+            executeJson.put("stopTime",getDateStringByZones(waterTimingBroadcastDO.getEndDate()));
+            if (Constant.ONE.equals(waterTimingBroadcastDO.getPeriodType())){
+                //鏃ヨ鍒�
+                JSONArray executeJsonArray = new JSONArray();
+                JSONObject executeJsonDataItem = new JSONObject();
+                executeJsonDataItem.put("beginTime",waterTimingBroadcastDO.getStartTime()+"+08:00");
+                executeJsonDataItem.put("endTime",waterTimingBroadcastDO.getEndTime()+"+08:00");
+                executeJsonDataItem.put("playMode","loop");
+                executeJsonDataItem.put("playNowTime","");
+                executeJsonDataItem.put("planSchemeExecID",0);
+                JSONObject secondDownOperationJson = new JSONObject();
+                if (Constant.ONE.equals(waterTimingBroadcastDO.getContentType())){
+                    //鏂囨湰
+                    secondDownOperationJson.put("audioSource","speechSynthesis");
+                    secondDownOperationJson.put("speechSynthesisContent",waterTimingBroadcastDO.getContent());
+                }else if (Constant.TWO.equals(waterTimingBroadcastDO.getContentType())){
+                    //闊抽
+                    secondDownOperationJson.put("audioSource","customAudio");
+                    String json = waterTimingBroadcastDO.getJson();
+                    JSONObject jsonData = JSONObject.parseObject(json);
+                    List<Integer> hkAudioIds = new ArrayList<>();
+                    hkAudioIds.add(jsonData.getIntValue(waterDeviceDO.getIp()));
+                    secondDownOperationJson.put("customAudioID",hkAudioIds);
+                }
+                secondDownOperationJson.put("audioLevel",5);
+                //璇█绫诲瀷
+                secondDownOperationJson.put("TTSLanguageType","chinese");
+                secondDownOperationJson.put("voiceType","female");
+                secondDownOperationJson.put("audioVolume",100);
+                executeJsonDataItem.put("Operation",secondDownOperationJson);
+                executeJsonArray.add(executeJsonDataItem);
+                executeJson.put("dailyScheduleList",executeJsonArray);
+            }else {
+                //鍛ㄨ鍒�
+                JSONArray executeJsonArray = new JSONArray();
+                List<String> executeTime = new ArrayList<>();
+                if (Constant.ONE.equals(waterTimingBroadcastDO.getPeriodType())){
+                    //鏃ヨ鍒� 寰幆涓�娆�
+                    executeTime.add("1");
+                }else if (Constant.TWO.equals(waterTimingBroadcastDO.getPeriodType())){
+                    //鍛ㄨ鍒掑涓�涓懆鍑�
+                    executeTime = Arrays.asList(waterTimingBroadcastDO.getExecuteTime().split(","));
+                }
+                for (String s : executeTime) {
+                    JSONObject executeJsonData = new JSONObject();
+                    if (Constant.TWO.equals(waterTimingBroadcastDO.getPeriodType())){
+                        //鍛ㄨ鍒掑涓�涓懆鍑�
+                        executeJsonData.put("dayOfWeek",Integer.parseInt(s));
+                    }
+                    JSONArray executeJsonDataArray = new JSONArray();
+                    JSONObject executeJsonDataItem = new JSONObject();
+                    executeJsonDataItem.put("beginTime",waterTimingBroadcastDO.getStartTime()+"+08:00");
+                    executeJsonDataItem.put("endTime",waterTimingBroadcastDO.getEndTime()+"+08:00");
+                    executeJsonDataItem.put("playMode","loop");
+                    executeJsonDataItem.put("playNowTime","");
+                    executeJsonDataItem.put("planSchemeExecID",0);
+                    JSONObject secondDownOperationJson = new JSONObject();
+                    if (Constant.ONE.equals(waterTimingBroadcastDO.getContentType())){
+                        //鏂囨湰
+                        secondDownOperationJson.put("audioSource","speechSynthesis");
+                        secondDownOperationJson.put("speechSynthesisContent",waterTimingBroadcastDO.getContent());
+                    }else if (Constant.TWO.equals(waterTimingBroadcastDO.getContentType())){
+                        //闊抽
+                        secondDownOperationJson.put("audioSource","customAudio");
+                        String json = waterTimingBroadcastDO.getJson();
+                        JSONObject jsonData = JSONObject.parseObject(json);
+                        List<Integer> hkAudioIds = new ArrayList<>();
+                        hkAudioIds.add(jsonData.getIntValue(waterDeviceDO.getIp()));
+                        secondDownOperationJson.put("customAudioID",hkAudioIds);
+                    }
+                    secondDownOperationJson.put("audioLevel",5);
+                    //璇█绫诲瀷
+                    secondDownOperationJson.put("TTSLanguageType","chinese");
+                    secondDownOperationJson.put("voiceType","female");
+                    secondDownOperationJson.put("audioVolume",10);
+                    executeJsonDataItem.put("Operation",secondDownOperationJson);
+                    executeJsonDataArray.add(executeJsonDataItem);
+                    executeJsonData.put("scheduleList",executeJsonDataArray);
+                    executeJsonArray.add(executeJsonData);
+
+                }
+                executeJson.put("weeklyScheduleList",executeJsonArray);
+            }
+
+            if (Constant.ONE.equals(waterTimingBroadcastDO.getPeriodType())){
+                //鏃ヨ鍒�
+                downArrayData.put("dailyScheduleInfo",executeJson);
+            }else {
+                //鍛ㄨ鍒�
+                downArrayData.put("weklyScheduleInfo",executeJson);
+            }
+            allJsonArray.add(downArrayData);
+        }
+        jsonObject.put("broadcastPlanSchemeList",allJsonArray);
+        log.info("娴峰悍鎾斁璁″垝涓嬪彂鍏ュ弬鍐呭 : " + jsonObject);
+
+        String result = HttpsUtil.doPostHk(param.getIp(),Integer.parseInt(StringUtils.defaultString(param.getPort(),"80"))
+                ,"/ISAPI/VideoIntercom/broadcast/AddPlanScheme?format=json",param.getDoorId(), param.getDoorName(),jsonObject.toJSONString());
+        return result;*/
+        return  null;
+    }
+    @Override
     public void setLedContent(TransparentChannelSingleRequest model) {
         Device device = findById(model.getDeviceId());
         if(device == null
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkCabinetServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkCabinetServiceImpl.java
index 2b4ff0f..bf05a2f 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkCabinetServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkCabinetServiceImpl.java
@@ -81,6 +81,7 @@
             || CollectionUtils.isEmpty(jkCabinet.getManagerIdList())
             || CollectionUtils.isEmpty(jkCabinet.getAuthMemberIdList())
             || Objects.isNull(jkCabinet.getDoubleAuth())
+            || Objects.isNull(jkCabinet.getAlcoholStatus())
 
             || Objects.isNull(jkCabinet.getRowNum())
             || jkCabinet.getRowNum() <= Constants.ZERO
@@ -214,6 +215,7 @@
                 || CollectionUtils.isEmpty(jkCabinet.getAuthMemberIdList())
                 || Objects.isNull(jkCabinet.getPort())
                 || Objects.isNull(jkCabinet.getDoubleAuth())
+                || Objects.isNull(jkCabinet.getAlcoholStatus())
         ){
             throw new BusinessException(ResponseStatus.BAD_REQUEST);
         }
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchCustomerServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchCustomerServiceImpl.java
index d059939..4f1aaeb 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchCustomerServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchCustomerServiceImpl.java
@@ -143,7 +143,7 @@
             startmodel.setSteps(allList.get(0).getStartSteps());
             if(StringUtils.isBlank(startmodel.getSteps())){
                 // (BigDecimal lat1, BigDecimal lon1, BigDecimal lat2, BigDecimal lon2)
-                startmodel.setDistance(DistanceCalculator.calculateDistanceDecinal(startmodel.getStartLatitude(),startmodel.getStartLogitude(),startmodel.getEndLatitude(),startmodel.getEndLatitude()));
+                startmodel.setDistance(DistanceCalculator.calculateDistanceDecinal(startmodel.getStartLatitude(),startmodel.getStartLogitude(),startmodel.getEndLatitude(),startmodel.getEndLogitude()));
                 startmodel.setSteps(comLocation +";"+allList.get(0).getLongitude()+","+allList.get(0).getLatitude());
             }
             list.add(startmodel);
@@ -186,7 +186,7 @@
                     if(param!=null && param.getDistance()!=0){//濡傛灉涔嬪墠宸茬粡鑾峰彇杩�
                         tt.setDistance(param.getDistance());
                     }else{
-                        tt.setDistance(DistanceCalculator.calculateDistanceDecinal(tt.getStartLatitude(),tt.getStartLogitude(),tt.getEndLatitude(),tt.getEndLatitude()));
+                        tt.setDistance(DistanceCalculator.calculateDistanceDecinal(tt.getStartLatitude(),tt.getStartLogitude(),tt.getEndLatitude(),tt.getEndLogitude()));
                     }
                 }
                 tt.setLocation(allList.get(i).getLocation());
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchServiceImpl.java
index cf239d5..95f0717 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchServiceImpl.java
@@ -12,6 +12,7 @@
 import com.doumee.core.wms.model.response.WmsBaseDataResponse;
 import com.doumee.core.wms.model.response.WmsBaseResponse;
 import com.doumee.dao.admin.request.JkOrdersImport;
+import com.doumee.dao.admin.request.SketchCateModel;
 import com.doumee.dao.business.*;
 import com.doumee.dao.business.dto.TelecomLineInfoDTO;
 import com.doumee.dao.business.model.*;
@@ -499,7 +500,6 @@
         c.setNeedList(Constants.equalsInteger(model.getForceUpdate(),0)?needList:customerList);
         return  c;
     }
-
     /**
      * 寮�濮嬪紓姝ユ墽琛岀嚎璺紭鍖栦换鍔�
      * @param model
@@ -508,6 +508,74 @@
     @Async
     public void startUpdateLineAsync(JkSketch model) {
         try {
+            int maxnum =100,distance = 500;
+            try {
+                maxnum = Integer.parseInt(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.JK_PLAN_MAX_CLUSTER).getCode());
+                distance = Integer.parseInt(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.JK_PLAN_DISTANCE_CLUSTER).getCode());
+            }catch (Exception e){
+            }
+            List<JkSketchCustomer> allCustomerList = model.getCustomerList();
+            //涓ゅ叕閲屽唴鏁版嵁瀹㈡埛鍚堝苟
+//            List<SketchCateModel> customerList =Clustering.clusterPoints(allCustomerList,1000);
+            List<SketchCateModel> customerList = new ClusterCustomKMeans().clusterPoints(allCustomerList,maxnum,distance);
+            List<JkLine> lineList = model.getLineList();
+            TspSolver.DataModel dataModel = new TspSolver.DataModel();
+            int vehicleNumber1 = lineList.size();//绾胯矾鏁伴噺
+            long[] vehicleCapacities1=new long[lineList.size()];//姣忚締杞︾殑鏈�澶ц鍗曢噺闄愬埗
+            long[] vehicleMaxNodes=new long[lineList.size()];//姣忚締杞︾殑鏈�澶ц鍗曢噺闄愬埗
+            long[] demands1 = new long[customerList.size()+1]; //鍚勪釜鐐圭殑璁㈠崟閲�
+            long[] demands2 = new long[customerList.size()+1]; //鍚勪釜鐐圭殑瀹㈡埗閲�
+            long[][] distanceMatrix1 = new long[customerList.size()+1][customerList.size()+1];
+            distanceMatrix1[0][0] = 0;
+            demands1[0] =0;//鍘熺偣
+            demands2[0] =0;//鍘熺偣
+            for (int i = 0; i < customerList.size(); i++) {
+                List<DistanceMapParam>  disList =  customerList.get(i).getStartPoint().getDistanceMapParamList();
+                distanceMatrix1[0][i+1] =  disList.get(0).getDistance();
+                distanceMatrix1[i+1][0] = disList.get(disList.size() -1).getDistance();
+                demands1[i+1] = Constants.formatBigdecimal( customerList.get(i).getTotalNum()).longValue();  //鍚勪釜鐐圭殑璁㈠崟閲�
+                demands2[i+1] = customerList.get(i).getTotalCustomer();  //鍚勪釜鐐圭殑璁㈠崟閲�
+                for (int j = 0; j < customerList.size(); j++) {
+                    distanceMatrix1[i+1][j+1] =disList.get(j+1).getDistance() ;
+                }
+            }
+            for (int i = 0; i < lineList.size(); i++) {
+                vehicleCapacities1[i] = lineList.get(i).getMaxOrder();//姣忚締杞︾殑鏈�澶ц鍗曢噺闄愬埗
+                vehicleMaxNodes[i] =lineList.get(i).getMaxCustomer();//鏈�澶у鎴锋暟
+            }
+            //鏋勯�犱紭鍖栨暟鎹ā鍨�
+            dataModel.initDataInfo(vehicleNumber1,demands1,demands2,vehicleCapacities1,distanceMatrix1,vehicleMaxNodes);
+            TspSolver.startSearch(dataModel);
+            JkSketch nowModel = jkSketchMapper.selectById(model.getId());
+            if(StringUtils.equals(model.getJobId(), nowModel.getJobId())){
+               log.error( "浼樺寲缁撴灉宸插け鏁堬紝闈炴渶杩戜竴娆℃搷浣滐紒");
+               return;
+            }
+            dealSearchSolution(model,  customerList,dataModel);
+        }catch (Exception e){
+            e.printStackTrace();
+            jkSketchMapper.update(null,new UpdateWrapper<JkSketch>().lambda()
+                    .eq(JkSketch::getId,model.getId() )
+                    .eq(JkSketch::getJobId,model.getJobId() )
+                    .set(JkSketch::getPlanLineInfo,"鏈�杩戜竴娆$嚎璺紭鍖栧け璐ワ紒"+e.getMessage())
+                    .set(JkSketch::getStatus,Constants.THREE)
+                    .set(JkSketch::getPlanLineEndDate,new Date()));
+        }
+    }
+
+    private List<JkSketchCustomer> getCustomerCateList(List<JkSketchCustomer> allCustomerList) {
+        List<JkSketchCustomer>  list = new ArrayList<>();
+        return  list;
+    }
+
+    /**
+     * 寮�濮嬪紓姝ユ墽琛岀嚎璺紭鍖栦换鍔�
+     * @param model
+     */
+    @Override
+    @Async
+    public void startUpdateLineAsyncOld(JkSketch model) {
+        try {
             List<JkSketchCustomer> customerList = model.getCustomerList();
             List<JkLine> lineList = model.getLineList();
             TspSolver.DataModel dataModel = new TspSolver.DataModel();
@@ -515,6 +583,7 @@
             long[] vehicleCapacities1=new long[lineList.size()];//姣忚締杞︾殑鏈�澶ц鍗曢噺闄愬埗
             long[] vehicleMaxNodes=new long[lineList.size()];//姣忚締杞︾殑鏈�澶ц鍗曢噺闄愬埗
             long[] demands1 = new long[customerList.size()+1]; //鍚勪釜鐐圭殑璁㈠崟閲�
+            long[] demands2 = new long[customerList.size()+1]; //鍚勪釜鐐圭殑瀹㈡埛閲�
             long[][] distanceMatrix1 = new long[customerList.size()+1][customerList.size()+1];
             distanceMatrix1[0][0] = 0;
             demands1[0] =0;//鍘熺偣
@@ -523,6 +592,7 @@
                 distanceMatrix1[0][i+1] =  disList.get(0).getDistance();
                 distanceMatrix1[i+1][0] = disList.get(disList.size() -1).getDistance();
                 demands1[i+1] = Constants.formatBigdecimal( customerList.get(i).getTotalNum()).longValue();  //鍚勪釜鐐圭殑璁㈠崟閲�
+                demands2[i+1] =1;  //鍚勪釜鐐圭殑璁㈠崟閲�
                 for (int j = 0; j < customerList.size(); j++) {
                     distanceMatrix1[i+1][j+1] =disList.get(j+1).getDistance() ;
                 }
@@ -542,9 +612,9 @@
                 vehicleMaxNodes[i] =lineList.get(i).getMaxCustomer();//鏈�澶у鎴锋暟
             }
             //鏋勯�犱紭鍖栨暟鎹ā鍨�
-            dataModel.initDataInfo(vehicleNumber1,demands1,vehicleCapacities1,distanceMatrix1,vehicleMaxNodes);
+            dataModel.initDataInfo(vehicleNumber1,demands1,demands2,vehicleCapacities1,distanceMatrix1,vehicleMaxNodes);
             TspSolver.startSearch(dataModel);
-            dealSearchSolution(model,dataModel);
+            dealSearchSolutionOld(model,dataModel);
         }catch (Exception e){
             e.printStackTrace();
             jkSketchMapper.update(null,new UpdateWrapper<JkSketch>().lambda()
@@ -563,6 +633,131 @@
     @Override
     @Async
     public  void startEditSketchLineAsync(JkSketch model) {
+        boolean success = true;
+        int totalDistance = 0;
+        List<JkSketchLine> lineList = model.getSketchLineList();
+        try {
+            MPJLambdaWrapper<JkSketchCustomer> queryWrapper = new MPJLambdaWrapper<>();
+            queryWrapper.selectAll(JkSketchCustomer.class )
+                    .selectAs(JkCustomer::getName,JkSketchCustomer::getName)
+                    .selectAs(JkCustomer::getCode,JkSketchCustomer::getCode)
+                    .selectAs(JkCustomer::getDistance,JkSketchCustomer::getDistanceJson)
+                    .selectAs(JkCustomer::getLongitude,JkSketchCustomer::getLongitude)
+                    .selectAs(JkCustomer::getLatitude,JkSketchCustomer::getLatitude)
+                    .selectAs(JkCustomer::getStartDistance,JkSketchCustomer::getStartDistance)
+                    .selectAs(JkCustomer::getEndDistance,JkSketchCustomer::getEndDistance)
+                    .leftJoin(JkCustomer.class,JkCustomer::getId,JkSketchCustomer::getCustomerId )
+                    .eq(JkSketchCustomer::getType, Constants.equalsInteger(model.getOptStatus(),Constants.ONE)?1:0)
+                    .eq(JkSketchCustomer::getSketchId, model.getId())
+                    .eq(JkSketchCustomer::getIsdeleted,Constants.ZERO)
+                    .orderByAsc(JkSketchCustomer::getSortnum);
+            List<JkSketchCustomer> customerList = jkSketchCustomerMapper.selectJoinList(JkSketchCustomer.class,queryWrapper);
+            if(customerList == null ||customerList.size() ==0){
+                throw  new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"璇ョ嚎璺鎴蜂俊鎭负绌猴紝涓嶆弧瓒充紭鍖栨潯浠讹紒");
+            }
+            int maxnum =100,distance = 500;
+            try {
+                maxnum = Integer.parseInt(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.JK_PLAN_MAX_CLUSTER).getCode());
+                distance = Integer.parseInt(systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.JK_PLAN_DISTANCE_CLUSTER).getCode());
+            }catch (Exception e){
+            }
+            int totalNum = 0;
+            for(JkSketchLine line : lineList){
+                //瀹屽杽绾胯矾瀹㈡埛浼樺寲鍙傛暟
+                List<JkSketchCustomer> customerListParam =  line.getCustomerList() ;
+                if(customerListParam ==null || customerListParam.size()==0){
+                    throw  new BusinessException(ResponseStatus.BAD_REQUEST);
+                }
+                initSketchCustomerListParam(line.getCustomerList(),customerList) ;
+                totalNum += customerListParam.size();
+            }
+            if(totalNum != Constants.formatIntegerNum(model.getOrderNum())){
+                throw  new BusinessException(ResponseStatus.BAD_REQUEST);
+            }
+            for(JkSketchLine line : lineList){
+                //閫愪釜璺嚎浼樺寲
+                List<JkSketchCustomer> allCustomerListParam =  line.getCustomerList() ;
+//                List<SketchCateModel> customerListParam = Clustering.clusterPoints(allCustomerListParam,1000);
+                List<SketchCateModel> customerListParam = new ClusterCustomKMeans().clusterPoints(allCustomerListParam,maxnum,distance);
+                TspSolver.DataModel dataModel = new TspSolver.DataModel();
+                int vehicleNumber1 = 1;//绾胯矾鏁伴噺
+                long[] vehicleCapacities1=new long[]{line.getMaxOrder()};//姣忚締杞︾殑鏈�澶ц鍗曢噺闄愬埗
+                long[] vehicleMaxNodes=new long[]{line.getMaxCustomer()};//姣忚締杞︾殑鏈�澶ц鍗曢噺闄愬埗
+                long[] demands1 = new long[customerListParam.size()+1]; //鍚勪釜鐐圭殑璁㈠崟閲�
+                long[] demands2 = new long[customerListParam.size()+1]; //鍚勪釜鐐圭殑璁㈠崟閲�
+                long[][] distanceMatrix1 = new long[customerListParam.size()+1][customerListParam.size()+1];
+                distanceMatrix1[0][0] = 0;
+                demands1[0] =0;//鍘熺偣
+                for (int i = 0; i < customerListParam.size(); i++) {
+                    List<DistanceMapParam>  disList =  customerListParam.get(i).getStartPoint().getDistanceMapParamList();
+                    distanceMatrix1[0][i+1] =  disList.get(0).getDistance();
+                    distanceMatrix1[i+1][0] = disList.get(disList.size() -1).getDistance();
+                    demands1[i+1] = Constants.formatBigdecimal( customerListParam.get(i).getTotalNum()).longValue();  //鍚勪釜鐐圭殑璁㈠崟閲�
+                    demands2[i+1] =   customerListParam.get(i).getTotalCustomer() ;  //鍚勪釜鐐圭殑璁㈠崟閲�
+                    for (int j = 0; j < customerListParam.size(); j++) {
+                        distanceMatrix1[i+1][j+1] =disList.get(j+1).getDistance() ;
+                    }
+                }
+                //鏋勯�犱紭鍖栨暟鎹ā鍨�
+                dataModel.initDataInfo(vehicleNumber1,demands1,demands2,vehicleCapacities1,distanceMatrix1,vehicleMaxNodes);
+                TspSolver.startSearch(dataModel);
+                if(dataModel.getSolutions()==null || dataModel.getSolutions().size()==0){
+                    throw  new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"绾胯矾銆�"+line.getLineName()+"銆戣皟鏁村け璐� 锛屾湭鑾峰緱鏈�浼樹氦閫氳鍒掓柟妗堬紒");
+                }
+                JkSketch nowModel = jkSketchMapper.selectById(model.getId());
+                if(StringUtils.equals(model.getJobId(), nowModel.getJobId())){
+                    throw  new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"绾胯矾銆�"+line.getLineName()+"銆戣皟鏁村け璐� 锛岄潪鏈�杩戜竴娆℃搷浣滐紒");
+                }
+
+                TspSolverSolutions so = dataModel.getSolutions().get(0);
+                List<Integer> routes = so.getRouteIndex();
+                totalDistance += so.getDistance();
+                if(routes.size() <=2) {
+                    throw  new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"绾胯矾銆�"+line.getLineName()+"銆戣皟鏁村け璐� 锛屾湭鑾峰緱鏈�浼樹氦閫氳鍒掓柟妗堬紒");
+                }
+                int index = 0;
+                line.setDistance(so.getDistance());
+                //鏈夋晥璺緞
+                for (Integer cIndex : routes){
+                    if(cIndex ==0){
+                        continue; //璧峰鐐逛笉澶勭悊
+                    }
+                    SketchCateModel cateModel = customerListParam.get(cIndex-1);
+                    for(int t=0;t<cateModel.getCustomerList().size();t++){
+                        JkSketchCustomer customer = cateModel.getCustomerList().get(t);
+                        customer.setSortnum(index++);
+                        if(t < cateModel.getCustomerList().size()-1){
+                            long tdistance = (long)Clustering.distanceTo(customer, cateModel.getCustomerList().get(t+1));
+                            line.setDistance(Constants.formatLongNum(line.getDistance()) +tdistance);
+                            totalDistance  += tdistance;
+                        }
+                    }
+                }
+            }
+        }catch (Exception e){
+            e.printStackTrace();
+            success =false;
+        }finally {
+            if(success){
+                List<JkSketchCustomer> allList = new ArrayList<>();
+                for(JkSketchLine line : lineList){
+                    allList.addAll(line.getCustomerList());
+                }
+                jkSketchLineMapper.updateById(lineList);
+                jkSketchCustomerMapper.updateById(allList);
+            }
+            jkSketchMapper.update(null,new UpdateWrapper<JkSketch>().lambda()
+                    .eq(JkSketch::getId,model.getId() )
+                    .eq(JkSketch::getJobId,model.getJobId() )
+                    .set(success,JkSketch::getDistance,totalDistance)
+                    .set(JkSketch::getPlanLineInfo,success?"鏈�杩戜竴娆$嚎璺皟鏁存垚鍔�":"鏈�杩戜竴娆$嚎璺皟鏁村け璐ワ紒")
+                    .set(JkSketch::getStatus,success?Constants.TWO:Constants.THREE)
+                    .set(JkSketch::getPlanLineEndDate,new Date()));
+        }
+    }
+    @Override
+    @Async
+    public  void startEditSketchLineAsyncOld(JkSketch model) {
         boolean success = true;
         int totalDistance = 0;
         List<JkSketchLine> lineList = model.getSketchLineList();
@@ -607,6 +802,7 @@
                 long[] vehicleCapacities1=new long[]{line.getMaxOrder()};//姣忚締杞︾殑鏈�澶ц鍗曢噺闄愬埗
                 long[] vehicleMaxNodes=new long[]{line.getMaxCustomer()};//姣忚締杞︾殑鏈�澶ц鍗曢噺闄愬埗
                 long[] demands1 = new long[customerListParam.size()+1]; //鍚勪釜鐐圭殑璁㈠崟閲�
+                long[] demands2 = new long[customerListParam.size()+1]; //鍚勪釜鐐圭殑璁㈠崟閲�
                 long[][] distanceMatrix1 = new long[customerListParam.size()+1][customerListParam.size()+1];
                 distanceMatrix1[0][0] = 0;
                 demands1[0] =0;//鍘熺偣
@@ -615,12 +811,13 @@
                     distanceMatrix1[0][i+1] =  disList.get(0).getDistance();
                     distanceMatrix1[i+1][0] = disList.get(disList.size() -1).getDistance();
                     demands1[i+1] = Constants.formatBigdecimal( customerListParam.get(i).getTotalNum()).longValue();  //鍚勪釜鐐圭殑璁㈠崟閲�
+                    demands2[i+1] = 1;  //鍚勪釜鐐圭殑璁㈠崟閲�
                     for (int j = 0; j < customerListParam.size(); j++) {
                         distanceMatrix1[i+1][j+1] =disList.get(j+1).getDistance() ;
                     }
                 }
                 //鏋勯�犱紭鍖栨暟鎹ā鍨�
-                dataModel.initDataInfo(vehicleNumber1,demands1,vehicleCapacities1,distanceMatrix1,vehicleMaxNodes);
+                dataModel.initDataInfo(vehicleNumber1,demands1,demands2,vehicleCapacities1,distanceMatrix1,vehicleMaxNodes);
                 TspSolver.startSearch(dataModel);
                 if(dataModel.getSolutions()==null || dataModel.getSolutions().size()==0){
                     throw  new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"绾胯矾銆�"+line.getLineName()+"銆戣皟鏁村け璐� 锛屾湭鑾峰緱鏈�浼樹氦閫氳鍒掓柟妗堬紒");
@@ -730,7 +927,7 @@
                 DistanceMapParam t = new DistanceMapParam();
                 t.setId(cm.getCustomerId());
                  DistanceMapParam param = getParamByCustomerIds( cm.getCustomerId(),distanceMapParamList);
-                if(param!=null){//濡傛灉涔嬪墠宸茬粡鑾峰彇杩�
+                if(param!=null && t.getDistance()>0){//濡傛灉涔嬪墠宸茬粡鑾峰彇杩�
                     t = param;
                 }else{
                     //濡傛灉鏈鍒掞紝鎸夌収鐩寸嚎璺濈
@@ -758,14 +955,27 @@
                 int index =0;
                 for(JkSketchCustomer c : customers){
                     if(index ==0){
-                        lineDistance+= Constants.formatLongNum(c.getStartDistance());
+                        if(Constants.formatLongNum(c.getStartDistance()) >0){
+                            lineDistance+= Constants.formatLongNum(c.getStartDistance());
+                        }else{
+                            lineDistance += DistanceCalculator.calculateDistanceDecinal(c.getLatitude(),c.getLongitude(),cLatitude,cLongitude);
+                        }
                     }
                     if(index == customers.size()-1){
-                        lineDistance+= Constants.formatLongNum(c.getEndDistance());
+                        if(Constants.formatLongNum(c.getEndDistance())>0){
+                            lineDistance+= Constants.formatLongNum(c.getEndDistance());
+                        }else{
+                            lineDistance += DistanceCalculator.calculateDistanceDecinal(c.getLatitude(),c.getLongitude(),cLatitude,cLongitude);
+                        }
                         break;
                     }
-                    DistanceMapParam param = getParamByCustomerIds( customers.get(index+1).getCustomerId(),getListFromJsonStr(c.getDistanceJson()));
-                    lineDistance += param.getDistance();
+                    JkSketchCustomer end = customers.get(index+1);
+                    DistanceMapParam param1 = getParamByCustomerIds(end.getCustomerId(),getListFromJsonStr(c.getDistanceJson()));
+                    if(param1 !=null && param1.getDistance()>0){
+                        lineDistance += param1.getDistance();
+                    }else{
+                        lineDistance += DistanceCalculator.calculateDistanceDecinal(c.getLatitude(),c.getLongitude(),end.getLatitude(),end.getLongitude());
+                    }
                     index++;
                   /*  for(JkSketchCustomer cm : customers){
                         DistanceMapParam param = getParamByCustomerIds( cm.getCustomerId(),getListFromJsonStr(c.getDistanceJson()));
@@ -815,7 +1025,116 @@
         return new ArrayList<>();
     }
 
-    private void dealSearchSolution(JkSketch model, TspSolver.DataModel dataModel) {
+    private void dealSearchSolution(JkSketch model, List<SketchCateModel> customerList,TspSolver.DataModel dataModel) {
+        Date date = new Date();
+        List<TspSolverSolutions> solutions = dataModel.getSolutions();
+        List<JkSketchLine> sketchLineList = new ArrayList<>();
+        List<JkSketchCustomer> sketchCustomerList  = new ArrayList<>();
+        long totalDistance = 0l;
+        if(solutions!=null && solutions.size()>0){
+            for(TspSolverSolutions so : solutions){
+                List<Integer> routes = so.getRouteIndex();
+                totalDistance+= so.getDistance();
+                if(routes.size() <=2) {
+                    continue;//鏃犲鎴风殑闈炴湁鏁堣矾绾�
+                }
+                JkLine  line =model.getLineList().get(so.getLineIndex());
+                JkSketchLine tModel =  new JkSketchLine();
+                tModel.setSketchId(model.getId());
+                tModel.setCreator(model.getEditor());
+                tModel.setCreateDate(date);
+                tModel.setLineId(line.getId());
+                tModel.setTotalNum(new BigDecimal(0));
+                tModel.setDateInfo(model.getDateInfo());
+                tModel.setType(Constants.ONE);
+                tModel.setSortnum(sketchLineList.size()+1);
+                tModel.setEditDate(tModel.getCreateDate());
+                tModel.setEditor(tModel.getCreator());
+                tModel.setIsdeleted(Constants.ZERO);
+                tModel.setDistance(so.getDistance());//
+                sketchLineList.add(tModel);
+                tModel.setCustomerList( new ArrayList<>());
+                //鏈夋晥璺緞
+                for (Integer cIndex : routes){
+                    if(cIndex ==0){
+                        continue; //璧峰鐐逛笉澶勭悊
+                    }
+//                    JkSketchCustomer customer = model.getCustomerList().get(cIndex-1);
+//                    tModel.setTotalNum(tModel.getTotalNum().add(Constants.formatBigdecimal(customer.getTotalNum())));//閫佽揣閲�
+                    SketchCateModel cateModel = customerList.get(cIndex-1);
+                    tModel.setTotalNum(tModel.getTotalNum().add(Constants.formatBigdecimal(cateModel.getTotalNum())));//閫佽揣閲�
+                    for(int t=0;t<cateModel.getCustomerList().size();t++){
+                        JkSketchCustomer customer = cateModel.getCustomerList().get(t);
+                        JkSketchCustomer cModel =  new JkSketchCustomer();
+                        cModel.setCreator(tModel.getCreator());
+                        cModel.setOrderId(customer.getOrderId());
+                        cModel.setCreateDate(tModel.getCreateDate());
+                        cModel.setType(Constants.ONE);
+                        cModel.setTotalNum(customer.getTotalNum());
+                        cModel.setDateInfo(model.getDateInfo());
+                        cModel.setSortnum(tModel.getCustomerList().size()+1);
+                        cModel.setEditDate(tModel.getCreateDate());
+                        cModel.setEditor(tModel.getCreator());
+                        cModel.setIsdeleted(Constants.ZERO);
+                        cModel.setSketchId(model.getId());
+                        cModel.setCustomerId(customer.getCustomerId());
+                        if(t < cateModel.getCustomerList().size()-1){
+                            long tdistance = (long)Clustering.distanceTo(customer, cateModel.getCustomerList().get(t+1));
+                            tModel.setDistance(Constants.formatLongNum(tModel.getDistance()) +tdistance);
+                            totalDistance  += tdistance;
+                        }
+                        tModel.getCustomerList().add(cModel);
+                    }
+                    tModel.setOrderNum( tModel.getCustomerList().size());
+                }
+            }
+        }
+        if(sketchLineList!=null && sketchLineList.size()>0){
+            jkSketchLineMapper.update(null,new UpdateWrapper<JkSketchLine>().lambda()
+                    .set(JkSketchLine::getIsdeleted,Constants.ONE)
+                    .eq(JkSketchLine::getIsdeleted,Constants.ZERO)
+                    .eq(JkSketchLine::getType,Constants.ONE)
+                    .eq(JkSketchLine::getSketchId,model.getId())
+                    .eq(JkSketchLine::getDateInfo,model.getDateInfo()));
+            jkSketchCustomerMapper.update(null,new UpdateWrapper<JkSketchCustomer>().lambda()
+                    .set(JkSketchCustomer::getIsdeleted,Constants.ONE)
+                    .eq(JkSketchCustomer::getIsdeleted,Constants.ZERO)
+                    .eq(JkSketchCustomer::getType,Constants.ONE)
+                    .eq(JkSketchCustomer::getSketchId,model.getId())
+                    .eq(JkSketchCustomer::getDateInfo,model.getDateInfo()));
+            if(sketchLineList.size()>0){
+                jkSketchLineMapper.insert(sketchLineList);
+            }
+            for(JkSketchLine l : sketchLineList){
+                if(l.getCustomerList()!=null ){
+                    for(JkSketchCustomer c :l.getCustomerList()){
+                        c.setSketchLineId(l.getId());
+                    }
+                    sketchCustomerList.addAll(l.getCustomerList());
+                }
+            }
+            if(sketchCustomerList.size()>0){
+                jkSketchCustomerMapper.insert(sketchCustomerList);
+            }
+            jkSketchMapper.update(null,new UpdateWrapper<JkSketch>().lambda()
+                    .eq(JkSketch::getId,model.getId() )
+//                    .eq(JkSketch::getJobId,model.getJobId() )
+                    .set(JkSketch::getLineNum,sketchLineList.size() )
+                    .set(JkSketch::getOptStatus,Constants.ONE)//宸茬敓鎴愪紭鍖栫嚎璺�
+                    .set(JkSketch::getDistance,totalDistance)
+                    .set(JkSketch::getPlanLineInfo,"鏈�杩戜竴娆$嚎璺紭鍖栨垚鍔燂紝浼樺寲鍚庢�昏窛绂伙細"+(totalDistance/1000)+"鍏噷锛�")
+                    .set(JkSketch::getStatus,Constants.TWO)
+                    .set(JkSketch::getPlanLineEndDate,date));
+        }else{
+            jkSketchMapper.update(null,new UpdateWrapper<JkSketch>().lambda()
+                    .eq(JkSketch::getId,model.getId() )
+//                    .eq(JkSketch::getJobId,model.getJobId() )
+                    .set(JkSketch::getPlanLineInfo,"鏈�杩戜竴娆$嚎璺紭鍖栧け璐�,鏈壘鍒版渶浼樿矾绾匡紒")
+                    .set(JkSketch::getStatus,Constants.THREE)
+                    .set(JkSketch::getPlanLineEndDate,date));
+        }
+    }
+    private void dealSearchSolutionOld(JkSketch model, TspSolver.DataModel dataModel) {
         Date date = new Date();
         List<TspSolverSolutions> solutions = dataModel.getSolutions();
         List<JkSketchLine> sketchLineList = new ArrayList<>();
@@ -876,11 +1195,13 @@
                     .set(JkSketchLine::getIsdeleted,Constants.ONE)
                     .eq(JkSketchLine::getIsdeleted,Constants.ZERO)
                     .eq(JkSketchLine::getType,Constants.ONE)
+                    .eq(JkSketchLine::getSketchId,model.getId())
                     .eq(JkSketchLine::getDateInfo,model.getDateInfo()));
             jkSketchCustomerMapper.update(null,new UpdateWrapper<JkSketchCustomer>().lambda()
                     .set(JkSketchCustomer::getIsdeleted,Constants.ONE)
                     .eq(JkSketchCustomer::getIsdeleted,Constants.ZERO)
                     .eq(JkSketchCustomer::getType,Constants.ONE)
+                    .eq(JkSketchCustomer::getSketchId,model.getId())
                     .eq(JkSketchCustomer::getDateInfo,model.getDateInfo()));
             if(sketchLineList.size()>0){
                 jkSketchLineMapper.insert(sketchLineList);
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/hksync/HkSyncBaseServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/hksync/HkSyncBaseServiceImpl.java
index 54013e0..8e8fac2 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/hksync/HkSyncBaseServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/hksync/HkSyncBaseServiceImpl.java
@@ -84,6 +84,11 @@
         return null;
     }
     @Override
+    public String syncHkBroadcastDevice(Device param){
+
+        return null;
+    }
+    @Override
 //    @Async
     public String syncPrivilege(PrivilegeGroupRequest param){
 
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/hksync/HkSyncDeviceServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/hksync/HkSyncDeviceServiceImpl.java
index be1567d..5ee45e1 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/hksync/HkSyncDeviceServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/hksync/HkSyncDeviceServiceImpl.java
@@ -197,6 +197,48 @@
             Constants.DEALING_HK_SYNCDEVICE =false;
         }
     }
+    @Override
+//    @Async
+    public String syncHkBroadcastDevice(Device param){
+        if(Constants.DEALING_HK_SYNCDEVICE){
+            throw  new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(), "鍚屾浠诲姟姝e湪鎵ц鍝︼紝璇风◢鍚庢煡鐪嬬粨鏋滐紒") ;
+        }
+        Constants.DEALING_HK_SYNCDEVICE =true;
+        try {
+            List<Device> deleteList = new ArrayList<>();
+            List<Device> addList = new ArrayList<>();
+            List<Device> editList = new ArrayList<>();
+            Date date = new Date();
+            //鏌ヨ鍏ㄩ儴骞挎挱鐐硅澶囨暟鎹�
+            List<Device> allList = deviceMapper.selectList(new QueryWrapper<Device>().lambda()
+                    .eq(Device::getType,Constants.FOUR));
+            List<FetchAudioDeviceInfoResponse> allHkList = getAllBroadcastDeviceList();
+            /**
+             * 鑾峰彇澧炲垹鏀规暟鎹泦鍚�
+             */
+            getBroadcastDeviceDataChangeList(allList,allHkList,addList,editList,deleteList,date);
+            if(deleteList.size()>0){
+                //閫昏緫鍒犻櫎
+                for(Device d : deleteList){
+                    deviceMapper.updateById(d);
+                }
+            }
+            if(addList.size()>0){
+                deviceMapper.insert(addList);
+            }
+            if(editList.size()>0){
+                for(Device d : editList){
+                    deviceMapper.updateById(d);
+                }
+            }
+            return "鍚屾鏁版嵁锛氭柊澧炪��"+addList.size()+"銆戞潯锛屾洿鏂般��"+editList.size()+"銆戞潯锛屽垹闄ゃ��"+deleteList.size()+"銆戞潯";
+        }catch (Exception e){
+            e.printStackTrace();
+            throw  new BusinessException(ResponseStatus.SERVER_ERROR.getCode(), "鍚屾澶辫触锛�");
+        }finally {
+            Constants.DEALING_HK_SYNCDEVICE =false;
+        }
+    }
 
     private void getBroadcastDataChangeList(List<Device> allList, List<FetchAudioChannelInfoResponse> allHkList, List<Device> addList, List<Device> editList, List<Device> deleteList, Date date) {
         if(allHkList!=null && allHkList.size()>0){
@@ -218,6 +260,27 @@
         }
         //鍒ゆ柇鑾峰彇鍒犻櫎鐨勯棬绂佽澶囷紝閫昏緫鍒犻櫎
         getDeleteBroadcastList(allList,allHkList,deleteList,date);
+    }
+    private void getBroadcastDeviceDataChangeList(List<Device> allList, List<FetchAudioDeviceInfoResponse> allHkList, List<Device> addList, List<Device> editList, List<Device> deleteList, Date date) {
+        if(allHkList!=null && allHkList.size()>0){
+            //鑾峰彇娴峰悍鍏ㄩ儴闂ㄧ缁勬暟鎹�
+            for(FetchAudioDeviceInfoResponse device : allHkList){
+                Device model = getExistedBroadcastDevice(device,allList);
+                if(model !=null){
+                    //濡傛灉宸插瓨鍦紝鍒欐洿鏂版暟鎹�
+                    model =  initBroadcastDeviceDataByHkData(model,device,date);
+                    editList.add(model);
+                }else{
+                    //濡傛灉涓嶅瓨鍦紝鍒欐柊澧炴暟鎹�
+                    model = new Device();
+                    model =  initBroadcastDeviceDataByHkData(model,device,date);
+                    model.setIsEntrance(Constants.ZERO);
+                    addList.add(model);
+                }
+            }
+        }
+        //鍒ゆ柇鑾峰彇鍒犻櫎鐨勯棬绂佽澶囷紝閫昏緫鍒犻櫎
+        getDeleteBroadcastDeviceList(allList,allHkList,deleteList,date);
     }
 
     @Override
@@ -332,6 +395,39 @@
                 throw  new BusinessException(ResponseStatus.SERVER_ERROR.getCode(), "瀵逛笉璧凤紝娴峰悍鍚屾鏁版嵁澶辫触~");
             }
             BaseListPageResponse<FetchAudioChannelInfoResponse> r = response.getData();
+            curTotal += 100;
+            if(curTotal >= r.getTotal()){
+                hasNext = false;
+            }
+            if(r.getList() == null || r.getList().size()==0){
+                hasNext =false;
+            }else{
+                allDoorList.addAll(r.getList());
+            }
+            curPage++;
+        }
+        return  allDoorList;
+    }
+    /**
+     * 鑾峰彇鍏ㄩ儴骞挎挱鐐规暟鎹�
+     * @return
+     */
+    public  List<FetchAudioDeviceInfoResponse>  getAllBroadcastDeviceList(){
+        List<FetchAudioDeviceInfoResponse> allDoorList = new ArrayList<>();
+        Date date = new Date();
+        boolean hasNext = true;
+        int curTotal = 0;
+        int curPage = 1;
+        while (hasNext){
+            //鍒嗛〉閬嶅巻寰幆鏌ヨ鎵�鏈夐棬绂佽澶囨暟鎹�
+            FetchAudioDeviceRequest param = new FetchAudioDeviceRequest();
+            param.setPageNo(curPage);
+            param.setPageSize(100);
+            BaseResponse<BaseListPageResponse<FetchAudioDeviceInfoResponse>>  response = HKService.fetchAudioDevice(param);
+            if(response == null || !StringUtils.equals(response.getCode(), HKConstants.RESPONSE_SUCCEE)){
+                throw  new BusinessException(ResponseStatus.SERVER_ERROR.getCode(), "瀵逛笉璧凤紝娴峰悍鍚屾鏁版嵁澶辫触~");
+            }
+            BaseListPageResponse<FetchAudioDeviceInfoResponse> r = response.getData();
             curTotal += 100;
             if(curTotal >= r.getTotal()){
                 hasNext = false;
@@ -463,6 +559,21 @@
         model.setResourceType(device.getAudioChannelType());
         model.setStatus(device.getState());
         model.setRegionName(device.getRegionName());
+        return  model;
+    }
+    private Device initBroadcastDeviceDataByHkData(Device model, FetchAudioDeviceInfoResponse device, Date date) {
+        model.setIsdeleted(Constants.ZERO);
+        model.setHkDate(date);
+        model.setHkId(device.getDeviceIndexCode());
+        model.setName(device.getDeviceName());
+        model.setHkStatus(Constants.ONE);
+        model.setType(Constants.THREE);
+        model.setChannelNo(device.getDeviceCode());
+        model.setChannelInfo(device.getDeviceType());
+        model.setResourceType(device.getDeviceType());
+        model.setStatus(Constants.ZERO);
+        model.setRemark(device.getDesc());
+        model.setRegionName(device.getRegionIndexCode());
         return  model;
     }
     private Device initDoorDataByHkData(Device model, DoorsInfoResponse door, Date date, List<AcsDeviceInfoResponse> allHkList) {
@@ -614,6 +725,17 @@
         }
         return  null;
     }
+    private Device getExistedBroadcastDevice(FetchAudioDeviceInfoResponse device, List<Device> allList) {
+        if(allList.size()>0){
+            for(Device r : allList){
+                if(StringUtils.equals(r.getHkId(), device.getDeviceIndexCode())){
+                    //琛ㄧず鏈垹闄�
+                    return  r;
+                }
+            }
+        }
+        return  null;
+    }
     private Device getExistedDevice(AcsDeviceInfoResponse device, List<Device> allList) {
         if(allList.size()>0){
             for(Device r : allList){
@@ -662,6 +784,17 @@
     private void getDeleteBroadcastList(List<Device> allList,  List<FetchAudioChannelInfoResponse> allHkList,List<Device> deleteList ,Date date) {
         if(allList!=null && allList.size()>0){
             for(Device device : allList){
+                if(isDeletedBroadcast(device,allHkList)){
+                    device.setIsdeleted(Constants.ONE);
+                    device.setEditDate(date);
+                    deleteList.add(device);
+                }
+            }
+        }
+    }
+    private void getDeleteBroadcastDeviceList(List<Device> allList,  List<FetchAudioDeviceInfoResponse> allHkList,List<Device> deleteList ,Date date) {
+        if(allList!=null && allList.size()>0){
+            for(Device device : allList){
                 if(isDeletedBroadcastDevice(device,allHkList)){
                     device.setIsdeleted(Constants.ONE);
                     device.setEditDate(date);
@@ -695,7 +828,7 @@
         return  true;
 
     }
-    private boolean isDeletedBroadcastDevice(Device device, List<FetchAudioChannelInfoResponse> allHkList) {
+    private boolean isDeletedBroadcast(Device device, List<FetchAudioChannelInfoResponse> allHkList) {
         if(allHkList.size()>0){
             for(FetchAudioChannelInfoResponse r : allHkList){
                 if(StringUtils.equals(device.getHkId(), r.getAudioChannelIndexCode())){
@@ -707,6 +840,18 @@
         return  true;
 
     }
+    private boolean isDeletedBroadcastDevice(Device device, List<FetchAudioDeviceInfoResponse> allHkList) {
+        if(allHkList.size()>0){
+            for(FetchAudioDeviceInfoResponse r : allHkList){
+                if(StringUtils.equals(device.getHkId(), r.getDeviceIndexCode())){
+                    //琛ㄧず鏈垹闄�
+                    return  false;
+                }
+            }
+        }
+        return  true;
+
+    }
     private boolean isDeletedDevice(Device device, List<AcsDeviceInfoResponse> allHkList) {
         if(allHkList.size()>0){
             for(AcsDeviceInfoResponse r : allHkList){

--
Gitblit v1.9.3