From 46124fe454f90d24171ebc5be0d9cfe2ab22cbc5 Mon Sep 17 00:00:00 2001
From: doum <doum>
Date: 星期一, 13 十月 2025 09:47:51 +0800
Subject: [PATCH] 最新版本541200007

---
 admin/src/views/business/jkCustomer.vue                                                                       |    1 
 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 |   61 +
 server/system_service/pom.xml                                                                                 |   57 +
 server/system_service/src/main/java/com/doumee/core/utils/tsp/TspSolver.java                                  |  280 +++++++++
 server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkLine.java                         |    3 
 server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketchCustomer.java               |   17 
 admin/src/components/business/OperaJkSketchLineListWindow.vue                                                 |   29 
 server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketch.java                       |   34 +
 admin/src/components/business/OperaJkSketchCustomerWindow.vue                                                 |  138 ++--
 admin/src/components/business/OperaJkSketchResultWindow.vue                                                   |  276 +++++++-
 server/visits/dmvisit_admin/pom.xml                                                                           |   12 
 server/visits/dmvisit_service/pom.xml                                                                         |    2 
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchLineServiceImpl.java     |    5 
 admin/src/api/business/jkSketchCustomer.js                                                                    |    7 
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/JkSketchService.java                  |    4 
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkLineServiceImpl.java           |   28 
 admin/src/views/business/jkLine.vue                                                                           |    2 
 admin/src/views/business/jkSketch.vue                                                                         |   21 
 server/system_service/src/main/java/com/doumee/core/utils/DateUtil.java                                       |   19 
 server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkOrders.java                       |   13 
 server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketchLine.java                   |   15 
 /dev/null                                                                                                     |  158 -----
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkCustomerServiceImpl.java       |    1 
 server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchServiceImpl.java         |  349 +++++++++++
 server/pom.xml                                                                                                |    8 
 server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/JkSketchCustomerCloudController.java         |    7 
 server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/JkSketchCloudController.java                 |    4 
 server/system_service/src/main/java/com/doumee/core/utils/DistanceCalculator.java                             |   21 
 admin/src/components/business/OperaJkSketchWindow.vue                                                         |  156 +++-
 server/system_service/src/main/java/com/doumee/core/utils/tsp/TspSolverSolutions.java                         |   24 
 31 files changed, 1,380 insertions(+), 374 deletions(-)

diff --git a/admin/src/api/business/jkSketchCustomer.js b/admin/src/api/business/jkSketchCustomer.js
index 830f80d..4ab690a 100644
--- a/admin/src/api/business/jkSketchCustomer.js
+++ b/admin/src/api/business/jkSketchCustomer.js
@@ -7,6 +7,13 @@
   })
 }
 
+// 鏌ヨ
+export function allList (data) {
+  return request.post('/visitsAdmin/cloudService/business/jkSketchCustomer/allList', data, {
+    trim: true
+  })
+}
+
 // 瀵煎嚭Excel
 export function exportExcel (data) {
   return request.post('/visitsAdmin/cloudService/business/jkSketchCustomer/exportExcel', data, {
diff --git a/admin/src/components/business/OperaJkSketchCustomerWindow.vue b/admin/src/components/business/OperaJkSketchCustomerWindow.vue
index 7719a25..898b90d 100644
--- a/admin/src/components/business/OperaJkSketchCustomerWindow.vue
+++ b/admin/src/components/business/OperaJkSketchCustomerWindow.vue
@@ -1,86 +1,104 @@
 <template>
   <GlobalWindow
     :title="title"
+    width="85%"
     :visible.sync="visible"
-    :confirm-working="isWorking"
-    @confirm="confirm"
   >
-    <el-form :model="form" ref="form" :rules="rules">
-      <el-form-item label="鍒涘缓浜虹紪鐮�" prop="creator">
-        <el-input v-model="form.creator" placeholder="璇疯緭鍏ュ垱寤轰汉缂栫爜" v-trim/>
-      </el-form-item>
-      <el-form-item label="鍒涘缓鏃堕棿" prop="createDate">
-        <el-date-picker v-model="form.createDate" value-format="yyyy-MM-dd" placeholder="璇疯緭鍏ュ垱寤烘椂闂�"></el-date-picker>
-      </el-form-item>
-      <el-form-item label="鏇存柊浜虹紪鐮�" prop="editor">
-        <el-input v-model="form.editor" placeholder="璇疯緭鍏ユ洿鏂颁汉缂栫爜" v-trim/>
-      </el-form-item>
-      <el-form-item label="鏇存柊鏃堕棿" prop="editDate">
-        <el-date-picker v-model="form.editDate" value-format="yyyy-MM-dd" placeholder="璇疯緭鍏ユ洿鏂版椂闂�"></el-date-picker>
-      </el-form-item>
-      <el-form-item label="鏄惁鍒犻櫎0鍚� 1鏄�" prop="isdeleted">
-        <el-input v-model="form.isdeleted" placeholder="璇疯緭鍏ユ槸鍚﹀垹闄�0鍚� 1鏄�" v-trim/>
-      </el-form-item>
-      <el-form-item label="澶囨敞" prop="info">
-        <el-input v-model="form.info" placeholder="璇疯緭鍏ュ娉�" v-trim/>
-      </el-form-item>
-      <el-form-item label="绾胯矾缂栫爜锛堝叧鑱攋k_sketch_line)" prop="sketchLineId">
-        <el-input v-model="form.sketchLineId" placeholder="璇疯緭鍏ョ嚎璺紪鐮侊紙鍏宠仈jk_sketch_line)" v-trim/>
-      </el-form-item>
-      <el-form-item label="绾胯矾浼樺寲缂栫爜锛堝叧鑱攋k_sketch)" prop="sketchId">
-        <el-input v-model="form.sketchId" placeholder="璇疯緭鍏ョ嚎璺紭鍖栫紪鐮侊紙鍏宠仈jk_sketch)" v-trim/>
-      </el-form-item>
-      <el-form-item label="閫佽揣閲�" prop="totalNum">
-        <el-input v-model="form.totalNum" placeholder="璇疯緭鍏ラ�佽揣閲�" v-trim/>
-      </el-form-item>
-      <el-form-item label="瀹㈡埛鏁�" prop="orderNum">
-        <el-input v-model="form.orderNum" placeholder="璇疯緭鍏ュ鎴锋暟" v-trim/>
-      </el-form-item>
-      <el-form-item label="鎺掑簭鐮�" prop="sortnum">
-        <el-input v-model="form.sortnum" placeholder="璇疯緭鍏ユ帓搴忕爜" v-trim/>
-      </el-form-item>
-      <el-form-item label="鏃ユ湡" prop="dateInfo">
-        <el-date-picker v-model="form.dateInfo" value-format="yyyy-MM-dd" placeholder="璇疯緭鍏ユ棩鏈�"></el-date-picker>
-      </el-form-item>
-    </el-form>
+    <TableLayout >
+      <!-- 鎼滅储琛ㄥ崟 -->
+      <el-form ref="searchForm" slot="search-form" :model="searchForm" label-width="100px" inline>
+        <el-form-item label="瀹㈡埛鍚嶇О" prop="name">
+          <el-input v-model="searchForm.name" placeholder="璇疯緭鍏ュ鎴峰悕绉�" @keypress.enter.native="search"></el-input>
+        </el-form-item>
+        <el-form-item label="瀹㈡埛绠�鐮�" prop="code">
+          <el-input v-model="searchForm.code" 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>
+        <el-table
+            :height="tableHeightNew"
+            v-loading="isWorking.search"
+            :data="tableData.list"
+            stripe
+            @selection-change="handleSelectionChange"
+        >
+          <el-table-column prop="sortnum" label="瀹㈡埛搴忓彿" min-width="100px"></el-table-column>
+          <el-table-column prop="code" label="瀹㈡埛绠�鐮�" min-width="120px"></el-table-column>
+          <el-table-column prop="name" label="瀹㈡埛鍚嶇О" min-width="120px"></el-table-column>
+          <el-table-column prop="lineName" label="绾胯矾鍚嶇О" min-width="180px" show-tooltip-when-overflow></el-table-column>
+          <el-table-column prop="totalNum" label="閫佽揣閲�(鏉�)" min-width="120px"></el-table-column>
+          <el-table-column prop="dateInfo" label="閫佽揣鏃ユ湡" min-width="120px"></el-table-column>
+        </el-table>
+        <pagination
+            @size-change="handleSizeChange"
+            @current-change="handlePageChange"
+            :pagination="tableData.pagination"
+        >
+        </pagination>
+      </template>
+    </TableLayout>
+    <template   v-slot:footer>
+      <el-button @click="visible=false">杩斿洖</el-button>
+    </template>
   </GlobalWindow>
 </template>
 
 <script>
-import BaseOpera from '@/components/base/BaseOpera'
+import BaseTable from '@/components/base/BaseTable'
+import TableLayout from '@/layouts/TableLayout'
+import Pagination from '@/components/common/Pagination'
 import GlobalWindow from '@/components/common/GlobalWindow'
 export default {
   name: 'OperaJkSketchCustomerWindow',
-  extends: BaseOpera,
-  components: { GlobalWindow },
+  extends: BaseTable,
+  components: { GlobalWindow, TableLayout, Pagination },
   data () {
     return {
       // 琛ㄥ崟鏁版嵁
-      form: {
-        id: null,
-        creator: '',
-        createDate: '',
-        editor: '',
-        editDate: '',
-        isdeleted: '',
-        info: '',
+      visible: false,
+      title: '',
+      searchForm: {
         sketchLineId: '',
-        sketchId: '',
-        totalNum: '',
-        orderNum: '',
-        sortnum: '',
-        dateInfo: ''
-      },
-      // 楠岃瘉瑙勫垯
-      rules: {
+        name: '',
+        code: ''
       }
     }
   },
   created () {
     this.config({
+      module: '浜ゆ帶-绾胯矾浼樺寲绾胯矾瀹㈡埛璁板綍淇℃伅琛�',
       api: '/business/jkSketchCustomer',
-      'field.id': 'id'
+      'field.id': 'id',
+      'field.main': 'id'
     })
+    this.search()
+  },
+  methods: {
+    open (title, row) {
+      this.title = title + (row.lineName)
+      this.searchForm.sketchLineId = row.id
+      this.visible = true
+      this.tableData = {
+        // 宸查�変腑鐨勬暟鎹�
+        selectedRows: [],
+        // 鎺掑簭鐨勫瓧娈�
+        sorts: [],
+        // 褰撳墠椤垫暟鎹�
+        list: [],
+        // 鍒嗛〉
+        pagination: {
+          pageIndex: 1,
+          pageSize: 10,
+          total: 0
+        }
+      }
+      this.search()
+    }
   }
 }
 </script>
diff --git a/admin/src/components/business/OperaJkSketchLineListWindow.vue b/admin/src/components/business/OperaJkSketchLineListWindow.vue
index 3bd5622..0085335 100644
--- a/admin/src/components/business/OperaJkSketchLineListWindow.vue
+++ b/admin/src/components/business/OperaJkSketchLineListWindow.vue
@@ -18,32 +18,52 @@
     <div style="display: block">
       <div  style="display: block;font-size: 16px;font-weight: 600;margin-bottom: 10px;">绾胯矾鏄庣粏</div>
       <div>
-        <el-table  :data="dataList" stripe  >
+        <el-table  :data="dataList" stripe> 
           <el-table-column prop="dateInfo" label="閫佽揣鏃ユ湡" min-width="130px"></el-table-column>
           <el-table-column prop="lineName" label="閫佽揣绾胯矾" min-width="130px">  </el-table-column>
           <el-table-column prop="orderNum" label="瀹㈡埛鏁�(鎴�)" min-width="130px"></el-table-column>
           <el-table-column prop="totalNum" label="閫佽揣閲�(鏉�)" min-width="130px"></el-table-column>
           <el-table-column prop="carCode" label="杞︾墝鍙�" min-width="100px"></el-table-column>
           <el-table-column prop="memberName" label="閫佽揣鍙告満" min-width="100px"></el-table-column>
+          <el-table-column prop="distance" label="鎬昏矾绋�(鍏噷)" min-width="100px">
+            <template slot-scope="{row}">
+              {{((row.distance ||0)/1000).toFixed(2)}}
+            </template>
+          </el-table-column>
+          <el-table-column
+              label="鎿嶄綔"
+              min-width="120"
+              align="center"
+              fixed="right"
+          >
+            <template slot-scope="{row}">
+              <el-button type="text" @click="$refs.operaJkSketchCustomerWindow.open('绾胯矾瀹㈡埛鏄庣粏鈥斺��', row)" icon="el-icon-view"  >鏌ョ湅瀹㈡埛</el-button>
+            </template>
+          </el-table-column>
         </el-table>
       </div>
     </div>
+    <template   v-slot:footer>
+      <el-button @click="visible=false">杩斿洖</el-button>
+    </template>
+    <OperaJkSketchCustomerWindow ref="operaJkSketchCustomerWindow"  />
   </GlobalWindow>
 </template>
 
 <script>
 import BaseOpera from '@/components/base/BaseOpera'
 import GlobalWindow from '@/components/common/GlobalWindow'
+import OperaJkSketchCustomerWindow from '@/components/business/OperaJkSketchCustomerWindow'
 export default {
   name: 'OperaJkSketchLineWindow',
   extends: BaseOpera,
-  components: { GlobalWindow },
+  components: { GlobalWindow, OperaJkSketchCustomerWindow},
   data () {
     return {
       // 琛ㄥ崟鏁版嵁
       model: {
       },
-      dataList:[],
+      dataList:[]
     }
   },
   created () {
@@ -66,6 +86,9 @@
         this.dataList = res
       })
     },
+    viewCustomer(row){
+
+    }
   }
 }
 </script>
diff --git a/admin/src/components/business/OperaJkSketchResultWindow.vue b/admin/src/components/business/OperaJkSketchResultWindow.vue
index 2bf3c7c..961e82f 100644
--- a/admin/src/components/business/OperaJkSketchResultWindow.vue
+++ b/admin/src/components/business/OperaJkSketchResultWindow.vue
@@ -1,82 +1,262 @@
 <template>
-  <el-dialog
-      class="center-title"
+  <GlobalWindow
       :title="title"
-      width="500px"
-      top="30vh"
+      width="100%"
       :visible.sync="visible"
       :confirm-working="isWorking"
       @confirm="confirm"
   >
-    <p class="tip-warn"><i class="el-icon-warning"></i>瀵煎叆璇存槑锛�<br>
-      1.璇峰厛涓嬭浇鏂囦欢妯℃澘锛屽苟鎸夌収妯℃澘瑕佸幓濉啓琛ㄦ牸鍐呭;<br>
-      2.姣忔瀵煎叆閿�鍞鍗曡〃绀哄嵆鍒犻櫎涔嬪墠瀵煎叆姝ゆ鐩稿簲鏃ユ湡鐨勮鍗曡褰曪紝浠ユ娆″鍏ョ殑鏁版嵁涓轰富;<br>
-    </p>
-    <el-form class="demo-form-inline" >
-      <el-form-item label="绾胯矾淇℃伅" required>
-        <div style="width: 100%;display: flex;align-items: center;">
-          <el-button type="primary"   @click="clickRef">鐐瑰嚮涓婁紶</el-button>
-          <el-button type="text" @click="exportTemplate">鐐瑰嚮涓嬭浇妯$増.EXCEL</el-button>
+    <div  style="display: block;margin-bottom: 30px;">
+      <div style="display: block;font-size: 16px;font-weight: 600;margin-bottom: 20px;">涓荤嚎璺俊鎭�</div>
+      <div style="display: flex;">
+        <div style="flex: 1">閫佽揣鏃ユ湡锛歿{model.dateInfo ||''}}</div>
+        <div style="flex: 1">涓荤嚎璺細{{model.categoryName ||''}}</div>
+        <div style="flex: 1">瀹㈡埛鏁帮細{{model.orderNum ||'-'}}</div>
+        <div style="flex: 1">閫佽揣閲�(鏉�)锛歿{model.totalNum ||'-'}}</div>
+      </div>
+      <div style="display: flex;margin-top: 30px">
+        <div style="flex: 1">浼樺寲鏃堕棿锛歿{model.planLineDate ||''}} - {{model.planLineEndDate ||''}}</div>
+      </div>
+      <div style="display: flex;margin-top: 20px" class="orange">
+        <div style="flex: 1">浼樺寲缁撴灉锛氫紭鍖栧墠鎬昏矾绋� <span  class="red" style="font-weight: bold"> {{((model.originDistance ||0)/1000).toFixed(2)}}</span> 鍏噷锛屼紭鍖栧悗鎬昏矾绋�<span class="green" style="font-weight: bold"> {{((model.distance ||0)/1000).toFixed(2)}} </span> 鍏噷</div>
+      </div>
+    </div>
+    <div style="display: block">
+      <div  style="display: block;font-size: 16px;font-weight: 600;margin-bottom: 10px;">绾胯矾鏄庣粏</div>
+      <div>
+        <el-table  :data="dataList" stripe  :row-class-name="tableRowClassName">
+          <el-table-column prop="dateInfo" label="閫佽揣鏃ユ湡" min-width="130px"></el-table-column>
+          <el-table-column prop="lineName" label="閫佽揣绾胯矾" min-width="130px">  </el-table-column>
+          <el-table-column prop="orderNum" label="瀹㈡埛鏁�(鎴�)" min-width="130px"> </el-table-column>
+          <el-table-column prop="totalNum" label="閫佽揣閲�(鏉�)" min-width="130px"></el-table-column>
+          <el-table-column prop="carCode" label="杞︾墝鍙�" min-width="100px"></el-table-column>
+          <el-table-column prop="memberName" label="閫佽揣鍙告満" min-width="100px"></el-table-column>
+          <el-table-column prop="distance" label="鎬昏矾绋�(鍏噷)" min-width="100px">
+            <template slot-scope="{row}">
+              {{((row.distance ||0)/1000).toFixed(2)}}
+            </template>
+          </el-table-column>
+          <el-table-column
+              label="鎿嶄綔"
+              min-width="120"
+              align="left"
+              fixed="right"
+          >
+            <template slot-scope="{row}">
+              <el-button type="text" @click="updateDo(row)" icon="el-icon-edit"   style="color: #0d68ff" v-if="!updating" >寰皟</el-button>
+              <template v-else-if="updating &&  currentRow.id ===row.id" >
+                <el-button type="text" style="color: #13ce66"  >鏈溅</el-button>
+                <el-button type="text" @click="cancelDo(row)"  icon="el-icon-delete"  style="color: red" >鍙栨秷</el-button>
+              </template>
+              <el-button type="text" @click="addDo(row)" icon="el-icon-plus"  style="color: red" v-else-if="updating &&  currentRow.id !==row.id" >鍔犲叆</el-button>
+            </template>
+          </el-table-column>
+        </el-table>
+      </div>
+    </div>
+
+    <div style="display: block;margin-top: 30px;border: 1px solid #f2f2f2;padding: 10px" v-if="updating">
+      <div  style="display: block;font-size: 16px;font-weight: 600;margin-bottom: 10px;">{{currentRow.lineName}} - 瀹㈡埛鏄庣粏</div>
+      <div>
+        <p class="tip-warn"><i class="el-icon-warning"></i>鎿嶄綔璇存槑锛�<br>
+          1.璇烽�夋嫨鑻ュ共瀹㈡埛淇℃伅锛岀偣鍑讳笂杩板叾浠栫嚎璺悗鐨�<span class="red">銆愬姞鍏ャ��</span>鎸夐挳锛屽皢閫変腑鐨勫鎴风Щ鍔犲埌瀵瑰簲绾胯矾涓�;<br>
+            2.鐐瑰嚮鏈溅绾胯矾鍚庣殑<span class="red">銆愬彇娑堛��</span>鎸夐挳锛屽彲鎾ら攢鏈溅寰皟鎿嶄綔;<br>
+        </p>
+        <el-table  :data="paginatedData" stripe  @selection-change="handleSelectionChange">>
+          <el-table-column type="selection" width="55"></el-table-column>
+          <el-table-column prop="code" label="瀹㈡埛绠�鐮�" min-width="130px"></el-table-column>
+          <el-table-column prop="name" label="瀹㈡埛鍚嶇О" min-width="130px">  </el-table-column>
+          <el-table-column prop="totalNum" label="閫佽揣閲�(鏉�)" min-width="130px"></el-table-column>
+          <el-table-column prop="location" label="瀹㈡埛鍦板潃" min-width="200px" show-tooltip-when-overflow></el-table-column>
+          <el-table-column prop="latitude" label="缁忕含搴�" min-width="200px">
+            <template slot-scope="{row}">
+               {{(row.longitude || 0).toFixed(6)}},{{(row.latitude || 0).toFixed(6)}}
+            </template>
+          </el-table-column>
+        </el-table>
+        <div class="table-pagination">
+          <el-pagination
+              @current-change="handleCurrentChange"
+              :current-page="currentPage"
+              :page-size="pageSize"
+              layout="total, prev, pager, next, jumper"
+              :total="totalItems">
+          </el-pagination>
         </div>
-        <div style="font-size: 14px; color: black;" v-if="fileName">{{fileName}}</div>
-      </el-form-item>
-    </el-form>
-    <input type="file" style="position: fixed; left: 0; top: -50px;" accept=".xlsx" ref="fileExcel" @change="result" />
+      </div>
+    </div>
     <template   v-slot:footer>
+      <el-button @click="confirmDo" type="primary" v-if="buttonName!==''">{{ buttonName||'纭' }}</el-button>
       <el-button @click="visible=false">杩斿洖</el-button>
     </template>
-  </el-dialog>
+  </GlobalWindow>
 </template>
 
 <script>
 import BaseOpera from '@/components/base/BaseOpera'
 import GlobalWindow from '@/components/common/GlobalWindow'
-import { importExcel } from '@/api/business/jkLine'
+import { allList as customerList } from '@/api/business/jkSketchCustomer'
 export default {
+  name: 'OperaJkSketchLineWindow',
   extends: BaseOpera,
-  // eslint-disable-next-line vue/no-unused-components
   components: { GlobalWindow },
   data () {
     return {
-      importing:false,
-      fileName: ''
+      // 琛ㄥ崟鏁版嵁
+      updating: false,
+      currentRow: null,
+      model: {
+      },
+      buttonName: '',
+      dataList: [],
+      currentPage: 1,
+      pageSize: 10,
+      totalItems: 0, // 鎬绘暟鎹潯鐩暟
+      allCustomerList: [],
+      tableData: [], // 鎵�鏈夋暟鎹�
+      selectRows: []
+    }
+  },
+  created () {
+    this.config({
+      api: '/business/jkSketchLine',
+      'field.id': 'id'
+    })
+  },
+  computed: {
+    paginatedData () {
+      const start = (this.currentPage - 1) * this.pageSize
+      const end = start + this.pageSize
+      return this.tableData.slice(start, end)
     }
   },
   methods: {
-    open (title) {
-      this.title = title
-      this.fileName = ''
+    confirmDo () {
+
+    },
+    open (title, target) {
+      this.title = title + target.categoryName
       this.visible = true
+      this.model = target
+      this.updating = false
+      this.selectRows = []
+      this.tableData = []
+      this.allCustomerList = []
+      this.currentRow = null
+      this.loadList()
     },
-    // 瀵煎嚭妯℃澘
-    exportTemplate () {
-      // 鎶曚繚鐢宠
-      window.open('/template/jkLineTemplate.xlsx')
+    updateDo (row) {
+      this.currentRow = row
+      this.tableData = row.customerList || []
+      this.totalItems = this.tableData.length
+      this.currentPage = 1
+      this.selectRows = []
+      this.updating = true
     },
-    clickRef () {
-      this.$refs.fileExcel.click()
+    cancelDo (row) {
+      this.selectRows = []
+      this.currentRow = null
+      this.updating = false
     },
-    result (e) {
-      const data = new FormData()
-      data.append('file', e.target.files[0])
-      importExcel(data)
+    addDo (row) {
+      if (!this.selectRows || !this.selectRows.length) {
+        this.$message.error('瀵逛笉璧凤紝璇疯嚦灏戦�夋嫨鏈変竴鏉″鎴疯褰曞姞鍏ヨ璺嚎锛�')
+        return
+      }
+      const tarray = []
+      let tNum = 0
+      this.currentRow.customerList.forEach(item => {
+        let flag = false
+        this.selectRows.forEach(item1 => {
+          if (item.id === item1.id) {
+            flag = true
+          }
+        })
+        if (!flag) {
+          tNum += (item.totalNum || 0)
+          tarray.push(item)
+        }
+      })
+      if(tarray.length === 0){
+        this.$message.error('瀵逛笉璧凤紝鏈溅绾胯矾鑷冲皯鐣欏瓨涓�涓鎴蜂俊鎭紝鏃犳硶鍏ㄩ儴娓呯┖锛�')
+        return
+      }
+      var rArray =  row.customerList || []
+      rArray = rArray.push(...this.selectRows)
+      let ttNum = 0
+      rArray.forEach(item => {
+        ttNum += (item.totalNum || 0)
+      })
+      if(tarray.length >= (row.maxCustomer||0)){
+        this.$message.error('瀵逛笉璧凤紝鍔犲叆鐨勭嚎璺渶澶ф敮鎸�'+ (row.maxOrderNum||0) + '瀹㈡埛锛�')
+        return
+      }
+      if(ttNum >= (row.maxOrder||0)){
+        this.$message.error('瀵逛笉璧凤紝鍔犲叆鐨勭嚎璺渶澶ф敮鎸�'+ (row.maxOrder||0) + '閫佽揣閲忥紒')
+        return
+      }
+      this.currentRow.customerList = tarray
+      this.currentRow.orderNum = this.currentRow.customerList.length
+      this.currentRow.totalNum = tNum
+      row.customerList = rArray
+      row.orderNum = row.customerList.length
+      row.totalNum = ttNum
+      this.currentRow = null
+      this.updating = false
+      this.buttonName = '淇濆瓨璋冩暣寮�濮嬩紭鍖�'
+    },
+    handleSelectionChange (rows) {
+      this.selectRows = rows
+    },
+    loadCustomerList () {
+      customerList({ sketchId: this.model.id })
         .then(res => {
-          this.$message.success('瀵煎叆鎴愬姛')
-          this.$emit('success')
-          this.visible = false
+          this.allCustomerList = res
+          if (this.allCustomerList && this.allCustomerList.length) {
+            this.dataList.forEach(item => {
+              var tarray = []
+              this.allCustomerList.forEach(item1 => {
+                if (item.id === item1.sketchLineId) {
+                  tarray.push(item1)
+                }
+              })
+              item.customerList = tarray
+            })
+          }
         })
-        .catch(err => {
-          // this.$message.error(err)
-          this.fileName = ''
-        })
-        .finally(() => {
-          this.$refs.fileExcel.value = null
-        })
+    },
+    loadList () {
+      this.api.allList({
+        sketchId: this.model.id
+      }).then(res => {
+        this.dataList = res
+        this.loadCustomerList()
+      })
+    },
+    tableRowClassName ({ row, rowIndex }) {
+      if (this.currentRow && row.id === this.currentRow.id) {
+        return 'warning-row'
+      } else {
+        return 'success-row'
+      }
+    },
+    handleCurrentChange (newPage) {
+      this.currentPage = newPage
     }
   }
 }
 </script>
-
-<style lang="scss" scoped>
-
+<style lang="scss">
+.el-table .warning-row {
+  background: rgba(161, 231, 20, 0.2) !important;
+  td{
+    background: rgba(161, 231, 20, 0.2) !important;
+  }
+}
+.el-table .success-row {
+  background: #f0f9eb !important;
+  td{
+    background: #f0f9eb !important;
+  }
+}
 </style>
diff --git a/admin/src/components/business/OperaJkSketchWindow.vue b/admin/src/components/business/OperaJkSketchWindow.vue
index 9fa4b61..830a411 100644
--- a/admin/src/components/business/OperaJkSketchWindow.vue
+++ b/admin/src/components/business/OperaJkSketchWindow.vue
@@ -1,57 +1,48 @@
 <template>
   <GlobalWindow
     :title="title"
+    width="70%"
     :visible.sync="visible"
     :confirm-working="isWorking"
     @confirm="confirm"
   >
-    <el-form :model="form" ref="form" :rules="rules">
-      <el-form-item label="鍒涘缓浜虹紪鐮�" prop="creator">
-        <el-input v-model="form.creator" placeholder="璇疯緭鍏ュ垱寤轰汉缂栫爜" v-trim/>
+    <p class="tip-warn"><i class="el-icon-warning"></i>浼樺寲璇存槑锛�<br>
+      1銆佸綋鍓嶄紭鍖栦换鍔℃渶澶氭敮鎸�<span class="orange">銆� {{lineNum}} 銆�</span>鏉$嚎璺�;<br>
+      2銆佸悎鐞嗛�夋嫨绾胯矾锛岄�夋嫨绾胯矾鐨勬�诲鎴锋暟鍜屾�婚�佽揣閲忛渶瑕佹弧瓒冲綋鏃ヨ鍗曠疮璁″��;<br>
+      3銆佸己鍒朵紭鍖栬〃绀哄拷鐣ヨ涓荤嚎浼樺寲涓殑浠诲姟锛岄噸鏂板紑鍚紭鍖栦换鍔★紙涓嶅缓璁級;<br>
+    </p>
+<!--    <el-form :model="form" ref="form" :rules="rules">
+      <el-form-item label="鐢熸垚绾胯矾鏁伴噺" prop="planLineNum">
+        <el-input type="number" disabled  v-model="form.planLineNum" placeholder="璇疯緭鍏ョ嚎璺暟" v-trim/>
       </el-form-item>
-      <el-form-item label="鍒涘缓鏃堕棿" prop="createDate">
-        <el-date-picker v-model="form.createDate" value-format="yyyy-MM-dd" placeholder="璇疯緭鍏ュ垱寤烘椂闂�"></el-date-picker>
-      </el-form-item>
-      <el-form-item label="鏇存柊浜虹紪鐮�" prop="editor">
-        <el-input v-model="form.editor" placeholder="璇疯緭鍏ユ洿鏂颁汉缂栫爜" v-trim/>
-      </el-form-item>
-      <el-form-item label="鏇存柊鏃堕棿" prop="editDate">
-        <el-date-picker v-model="form.editDate" value-format="yyyy-MM-dd" placeholder="璇疯緭鍏ユ洿鏂版椂闂�"></el-date-picker>
-      </el-form-item>
-      <el-form-item label="鏄惁鍒犻櫎0鍚� 1鏄�" prop="isdeleted">
-        <el-input v-model="form.isdeleted" placeholder="璇疯緭鍏ユ槸鍚﹀垹闄�0鍚� 1鏄�" v-trim/>
-      </el-form-item>
-      <el-form-item label="澶囨敞" prop="info">
-        <el-input v-model="form.info" placeholder="璇疯緭鍏ュ娉�" v-trim/>
-      </el-form-item>
-      <el-form-item label="涓荤嚎璺紪鐮侊紙鍏宠仈category)" prop="categoryId">
-        <el-input v-model="form.categoryId" placeholder="璇疯緭鍏ヤ富绾胯矾缂栫爜锛堝叧鑱攃ategory)" v-trim/>
-      </el-form-item>
-      <el-form-item label="閫佽揣閲�" prop="totalNum">
-        <el-input v-model="form.totalNum" placeholder="璇疯緭鍏ラ�佽揣閲�" v-trim/>
-      </el-form-item>
-      <el-form-item label="瀹㈡埛鏁�" prop="orderNum">
-        <el-input v-model="form.orderNum" placeholder="璇疯緭鍏ュ鎴锋暟" v-trim/>
-      </el-form-item>
-      <el-form-item label="鐘舵�� 0鏈紭鍖� 1浼樺寲涓� 2宸蹭紭鍖�" prop="status">
-        <el-input v-model="form.status" placeholder="璇疯緭鍏ョ姸鎬� 0鏈紭鍖� 1浼樺寲涓� 2宸蹭紭鍖�" v-trim/>
-      </el-form-item>
-      <el-form-item label="鎺掑簭鐮�" prop="sortnum">
-        <el-input v-model="form.sortnum" placeholder="璇疯緭鍏ユ帓搴忕爜" v-trim/>
-      </el-form-item>
-      <el-form-item label="鏃ユ湡" prop="dateInfo">
-        <el-date-picker v-model="form.dateInfo" value-format="yyyy-MM-dd" placeholder="璇疯緭鍏ユ棩鏈�"></el-date-picker>
-      </el-form-item>
-      <el-form-item label="浼樺寲璁板綍缂栫爜(浣滀负key鍊煎瓨redis锛�" prop="jobId">
-        <el-input v-model="form.jobId" placeholder="璇疯緭鍏ヤ紭鍖栬褰曠紪鐮�(浣滀负key鍊煎瓨redis锛�" v-trim/>
-      </el-form-item>
-    </el-form>
+    </el-form>-->
+    <div>
+      <el-form :model="form" ref="form" :rules="rules">
+        <el-form-item label="鏄惁寮哄埗浼樺寲" prop="forceUpdate">
+          <el-radio-group v-model="form.forceUpdate">
+            <el-radio :label="0" :value="0">涓嶅己鍒�</el-radio>
+            <el-radio :label="1" :value="1">寮哄埗</el-radio>
+          </el-radio-group>
+        </el-form-item>
+        <el-form-item label="閫夋嫨鐢熸垚绾胯矾" prop="lineIdList" >
+          <el-table  :data="lineList" stripe    @selection-change="handleSelectionChange">
+            <el-table-column type="selection" width="55"></el-table-column>
+            <el-table-column prop="name" label="閫佽揣绾胯矾" min-width="130px" show-tooltip-when-overflow>  </el-table-column>
+            <el-table-column prop="maxCustomer" label="瀹㈡埛鏁�(鎴�)" min-width="100px"  show-tooltip-when-overflow></el-table-column>
+            <el-table-column prop="maxOrder" label="閫佽揣閲�(鏉�)" min-width="100px"  show-tooltip-when-overflow></el-table-column>
+            <el-table-column prop="carCode" label="杞︾墝鍙�" min-width="100px"></el-table-column>
+            <el-table-column prop="memberName" label="閫佽揣鍙告満" min-width="100px"></el-table-column>
+          </el-table>
+        </el-form-item>
+      </el-form>
+    </div>
   </GlobalWindow>
 </template>
 
 <script>
 import BaseOpera from '@/components/base/BaseOpera'
 import GlobalWindow from '@/components/common/GlobalWindow'
+import { allList } from '@/api/business/jkLine'
 export default {
   name: 'OperaJkSketchWindow',
   extends: BaseOpera,
@@ -61,22 +52,17 @@
       // 琛ㄥ崟鏁版嵁
       form: {
         id: null,
-        creator: '',
-        createDate: '',
-        editor: '',
-        editDate: '',
-        isdeleted: '',
-        info: '',
-        categoryId: '',
-        totalNum: '',
-        orderNum: '',
-        status: '',
-        sortnum: '',
-        dateInfo: '',
-        jobId: ''
+        planLineNum: '',
+        forceUpdate: 0,
+        lineIdList: []
       },
+      categoryId: null,
+      lineList: [],
+      lineNum: null,
       // 楠岃瘉瑙勫垯
       rules: {
+        lineIdList: [{ required: true, message: '璇烽�夋嫨鐢熸垚绾胯矾鏁伴噺' }],
+        forceUpdate: [{ required: true, message: '璇烽�夋嫨鏄惁寮哄埗浼樺寲' }]
       }
     }
   },
@@ -85,6 +71,70 @@
       api: '/business/jkSketch',
       'field.id': 'id'
     })
+  },
+  methods: {
+    handleSelectionChange (rows) {
+      this.form.lineIdList = []
+      if (rows || rows.length) {
+        rows.forEach(item => {
+          this.form.lineIdList.push(item.id)
+        })
+      }
+    },
+    open (title, target) {
+      if (!target || !target.id) {
+        return
+      }
+      this.lineList = []
+      this.title = title
+      this.visible = true
+      this.categoryId = target.categoryId
+      this.form.id = target.id
+      this.form.planLineNum = target.planLineNum
+      this.form.forceUpdate = 0
+      this.form.lineIdList = []
+      this.loadLines()
+    },
+    confirm () {
+      this.$refs.form.validate((valid) => {
+        if (!valid) {
+          return
+        }
+      /*  if (this.form.planLineNum <= 0 || this.form.planLineNum > this.lineNum) {
+          this.$message.error('浼樺寲绾胯矾鏁板繀椤诲湪[1-' + this.lineNum + ']鑼冨洿鍐咃紒')
+          return
+        }*/
+        this.confirmDo()
+      })
+    },
+    confirmDo () {
+      // 璋冪敤鏂板缓鎺ュ彛
+      this.isWorking = true
+      this.api.updateById({
+        id: this.form.id,
+        lineIdList: this.form.lineIdList,
+        forceUpdate: this.form.forceUpdate
+      })
+        .then(() => {
+          this.visible = false
+          this.$tip.apiSuccess('浼樺寲浠诲姟姝e湪鍚庡彴鎵ц锛岃绛夊緟浼樺寲瀹屾垚鍚庢煡鐪嬩紭鍖栫粨鏋滐紒')
+          this.$emit('success')
+        })
+        .catch(e => {
+          // this.$tip.apiFailed(e)
+        })
+        .finally(() => {
+          this.isWorking = false
+        })
+    },
+    loadLines () {
+      allList({
+        categoryId: this.categoryId
+      }).then(res => {
+        this.lineList = res || []
+        this.lineNum = this.lineList.length
+      })
+    }
   }
 }
 </script>
diff --git a/admin/src/views/business/jkCustomer.vue b/admin/src/views/business/jkCustomer.vue
index 8c003f3..1e5707a 100644
--- a/admin/src/views/business/jkCustomer.vue
+++ b/admin/src/views/business/jkCustomer.vue
@@ -45,6 +45,7 @@
         <li><el-button type="danger" @click="deleteByIdInBatch" icon="el-icon-delete" v-permissions="['business:jkcustomer:delete']">鍒犻櫎</el-button></li>
       </ul>
       <el-table
+          :height="tableHeightNew"
         v-loading="isWorking.search"
         :data="tableData.list"
         stripe
diff --git a/admin/src/views/business/jkLine.vue b/admin/src/views/business/jkLine.vue
index 255cc63..c71ffc3 100644
--- a/admin/src/views/business/jkLine.vue
+++ b/admin/src/views/business/jkLine.vue
@@ -31,6 +31,8 @@
         <li><el-button type="danger" @click="deleteByIdInBatch" icon="el-icon-delete" v-permissions="['business:jkline:delete']">鍒犻櫎</el-button></li>
       </ul>
       <el-table
+
+          :height="tableHeightNew"
         v-loading="isWorking.search"
         :data="tableData.list"
         stripe
diff --git a/admin/src/views/business/jkSketch.vue b/admin/src/views/business/jkSketch.vue
index 134b626..96b57a0 100644
--- a/admin/src/views/business/jkSketch.vue
+++ b/admin/src/views/business/jkSketch.vue
@@ -38,30 +38,33 @@
 <!--
         <el-table-column type="selection" width="55"></el-table-column>
 -->
-        <el-table-column prop="dateInfo" label="閫佽揣鏃ユ湡" min-width="130px"></el-table-column>
-        <el-table-column prop="categoryName" label="涓荤嚎璺�" min-width="130px">
+        <el-table-column prop="dateInfo" label="閫佽揣鏃ユ湡" min-width="100px" align="center"></el-table-column>
+        <el-table-column prop="categoryName" label="涓荤嚎璺�-褰撳墠绾胯矾鏁�" min-width="200px" align="center">
           <template slot-scope="{row}">
-            <span class="blue" style="cursor: pointer" @click="$refs.operaJkSketchLineListWindow.open('閰嶉�佺嚎璺槑缁�', row)">{{ row.categoryName }}锛坽{row.lineNum||0}}鏉$嚎璺級</span>
+            <span class="blue" style="cursor: pointer" @click="$refs.operaJkSketchLineListWindow.open('閰嶉�佺嚎璺槑缁�', row)">{{ row.categoryName }}</span>
+            <span class="orange" style="margin-left: 10px">銆� {{row.lineNum||0}} 銆戞潯绾胯矾</span>
           </template>
         </el-table-column>
-        <el-table-column prop="orderNum" label="瀹㈡埛鏁�(鎴�)" min-width="130px"></el-table-column>
-        <el-table-column prop="totalNum" label="閫佽揣閲�(鏉�)" min-width="130px"></el-table-column>
-        <el-table-column prop="status" label="浼樺寲鐘舵��" min-width="100px">
+        <el-table-column prop="orderNum" label="瀹㈡埛鏁�(鎴�)" min-width="100px" align="center"></el-table-column>
+        <el-table-column prop="totalNum" label="閫佽揣閲�(鏉�)" min-width="100px" align="center"></el-table-column>
+        <el-table-column prop="status" label="浼樺寲鐘舵��" min-width="100px" align="center">
           <template slot-scope="{row}">
             <span v-if="row.status === 0" class="blue">鏈紭鍖�</span>
-            <span v-if="row.status === 1" class="red">浼樺寲涓�</span>
+            <span v-if="row.status === 1" class="red">浼樺寲涓� 銆� {{row.planLineNum||0}} 銆戞潯绾胯矾</span>
             <span v-if="row.status === 2" class="green">宸蹭紭鍖�</span>
+            <span v-if="row.status === 3" class="green">浼樺寲澶辫触</span>
           </template>
         </el-table-column>
         <el-table-column
           v-if="containPermissions(['business:jksketch:update', 'business:jksketch:delete'])"
           label="鎿嶄綔"
           min-width="120"
+          align="left"
           fixed="right"
         >
           <template slot-scope="{row}">
             <el-button type="text" @click="$refs.operaJkSketchWindow.open('绾胯矾浼樺寲', row)" icon="el-icon-edit" v-permissions="['business:jksketch:update']">绾胯矾浼樺寲</el-button>
-            <el-button type="text" @click="$refs.OperaJkSketchResultWindow.open('绾胯矾浼樺寲缁撴灉', row)" icon="el-icon-view" v-if="row.status ==2" >浼樺寲缁撴灉</el-button>
+            <el-button type="text" @click="$refs.OperaJkSketchResultWindow.open('浼樺寲缁撴灉寰皟-', row)" icon="el-icon-edit" v-if="row.status ==2" >浼樺寲缁撴灉寰皟</el-button>
           </template>
         </el-table-column>
       </el-table>
@@ -76,7 +79,7 @@
     <OperaJkSketchWindow ref="operaJkSketchWindow" @success="handlePageChange"/>
     <OperaJkSketchResultWindow ref="OperaJkSketchResultWindow" @success="handlePageChange"/>
     <OperaJkSketchImportWindow ref="OperaJkSketchImportWindow" @success="handlePageChange"/>
-    <OperaJkSketchLineListWindow ref="operaJkSketchLineListWindow"  />
+    <OperaJkSketchLineListWindow ref="operaJkSketchLineListWindow"  @success="handlePageChange" />
   </TableLayout>
 </template>
 
diff --git a/server/pom.xml b/server/pom.xml
index 540fde6..4050b74 100644
--- a/server/pom.xml
+++ b/server/pom.xml
@@ -42,7 +42,13 @@
         <type>pom</type>
         <scope>import</scope>
       </dependency>
-
+        <dependency>
+          <groupId>com.google.protobuf</groupId>
+          <artifactId>protobuf-java</artifactId>
+          <version>4.31.1</version>
+          <type>pom</type>
+          <scope>import</scope>
+        </dependency>
       <!-- Alibaba Cloud 渚濊禆绠$悊 -->
       <dependency>
         <groupId>com.alibaba.cloud</groupId>
diff --git a/server/system_service/pom.xml b/server/system_service/pom.xml
index daab417..1439845 100644
--- a/server/system_service/pom.xml
+++ b/server/system_service/pom.xml
@@ -21,7 +21,7 @@
         <mybatis.plus.version>3.5.7</mybatis.plus.version>
         <apache.shiro.version>1.7.0</apache.shiro.version>
         <oshi.version>5.7.0</oshi.version>
-        <jna.version>5.7.0</jna.version>
+        <jna.version>5.14.0</jna.version>
         <poi.version>5.0.0</poi.version>
         <spring-cloud.version>2021.0.3</spring-cloud.version>
         <spring-cloud-alibaba.version>2021.0.1.0</spring-cloud-alibaba.version>
@@ -36,7 +36,6 @@
         <!-- 闃块噷浜慜SS瀛樺偍 -->
         <aliyun-oss.version>3.8.0</aliyun-oss.version>
     </properties>
-
     <dependencies>
         <dependency>
             <groupId>org.springframework.boot</groupId>
@@ -185,16 +184,16 @@
             <groupId>com.github.oshi</groupId>
             <artifactId>oshi-core</artifactId>
             <version>${oshi.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>net.java.dev.jna</groupId>
-            <artifactId>jna</artifactId>
-            <version>${jna.version}</version>
-        </dependency>
-        <dependency>
-            <groupId>net.java.dev.jna</groupId>
-            <artifactId>jna-platform</artifactId>
-            <version>${jna.version}</version>
+            <exclusions>
+                <exclusion>
+                    <artifactId>jna-platform</artifactId>
+                    <groupId>net.java.dev.jna</groupId>
+                </exclusion>
+                <exclusion>
+                    <artifactId>jna</artifactId>
+                    <groupId>net.java.dev.jna</groupId>
+                </exclusion>
+            </exclusions>
         </dependency>
         <!-- https://mvnrepository.com/artifact/com.github.yulichang/mybatis-plus-join -->
         <dependency>
@@ -316,7 +315,6 @@
                 <type>pom</type>
                 <scope>import</scope>
             </dependency>
-
        <!-- <dependency>
             <groupId>org.springframework.boot</groupId>
             <artifactId>spring-boot-dependencies</artifactId>
@@ -340,11 +338,40 @@
             <type>pom</type>
             <scope>import</scope>
         </dependency>-->
-         <dependency>
+    <!--    <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+            <version>4.31.1</version>
+        </dependency>
+-->
+        <!-- <dependency>
             <groupId>com.google.ortools</groupId>
             <artifactId>ortools-java</artifactId>
             <version>9.14.6206</version>
+             <exclusions>
+                 <exclusion>
+                     <groupId>com.google.protobuf</groupId>
+                     <artifactId>protobuf-java</artifactId>
+                 </exclusion>
+             </exclusions>
         </dependency>
-
+-->
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+            <version>4.31.1</version>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>com.google.ortools</groupId>
+            <artifactId>ortools-java</artifactId>
+            <version>9.14.6206</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.protobuf</groupId>
+                    <artifactId>protobuf-java</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
     </dependencies>
 </project>
\ No newline at end of file
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 e83550f..0d2ca0c 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
@@ -161,6 +161,7 @@
     public static final String LIQUID_LEVEL_UNIT ="LIQUID_LEVEL_UNIT" ;
     public static final String OUT_HY_LOT_TOTAL ="OUT_HY_LOT_TOTAL" ;
     public static final String BANNER_IMG ="BANNER_IMG" ;
+    public static final String COMPANY_LOCATION = "COMPANY_LOCATION";
     public static final String GAODE_LOCATION_GEOAPI_URL = "GAODE_LOCATION_GEOAPI_URL";
 
     public static  boolean DEALING_HK_SYNCPRIVILEGE= false;
@@ -520,6 +521,7 @@
     public interface RedisKeys {
         public static final String IMPORTING_CARS ="IMPORTING_CARS";
         public static final String CHECKING_JKCUSTOMER_LOCATION ="CHECKING_JKCUSTOMER_LOCATION";
+        public static final String JKLINE_JOB ="JKLINE_JOB_";
         public static final String IMPORTING_JKCUSTOMER ="IMPORTING_JKCUSTOMER";
         public static final String IMPORTING_JKORDERS ="IMPORTING_JKORDERS";
         public static final String IMPORTING_JKLINE ="IMPORTING_JKLINE";
diff --git a/server/system_service/src/main/java/com/doumee/core/utils/DateUtil.java b/server/system_service/src/main/java/com/doumee/core/utils/DateUtil.java
index 3729091..7f2fc50 100644
--- a/server/system_service/src/main/java/com/doumee/core/utils/DateUtil.java
+++ b/server/system_service/src/main/java/com/doumee/core/utils/DateUtil.java
@@ -3120,6 +3120,25 @@
     }
 
     /**
+     * 鑾峰彇褰撳墠鏃ユ湡鏄槦鏈熷嚑<br>
+     *
+     * @param dt
+     * @return 褰撳墠鏃ユ湡鏄槦鏈熷嚑
+     */
+    public static String getWeekZhouOfDate(Date dt) {
+        String[] weekDays = { "鍛ㄦ棩", "鍛ㄤ竴", "鍛ㄤ簩", "鍛ㄤ笁", "鍛ㄥ洓", "鍛ㄤ簲", "鍛ㄥ叚" };
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(dt);
+
+        int w = cal.get(Calendar.DAY_OF_WEEK) - 1;
+        if (w < 0)
+        {
+            w = 0;
+        }
+
+        return weekDays[w];
+    }
+    /**
      * 鑾峰彇鏄熸湡鏁�
      *
      * @param dt
diff --git a/server/system_service/src/main/java/com/doumee/core/utils/DistanceCalculator.java b/server/system_service/src/main/java/com/doumee/core/utils/DistanceCalculator.java
new file mode 100644
index 0000000..64f2904
--- /dev/null
+++ b/server/system_service/src/main/java/com/doumee/core/utils/DistanceCalculator.java
@@ -0,0 +1,21 @@
+package com.doumee.core.utils;
+public class DistanceCalculator {
+    private static final double EARTH_RADIUS = 6371.0; // 鍦扮悆鍗婂緞锛堝崟浣嶏細鍏噷锛�
+
+    public static void main(String[] args) {
+        //118.363428,31.326485
+        //118.363312,31.326638
+        System.out.println(calculateDistance(39.326638d,116.363312d,31.326606,118.363272));
+    }
+    public static long calculateDistance(double lat1, double lon1, double lat2, double lon2) {
+        double dLat = Math.toRadians(lat2 - lat1);
+        double dLon = Math.toRadians(lon2 - lon1);
+
+        double a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
+                Math.cos(Math.toRadians(lat1)) * Math.cos(Math.toRadians(lat2)) *
+                        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 * 1000);
+    }
+}
\ No newline at end of file
diff --git a/server/system_service/src/main/java/com/doumee/core/utils/TspSolver.java b/server/system_service/src/main/java/com/doumee/core/utils/TspSolver.java
deleted file mode 100644
index 06e17e2..0000000
--- a/server/system_service/src/main/java/com/doumee/core/utils/TspSolver.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package com.doumee.core.utils;
-
-import com.google.ortools.Loader;
-import com.google.ortools.constraintsolver.*;
-import lombok.extern.slf4j.Slf4j;
-
-@Slf4j
-public class TspSolver {
-    public static void main(String[] args) throws Exception {
-        // 鍒濆鍖栨暟鎹ā鍨�
-        Loader.loadNativeLibraries();
-        DataModel data = new DataModel();
-        data.initDataList();//鏋勯�犳暟鎹�
-
-        long start =System.currentTimeMillis();
-        System.out.println("=============start=========="+start);
-        //鍒涘缓姹傝В鍣╩anager瀵硅薄锛屽垵濮嬪寲姹傝В鍣ㄦ暟鎹�
-        RoutingIndexManager manager =  new RoutingIndexManager(data.distanceMatrix.length, data.vehicleNumber, data.depot);
-
-        // 鍒濆鍖栨眰瑙e櫒
-        RoutingModel routing = new RoutingModel(manager);
-
-//        // 娉ㄥ唽鍥炶皟鍑芥暟
-        final int transitCallbackIndex =
-                routing.registerTransitCallback((long fromIndex, long toIndex) -> {
-                    int fromNode = manager.indexToNode(fromIndex);
-                    int toNode = manager.indexToNode(toIndex);
-                    return data.distanceMatrix[fromNode][toNode];
-                });
-
-        // 瀹氫箟鍥炶皟鍑芥暟鑷虫瘡鏉¤矾绾�
-        routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
-        // 澧炲姞璺濈缁村害绾︽潫
-        routing.addDimension(transitCallbackIndex, 0, 30000,
-                true,
-                "Distance");
-        RoutingDimension distanceDimension = routing.getMutableDimension("Distance");
-        distanceDimension.setGlobalSpanCostCoefficient(100);
-//        // 娣诲姞瀹归噺闄愬埗
-        final int demandCallbackIndex = routing.registerUnaryTransitCallback((long fromIndex) -> {
-            int fromNode = manager.indexToNode(fromIndex);
-            return data.demands[fromNode];
-        });
-        routing.addDimensionWithVehicleCapacity(demandCallbackIndex, 0, data.vehicleCapacities, true, "Capacity");
-
-        Solver solver = routing.solver();
-
-
-        //璁剧疆鎼滅储鏂规硶
-        RoutingSearchParameters searchParameters =
-                main.defaultRoutingSearchParameters()
-                        .toBuilder()
-                        .setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
-                        .build();
-
-        // 鎵ц绠楁硶
-        Assignment solution = routing.solveWithParameters(searchParameters);
-
-        // 鎵撳嵃璺嚎
-        printSolution(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");
-    }
-
-    static void printSolution(
-            DataModel data, RoutingModel routing, RoutingIndexManager manager, Assignment solution) {
-        long maxRouteDistance = 0;
-        for (int i = 0; i < data.vehicleNumber; ++i) {
-            long index = routing.start(i);
-            log.info("Route for Vehicle " + i + ":");
-            long routeDistance = 0;
-            int routeDemand = 0;
-            String route = "";
-            while (!routing.isEnd(index)) {
-                route += manager.indexToNode(index) + " -> ";
-                routeDemand += data.demands[manager.indexToNode(index)];
-                long previousIndex = index;
-                index = solution.value(routing.nextVar(index));
-                routeDistance += routing.getArcCostForVehicle(previousIndex, index, i);
-            }
-            log.info(route + manager.indexToNode(index));
-            log.info("Distance of the route: " + routeDistance + "m"+"  Capacity of the route:"+routeDemand+"/"+data.vehicleCapacities[i]);
-            maxRouteDistance = Math.max(routeDistance, maxRouteDistance);
-        }
-        log.info("Maximum of the route distances: " + maxRouteDistance + "m");
-    }
-
-    static class DataModel {
-        //璺濈鐭╅樀
-        public int lenght;
-        //鏈�澶ц溅杈嗛檺鍒�
-        public  int vehicleNumber;
-        //璧风偣
-        public static final int depot = 0;
-
-        //姣忎竴涓偣鐨勫晢鍝佺殑鏁伴噺
-        public   long[] demands;
-        //杞﹁締鏈�澶у杞�
-        public   long[] vehicleCapacities ;
-        public   long[][] distanceMatrix ;
-        public   void initDataList(){
-            lenght = 500;
-            vehicleNumber = 8;
-            demands = new long[lenght];
-            vehicleCapacities =new long[vehicleNumber];
-            distanceMatrix =  new long[lenght][lenght];
-            int total0 =0;
-            for (int i = 0; i <vehicleNumber ; i++) {
-                long tem = (long) (Math.random() * 1000 + 20000);
-                vehicleCapacities[i] = tem;
-                total0+=tem;
-                System.out.print(tem+" ,");
-            }
-            System.out.println( "\ntotal Capacity:"+total0+"=====================");
-            long total = 0;
-            for (int i = 0; i <lenght ; i++) {
-                long tem =  (int)(Math.random()*100+100);
-                demands[i] =tem;
-                total+=tem;
-                System.out.print(tem+" ,");
-                for (int j = 0; j <lenght ; j++) {
-                    if(i == j){
-                        distanceMatrix[i][j] =0;
-                    }
-                    if(i<j){
-                        distanceMatrix[i][j] =(int)(Math.random()*1000+1);
-                        distanceMatrix[j][i] =    distanceMatrix[i][j];
-                    }
-                }
-            }
-
-            System.out.println( "\ntotal Demands:"+total+"=====================");
-        }
-       /* public final long[][] distanceMatrix = {
-                {0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662},
-                {548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674, 1016, 868, 1210},
-                {776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164, 1130, 788, 1552, 754},
-                {696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822, 1164, 560, 1358},
-                {582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708, 1050, 674, 1244},
-                {274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628, 514, 1050, 708},
-                {502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856, 514, 1278, 480},
-                {194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320, 662, 742, 856},
-                {308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662, 320, 1084, 514},
-                {194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388, 274, 810, 468},
-                {536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764, 730, 388, 1152, 354},
-                {502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114, 308, 650, 274, 844},
-                {388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194, 536, 388, 730},
-                {354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0, 342, 422, 536},
-                {468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536, 342, 0, 764, 194},
-                {776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274, 388, 422, 764, 0, 798},
-                {662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730, 536, 194, 798, 0},
-        };*/
-
-    }
-
-}
\ No newline at end of file
diff --git a/server/system_service/src/main/java/com/doumee/core/utils/tsp/TspSolver.java b/server/system_service/src/main/java/com/doumee/core/utils/tsp/TspSolver.java
new file mode 100644
index 0000000..1a2628a
--- /dev/null
+++ b/server/system_service/src/main/java/com/doumee/core/utils/tsp/TspSolver.java
@@ -0,0 +1,280 @@
+package com.doumee.core.utils.tsp;
+
+import com.doumee.core.constants.ResponseStatus;
+import com.doumee.core.exception.BusinessException;
+import com.google.ortools.Loader;
+import com.google.ortools.constraintsolver.*;
+import lombok.extern.slf4j.Slf4j;
+import com.google.protobuf.Internal.IntListAdapter.IntConverter;
+import  com.google.ortools.constraintsolver.mainJNI;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+public class TspSolver {
+    public static void main(String[] args) throws Exception {
+        DataModel data = new DataModel();
+        data.initDataList();//鏋勯�犳暟鎹�
+
+        startSearch(data);
+        /*// 鍒濆鍖栨暟鎹ā鍨�
+        Loader.loadNativeLibraries();
+        DataModel data = new DataModel();
+        data.initDataList();//鏋勯�犳暟鎹�
+
+        long start =System.currentTimeMillis();
+        System.out.println("=============start=========="+start);
+        //鍒涘缓姹傝В鍣╩anager瀵硅薄锛屽垵濮嬪寲姹傝В鍣ㄦ暟鎹�
+        RoutingIndexManager manager =  new RoutingIndexManager(data.distanceMatrix.length, data.vehicleNumber, data.depot);
+
+        // 鍒濆鍖栨眰瑙e櫒
+        RoutingModel routing = new RoutingModel(manager);
+
+//        // 娉ㄥ唽鍥炶皟鍑芥暟
+        final int transitCallbackIndex =
+                routing.registerTransitCallback((long fromIndex, long toIndex) -> {
+                    int fromNode = manager.indexToNode(fromIndex);
+                    int toNode = manager.indexToNode(toIndex);
+                    return data.distanceMatrix[fromNode][toNode];
+                });
+
+        // 瀹氫箟鍥炶皟鍑芥暟鑷虫瘡鏉¤矾绾�
+        routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
+        // 澧炲姞璺濈缁村害绾︽潫
+        routing.addDimension(transitCallbackIndex, 0, 30000,
+                true,
+                "Distance");
+        RoutingDimension distanceDimension = routing.getMutableDimension("Distance");
+        distanceDimension.setGlobalSpanCostCoefficient(100);
+//        // 娣诲姞瀹归噺闄愬埗
+        final int demandCallbackIndex = routing.registerUnaryTransitCallback((long fromIndex) -> {
+            int fromNode = manager.indexToNode(fromIndex);
+            return data.demands[fromNode];
+        });
+        routing.addDimensionWithVehicleCapacity(demandCallbackIndex, 0, data.vehicleCapacities, true, "Capacity");
+
+        Solver solver = routing.solver();
+
+
+        //璁剧疆鎼滅储鏂规硶
+        RoutingSearchParameters searchParameters =
+                main.defaultRoutingSearchParameters()
+                        .toBuilder()
+                        .setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
+                        .build();
+
+        // 鎵ц绠楁硶
+        Assignment solution = routing.solveWithParameters(searchParameters);
+
+        // 鎵撳嵃璺嚎
+        printSolution(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");
+    */}
+    public static void startSearch(DataModel data) {
+        // 鍒濆鍖栨暟鎹ā鍨�
+        Loader.loadNativeLibraries();
+        long start =System.currentTimeMillis();
+        System.out.println("=============start=========="+start);
+        //鍒涘缓姹傝В鍣╩anager瀵硅薄锛屽垵濮嬪寲姹傝В鍣ㄦ暟鎹�
+        RoutingIndexManager manager =  new RoutingIndexManager(data.distanceMatrix.length, data.vehicleNumber, data.depot);
+
+        // 鍒濆鍖栨眰瑙e櫒
+        RoutingModel routing = new RoutingModel(manager);
+
+        // 娉ㄥ唽鍥炶皟鍑芥暟
+        final int transitCallbackIndex =
+                routing.registerTransitCallback((long fromIndex, long toIndex) -> {
+                    int fromNode = manager.indexToNode(fromIndex);
+                    int toNode = manager.indexToNode(toIndex);
+                    return data.distanceMatrix[fromNode][toNode];
+                });
+
+        // 瀹氫箟鍥炶皟鍑芥暟鑷虫瘡鏉¤矾绾�
+        routing.setArcCostEvaluatorOfAllVehicles(transitCallbackIndex);
+        // 澧炲姞璺濈缁村害绾︽潫
+        routing.addDimension(transitCallbackIndex, 0, 300000000,
+                true,
+                "Distance");
+        RoutingDimension distanceDimension = routing.getMutableDimension("Distance");
+        distanceDimension.setGlobalSpanCostCoefficient(100);
+//        // 娣诲姞瀹归噺闄愬埗
+        final int demandCallbackIndex = routing.registerUnaryTransitCallback((long fromIndex) -> {
+            int fromNode = manager.indexToNode(fromIndex);
+            return data.demands[fromNode];
+        });
+        routing.addDimensionWithVehicleCapacity(demandCallbackIndex, 0, data.vehicleCapacities, true, "Capacity");
+//        routing.addDimensionWithVehicleTransits()
+        Solver solver = routing.solver();
+
+        //璁剧疆鎼滅储鏂规硶
+        RoutingSearchParameters searchParameters =
+                main.defaultRoutingSearchParameters()
+                        .toBuilder()
+                        .setFirstSolutionStrategy(FirstSolutionStrategy.Value.PATH_CHEAPEST_ARC)
+                        .build();
+
+        // 鎵ц绠楁硶
+        Assignment solution = routing.solveWithParameters(searchParameters);
+        if(solution ==null){
+            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");
+    }
+    static void resultSolution( DataModel data, RoutingModel routing, RoutingIndexManager manager, Assignment solution) {
+        long maxRouteDistance = 0;
+         List<TspSolverSolutions> mapList = new ArrayList<>();
+        for (int i = 0; i < data.vehicleNumber; ++i) {
+            TspSolverSolutions t = new TspSolverSolutions();
+            t.setLineIndex(i);
+            long index = routing.start(i);
+            log.info("Route for Vehicle " + i + ":");
+            long routeDistance = 0;
+            int routeDemand = 0;
+            String route = "";
+            List<Integer> routeList = new ArrayList<>();
+            while (!routing.isEnd(index)) {
+                int tNode = manager.indexToNode(index);
+                routeList.add( tNode);
+                route += tNode+ " -> ";
+                routeDemand += data.demands[tNode];
+                long previousIndex = index;
+                index = solution.value(routing.nextVar(index));
+                routeDistance += routing.getArcCostForVehicle(previousIndex, index, i);
+            }
+            int tNode = manager.indexToNode(index);
+            routeList.add( tNode);
+            log.info(route + tNode);
+            t.setRouteIndex(routeList);
+            t.setDistance(routeDistance);
+            log.info("Distance of the route: " + routeDistance + "m"+"  Capacity of the route:"+routeDemand+"/"+data.vehicleCapacities[i]);
+            maxRouteDistance = Math.max(routeDistance, maxRouteDistance);
+            mapList.add(t);
+        }
+        data.setSolutions(mapList);
+        log.info("Maximum of the route distances: " + maxRouteDistance + "m");
+    }
+    static void printSolution( DataModel data, RoutingModel routing, RoutingIndexManager manager, Assignment solution) {
+        long maxRouteDistance = 0;
+        for (int i = 0; i < data.vehicleNumber; ++i) {
+            long index = routing.start(i);
+            log.info("Route for Vehicle " + i + ":");
+            long routeDistance = 0;
+            int routeDemand = 0;
+            String route = "";
+            List<Integer> routeList = new ArrayList<>();
+            while (!routing.isEnd(index)) {
+                int tNode = manager.indexToNode(index);
+                routeList.add( tNode);
+                route += tNode+ " -> ";
+                routeDemand += data.demands[tNode];
+                long previousIndex = index;
+                index = solution.value(routing.nextVar(index));
+                routeDistance += routing.getArcCostForVehicle(previousIndex, index, i);
+            }
+            log.info(route + manager.indexToNode(index));
+            log.info("Distance of the route: " + routeDistance + "m"+"  Capacity of the route:"+routeDemand+"/"+data.vehicleCapacities[i]);
+            maxRouteDistance = Math.max(routeDistance, maxRouteDistance);
+        }
+        log.info("Maximum of the route distances: " + maxRouteDistance + "m");
+    }
+
+    public static void startOptimize(){
+
+
+    }
+
+   public static class DataModel {
+        //璺濈鐭╅樀
+        public int lenght;
+        //鏈�澶ц溅杈嗛檺鍒�
+        public  int vehicleNumber;
+        public List<TspSolverSolutions> solutions;
+        //璧风偣
+        public static final int depot = 0;
+
+        //姣忎竴涓偣鐨勫晢鍝佺殑鏁伴噺
+        public   long[] demands;
+        //杞﹁締鏈�澶у杞�
+        public   long[] vehicleCapacities ;
+        public   long[][] distanceMatrix ;
+
+       public List<TspSolverSolutions> getSolutions() {
+           return solutions;
+       }
+
+       public void setSolutions(List<TspSolverSolutions> solutions) {
+           this.solutions = solutions;
+       }
+
+       public  void initDataInfo(int vehicleNumber1, long[] demands1, long[] vehicleCapacities1, long[][] distanceMatrix1){
+            this.demands = demands1;
+            this.vehicleNumber = vehicleNumber1;
+            this.vehicleCapacities=vehicleCapacities1;
+            this.distanceMatrix=distanceMatrix1;
+        }
+        public   void initDataList(){
+            lenght = 100;
+            vehicleNumber = 7;
+            demands = new long[lenght];
+            vehicleCapacities =new long[vehicleNumber];
+            distanceMatrix =  new long[lenght][lenght];
+            int total0 =0;
+            for (int i = 0; i <vehicleNumber ; i++) {
+                long tem = (long) (Math.random() * 1000 + 20000);
+                vehicleCapacities[i] = tem;
+                total0+=tem;
+                System.out.print(tem+" ,");
+            }
+            System.out.println( "\ntotal Capacity:"+total0+"=====================");
+            long total = 0;
+            for (int i = 0; i <lenght ; i++) {
+                long tem =  (int)(Math.random()*100+100);
+                demands[i] =tem;
+                total+=tem;
+                System.out.print(tem+" ,");
+                for (int j = 0; j <lenght ; j++) {
+                    if(i == j){
+                        distanceMatrix[i][j] =0;
+                    }
+                    if(i<j){
+                        distanceMatrix[i][j] =(int)(Math.random()*1000+1);
+                        distanceMatrix[j][i] =    distanceMatrix[i][j];
+                    }
+                }
+            }
+
+            System.out.println( "\ntotal Demands:"+total+"=====================");
+        }
+       /* public final long[][] distanceMatrix = {
+                {0, 548, 776, 696, 582, 274, 502, 194, 308, 194, 536, 502, 388, 354, 468, 776, 662},
+                {548, 0, 684, 308, 194, 502, 730, 354, 696, 742, 1084, 594, 480, 674, 1016, 868, 1210},
+                {776, 684, 0, 992, 878, 502, 274, 810, 468, 742, 400, 1278, 1164, 1130, 788, 1552, 754},
+                {696, 308, 992, 0, 114, 650, 878, 502, 844, 890, 1232, 514, 628, 822, 1164, 560, 1358},
+                {582, 194, 878, 114, 0, 536, 764, 388, 730, 776, 1118, 400, 514, 708, 1050, 674, 1244},
+                {274, 502, 502, 650, 536, 0, 228, 308, 194, 240, 582, 776, 662, 628, 514, 1050, 708},
+                {502, 730, 274, 878, 764, 228, 0, 536, 194, 468, 354, 1004, 890, 856, 514, 1278, 480},
+                {194, 354, 810, 502, 388, 308, 536, 0, 342, 388, 730, 468, 354, 320, 662, 742, 856},
+                {308, 696, 468, 844, 730, 194, 194, 342, 0, 274, 388, 810, 696, 662, 320, 1084, 514},
+                {194, 742, 742, 890, 776, 240, 468, 388, 274, 0, 342, 536, 422, 388, 274, 810, 468},
+                {536, 1084, 400, 1232, 1118, 582, 354, 730, 388, 342, 0, 878, 764, 730, 388, 1152, 354},
+                {502, 594, 1278, 514, 400, 776, 1004, 468, 810, 536, 878, 0, 114, 308, 650, 274, 844},
+                {388, 480, 1164, 628, 514, 662, 890, 354, 696, 422, 764, 114, 0, 194, 536, 388, 730},
+                {354, 674, 1130, 822, 708, 628, 856, 320, 662, 388, 730, 308, 194, 0, 342, 422, 536},
+                {468, 1016, 788, 1164, 1050, 514, 514, 662, 320, 274, 388, 650, 536, 342, 0, 764, 194},
+                {776, 868, 1552, 560, 674, 1050, 1278, 742, 1084, 810, 1152, 274, 388, 422, 764, 0, 798},
+                {662, 1210, 754, 1358, 1244, 708, 480, 856, 514, 468, 354, 844, 730, 536, 194, 798, 0},
+        };*/
+
+    }
+
+}
\ No newline at end of file
diff --git a/server/system_service/src/main/java/com/doumee/core/utils/tsp/TspSolverSolutions.java b/server/system_service/src/main/java/com/doumee/core/utils/tsp/TspSolverSolutions.java
new file mode 100644
index 0000000..4e7f84b
--- /dev/null
+++ b/server/system_service/src/main/java/com/doumee/core/utils/tsp/TspSolverSolutions.java
@@ -0,0 +1,24 @@
+package com.doumee.core.utils.tsp;
+
+import com.doumee.core.constants.ResponseStatus;
+import com.doumee.core.exception.BusinessException;
+import com.google.ortools.Loader;
+import com.google.ortools.constraintsolver.*;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+@Slf4j
+@Data
+public class TspSolverSolutions {
+     private int lineIndex;
+     private List<Integer> routeIndex;
+     private long distance;
+
+
+
+}
\ No newline at end of file
diff --git a/server/visits/dmvisit_admin/pom.xml b/server/visits/dmvisit_admin/pom.xml
index ed28378..0bcd92a 100644
--- a/server/visits/dmvisit_admin/pom.xml
+++ b/server/visits/dmvisit_admin/pom.xml
@@ -20,6 +20,18 @@
             <groupId>com.doumee</groupId>
             <artifactId>dmvisit_service</artifactId>
             <version>1.0.0-SNAPSHOT</version>
+            <exclusions>
+                <exclusion>
+                    <groupId>com.google.protobuf</groupId>
+                    <artifactId>protobuf-java</artifactId>
+                </exclusion>
+            </exclusions>
+        </dependency>
+        <dependency>
+            <groupId>com.google.protobuf</groupId>
+            <artifactId>protobuf-java</artifactId>
+            <version>4.31.1</version>
+            <scope>compile</scope>
         </dependency>
     </dependencies>
     <build>
diff --git a/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/JkSketchCloudController.java b/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/JkSketchCloudController.java
index dae2c7b..34df5fa 100644
--- a/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/JkSketchCloudController.java
+++ b/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/JkSketchCloudController.java
@@ -66,7 +66,9 @@
     @PostMapping("/updateById")
     @CloudRequiredPermission("business:jksketch:update")
     public ApiResponse updateById(@RequestBody JkSketch jkSketch, @RequestHeader(Constants.HEADER_USER_TOKEN) String token) {
-        jkSketchService.updateById(jkSketch);
+        jkSketch.setLoginUserInfo(this.getLoginUser(token));
+        JkSketch model = jkSketchService.updateById(jkSketch);
+        jkSketchService.startUpdateLineAsync(model);//寮傛浼樺寲
         return ApiResponse.success(null);
     }
 
diff --git a/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/JkSketchCustomerCloudController.java b/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/JkSketchCustomerCloudController.java
index 1f145ab..3bfdf73 100644
--- a/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/JkSketchCustomerCloudController.java
+++ b/server/visits/dmvisit_admin/src/main/java/com/doumee/cloud/admin/JkSketchCustomerCloudController.java
@@ -75,6 +75,13 @@
         return ApiResponse.success(jkSketchCustomerService.findPage(pageWrap));
     }
 
+    @ApiOperation("鍒楄〃鏌ヨ")
+    @PostMapping("/allList")
+    @CloudRequiredPermission("business:jksketchcustomer:query")
+    public ApiResponse<List<JkSketchCustomer>> allList (@RequestBody JkSketchCustomer pageWrap) {
+        return ApiResponse.success(jkSketchCustomerService.findList(pageWrap));
+    }
+
     @ApiOperation("瀵煎嚭Excel")
     @PostMapping("/exportExcel")
     @CloudRequiredPermission("business:jksketchcustomer:exportExcel")
diff --git a/server/visits/dmvisit_service/pom.xml b/server/visits/dmvisit_service/pom.xml
index 7bacbec..6f4a7ca 100644
--- a/server/visits/dmvisit_service/pom.xml
+++ b/server/visits/dmvisit_service/pom.xml
@@ -21,7 +21,7 @@
             <groupId>com.doumee</groupId>
             <artifactId>system_service</artifactId>
             <version>1.0.0-SNAPSHOT</version>
-        </dependency>
+         </dependency>
         <dependency>
             <groupId>com.doumee</groupId>
             <artifactId>emaysms</artifactId>
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkLine.java b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkLine.java
index 2ac8109..e8fbc74 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkLine.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkLine.java
@@ -97,6 +97,9 @@
     @ExcelColumn(name="鎵�灞炰富绾胯矾",index = 2,width = 10)
     @TableField(exist = false)
     private String categoryName;
+    @ApiModelProperty(value = "鍙告満", example = "1")
+    @TableField(exist = false)
+    private String memberName;
 
 
 }
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkOrders.java b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkOrders.java
index 9a369f0..3a3f4ca 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkOrders.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkOrders.java
@@ -13,6 +13,8 @@
 
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 浜ゆ帶-閿�鍞鍗曚俊鎭〃
@@ -83,6 +85,9 @@
     @ApiModelProperty(value = "鍚岀彮缁勯棿瀹㈡埛浣嶇疆璺濈鏁扮粍锛孾{a:12,b:100},{a:13,b:200},...],a锛氬鎴风紪鐮侊紝b锛氫笌瀹㈡埛a涔嬮棿鐨勮窛绂�")
     //@ExcelColumn(name="鍚岀彮缁勯棿瀹㈡埛浣嶇疆璺濈鏁扮粍锛孾{a:12,b:100},{a:13,b:200},...],a锛氬鎴风紪鐮侊紝b锛氫笌瀹㈡埛a涔嬮棿鐨勮窛绂�")
     private String distances;
+    @ApiModelProperty(value = "鍚岀彮缁勯棿瀹㈡埛浣嶇疆璺濈鏁扮粍锛孾{a:12,b:100},{a:13,b:200},...],a锛氬鎴风紪鐮侊紝b锛氫笌瀹㈡埛a涔嬮棿鐨勮窛绂�")
+    @TableField(exist = false)
+    private List<Map<String,Object>> distanceList;
 
     @ApiModelProperty(value = "瀹㈡埛濮撳悕", example = "1")
     @ExcelColumn(name="瀹㈡埛濮撳悕",index = 2,width = 10)
@@ -104,5 +109,13 @@
     //@ExcelColumn(name="鎵�灞炰富绾胯矾",index = 2,width = 10)
     @TableField(exist = false)
     private Integer categoryId;
+    @ApiModelProperty(value = "缁忓害", example = "1")
+    //@ExcelColumn(name="缁忓害")
+    @TableField(exist = false)
+    private BigDecimal longitude;
 
+    @ApiModelProperty(value = "缁村害", example = "1")
+    //@ExcelColumn(name="缁村害")
+    @TableField(exist = false)
+    private BigDecimal latitude;
 }
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketch.java b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketch.java
index c0220a8..38b8f3e 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketch.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketch.java
@@ -13,6 +13,7 @@
 
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.List;
 
 /**
  * 浜ゆ帶-绾胯矾浼樺寲璁板綍淇℃伅琛�
@@ -64,6 +65,17 @@
     @ApiModelProperty(value = "鏈�鏂颁紭鍖栫嚎璺暟", example = "1")
     //@ExcelColumn(name="涓荤嚎璺紪鐮侊紙鍏宠仈category)")
     private Integer planLineNum;
+    @ApiModelProperty(value = "浼樺寲缁撴灉", example = "1")
+    //@ExcelColumn(name="涓荤嚎璺紪鐮侊紙鍏宠仈category)")
+    private String planLineInfo;
+    @ApiModelProperty(value = "浼樺寲鏃堕棿", example = "1")
+    //@ExcelColumn(name="涓荤嚎璺紪鐮侊紙鍏宠仈category)")
+    private Date planLineDate;
+    @ApiModelProperty(value = "浼樺寲缁撴潫鏃堕棿", example = "1")
+    private Date planLineEndDate;
+    @ApiModelProperty(value = "浼樺寲浜哄憳", example = "1")
+    //@ExcelColumn(name="涓荤嚎璺紪鐮侊紙鍏宠仈category)")
+    private Integer planLineUserId;
 
     @ApiModelProperty(value = "閫佽揣閲�", example = "1")
     @ExcelColumn(name="閫佽揣閲忥紙鏉★級",index = 4,width = 10)
@@ -73,8 +85,8 @@
     @ExcelColumn(name="瀹㈡埛鏁帮紙鎴凤級",index = 3,width = 7)
     private Integer orderNum;
 
-    @ApiModelProperty(value = "鐘舵�� 0鏈紭鍖� 1浼樺寲涓� 2宸蹭紭鍖�", example = "1")
-    @ExcelColumn(name="鐘舵��",index = 5,width = 10,valueMapping = "0=鏈紭鍖�;1=浼樺寲涓�;2=宸蹭紭鍖�;")
+    @ApiModelProperty(value = "鐘舵�� 0鏈紭鍖� 1浼樺寲涓� 2宸蹭紭鍖� 3浼樺寲澶辫触", example = "1")
+    @ExcelColumn(name="鐘舵��",index = 5,width = 10,valueMapping = "0=鏈紭鍖�;1=浼樺寲涓�;2=宸蹭紭鍖�;3=浼樺寲澶辫触;")
     private Integer status;
 
     @ApiModelProperty(value = "鎺掑簭鐮�", example = "1")
@@ -83,15 +95,31 @@
     @ApiModelProperty(value = "浼樺寲璁板綍缂栫爜(浣滀负key鍊煎瓨redis锛�", example = "1")
     //@ExcelColumn(name="鐝粍缂栫爜锛堝叧鑱攃ategory锛�")
     private String jobId;
+    @ApiModelProperty(value = "浼樺寲閲岀▼鏁帮紙绫筹級", example = "1")
+    private Long distance;
+    @ApiModelProperty(value = "鍘熷閲岀▼鏁帮紙绫筹級", example = "1")
+    private Long originDistance;
     @ApiModelProperty(value = "鏃ユ湡")
     @ExcelColumn(name="閫佽揣鏃ユ湡",index = 1,width = 10)
     @JsonFormat(pattern = "yyyy-MM-dd")
     private Date dateInfo;
 
-
     @ApiModelProperty(value = "鎵�灞炰富绾胯矾", example = "1")
     @ExcelColumn(name="涓荤嚎璺�",index = 2,width = 10)
     @TableField(exist = false)
     private String categoryName;
+    @ApiModelProperty(value = "鏄惁寮哄埗浼樺寲 0鍚� 1鏄�", example = "1")
+    @TableField(exist = false)
+    private Integer forceUpdate;
+
+    @ApiModelProperty(value = "绾胯矾瀹㈡埛璁㈠崟淇℃伅", example = "1")
+    @TableField(exist = false)
+    List<JkSketchCustomer> customerList;
+    @ApiModelProperty(value = "绾胯矾闆嗗悎", example = "1")
+    @TableField(exist = false)
+    List<JkLine> lineList;
+    @ApiModelProperty(value = "绾胯矾缂栫爜闆嗗悎", example = "1")
+    @TableField(exist = false)
+    List<Integer> lineIdList;
 
 }
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 b30a3f9..28f332c 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
@@ -13,6 +13,8 @@
 
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.List;
+import java.util.Map;
 
 /**
  * 浜ゆ帶-绾胯矾浼樺寲绾胯矾瀹㈡埛璁板綍淇℃伅琛�
@@ -104,4 +106,19 @@
     //@ExcelColumn(name="鎵�灞炰富绾胯矾",index = 2,width = 10)
     @TableField(exist = false)
     private Integer categoryId;
+    @ApiModelProperty(value = "缁忓害", example = "1")
+    //@ExcelColumn(name="缁忓害")
+    @TableField(exist = false)
+    private BigDecimal longitude;
+    @ApiModelProperty(value = "鎵�鍦ㄤ綅缃�")
+    @TableField(exist = false)
+    private String location;
+    @ApiModelProperty(value = "缁村害", example = "1")
+    //@ExcelColumn(name="缁村害")
+    @TableField(exist = false)
+    private BigDecimal latitude;
+
+    @ApiModelProperty(value = "鍚岀彮缁勯棿瀹㈡埛浣嶇疆璺濈鏁扮粍锛孾{a:12,b:100},{a:13,b:200},...],a锛氬鎴风紪鐮侊紝b锛氫笌瀹㈡埛a涔嬮棿鐨勮窛绂�")
+    @TableField(exist = false)
+    private List<Map<String,Object>> distanceList;
 }
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketchLine.java b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketchLine.java
index 3361816..b785c86 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketchLine.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/dao/business/model/JkSketchLine.java
@@ -13,6 +13,7 @@
 
 import java.math.BigDecimal;
 import java.util.Date;
+import java.util.List;
 
 /**
  * 浜ゆ帶-绾胯矾浼樺寲绾胯矾璁板綍淇℃伅琛�
@@ -58,6 +59,9 @@
     @ApiModelProperty(value = "绾胯矾缂栫爜锛堝叧鑱攋k_line)", example = "1")
     @ExcelColumn(name="绾胯矾缂栫爜锛堝叧鑱攋k_line)")
     private Integer lineId;
+    @ApiModelProperty(value = "璺▼鏁�", example = "1")
+    @ExcelColumn(name="璺▼鏁�")
+    private Long distance;
 
     @ApiModelProperty(value = "绾胯矾浼樺寲缂栫爜锛堝叧鑱攋k_sketch)", example = "1")
     @ExcelColumn(name="绾胯矾浼樺寲缂栫爜锛堝叧鑱攋k_sketch)")
@@ -96,5 +100,16 @@
     @ApiModelProperty(value = "鎵�灞炰富绾胯矾缂栫爜", example = "1")
     @TableField(exist = false)
     private Integer categoryId;
+    @ApiModelProperty(value = "瀹㈡埛鏄庣粏", example = "1")
+    @TableField(exist = false)
+    private List<JkSketchCustomer> customerList;
+
+    @ApiModelProperty(value = "鏈�澶у鎴烽噺", example = "1")
+    @TableField(exist = false)
+    private Integer maxCustomer;
+
+    @ApiModelProperty(value = "鏈�澶ц鍗曢噺", example = "1")
+    @TableField(exist = false)
+    private Integer maxOrder;
 
 }
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 eb399fc..5f7fe5d 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
@@ -49,7 +49,7 @@
      *
      * @param jkSketch 瀹炰綋瀵硅薄
      */
-    void updateById(JkSketch jkSketch);
+    JkSketch updateById(JkSketch jkSketch );
 
     /**
      * 鎵归噺涓婚敭鏇存柊
@@ -99,4 +99,6 @@
     long count(JkSketch jkSketch);
 
     List<JkSketch> importBatch(MultipartFile file, String dateInfo, LoginUserInfo loginUser);
+
+    void startUpdateLineAsync(JkSketch model);
 }
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkCustomerServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkCustomerServiceImpl.java
index a857bb0..7c580ce 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkCustomerServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkCustomerServiceImpl.java
@@ -271,6 +271,7 @@
                             );
                         }
                     }else{
+                        log.error("鏇存柊浜ゆ帶涓績瀹㈡埛缁忕含搴︿俊鎭�=====鑾峰彇json=========="+json);
                         log.error("鏇存柊浜ゆ帶涓績瀹㈡埛缁忕含搴︿俊鎭�=====鑾峰彇澶辫触=========="+c.getName()+"-"+c.getLocation());
                     }
                 }catch (Exception e){
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkLineServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkLineServiceImpl.java
index 21ef83c..1b1f6cb 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkLineServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkLineServiceImpl.java
@@ -147,10 +147,32 @@
 
     @Override
     public List<JkLine> findList(JkLine jkLine) {
+
+        MPJLambdaWrapper<JkLine> queryWrapper = new MPJLambdaWrapper<>();
         jkLine.setIsdeleted(Constants.ZERO);
-        QueryWrapper<JkLine> wrapper = new QueryWrapper<>(jkLine);
-        wrapper.lambda().orderByAsc(JkLine::getCode);
-        return jkLineMapper.selectList(wrapper);
+        queryWrapper.selectAll(JkLine.class )
+                .selectAs(Member::getName,JkLine::getMemberName)
+                .selectAs(Cars::getCode,JkLine::getCarCode)
+                .leftJoin(Cars.class,Cars::getId,JkLine::getCarId )
+                .leftJoin(Member.class,Member::getId,Cars::getMemberId );
+        jkLine.setIsdeleted(Constants.ZERO);
+        if (jkLine.getIsdeleted() != null) {
+            queryWrapper.eq(JkLine::getIsdeleted, jkLine.getIsdeleted());
+        }
+        if (jkLine.getCategoryId() != null) {
+            queryWrapper.eq(JkLine::getCategoryId, jkLine.getCategoryId());
+        }
+        if (jkLine.getCarId() != null) {
+            queryWrapper.eq(JkLine::getCarId, jkLine.getCarId());
+        }
+        if (jkLine.getStatus() != null) {
+            queryWrapper.eq(JkLine::getStatus, jkLine.getStatus());
+        }
+        if (jkLine.getSortnum() != null) {
+            queryWrapper.eq(JkLine::getSortnum, jkLine.getSortnum());
+        }
+        queryWrapper.orderByAsc(JkLine::getCode);
+        return jkLineMapper.selectJoinList(JkLine.class,queryWrapper);
     }
   
     @Override
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 dd415bf..467a4b4 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
@@ -84,8 +84,58 @@
 
     @Override
     public List<JkSketchCustomer> findList(JkSketchCustomer jkSketchCustomer) {
-        QueryWrapper<JkSketchCustomer> wrapper = new QueryWrapper<>(jkSketchCustomer);
-        return jkSketchCustomerMapper.selectList(wrapper);
+        MPJLambdaWrapper<JkSketchCustomer> queryWrapper = new MPJLambdaWrapper<>();
+        jkSketchCustomer.setIsdeleted(Constants.ZERO);
+        queryWrapper.selectAll(JkSketchCustomer.class )
+                .selectAs(JkCustomer::getName,JkSketchCustomer::getName)
+                .selectAs(JkCustomer::getCode,JkSketchCustomer::getCode)
+                .selectAs(JkCustomer::getLatitude,JkSketchCustomer::getLatitude)
+                .selectAs(JkCustomer::getLongitude,JkSketchCustomer::getLongitude)
+                .selectAs(JkCustomer::getLocation,JkSketchCustomer::getLocation)
+                .leftJoin(JkCustomer.class,JkCustomer::getId,JkSketchCustomer::getCustomerId ) ;
+        queryWrapper.like(jkSketchCustomer.getCode()!=null,JkCustomer::getCode,jkSketchCustomer.getCode());
+        queryWrapper.like(jkSketchCustomer.getName()!=null,JkCustomer::getName,jkSketchCustomer.getName());
+        if (jkSketchCustomer.getId() != null) {
+            queryWrapper.eq(JkSketchCustomer::getId,jkSketchCustomer.getId());
+        }
+        if (jkSketchCustomer.getCreator() != null) {
+            queryWrapper.eq(JkSketchCustomer::getCreator,jkSketchCustomer.getCreator());
+        }
+        if (jkSketchCustomer.getCreateDate() != null) {
+            queryWrapper.ge(JkSketchCustomer::getCreateDate, Utils.Date.getStart(jkSketchCustomer.getCreateDate()));
+            queryWrapper.le(JkSketchCustomer::getCreateDate, Utils.Date.getEnd(jkSketchCustomer.getCreateDate()));
+        }
+        if (jkSketchCustomer.getEditor() != null) {
+            queryWrapper.eq(JkSketchCustomer::getEditor,jkSketchCustomer.getEditor());
+        }
+        if (jkSketchCustomer.getEditDate() != null) {
+            queryWrapper.ge(JkSketchCustomer::getEditDate, Utils.Date.getStart(jkSketchCustomer.getEditDate()));
+            queryWrapper.le(JkSketchCustomer::getEditDate, Utils.Date.getEnd(jkSketchCustomer.getEditDate()));
+        }
+        if (jkSketchCustomer.getIsdeleted() != null) {
+            queryWrapper.eq(JkSketchCustomer::getIsdeleted,jkSketchCustomer.getIsdeleted());
+        }
+        if (jkSketchCustomer.getInfo() != null) {
+            queryWrapper.eq(JkSketchCustomer::getInfo,jkSketchCustomer.getInfo());
+        }
+        if (jkSketchCustomer.getSketchLineId() != null) {
+            queryWrapper.eq(JkSketchCustomer::getSketchLineId,jkSketchCustomer.getSketchLineId());
+        }
+        if (jkSketchCustomer.getSketchId() != null) {
+            queryWrapper.eq(JkSketchCustomer::getSketchId,jkSketchCustomer.getSketchId());
+        }
+        if (jkSketchCustomer.getTotalNum() != null) {
+            queryWrapper.eq(JkSketchCustomer::getTotalNum,jkSketchCustomer.getTotalNum());
+        }
+        if (jkSketchCustomer.getOrderId() != null) {
+            queryWrapper.eq(JkSketchCustomer::getOrderId,jkSketchCustomer.getOrderId());
+        }
+        if (jkSketchCustomer.getSortnum() != null) {
+            queryWrapper.eq(JkSketchCustomer::getSortnum,jkSketchCustomer.getSortnum());
+        }
+
+        queryWrapper.orderByAsc(JkSketchCustomer::getSketchLineId,JkSketchCustomer::getSortnum);
+       return   jkSketchCustomerMapper.selectJoinList(JkSketchCustomer.class,queryWrapper);
     }
   
     @Override
@@ -102,10 +152,13 @@
                 .selectAs(Category::getName,JkSketchCustomer::getCategoryName)
                 .leftJoin(JkOrders.class,JkOrders::getId,JkSketchCustomer::getOrderId )
                 .leftJoin(JkCustomer.class,JkCustomer::getId,JkSketchCustomer::getCustomerId )
-                .leftJoin(JkLine.class,JkLine::getId,JkOrders::getLineId )
+                .leftJoin(JkSketchLine.class,JkSketchLine::getId,JkSketchCustomer::getSketchLineId )
+                .leftJoin(JkLine.class,JkLine::getId,JkSketchLine::getLineId )
                 .leftJoin(Category.class,Category::getId,JkLine::getCategoryId );
         queryWrapper.eq( pageWrap.getModel().getCategoryId()!=null,JkLine::getCategoryId, pageWrap.getModel().getCategoryId());
         queryWrapper.eq( pageWrap.getModel().getDateInfo()!=null,JkSketchCustomer::getDateInfo, pageWrap.getModel().getDateInfo());
+        queryWrapper.like( pageWrap.getModel().getCode()!=null,JkCustomer::getCode, pageWrap.getModel().getCode());
+        queryWrapper.like( pageWrap.getModel().getName()!=null,JkCustomer::getName, pageWrap.getModel().getName());
 
         if (pageWrap.getModel().getId() != null) {
             queryWrapper.eq(JkSketchCustomer::getId, pageWrap.getModel().getId());
@@ -146,7 +199,7 @@
             queryWrapper.eq(JkSketchCustomer::getSortnum, pageWrap.getModel().getSortnum());
         }
 
-        queryWrapper.orderByAsc(JkSketchCustomer::getSketchLineId);
+        queryWrapper.orderByAsc(JkSketchCustomer::getSketchLineId,JkSketchCustomer::getSortnum);
         IPage<JkSketchCustomer> result = jkSketchCustomerMapper.selectJoinPage(page, JkSketchCustomer.class,queryWrapper);
         return PageData.from(result);
     }
diff --git a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchLineServiceImpl.java b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchLineServiceImpl.java
index 2aa3ea3..b0cb3b6 100644
--- a/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchLineServiceImpl.java
+++ b/server/visits/dmvisit_service/src/main/java/com/doumee/service/business/impl/JkSketchLineServiceImpl.java
@@ -89,12 +89,15 @@
                 .selectAs(JkLine::getName,JkSketchLine::getLineName)
                 .selectAs(Category::getId,JkSketchLine::getCategoryId)
                 .selectAs(Category::getName,JkSketchLine::getCategoryName)
+                .selectAs(JkLine::getMaxOrder,JkSketchLine::getMaxOrder)
+                .selectAs(JkLine::getMaxCustomer,JkSketchLine::getMaxCustomer)
                 .leftJoin(JkLine.class,JkLine::getId,JkOrders::getLineId )
                 .leftJoin(Cars.class,Cars::getId,JkLine::getCarId )
                 .leftJoin(Member.class,Member::getId,Cars::getMemberId )
                 .leftJoin(Category.class,Category::getId,JkLine::getCategoryId );
         wrapper.eq( jkSketchLine.getSketchId()!=null,JkSketchLine::getSketchId, jkSketchLine.getSketchId())
-                .eq(  JkSketchLine::getIsdeleted,Constants.ZERO);
+                .eq(  JkSketchLine::getIsdeleted,Constants.ZERO)
+                .orderByAsc(JkLine::getSortnum );
 
         return jkSketchLineMapper.selectJoinList(JkSketchLine.class,wrapper);
     }
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 d3c1ca2..cf6ef90 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
@@ -4,16 +4,15 @@
 import com.doumee.core.annotation.excel.ExcelImporter;
 import com.doumee.core.constants.ResponseStatus;
 import com.doumee.core.exception.BusinessException;
-import com.doumee.core.utils.Constants;
-import com.doumee.core.utils.DateUtil;
-import com.doumee.dao.admin.request.JkCustomerImport;
+import com.doumee.core.utils.*;
+import com.doumee.core.utils.tsp.TspSolver;
+import com.doumee.core.utils.tsp.TspSolverSolutions;
 import com.doumee.dao.admin.request.JkOrdersImport;
 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.Utils;
 import com.doumee.service.business.JkSketchService;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
 import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
@@ -21,17 +20,18 @@
 import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
 import com.github.yulichang.wrapper.MPJLambdaWrapper;
 import org.apache.commons.lang3.StringUtils;
+import org.checkerframework.checker.units.qual.C;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.scheduling.annotation.Async;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 import org.springframework.util.CollectionUtils;
 import org.springframework.web.multipart.MultipartFile;
 
 import java.math.BigDecimal;
-import java.util.ArrayList;
+import java.util.*;
 import java.util.Date;
-import java.util.List;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -85,10 +85,301 @@
         }
         jkSketchMapper.deleteBatchIds(ids);
     }
+    //绾胯矾浼樺寲
+    @Override
+    public JkSketch updateById(JkSketch jkSketch ) {
+        JkSketch model = jkSketchMapper.selectById(jkSketch.getId());
+        if(model == null ||Constants.equalsInteger(model.getIsdeleted(),Constants.ONE)){
+            throw  new BusinessException(ResponseStatus.DATA_EMPTY);
+        }
+        if( model.getDateInfo() ==  null){
+            throw  new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"璇ョ嚎璺棩鏈熶俊鎭笉姝g‘锛屼笉鏀寔浼樺寲锛�");
+        }
+       if(Constants.equalsInteger(Constants.ZERO,jkSketch.getForceUpdate()) && Constants.equalsInteger(model.getStatus(),Constants.ONE)){
+            throw  new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"璇ョ嚎璺瓨鍦ㄦ鍦ㄤ紭鍖栦腑锛岃鑰愬績绛夊緟浼樺寲瀹屾垚鎴栬�呴�夋嫨寮哄埗浼樺寲鎿嶄綔锛�");
+        }
+
+         if(  jkSketch.getLineIdList() ==null || jkSketch.getLineIdList().size()==0 ){
+            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"璇烽�夋嫨鏈夋晥鍚堢悊鐨勭嚎璺繘琛屼紭鍖栨搷浣滐紒");
+        }
+        //褰撳墠鎵�鏈夌嚎璺�(绗﹀悎鏉′欢鐨勭嚎璺級
+        List<JkLine> lineList =  jkLineMapper.selectJoinList(JkLine.class,new MPJLambdaWrapper<JkLine>()
+                .selectAll(JkLine.class)
+                .eq(JkLine::getWeeks,DateUtil.getWeekZhouOfDate(model.getDateInfo()))//鍙兘閫夋嫨褰撳墠鐨勭嚎璺�
+                .eq(JkLine::getIsdeleted,Constants.ZERO)
+                .in(JkLine::getId,jkSketch.getLineIdList())
+        );
+        Integer totalCus = 0,totalNum =0;
+        for(JkLine line :lineList){
+            totalCus += Constants.formatIntegerNum(line.getMaxCustomer());//鎬诲鎴烽噺
+            totalNum += Constants.formatIntegerNum(line.getMaxOrder());//鎬婚�佽揣閲�
+        }
+
+        if( totalCus < Constants.formatIntegerNum(model.getOrderNum())  ){
+            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"璇ョ嚎璺鍗曞鎴锋暟閲忚秴杩囦簡绾胯矾鎬诲鎴烽噺闄愬埗锛屾棤娉曡繘琛屼紭鍖栵紒");
+        }
+        if( totalNum < Constants.formatBigdecimal(model.getTotalNum()).doubleValue()){
+            throw  new BusinessException(ResponseStatus.BAD_REQUEST.getCode(),"璇ョ嚎璺鍗曢�佽揣閲忚秴杩囦簡绾胯矾鎬婚�佽揣閲忛檺鍒讹紝鏃犳硶杩涜浼樺寲锛�");
+        }
+        model.setLineList(lineList);//绾胯矾闆嗗悎
+        model.setCustomerList(checkJketchCustomerLocation(model));//璁㈠崟闆嗗悎
+        model.setStatus(Constants.ONE);
+        model.setPlanLineNum(lineList.size());
+        model.setEditDate(new Date());
+        model.setEditor(jkSketch.getLoginUserInfo().getId());
+        model.setPlanLineDate(model.getEditDate());
+        model.setPlanLineUserId(jkSketch.getLoginUserInfo().getId());
+        model.setJobId(UUID.randomUUID().toString());
+        redisTemplate.opsForValue().set(Constants.RedisKeys.JKLINE_JOB+model.getJobId(),true );//鍋氬紓姝ュ鐞�
+        jkSketchMapper.updateById(model);
+        return model;
+    }
 
     @Override
-    public void updateById(JkSketch jkSketch) {
-        jkSketchMapper.updateById(jkSketch);
+    @Async
+    public void startUpdateLineAsync(JkSketch model) {
+        try {
+            List<JkSketchCustomer> customerList = model.getCustomerList();
+            List<JkLine> lineList = model.getLineList();
+            TspSolver.DataModel dataModel = new TspSolver.DataModel();
+            int vehicleNumber1 = lineList.size();//绾胯矾鏁伴噺
+            long[] vehicleCapacities1=new long[lineList.size()];//姣忚締杞︾殑鏈�澶ц鍗曢噺闄愬埗
+            long[] demands1 = new long[customerList.size()+1]; //鍚勪釜鐐圭殑璁㈠崟閲�
+            long[][] distanceMatrix1 = new long[customerList.size()+1][customerList.size()+1];
+            demands1[0] =0;//鍘熺偣
+            double cLatitude =0;
+            double cLongitude =0;
+            String location = systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.COMPANY_LOCATION).getCode();
+            try {
+                String[] ss = location.split(",");
+                cLongitude = Double.parseDouble(ss[0]);
+                cLatitude = Double.parseDouble(ss[1]);
+            }catch (Exception e){
+
+            }
+
+            for (int i = 0; i < customerList.size(); i++) {
+                distanceMatrix1[0][i] =  DistanceCalculator.calculateDistance(cLatitude,cLongitude,customerList.get(i).getLatitude().doubleValue(),customerList.get(i).getLongitude().doubleValue())/1000;
+                distanceMatrix1[i][0] = distanceMatrix1[0][i];
+                demands1[i+1] = Constants.formatBigdecimal( customerList.get(i).getTotalNum()).longValue();  //鍚勪釜鐐圭殑璁㈠崟閲�
+                List<Map<String,Object>> disList = customerList.get(i).getDistanceList();
+                for (int j = 0; j< disList.size(); j++) {
+                    if(disList.size()>j){
+                        distanceMatrix1[i+1][j+1]  = (Long) disList.get(j).get("b")/1000;//鏋勯�犺窛绂荤煩闃�
+                    }else{
+                        distanceMatrix1[i+1][j+1]  = 1l;
+                    }
+                }
+            }
+            for (int i = 0; i < lineList.size(); i++) {
+                vehicleCapacities1[i] = lineList.get(i).getMaxOrder();//姣忚締杞︾殑鏈�澶ц鍗曢噺闄愬埗
+            }
+            //鏋勯�犱紭鍖栨暟鎹ā鍨�
+            dataModel.initDataInfo(vehicleNumber1,demands1,vehicleCapacities1,distanceMatrix1);
+            TspSolver.startSearch(dataModel);
+            dealSearchSolution(model,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,"鏈�杩戜竴娆$嚎璺紭鍖栧け璐ワ紒")
+                    .set(JkSketch::getStatus,Constants.THREE)
+                    .set(JkSketch::getPlanLineEndDate,new Date()));
+        }
+
+    }
+
+    private void dealSearchSolution(JkSketch model, 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();
+                if(routes.size() <=2) {
+                    continue;//鏃犲鎴风殑闈炴湁鏁堣矾绾�
+                }
+                totalDistance+= so.getDistance();
+                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.setOrderNum(routes.size()-2);
+                tModel.setDateInfo(model.getDateInfo());
+                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 || cIndex == routes.size()-1){
+                        continue; //璧峰鐐逛笉澶勭悊
+                    }
+                    JkSketchCustomer customer = model.getCustomerList().get(cIndex-1);
+                    tModel.setTotalNum(tModel.getTotalNum().add(Constants.formatBigdecimal(customer.getTotalNum())));//閫佽揣閲�
+                    JkSketchCustomer cModel =  new JkSketchCustomer();
+                    cModel.setCreator(tModel.getCreator());
+                    cModel.setOrderId(customer.getOrderId());
+                    cModel.setCreateDate(tModel.getCreateDate());
+                    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());
+                    tModel.getCustomerList().add(cModel);
+                    if(cIndex ==0 || cIndex == routes.size()-1){
+                        continue; //璧峰鐐逛笉澶勭悊
+                    }
+                }
+            }
+        }
+        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::getDateInfo,model.getDateInfo()));
+            jkSketchCustomerMapper.update(null,new UpdateWrapper<JkSketchCustomer>().lambda()
+                    .set(JkSketchCustomer::getIsdeleted,Constants.ONE)
+                    .eq(JkSketchCustomer::getIsdeleted,Constants.ZERO)
+                    .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::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   List<JkSketchCustomer>  checkJketchCustomerLocation(JkSketch model) {
+
+        MPJLambdaWrapper<JkSketchCustomer> queryWrapper = new MPJLambdaWrapper<>();
+        queryWrapper.selectAll(JkSketchCustomer.class )
+                .selectAs(JkCustomer::getName,JkSketchCustomer::getName)
+                .selectAs(JkCustomer::getCode,JkSketchCustomer::getCode)
+                .selectAs(JkCustomer::getLongitude,JkSketchCustomer::getLongitude)
+                .selectAs(JkCustomer::getLatitude,JkSketchCustomer::getLatitude)
+                .leftJoin(JkCustomer.class,JkCustomer::getId,JkSketchCustomer::getCustomerId )
+                .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(),"璇ョ嚎璺鎴蜂俊鎭负绌猴紝涓嶆弧瓒充紭鍖栨潯浠讹紒");
+        }
+        String errorMsg ="";
+        for(JkSketchCustomer c : customerList){
+            if(c.getLatitude()==null || c.getLongitude() ==null){
+                errorMsg += c.getName()+"-"+c.getName()+"锛�";
+            }
+        }
+        if(StringUtils.isNotBlank(errorMsg)){
+            throw  new BusinessException(ResponseStatus.NOT_ALLOWED.getCode(),"璇ョ嚎璺鎴�:"+errorMsg+"瀹氫綅淇℃伅涓嶅畬鏁达紝涓嶆弧瓒充紭鍖栨潯浠讹紒");
+        }
+        for(JkSketchCustomer c : customerList){
+            List<Map<String,Object>> tmpList = new ArrayList<>();
+            for(JkSketchCustomer cm : customerList){
+                Map<String,Object> t = new HashMap<>();
+                t.put("a",cm.getId());
+                if(Constants.equalsInteger(c.getCustomerId(),cm.getCustomerId())){
+                    t.put("b",0l);
+                }else{
+                    t.put("b", DistanceCalculator.calculateDistance(
+                            Constants.formatBigdecimal(c.getLatitude()).doubleValue(),
+                            Constants.formatBigdecimal(c.getLatitude()).doubleValue(),
+                            Constants.formatBigdecimal(cm.getLatitude()).doubleValue(),
+                            Constants.formatBigdecimal(cm.getLongitude()).doubleValue()));
+                }
+                tmpList.add(t);
+            }
+            c.setDistanceList(tmpList);
+        }
+
+        if(Constants.equalsInteger(Constants.ZERO,model.getStatus())){
+            //濡傛灉鏄湭浼樺寲鐘舵�侊紝璁$畻鍘熷璺濈
+            long totalDistance = 0;
+            MPJLambdaWrapper<JkSketchLine> queryWrapper1 = new MPJLambdaWrapper<>();
+            queryWrapper1.selectAll(JkSketchLine.class )
+                    .eq(JkSketchLine::getSketchId, model.getId())
+                    .eq(JkSketchLine::getIsdeleted,Constants.ZERO);
+            List<JkSketchLine> lineList = jkSketchLineMapper.selectJoinList(JkSketchLine.class,queryWrapper1);//
+            if(lineList!=null ||lineList.size()>0){
+                double cLatitude =0;
+                double cLongitude =0;
+                String location = systemDictDataBiz.queryByCode(Constants.SYSTEM,Constants.COMPANY_LOCATION).getCode();
+                try {
+                    String[] ss = location.split(",");
+                    cLongitude = Double.parseDouble(ss[0]);
+                    cLatitude = Double.parseDouble(ss[1]);
+                }catch (Exception e){
+
+                }
+                for(JkSketchLine line : lineList){
+                    boolean isFirst =true;
+                    JkSketchCustomer last = null;
+                    for(JkSketchCustomer c : customerList){
+                        if(Constants.equalsInteger(c.getSketchLineId(),line.getId())){
+                            if(isFirst){
+                                totalDistance += DistanceCalculator.calculateDistance(cLatitude,cLongitude
+                                        ,Constants.formatBigdecimal(c.getLatitude()).doubleValue()
+                                        ,Constants.formatBigdecimal(c.getLongitude()).doubleValue());
+                            }else{
+                                totalDistance += DistanceCalculator.calculateDistance(Constants.formatBigdecimal(c.getLatitude()).doubleValue()
+                                        ,Constants.formatBigdecimal(c.getLongitude()).doubleValue()
+                                        ,Constants.formatBigdecimal(last.getLatitude()).doubleValue()
+                                        ,Constants.formatBigdecimal(last.getLongitude()).doubleValue());
+                            }
+                            last = c;
+                            isFirst=false;
+                        }
+                        if(last!=null){
+                            totalDistance += DistanceCalculator.calculateDistance(cLatitude,cLongitude
+                                    ,Constants.formatBigdecimal(last.getLatitude()).doubleValue()
+                                    ,Constants.formatBigdecimal(last.getLongitude()).doubleValue());
+                        }
+                    }
+                }
+
+            }
+            model.setOriginDistance(totalDistance);
+        }
+
+        return customerList;
     }
 
     @Override
@@ -185,6 +476,7 @@
         return jkSketchMapper.selectCount(wrapper);
     }
 
+
     @Override
     @Transactional(rollbackFor = {Exception.class,BusinessException.class})
     public List<JkSketch> importBatch(MultipartFile file, String dateInfoStr, LoginUserInfo loginUser){
@@ -216,9 +508,11 @@
                     .selectAll(JkCustomer.class)
                     .eq(JkCustomer::getIsdeleted,Constants.ZERO)
             );
+            String week =  DateUtil.getWeekZhouOfDate(dateInfo);
             //褰撳墠鎵�鏈夌嚎璺�
             List<JkLine> lineList =  jkLineMapper.selectJoinList(JkLine.class,new MPJLambdaWrapper<JkLine>()
                     .selectAll(JkLine.class)
+                    .eq(JkLine::getWeeks,week)//鍙兘閫夋嫨褰撳墠鐨勭嚎璺�
                     .eq(JkLine::getIsdeleted,Constants.ZERO)
             );
             List<JkOrders> newOrderList = new ArrayList<>();
@@ -256,7 +550,7 @@
                 jkOrdersMapper.insert(newOrderList);
             }
 
-            List<JkSketchLine> sketchLineList = initNewSketchLineList(newList,newOrderList);
+            List<JkSketchLine> sketchLineList = initNewSketchLineList(newList,newOrderList,lineList);
             jkSketchLineMapper.update(null,new UpdateWrapper<JkSketchLine>().lambda()
                     .set(JkSketchLine::getIsdeleted,Constants.ONE)
                     .eq(JkSketchLine::getIsdeleted,Constants.ZERO)
@@ -285,6 +579,8 @@
 
     }
 
+
+
     private List<JkSketchCustomer> initNewSketchCustomerList(List<JkSketchLine> sketchLineList, List<JkOrders> newOrderList) {
         List<JkSketchCustomer> list =new ArrayList<>();
         for(JkOrders orders : newOrderList){
@@ -308,9 +604,25 @@
         }
         return list;
     }
-    private List<JkSketchLine> initNewSketchLineList(List<JkSketch> newList, List<JkOrders> newOrderList) {
+    private List<JkSketchLine> initNewSketchLineList(List<JkSketch> newList, List<JkOrders> newOrderList,List<JkLine> lineList) {
         List<JkSketchLine> list =new ArrayList<>();
-        for(JkOrders orders : newOrderList){
+        for (JkLine line : lineList){
+            JkSketchLine tModel =  new JkSketchLine();
+            tModel.setSketchId(getSKetchIdByyCategoryId(line.getCategoryId(),newList));
+            tModel.setCreator(newList.get(0).getCreator());
+            tModel.setCreateDate(newList.get(0).getCreateDate());
+            tModel.setLineId(line.getId());
+            initOrderAndTotalNum(tModel,line.getId(),newOrderList);
+            tModel.setDateInfo(newList.get(0).getDateInfo());
+            tModel.setSortnum(list.size()+1);
+            tModel.setEditDate(tModel.getCreateDate());
+            tModel.setEditor(tModel.getCreator());
+            tModel.setIsdeleted(Constants.ZERO);
+            if(tModel.getSketchId()!=null && Constants.formatIntegerNum(tModel.getOrderNum()) >0){
+                list.add(tModel);
+            }
+        }
+        /*for(JkOrders orders : newOrderList){
             JkSketchLine tModel = findModelFromListByLineId(orders.getLineId(),list);
             if(tModel!=null){
                 tModel.setTotalNum(  tModel.getTotalNum().add(orders.getNum()));//璁㈠崟閲忕疮璁�
@@ -332,8 +644,17 @@
                     list.add(tModel);
                 }
             }
-        }
+        }*/
         return list;
+    }
+
+    private void initOrderAndTotalNum(JkSketchLine tModel, Integer id, List<JkOrders> newOrderList) {
+        for(JkOrders orders : newOrderList){
+            if(Constants.equalsInteger(orders.getLineId(),id)){
+                tModel.setOrderNum(Constants.formatIntegerNum(tModel.getOrderNum())+1);
+                tModel.setTotalNum(Constants.formatBigdecimal(tModel.getTotalNum()).add(Constants.formatBigdecimal(orders.getNum())));
+            }
+        }
     }
 
     private Integer getSKetchIdByyCategoryId(Integer categoryId, List<JkSketch> newList) {
@@ -430,7 +751,7 @@
         }
         JkLine line = findLineFromListByName(model.getLineName(),lineList);
         if(line == null){
-            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "瀵逛笉璧凤紝绗�" + (index + 3) + "琛岀嚎璺��" + model.getLineName() + "銆戜笉瀛樺湪锛岃妫�鏌ヨ〃鏍煎唴瀹癸紒");
+            throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "瀵逛笉璧凤紝绗�" + (index + 3) + "琛岀嚎璺��" + model.getLineName() + "銆戜笉瀛樺湪鎴栬�呴厤閫佸懆鏈熶笉绗﹀悎锛岃妫�鏌ヨ〃鏍煎唴瀹癸紒");
         }
 
         JkOrders tModel =   new JkOrders();
@@ -441,6 +762,8 @@
         tModel.setNum(getDecimalByVal(model.getNum()));
         tModel.setCustomerId(customer.getId());
         tModel.setDateInfo(dateInfo);
+        tModel.setLatitude(customer.getLatitude());
+        tModel.setLongitude(customer.getLongitude());
         tModel.setSortnum(model.getSortnum());
         tModel.setLineId(line.getId());
         tModel.setCategoryId(line.getCategoryId());

--
Gitblit v1.9.3