From 89fd2cf7202c321512c2ea699a3a220a7138ed44 Mon Sep 17 00:00:00 2001
From: wujianwei <wjw@11.com>
Date: 星期四, 09 四月 2026 10:40:52 +0800
Subject: [PATCH] Merge remote-tracking branch 'origin/cwxt_master' into cwxt_master

---
 ui/admin-ui3/src/views/tms/tmsQuoteDetail/index.vue |  584 +++++++++++++++++++++++++++++++++++++++++-----------------
 1 files changed, 413 insertions(+), 171 deletions(-)

diff --git a/ui/admin-ui3/src/views/tms/tmsQuoteDetail/index.vue b/ui/admin-ui3/src/views/tms/tmsQuoteDetail/index.vue
index b352e65..dc24091 100644
--- a/ui/admin-ui3/src/views/tms/tmsQuoteDetail/index.vue
+++ b/ui/admin-ui3/src/views/tms/tmsQuoteDetail/index.vue
@@ -44,8 +44,41 @@
             v-hasPermi="['tms:tmsQuoteDetail:export']"
         >瀵煎嚭
         </el-button>
+        <el-button
+            type="default"
+            plain
+            icon="Back"
+            @click="handleBack"
+        >杩斿洖
+        </el-button>
       </template>
-    </avue-crud>
+
+      <template #items-form="scope">
+        <avue-crud
+            :option="{...itemsTableOption,selection: !scope.disabled}"          @selection-change="selectionChange2"
+
+            :data="form.items" ref="itemsCrudRef"
+        >
+          <template #freightPrice="{row}">
+            <el-input v-model="row.freightPrice" :min="1" :disabled="scope.disabled || !rowKeys.includes(row.rowKey)" type="number" placeholder="璇疯緭鍏ラ噾棰�"></el-input>
+          </template>
+          <template #currency="{row}">
+            <el-radio-group v-model="row.currency"  :disabled="scope.disabled || !rowKeys.includes(row.rowKey)">
+              <el-radio
+                  v-for="dict in sys_currency"
+                  :key="dict.value"
+                  :label="dict.value"
+              >{{ dict.label }}</el-radio>
+            </el-radio-group>
+          </template>
+          <template #taxRate="{row}">
+            <el-input v-model="row.taxRate" :disabled="scope.disabled || !rowKeys.includes(row.rowKey)" type="number" placeholder="璇疯緭鍏ョ◣鐐�%"></el-input>
+          </template>
+        </avue-crud>
+      </template>
+
+
+        </avue-crud>
   </basicContainer>
 </template>
 
@@ -65,10 +98,14 @@
 import {usePagePlus} from "@/hooks/usePagePlus";
 import {hasPermission} from "@/utils/permissionUtils";
 import {getTmsServiceProvider, listTmsServiceProvider} from "@/api/tms/tmsServiceProvider";
+import {getArea, getCity, getProvince, getStreet} from "@/api/tms/tmsRegion";
+import {useRoute,useRouter } from "vue-router";
+import {randomId} from "@smallwei/avue";
 
 const {proxy} = useCurrentInstance();
 const crudRef = ref();
-
+const route = useRoute();
+const router  = useRouter();
 const permissionList = computed(() => {
   return {
     addBtn: hasPermission(["tms:tmsQuoteDetail:add"]),
@@ -77,7 +114,8 @@
     viewBtn: hasPermission(["tms:tmsQuoteDetail:query"]),
   }
 })
-
+const {vehicle_type,sys_currency} =
+    proxy.useDict("vehicle_type","sys_currency");
 const data = reactive({
   form: <TmsQuoteDetailI>{},
   queryParams: <TmsQuoteDetailI & PageQueryInterface>{},
@@ -87,8 +125,9 @@
     currentPage: 1,
   },
   selectionList: [],
+  selectionList2: [],
 })
-const {queryParams, form, page, selectionList} = toRefs(data);
+const {queryParams, form, page, selectionList,selectionList2} = toRefs(data);
 const option = ref({
   pageKey: 'TmsQuoteDetail',
   rowKey: 'id',
@@ -101,7 +140,7 @@
         systemCode: {
           label: '绯荤粺缂栧彿',
           addDisplay: false,
-          editDisplay: true, disabled: true,
+          editDisplay: false,
           viewDisplay: true,
         },
         quotePlanCode: {
@@ -110,99 +149,99 @@
           editDisplay: false,
           viewDisplay: true,
         },
-        vehicleProviderId: {
-          label: '杞﹁締鏈嶅姟鍟�',
-          display: true,
-          editDisplay: true,row:true,
-          viewDisplay: true,
-          hide: false,
-          search: true,
-          rules: [
-            {
-              required: true,
-              message: "杞﹁締鏈嶅姟鍟嗕笉鑳戒负绌�", trigger: "change"
-            }
-          ],
-          type: 'table', suffixIcon: 'search',
-          children: {
-            border: true,
-            searchLabelWidth: 100,
-            searchMenuSpan: 5,
-            column: {
-              serviceCode: {
-                label: '鏈嶅姟鍟嗙紪鐮�', minWidth: 130,
-                search: true,
-              },
-              serviceShortName: {
-                label: '鏈嶅姟鍟嗙畝绉�', minWidth: 120,
-                search: true,
-              },
-              serviceType: {
-                label: '鏈嶅姟绫诲瀷', multiple: true,
-                type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/service_type',
-                minWidth: 150,
-              },
-              isTransport: {
-                label: '鏄惁杩愯緭鏈嶅姟鍟�',
-                type: 'radio', dataType: 'string', dicUrl: '/system/dict/data/type/sys_number_is',
-                minWidth: 150,
-              },
-              isStorage: {
-                label: '鏄惁浠撳偍鏈嶅姟鍟�',
-                type: 'radio', dataType: 'string', dicUrl: '/system/dict/data/type/sys_number_is',
-                minWidth: 150,
-              },
-              isExpress: {
-                label: '鏄惁蹇�掓湇鍔″晢',
-                type: 'radio', dataType: 'string', dicUrl: '/system/dict/data/type/sys_number_is',
-                minWidth: 150,
-              },
-              contactName: {
-                label: '鑱旂郴浜哄鍚�', minWidth: 120,
-              },
-            },
-
-          },
-          props: {
-            label: 'serviceShortName',
-            value: 'id'
-          },
-          onLoad: ({page, value, data}: { page: any, value: any, data: any }, callback: any) => {
-            if (value) {
-              let id = value;
-              if (Array.isArray(value)) {
-                id = value[0]
-              }
-              getTmsServiceProvider(id).then(res => {
-                return callback(res.data || {})
-              })
-            } else {
-              listTmsServiceProvider({pageSize: page.pageSize, pageNum: page.currentPage, ...data}).then(res => {
-                return callback({
-                  total: res.total,
-                  data: res.rows || [],
-                })
-              })
-            }
-
-          },
-          change: (val: any) => {
-            const table = crudRef.value?.getPropRef?.('vehicleProviderId')?.$refs?.temp;
-            if (!table) return;
-            let active = table.active;
-            if (Array.isArray(active)) active = active[0];
-            if (active) {
-              Object.assign(form.value, {
-                vehicleProviderId: active.id,
-                vehicleProviderName: active.serviceShortName,
-              });
-            }
-          },
-        },
-        startRegion: {
+        // vehicleProviderId: {
+        //   label: '杞﹁締鏈嶅姟鍟�',
+        //   display: true,
+        //   editDisplay: true,row:true,
+        //   viewDisplay: true,
+        //   hide: false,
+        //   search: true,
+        //   rules: [
+        //     {
+        //       required: true,
+        //       message: "杞﹁締鏈嶅姟鍟嗕笉鑳戒负绌�", trigger: "change"
+        //     }
+        //   ],
+        //   type: 'table', suffixIcon: 'search',
+        //   children: {
+        //     border: true,
+        //     searchLabelWidth: 100,
+        //     searchMenuSpan: 5,
+        //     column: {
+        //       serviceCode: {
+        //         label: '鏈嶅姟鍟嗙紪鐮�', minWidth: 130,
+        //         search: true,
+        //       },
+        //       serviceShortName: {
+        //         label: '鏈嶅姟鍟嗙畝绉�', minWidth: 120,
+        //         search: true,
+        //       },
+        //       serviceType: {
+        //         label: '鏈嶅姟绫诲瀷', multiple: true,
+        //         type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/service_type',
+        //         minWidth: 150,
+        //       },
+        //       isTransport: {
+        //         label: '鏄惁杩愯緭鏈嶅姟鍟�',
+        //         type: 'radio', dataType: 'string', dicUrl: '/system/dict/data/type/sys_number_is',
+        //         minWidth: 150,
+        //       },
+        //       isStorage: {
+        //         label: '鏄惁浠撳偍鏈嶅姟鍟�',
+        //         type: 'radio', dataType: 'string', dicUrl: '/system/dict/data/type/sys_number_is',
+        //         minWidth: 150,
+        //       },
+        //       isExpress: {
+        //         label: '鏄惁蹇�掓湇鍔″晢',
+        //         type: 'radio', dataType: 'string', dicUrl: '/system/dict/data/type/sys_number_is',
+        //         minWidth: 150,
+        //       },
+        //       contactName: {
+        //         label: '鑱旂郴浜哄鍚�', minWidth: 120,
+        //       },
+        //     },
+        //
+        //   },
+        //   props: {
+        //     label: 'serviceShortName',
+        //     value: 'id'
+        //   },
+        //   onLoad: ({page, value, data}: { page: any, value: any, data: any }, callback: any) => {
+        //     if (value) {
+        //       let id = value;
+        //       if (Array.isArray(value)) {
+        //         id = value[0]
+        //       }
+        //       getTmsServiceProvider(id).then(res => {
+        //         return callback(res.data || {})
+        //       })
+        //     } else {
+        //       listTmsServiceProvider({pageSize: page.pageSize, pageNum: page.currentPage, ...data}).then(res => {
+        //         return callback({
+        //           total: res.total,
+        //           data: res.rows || [],
+        //         })
+        //       })
+        //     }
+        //
+        //   },
+        //   change: (val: any) => {
+        //     const table = crudRef.value?.getPropRef?.('vehicleProviderId')?.$refs?.temp;
+        //     if (!table) return;
+        //     let active = table.active;
+        //     if (Array.isArray(active)) active = active[0];
+        //     if (active) {
+        //       Object.assign(form.value, {
+        //         vehicleProviderId: active.id,
+        //         vehicleProviderName: active.serviceShortName,
+        //       });
+        //     }
+        //   },
+        // },
+        startRegionCode: {
           label: '璧风偣琛屾斂鍖哄煙',
           addDisplay: true,
-          editDisplay: true,
+          editDisplay: true,dataType: 'string',
           viewDisplay: true,
           type:'cascader',
           rules: [
@@ -216,38 +255,135 @@
             label: 'name',
             value: 'code'
           },
+          change:({value=[]}:{value:any})=>{
+            if (value && value.length>0){
+              const cascader = crudRef.value?.getPropRef?.('startRegionCode')?.$refs?.temp;
+              console.log('cascader.getCheckedNodes()',cascader.getCheckedNodes())
+              if (cascader.getCheckedNodes() && cascader.getCheckedNodes().length >0){
 
+                form.value.startRegionCode= cascader.getCheckedNodes()[0].pathValues.toString();
+                form.value.startRegion= cascader.getCheckedNodes()[0].text!;
+                form.value.transportRoute = `${form.value.startRegion}->${form.value.endRegion}`;
+              }
+            }
+          },
+          lazyLoad (node:any, resolve:any) {
+            const stopLevel = 3;
+            const level = node.level;
+            const data = node.data || {};
+            const code = data.code;
+            let list:any = [];
+            const callback = () => {
+              resolve((list || []).map((ele:any) => ({
+                ...ele,
+                leaf: level >= stopLevel
+              })));
+            };
+            if (level === 0) {
+              getProvince().then(res => {
+                list = res.data || [];
+                callback();
+              });
+            } else if (level === 1) {
+              getCity(code).then(res => {
+                list = res.data ||[];
+                callback();
+              });
+            } else if (level === 2) {
+              getArea(code).then(res => {
+                list = res.data ||  [];
+                callback();
+              });
+            }else if (level === 3) {
+              getStreet(code).then(res => {
+                list = res.data || [];
+                callback();
+              });
+            } else {
+              callback();
+            }
+          }
         },
-        startWarehouse: {
-          label: '璧风偣浠撳簱',
-          addDisplay: true,
-          editDisplay: true,
-          viewDisplay: true,
-          hide: false,
-          search: true,
-        },
-        endRegion: {
+        // startWarehouse: {
+        //   label: '璧风偣浠撳簱',
+        //   addDisplay: true,
+        //   editDisplay: true,
+        //   viewDisplay: true,
+        //   type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/sys_warehouse',
+        //
+        // },
+        endRegionCode: {
           label: '缁堢偣琛屾斂鍖哄煙',
           addDisplay: true,
           editDisplay: true,
-          viewDisplay: true,
-          hide: false,
-          search: true,
+          viewDisplay: true,dataType: 'string',
+          type:'cascader',
           rules: [
             {
               required: true,
               message: "缁堢偣琛屾斂鍖哄煙涓嶈兘涓虹┖", trigger: "blur"
             }
           ],
+          lazy: true,
+          props: {
+            label: 'name',
+            value: 'code'
+          },
+          change:({value=[]}:{value:any})=>{
+            if (value && value.length>0){
+              const cascader = crudRef.value?.getPropRef?.('endRegionCode')?.$refs?.temp;
+              if (cascader.getCheckedNodes() && cascader.getCheckedNodes().length >0){
+                form.value.endRegionCode= cascader.getCheckedNodes()[0].pathValues.toString();
+                form.value.endRegion= cascader.getCheckedNodes()[0].text!;
+                form.value.transportRoute = `${form.value.startRegion}->${form.value.endRegion}`;
+              }
+            }
+          },
+          lazyLoad (node:any, resolve:any) {
+            const stopLevel = 3;
+            const level = node.level;
+            const data = node.data || {};
+            const code = data.code;
+            let list:any = [];
+            const callback = () => {
+              resolve((list || []).map((ele:any) => ({
+                ...ele,
+                leaf: level >= stopLevel
+              })));
+            };
+            if (level === 0) {
+              getProvince().then(res => {
+                list = res.data || [];
+                callback();
+              });
+            } else if (level === 1) {
+              getCity(code).then(res => {
+                list = res.data ||[];
+                callback();
+              });
+            } else if (level === 2) {
+              getArea(code).then(res => {
+                list = res.data ||  [];
+                callback();
+              });
+            }else if (level === 3) {
+              getStreet(code).then(res => {
+                list = res.data || [];
+                callback();
+              });
+            } else {
+              callback();
+            }
+          }
         },
-        endWarehouse: {
-          label: '缁堢偣浠撳簱',
-          addDisplay: true,
-          editDisplay: true,
-          viewDisplay: true,
-          hide: false,
-          search: true,
-        },
+        // endWarehouse: {
+        //   label: '缁堢偣浠撳簱',
+        //   addDisplay: true,
+        //   editDisplay: true,
+        //   viewDisplay: true,
+        //   type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/sys_warehouse',
+        //
+        // },
         transportRoute: {
           label: '杩愯緭绾胯矾',span:24,
           disabled: true,
@@ -266,11 +402,10 @@
         },
         vehicleType: {
           label: '杞﹀瀷',
-          addDisplay: true,
+          addDisplay: false,
           editDisplay: true,
           viewDisplay: true,
-          hide: false,
-          search: true,
+          type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/vehicle_type',
           rules: [
             {
               required: true,
@@ -278,29 +413,27 @@
             }
           ],
         },
-        transportMode: {
-          label: '杩愯緭鏂瑰紡',
-          addDisplay: true,
-          editDisplay: true,
-          viewDisplay: true,
-          hide: false,
-          search: true,
-        },
-        routeType: {
-          label: '绾胯矾绫诲瀷',
-          addDisplay: true,
-          editDisplay: true,
-          viewDisplay: true,
-          hide: false,
-          search: true,
-        },
+        // transportMode: {
+        //   label: '杩愯緭鏂瑰紡',
+        //   addDisplay: true,
+        //   editDisplay: true,
+        //   viewDisplay: true,
+        //   type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/transport_mode',
+        //
+        // },
+        // routeType: {
+        //   label: '绾胯矾绫诲瀷',
+        //   addDisplay: true,
+        //   editDisplay: true,
+        //   viewDisplay: true,
+        //   type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/route_type',
+        //
+        // },
         freightPrice: {
-          label: '杩愯垂鎶ヤ环',
-          addDisplay: true,
+          label: '杩愯垂鎶ヤ环',      addDisplay: false,
           editDisplay: true,
-          viewDisplay: true,
-          hide: false,
-          search: true,
+          viewDisplay: true,type: 'number',
+
           rules: [
             {
               required: true,
@@ -308,6 +441,37 @@
             }
           ],
         },
+        currency: {
+          label: '甯佸埗',addDisplay: false,
+          type: 'radio', dataType: 'string', dicUrl: '/system/dict/data/type/sys_currency',
+          rules: [
+            {
+              required: true,
+              message: "杩愯垂鎶ヤ环涓嶈兘涓虹┖", trigger: "blur"
+            }
+          ],
+        },
+        taxRate: {
+          label: '绋庣偣%',
+          addDisplay: false,
+          editDisplay: true,
+          viewDisplay: true,type: 'number',
+          rules: [
+            {
+              required: true,
+              message: "taxRate涓嶈兘涓虹┖", trigger: "blur"
+            }
+          ],
+        },
+      }
+    },
+    {
+      label: '杞﹀瀷鎶ヤ环',
+      prop: 'cxbj', addDisplay: true,editDisplay: false,viewDisplay: false,
+      column: {
+        items:{
+          label: '',labelWidth:0,span:24,
+        }
       }
     },
     {
@@ -317,7 +481,7 @@
         status: {
           label: '鐘舵��',
           type: 'radio', dicUrl: '/system/dict/data/type/sys_normal_disable',
-          addDisplay: false,
+          addDisplay: false,dataType:'string',
           editDisplay: true,
           viewDisplay: true,
           hide: false,
@@ -386,11 +550,11 @@
       label: '鎶ヤ环鏂规缂栧彿',minWidth:150,
       display: false,
     },
-    vehicleProviderName: {
-      label: '杞﹁締鏈嶅姟鍟�',minWidth:150,
-      display: false,
-      search: true,
-    },
+    // vehicleProviderName: {
+    //   label: '杞﹁締鏈嶅姟鍟�',minWidth:150,
+    //   display: false,
+    //   search: true,
+    // },
     transportRoute: {
       label: '杩愯緭绾胯矾',minWidth:150,
       display: false,overHidden: true,
@@ -399,45 +563,64 @@
     startRegion: {
       label: '璧风偣琛屾斂鍖哄煙',
       display: false,minWidth:150,
-      hide: false,
+      hide: false,overHidden: true,
       search: false,
     },
-    startWarehouse: {
-      label: '璧风偣浠撳簱',   display: false,
-      hide: false,minWidth:150,
-      search: true,
-    },
+    // startWarehouse: {
+    //   label: '璧风偣浠撳簱',   display: false,
+    //   hide: false,minWidth:150,
+    //   search: true,
+    //   type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/sys_warehouse',
+    //
+    // },
     endRegion: {
-      label: '缁堢偣琛屾斂鍖哄煙',
+      label: '缁堢偣琛屾斂鍖哄煙',overHidden: true,
       display: false,minWidth:150,
       hide: false,
     },
-    endWarehouse: {
-      label: '缁堢偣浠撳簱',
-      display: false,minWidth:150,
-      hide: false,
-      search: true,
-    },
+    // endWarehouse: {
+    //   label: '缁堢偣浠撳簱',
+    //   display: false,minWidth:150,
+    //   type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/sys_warehouse',
+    //   search: true,
+    // },
     vehicleType: {
       label: '杞﹀瀷',
       display: false,minWidth:150,
-      hide: false,
+      type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/vehicle_type',
       search: true,
     },
-    transportMode: {
-      label: '杩愯緭鏂瑰紡',minWidth:150,
+    // transportMode: {
+    //   label: '杩愯緭鏂瑰紡',minWidth:150,
+    //   display: false,
+    //   hide: false,
+    //   search: true,
+    //   type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/transport_mode',
+    //
+    // },
+    // routeType: {
+    //   label: '绾胯矾绫诲瀷',
+    //   display: false,
+    //   hide: false,minWidth:150,
+    //   search: true,
+    //   type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/route_type',
+    //
+    // },
+    freightPrice: {
+      label: '杩愯垂鎶ヤ环',
       display: false,
-      hide: false,
-      search: true,
+      hide: false,minWidth:150,
     },
-    routeType: {
-      label: '绾胯矾绫诲瀷',
+    currency: {
+      label: '甯佸埗',
       display: false,
       hide: false,minWidth:150,
       search: true,
+      type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/sys_currency',
+
     },
-    freightPrice: {
-      label: '杩愯垂鎶ヤ环',
+    taxRate: {
+      label: '绋庣偣%',
       display: false,
       hide: false,minWidth:150,
     },
@@ -458,7 +641,28 @@
     },
   }
 })
-
+const itemsTableOption = ref({
+  pageKey: 'itemsTable',
+  rowKey: 'rowKey',
+  header: false,
+  addBtn: false,menu: false,
+  column:{
+    vehicleType:{
+      label: '杞﹀瀷',
+      type: 'select', dataType: 'string', dicUrl: '/system/dict/data/type/vehicle_type',
+    },
+    freightPrice:{
+      label: '*杩愯垂鎶ヤ环', hide: false
+    },
+    currency:{
+      label: '甯佸埗',hide: false
+    },
+    taxRate:{
+      label: '绋庣偣%',hide: false
+    },
+  }
+})
+const itemsCrudRef =ref()
 const {
   tableData,
   pageF,
@@ -493,8 +697,46 @@
   },
   handleSelectionChangeFunc: (selection: any) => {
     selectionList.value = selection;
-  }
-})
+  },
+  getBeginListFunc(params:any = {}){
+    params.quotePlanId = (route.query?.quotePlanId||'') as string;
+    return params;
+  },
+  rowSaveBegin:(row:any,loading:any)=>{
+    row.quotePlanId = (route.query?.quotePlanId||'') as string;
+    if (selectionList2.value.length == 0){
+      proxy.$modal.msgError("璇疯嚦灏戦�夋嫨涓�鏉¤溅鍨嬫姤浠�");
+      loading();
+      throw new Error("璇疯嚦灏戦�夋嫨涓�鏉¤溅鍨嬫姤浠�");
 
+    }
+    let filter = selectionList2.value.filter((item:any)=>{
+      return !item.freightPrice || !item.currency
+    });
+    if (filter.length > 0){
+      proxy.$modal.msgError("璇峰~鍐欐墍鏈夊繀濉」");
+      loading();
+      throw new Error("璇峰~鍐欐墍鏈夊繀濉」")
+    }
+    row.quoteItems = selectionList2.value;
+
+  },
+  handleBeforeOpenFunc:(type:string)=>{
+    form.value.items = [];
+    if (type === 'add'){
+      form.value.items = vehicle_type.value.map((item:any)=>{
+        return { rowKey: randomId() ,vehicleType: item.value,}
+      })
+    }
+  },
+})
+const handleBack = () => {
+  router.back()
+}
+const rowKeys = ref<any>([]);
+const selectionChange2 = (selection?: any[]) => {
+  selectionList2.value = selection;
+  rowKeys.value = selection?.map((item:any)=>item.rowKey);
+}
 
 </script>

--
Gitblit v1.8.0