瀏覽代碼

feat: 首页新增对customer的筛选

Jack Zhou 1 周之前
父節點
當前提交
579caba335

+ 0 - 1
src/components/DateRange/src/components/QuickCalendarDate.vue

@@ -25,7 +25,6 @@ const ETDDate = ref(props.Date)
 watch(
   () => props.Date,
   (current) => {
-    console.log('props.Date', props.Date)
     ETDDate.value = current
   },
   {

+ 50 - 35
src/views/Dashboard/src/DashboardView.new.vue

@@ -9,6 +9,7 @@ import RecentStatus from './components/RecentStatus.vue'
 import ScoringSystem from './components/ScoringSystem.vue'
 import TopMap from './components/TopMap.vue'
 import DashFilters from './components/DashFiters.vue'
+import CustomerFilter from './components/CustomerFilter.vue'
 import { useRouter } from 'vue-router'
 import { ElMessage } from 'element-plus'
 import { formatNumber } from '@/utils/tools'
@@ -39,6 +40,11 @@ const changeCancel = (id: any) => {
   Management.value[id - 1].switchValue = false
 }
 
+const customerInfo = ref({
+  customerCode: '',
+  customerType: ''
+})
+
 //RecentStatusList
 const RecentStatusList = ref()
 const pageInfo = ref({ pageNo: 1, pageSize: 10, total: 10000 })
@@ -77,15 +83,7 @@ const GetDashboardData = () => {
       revenueDefaultData.value = res.data.RevenueDefaultData
 
       nextTick(() => {
-        //   GetKpiData(kpiDefaultData.value)
-        //   GetPendingEcharts(pendingDefaultData.value)
         getTableData(recentDefaultData.value, false)
-        //   GetETDEcharts(etdDefaultData.value)
-        //   GetContainerCountEcharts(containerDefaultData.value)
-        //   GetTop10ODEcharts(top10DefaultData.value)
-        //   GetCo2EmissionEcharts(co2OriginDefaultData.value)
-        //   GetCo2DestinationEcharts(co2DestinationDefaultData.value)
-        //   GetRevenueEcharts(revenueDefaultData.value)
       })
     }
   })
@@ -126,11 +124,13 @@ const kpiArrivalLoading = ref(false)
 const GetKpiData = (val: any) => {
   kpiLoading.value = true
   kpiArrivalLoading.value = true
+  kpiDefaultData.value = val
   // 获取KPI Departure图表数据
   $api
     .GetKPIEcharts({
       r_type: 'atd_r4',
-      ...val
+      ...val,
+      ...customerInfo.value
     })
     .then((res: any) => {
       if (res.code === 200) {
@@ -180,10 +180,12 @@ const GetPendingEcharts = (val: any) => {
   // 获取Pending Departure图表数据
   pendingLoading.value = true
   pendingArrivalLoading.value = true
+  pendingDefaultData.value = val
   $api
     .GetPendingEcharts({
       r_type: 'r4',
-      ...val
+      ...val,
+      ...customerInfo.value
     })
     .then((res: any) => {
       if (res.code === 200) {
@@ -194,14 +196,14 @@ const GetPendingEcharts = (val: any) => {
       }
     })
     .finally(() => {
-      console.log('pendingLoading', pendingLoading.value)
       pendingLoading.value = false
     })
   // 获取Pending Arrival图表数据
   $api
     .GetPendingEcharts({
       r_type: 'r3',
-      ...val
+      ...val,
+      ...customerInfo.value
     })
     .then((res: any) => {
       if (res.code === 200) {
@@ -225,9 +227,11 @@ const etdLoading = ref(false)
 // 获取ETD/ETA 图表数据
 const GetETDEcharts = (val: any) => {
   etdLoading.value = true
+  etdDefaultData.value = val
   $api
     .GetETDEcharts({
-      ...val
+      ...val,
+      ...customerInfo.value
     })
     .then((res: any) => {
       if (res.code === 200) {
@@ -253,9 +257,11 @@ const containerObj = reactive({
 const containerLoading = ref(false)
 const GetContainerCountEcharts = (val: any) => {
   containerLoading.value = true
+  containerDefaultData.value = val
   $api
     .GetContainerCountEcharts({
-      ...val
+      ...val,
+      ...customerInfo.value
     })
     .then((res: any) => {
       if (res.code === 200) {
@@ -291,10 +297,11 @@ const top10Originref = ref()
 const top10Destinationref = ref()
 const GetTop10ODEcharts = (val: any) => {
   topOriginLoading.value = true
-
+  top10DefaultData.value = val
   $api
     .GetTop10ODEcharts({
-      ...val
+      ...val,
+      ...customerInfo.value
     })
     .then((res: any) => {
       if (res.code === 200) {
@@ -329,9 +336,11 @@ const emissionObj = reactive({
 })
 const GetCo2EmissionEcharts = (val: any) => {
   emissionLoading.value = true
+  co2OriginDefaultData.value = val
   $api
     .GetCo2EmissionEcharts({
-      ...val
+      ...val,
+      ...customerInfo.value
     })
     .then((res: any) => {
       if (res.code === 200) {
@@ -359,9 +368,11 @@ const destinationObj = reactive({
 const destinationLoading = ref(false)
 const GetCo2DestinationEcharts = (val: any) => {
   destinationLoading.value = true
+  co2DestinationDefaultData.value = val
   $api
     .GetCo2DestinationEcharts({
-      ...val
+      ...val,
+      ...customerInfo.value
     })
     .then((res: any) => {
       if (res.code === 200) {
@@ -395,9 +406,11 @@ const GetRevenueEcharts = (val: any) => {
   revenue_date_start.value = val.date_start
   revenue_date_end.value = val.date_end
   revenueLoading.value = true
+  revenueDefaultData.value = val
   $api
     .GetRevenueEcharts({
-      ...val
+      ...val,
+      ...customerInfo.value
     })
     .then((res: any) => {
       if (res.code === 200) {
@@ -443,7 +456,7 @@ const SaveFilters = () => {
   Management.value.forEach((item: any, index: any) => {
     item.id = index + 1
   })
-  const dashboardObj = {
+  const filterConfig = {
     kpiDefaultData: kpiDefaultData.value,
     pendingDefaultData: pendingDefaultData.value,
     recentDefaultData: recentDefaultData.value,
@@ -454,21 +467,20 @@ const SaveFilters = () => {
     co2DestinationDefaultData: co2DestinationDefaultData.value,
     revenueDefaultData: revenueDefaultData.value
   }
-  console.log(dashboardObj, '保存内容')
-  // $api
-  //   .SaveLayout({
-  //     management: Management.value,
-  //     dashboardObj
-  //   })
-  //   .then((res: any) => {
-  //     if (res.code == 200) {
-  //       ElMessage({
-  //         message: res.data.msg,
-  //         duration: 3000,
-  //         type: 'success'
-  //       })
-  //     }
-  //   })
+  $api
+    .SaveLayout({
+      management: Management.value,
+      dashboardObj: filterConfig
+    })
+    .then((res: any) => {
+      if (res.code == 200) {
+        ElMessage({
+          message: res.data.msg,
+          duration: 3000,
+          type: 'success'
+        })
+      }
+    })
 }
 //ETD to ETA(DAYS)点击跳转
 const pie_chart_ETD = ref()
@@ -923,6 +935,8 @@ const handleGuide = () => {
         />
       </div>
     </div>
+    <!-- customer-filter -->
+    <CustomerFilter></CustomerFilter>
     <!-- 图表 -->
     <div class="echarts">
       <VueDraggable
@@ -1355,6 +1369,7 @@ const handleGuide = () => {
   align-items: center;
   justify-content: space-between;
 }
+
 .iconfont {
   vertical-align: -2px;
 }

+ 150 - 0
src/views/Dashboard/src/components/CustomerFilter.vue

@@ -0,0 +1,150 @@
+<script setup lang="ts">
+import { cloneDeep, debounce } from 'lodash'
+import axios from 'axios'
+
+const props = defineProps({
+  data: {
+    type: Array as () => string[],
+    default: () => []
+  }
+})
+
+const selectData = ref<string[]>([])
+watch(
+  () => props.data,
+  (newValue) => {
+    selectData.value = cloneDeep(newValue) || []
+  },
+  {
+    deep: true,
+    immediate: true
+  }
+)
+const emit = defineEmits(['changeData'])
+const changeData = (val: string[]) => {
+  // 同步选中状态
+  emit('changeData', val)
+}
+
+interface ListItem {
+  label: string
+  id: string
+}
+
+const options = ref<ListItem[]>([])
+const loading = ref(false)
+const currentController = ref<AbortController | null>(null)
+
+const remoteMethod = (query: string) => {
+  currentController.value?.abort()
+
+  const newController = new AbortController()
+  currentController.value = newController
+  loading.value = true
+
+  $api
+    .getSpecificRolesPartyID({ term: query }, { signal: newController.signal })
+    .then((res) => {
+      if (!newController.signal.aborted && res.code === 200) {
+        options.value = (res.data || []).map((item) => ({
+          id: item.id,
+          label: item.label
+        }))
+      }
+    })
+    .catch((err) => {
+      options.value = []
+      if (!axios.isCancel(err) && !newController.signal.aborted) {
+        ElMessage.error('Failed to load options')
+      }
+    })
+    .finally(() => {
+      // 仅当这是最新请求时,才关闭 loading
+      if (currentController.value === newController) {
+        loading.value = false
+      }
+    })
+}
+
+// 防抖版本(可选)
+const debouncedRemoteMethod = debounce(remoteMethod, 200)
+
+onUnmounted(() => {
+  currentController.value?.abort()
+})
+
+const type = ref('')
+const typeOptions = ref([
+  {
+    label: 'Shipper',
+    value: 'shipper_id'
+  },
+  {
+    label: 'Consignee',
+    value: 'consignee_id'
+  },
+  {
+    label: 'Controlling Customer',
+    value: 'customer_code'
+  },
+  {
+    label: 'Bill to',
+    value: 'billto_id'
+  },
+  {
+    label: 'Notify Party',
+    value: 'notify_party_id'
+  }
+])
+</script>
+
+<template>
+  <div class="customer-filter">
+    <el-select
+      :model-value="selectData"
+      multiple
+      filterable
+      reserve-keyword
+      placeholder="Search by Customer code, Customer name"
+      :loading="loading"
+      style="width: 400px"
+      popper-class="part-id-select-popper"
+      :filter-method="debouncedRemoteMethod"
+      @change="changeData"
+    >
+      <el-option
+        v-for="item in options"
+        :key="item.id + item.label"
+        :label="item.label"
+        :value="item.label"
+      >
+        <div class="select-option">
+          <el-checkbox :model-value="selectData.includes(item.label)" style="flex: 1">
+            <span style="display: inline-block; width: 220px">{{ item.label }}</span>
+            <span class="text-ellipsis" style="flex: 1; width: 200px">{{ item.id }}</span>
+          </el-checkbox>
+        </div>
+      </el-option>
+    </el-select>
+    <el-select placeholder="Customer Type" v-model="type" style="width: 240px; margin-left: 8px">
+      <el-option
+        v-for="item in typeOptions"
+        :key="item.value"
+        :label="item.label"
+        :value="item.value"
+      ></el-option>
+    </el-select>
+    <el-button class="el-button--default">Search</el-button>
+  </div>
+</template>
+
+<style lang="scss" scoped>
+.customer-filter {
+  display: flex;
+  align-items: center;
+  height: 48px;
+  padding-left: 24px;
+  border: 1px solid var(--color-border);
+  margin-bottom: 8px;
+}
+</style>

+ 5 - 3
src/views/Dashboard/src/components/DashFiters.vue

@@ -116,12 +116,15 @@ const getdefaultdata = (data: any, isReset: boolean = false) => {
     DateRangeSearch()
   }
 }
-watch(
+let unwatch // 先声明
+
+unwatch = watch(
   () => props.defaultData,
   (value) => {
-    if (value && Object.keys(value).length) {
+    if (value && Object.keys(value).length > 0) {
       nextTick(() => {
         getdefaultdata(value)
+        unwatch() // ✅ 现在可以安全调用
       })
     }
   },
@@ -130,7 +133,6 @@ watch(
     deep: true
   }
 )
-
 const changeCheckboxGroup1 = (val: any) => {
   if (val.length == 4) {
     checkboxGroup1.value = ['All']