|
|
@@ -0,0 +1,1614 @@
|
|
|
+<script lang="ts" setup>
|
|
|
+import { ref, onMounted, reactive } from 'vue'
|
|
|
+import { VueDraggable } from 'vue-draggable-plus'
|
|
|
+import PieChart from './components/PieChart.vue'
|
|
|
+import SellerChart from './components/SellerChart.vue'
|
|
|
+import BarChart from './components/BarChart.vue'
|
|
|
+import RevenueChart from './components/RevenueChart.vue'
|
|
|
+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 { useRouter } from 'vue-router'
|
|
|
+import { ElMessage } from 'element-plus'
|
|
|
+import { formatNumber } from '@/utils/tools'
|
|
|
+import { useFiltersStore, FiltersType } from '@/stores/modules/filtersList'
|
|
|
+import dayjs from 'dayjs'
|
|
|
+import { useUserStore } from '@/stores/modules/user'
|
|
|
+
|
|
|
+const userStore = useUserStore()
|
|
|
+const formatDate = userStore.dateFormat
|
|
|
+const filtersStore = useFiltersStore()
|
|
|
+
|
|
|
+const router = useRouter()
|
|
|
+const activeName = ref('first')
|
|
|
+const SaveVisible = ref(false)
|
|
|
+// 可拖拽模块的列表
|
|
|
+interface ManagementItem {
|
|
|
+ title: string
|
|
|
+ switchValue: boolean
|
|
|
+ isRevenueDisplay: boolean
|
|
|
+ text: string
|
|
|
+ id: number
|
|
|
+ title1: string
|
|
|
+ title2: string
|
|
|
+}
|
|
|
+const Management = ref<ManagementItem[]>([])
|
|
|
+
|
|
|
+const changeCancel = (id: any) => {
|
|
|
+ Management.value[id - 1].switchValue = false
|
|
|
+}
|
|
|
+
|
|
|
+//RecentStatusList
|
|
|
+const RecentStatusList = ref()
|
|
|
+const pageInfo = ref({ pageNo: 1, pageSize: 10, total: 10000 })
|
|
|
+const isShowtitle1 = ref(true)
|
|
|
+// 点击tab
|
|
|
+const handleTabClick = (tab: any) => {
|
|
|
+ if (tab.props.name == 'first') {
|
|
|
+ isShowtitle1.value = true
|
|
|
+ } else {
|
|
|
+ isShowtitle1.value = false
|
|
|
+ }
|
|
|
+ GetTop10ODEcharts(dashboardObj.Top10faultData)
|
|
|
+}
|
|
|
+const KPIDefaulteData = ref()
|
|
|
+const PendingDefaulteData = ref()
|
|
|
+const RecentDefaulteData = ref()
|
|
|
+const ETDDefaulteData = ref()
|
|
|
+const ContainerefaultData = ref()
|
|
|
+const Top10DefaultData = ref()
|
|
|
+const Co2OriginDefaultData = ref()
|
|
|
+const Co2DestinationDefaultData = ref()
|
|
|
+const RevenueDefaultData = ref()
|
|
|
+// 获取首页数据
|
|
|
+let dashboardObj: any = {}
|
|
|
+const GetDashboardData = () => {
|
|
|
+ $api.getDashboardFilters({}).then((res: any) => {
|
|
|
+ if (res.code == 200) {
|
|
|
+ //给默认筛选条件赋值
|
|
|
+ KPIDefaulteData.value = res.data.KPIDefaulteData
|
|
|
+ dashboardObj.KPIDefaulteData = res.data.KPIDefaulteData
|
|
|
+ PendingDefaulteData.value = res.data.PendingDefaultData
|
|
|
+ dashboardObj.PendingDefaultData = res.data.PendingDefaultData
|
|
|
+ RecentDefaulteData.value = res.data.RecentDefaultData
|
|
|
+ dashboardObj.RecentDefaultData = res.data.RecentDefaultData
|
|
|
+ ETDDefaulteData.value = res.data.ETDDefaultData
|
|
|
+ dashboardObj.ETDDefaultData = res.data.ETDDefaultData
|
|
|
+ ContainerefaultData.value = res.data.ContainerefaultData
|
|
|
+ dashboardObj.ContainerefaultData = res.data.ContainerefaultData
|
|
|
+ Top10DefaultData.value = res.data.Top10faultData
|
|
|
+ dashboardObj.Top10faultData = res.data.Top10faultData
|
|
|
+ Co2OriginDefaultData.value = res.data.OriginCo2Top10faultData
|
|
|
+ dashboardObj.OriginCo2Top10faultData = res.data.OriginCo2Top10faultData
|
|
|
+ Co2DestinationDefaultData.value = res.data.DestinationCo2Top10faultData
|
|
|
+ dashboardObj.DestinationCo2Top10faultData = res.data.DestinationCo2Top10faultData
|
|
|
+ RevenueDefaultData.value = res.data.RevenueDefaultData
|
|
|
+ dashboardObj.RevenueDefaultData = res.data.RevenueDefaultData
|
|
|
+
|
|
|
+ nextTick(() => {
|
|
|
+ GetKpiData(KPIDefaulteData.value)
|
|
|
+ GetPendingEcharts(PendingDefaulteData.value)
|
|
|
+ getTableData(false, RecentDefaulteData.value)
|
|
|
+ GetETDEcharts(ETDDefaulteData.value)
|
|
|
+ GetContainerCountEcharts(ContainerefaultData.value)
|
|
|
+ GetTop10ODEcharts(Top10DefaultData.value)
|
|
|
+ GetCo2EmissionEcharts(Co2OriginDefaultData.value)
|
|
|
+ GetCo2DestinationEcharts(Co2DestinationDefaultData.value)
|
|
|
+ GetRevenueEcharts(RevenueDefaultData.value)
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+// 获取表单数据
|
|
|
+const getTableData = (isPage: any, val: any) => {
|
|
|
+ dashboardObj.RecentDefaultData = val
|
|
|
+ const rc = isPage ? pageInfo.value.total : -1
|
|
|
+ $api
|
|
|
+ .GetDashboardData({
|
|
|
+ cp: pageInfo.value.pageNo,
|
|
|
+ ps: pageInfo.value.pageSize,
|
|
|
+ rc,
|
|
|
+ ...val
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ pageInfo.value.total = Number(res.data.rc)
|
|
|
+ Management.value = res.data.Management
|
|
|
+ RecentStatusList.value = res.data.searchData
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+const KPIobj = reactive({
|
|
|
+ ETD_Title: '',
|
|
|
+ ETDList: [],
|
|
|
+ ETD_Radius: [],
|
|
|
+ download_name: ''
|
|
|
+})
|
|
|
+const Arrivalobj = reactive({
|
|
|
+ ETD_Title: '',
|
|
|
+ ETDList: [],
|
|
|
+ ETD_Radius: [],
|
|
|
+ download_name: ''
|
|
|
+})
|
|
|
+const KPILoading = ref(true)
|
|
|
+const KPIArrivalLoading = ref(true)
|
|
|
+//查询KPI
|
|
|
+const GetKpiData = (val: any) => {
|
|
|
+ dashboardObj.KPIDefaulteData = val
|
|
|
+ // 获取KPI Departure图表数据
|
|
|
+ $api
|
|
|
+ .GetKPIEcharts({
|
|
|
+ r_type: 'atd_r4',
|
|
|
+ ...val
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ KPIobj.ETD_Title = `{a|${res.data.title1}} {b|${res.data.title2}}`
|
|
|
+ KPIobj.ETDList = res.data.ETDList
|
|
|
+ KPIobj.ETD_Radius = res.data.ETD_Radius
|
|
|
+ KPIobj.download_name = res.data.download_name
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ KPILoading.value = false
|
|
|
+ })
|
|
|
+ // 获取KPI Arrival图表数据
|
|
|
+ $api
|
|
|
+ .GetKPIEcharts({
|
|
|
+ r_type: 'ata_r3',
|
|
|
+ ...val
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ Arrivalobj.ETD_Title = `{a|${res.data.title1}} {b|${res.data.title2}}`
|
|
|
+ Arrivalobj.ETDList = res.data.ETDList
|
|
|
+ Arrivalobj.ETD_Radius = res.data.ETD_Radius
|
|
|
+ Arrivalobj.download_name = res.data.download_name
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ KPIArrivalLoading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+const Pendingobj = reactive({
|
|
|
+ ETD_Title: '',
|
|
|
+ ETDList: [],
|
|
|
+ ETD_Radius: [],
|
|
|
+ download_name: ''
|
|
|
+})
|
|
|
+const PendingArrivalobj = reactive({
|
|
|
+ ETD_Title: '',
|
|
|
+ ETDList: [],
|
|
|
+ ETD_Radius: [],
|
|
|
+ download_name: ''
|
|
|
+})
|
|
|
+const PendingLoading = ref(true)
|
|
|
+const PendingArrivalLoading = ref(true)
|
|
|
+// 查询Pending
|
|
|
+const GetPendingEcharts = (val: any) => {
|
|
|
+ dashboardObj.PendingDefaultData = val
|
|
|
+ // 获取Pending Departure图表数据
|
|
|
+ $api
|
|
|
+ .GetPendingEcharts({
|
|
|
+ r_type: 'r4',
|
|
|
+ ...val
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ Pendingobj.ETD_Title = `{a|${res.data.title1}} {b|${res.data.title2}}`
|
|
|
+ Pendingobj.ETDList = res.data.ETDList
|
|
|
+ Pendingobj.ETD_Radius = res.data.ETD_Radius
|
|
|
+ Pendingobj.download_name = res.data.download_name
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ PendingLoading.value = false
|
|
|
+ })
|
|
|
+ // 获取Pending Arrival图表数据
|
|
|
+ $api
|
|
|
+ .GetPendingEcharts({
|
|
|
+ r_type: 'r3',
|
|
|
+ ...val
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ PendingArrivalobj.ETD_Title = `{a|${res.data.title1}} {b|${res.data.title2}}`
|
|
|
+ PendingArrivalobj.ETDList = res.data.ETDList
|
|
|
+ PendingArrivalobj.ETD_Radius = res.data.ETD_Radius
|
|
|
+ PendingArrivalobj.download_name = res.data.download_name
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ PendingArrivalLoading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+const ETDobj = reactive({
|
|
|
+ ETD_Title: '',
|
|
|
+ ETDList: [],
|
|
|
+ ETD_Radius: [],
|
|
|
+ download_name: ''
|
|
|
+})
|
|
|
+const ETDLoading = ref(true)
|
|
|
+// 获取ETD/ETA 图表数据
|
|
|
+const GetETDEcharts = (val: any) => {
|
|
|
+ dashboardObj.ETDDefaultData = val
|
|
|
+ $api
|
|
|
+ .GetETDEcharts({
|
|
|
+ ...val
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ ETDobj.ETD_Title = `{a|${res.data.ETD_Title}}`
|
|
|
+ ETDobj.ETDList = res.data.ETDList
|
|
|
+ ETDobj.ETD_Radius = res.data.ETD_Radius
|
|
|
+ ETDobj.download_name = res.data.download_name
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ ETDLoading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+// 获取ContainerCount
|
|
|
+const containerObj = reactive({
|
|
|
+ bar_title: '',
|
|
|
+ barList: [],
|
|
|
+ barSeries: [],
|
|
|
+ Max: 0,
|
|
|
+ interval: 0,
|
|
|
+ download_name: ''
|
|
|
+})
|
|
|
+const containerLoading = ref(true)
|
|
|
+const GetContainerCountEcharts = (val: any) => {
|
|
|
+ dashboardObj.ContainerefaultData = val
|
|
|
+ $api
|
|
|
+ .GetContainerCountEcharts({
|
|
|
+ ...val
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ containerObj.bar_title = res.data.ContainerCount_Title
|
|
|
+ containerObj.barList = res.data.ContainerCountList
|
|
|
+ containerObj.barSeries = res.data.ContainerCounSeries
|
|
|
+ containerObj.Max = res.data.Max
|
|
|
+ containerObj.interval = res.data.interval
|
|
|
+ containerObj.download_name = res.data.download_name
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ containerLoading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+const topdestinationinType = ref()
|
|
|
+const toporiginType = ref()
|
|
|
+//获取Top10 Origin/Destination
|
|
|
+const Top10Obj = reactive({
|
|
|
+ OriginData: [],
|
|
|
+ DestinationData: []
|
|
|
+})
|
|
|
+const Top1OInterval = reactive({
|
|
|
+ Max: 0,
|
|
|
+ interval: 0
|
|
|
+})
|
|
|
+const Top1OInterval_dest = reactive({
|
|
|
+ Max: 0,
|
|
|
+ interval: 0
|
|
|
+})
|
|
|
+const TopOriginLoading = ref(true)
|
|
|
+const Top10Originref = ref()
|
|
|
+const Top10Destinationref = ref()
|
|
|
+const GetTop10ODEcharts = (val: any) => {
|
|
|
+ dashboardObj.Top10faultData = val
|
|
|
+ $api
|
|
|
+ .GetTop10ODEcharts({
|
|
|
+ ...val
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ // Top10Originref.value[0].updataMapObj(dashboardObj.Top10faultData)
|
|
|
+ if (isShowtitle1.value) {
|
|
|
+ Top10Originref.value[0].updataMapObj(res.data.toporiginMap)
|
|
|
+ } else {
|
|
|
+ Top10Destinationref.value[0].updataMapObj(res.data.topdestinationinMap)
|
|
|
+ }
|
|
|
+ Top10Obj.DestinationData = res.data.seller_data_list_destination
|
|
|
+ Top10Obj.OriginData = res.data.seller_data_list_origin
|
|
|
+ Top1OInterval.Max = res.data.Max
|
|
|
+ Top1OInterval.interval = res.data.interval
|
|
|
+ Top1OInterval_dest.Max = res.data.dest_Max
|
|
|
+ Top1OInterval_dest.interval = res.data.dest_interval
|
|
|
+ topdestinationinType.value = res.data.topdestinationinType
|
|
|
+ toporiginType.value = res.data.toporiginType
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ TopOriginLoading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+//获取CO2 Origin
|
|
|
+const EmissionLoading = ref(true)
|
|
|
+const EmissionObj = reactive({
|
|
|
+ bar_title: '',
|
|
|
+ barList: [],
|
|
|
+ barSeries: [],
|
|
|
+ Max: 0,
|
|
|
+ interval: 0,
|
|
|
+ download_name: ''
|
|
|
+})
|
|
|
+const GetCo2EmissionEcharts = (val: any) => {
|
|
|
+ dashboardObj.OriginCo2Top10faultData = val
|
|
|
+ $api
|
|
|
+ .GetCo2EmissionEcharts({
|
|
|
+ ...val
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ EmissionObj.bar_title = res.data.ContainerCount_Title
|
|
|
+ EmissionObj.barList = res.data.ContainerCountList
|
|
|
+ EmissionObj.barSeries = res.data.ContainerCounSeries
|
|
|
+ EmissionObj.Max = res.data.Max
|
|
|
+ EmissionObj.interval = res.data.interval
|
|
|
+ EmissionObj.download_name = res.data.download_name
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ EmissionLoading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+//获取CO2 Destination
|
|
|
+const DestinationObj = reactive({
|
|
|
+ bar_title: '',
|
|
|
+ barList: [],
|
|
|
+ barSeries: [],
|
|
|
+ Max: 0,
|
|
|
+ interval: 0,
|
|
|
+ download_name: ''
|
|
|
+})
|
|
|
+const DestinationLoading = ref(true)
|
|
|
+const GetCo2DestinationEcharts = (val: any) => {
|
|
|
+ dashboardObj.DestinationCo2Top10faultData = val
|
|
|
+ $api
|
|
|
+ .GetCo2DestinationEcharts({
|
|
|
+ ...val
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ DestinationObj.bar_title = res.data.ContainerCount_Title
|
|
|
+ DestinationObj.barList = res.data.ContainerCountList
|
|
|
+ DestinationObj.barSeries = res.data.ContainerCounSeries
|
|
|
+ DestinationObj.Max = res.data.Max
|
|
|
+ DestinationObj.interval = res.data.interval
|
|
|
+ DestinationObj.download_name = res.data.download_name
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ DestinationLoading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+//获取Revenue Spent
|
|
|
+
|
|
|
+const RevenueObj = reactive({
|
|
|
+ bar_title: '',
|
|
|
+ barList: [],
|
|
|
+ barSeries: [],
|
|
|
+ Max: 0,
|
|
|
+ interval: 0,
|
|
|
+ download_name: '',
|
|
|
+ isShowTooltips: true
|
|
|
+})
|
|
|
+const RevenueLoading = ref(true)
|
|
|
+const revenue_date_start = ref()
|
|
|
+const revenue_date_end = ref()
|
|
|
+const GetRevenueEcharts = (val: any) => {
|
|
|
+ revenue_date_start.value = val.date_start
|
|
|
+ revenue_date_end.value = val.date_end
|
|
|
+ dashboardObj.RevenueDefaultData = val
|
|
|
+ $api
|
|
|
+ .GetRevenueEcharts({
|
|
|
+ ...val
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code === 200) {
|
|
|
+ RevenueObj.bar_title = res.data.bar_title
|
|
|
+ RevenueObj.barList = res.data.barList
|
|
|
+ RevenueObj.barSeries = res.data.barSeries
|
|
|
+ RevenueObj.Max = res.data.Max
|
|
|
+ RevenueObj.interval = res.data.interval
|
|
|
+ RevenueObj.download_name = res.data.download_name
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .finally(() => {
|
|
|
+ RevenueLoading.value = false
|
|
|
+ })
|
|
|
+}
|
|
|
+onMounted(() => {
|
|
|
+ GetDashboardData()
|
|
|
+})
|
|
|
+
|
|
|
+// Save Layout
|
|
|
+const SaveLayout = () => {
|
|
|
+ SaveVisible.value = false
|
|
|
+ Management.value.forEach((item: any, index: any) => {
|
|
|
+ item.id = index + 1
|
|
|
+ })
|
|
|
+ $api
|
|
|
+ .SaveLayout({
|
|
|
+ management: Management.value
|
|
|
+ })
|
|
|
+ .then((res: any) => {
|
|
|
+ if (res.code == 200) {
|
|
|
+ ElMessage({
|
|
|
+ message: res.data.msg,
|
|
|
+ duration: 3000,
|
|
|
+ type: 'success'
|
|
|
+ })
|
|
|
+ }
|
|
|
+ })
|
|
|
+}
|
|
|
+//Save Filters
|
|
|
+const SaveFilters = () => {
|
|
|
+ SaveVisible.value = false
|
|
|
+ Management.value.forEach((item: any, index: any) => {
|
|
|
+ item.id = index + 1
|
|
|
+ })
|
|
|
+ $api
|
|
|
+ .SaveLayout({
|
|
|
+ management: Management.value,
|
|
|
+ dashboardObj
|
|
|
+ })
|
|
|
+ .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()
|
|
|
+const pie_chart_pending_arrival = ref()
|
|
|
+const pie_chart_pending_departure = ref()
|
|
|
+const pie_chart_kpi_departure = ref()
|
|
|
+const pie_chart_kpi_arrival = ref()
|
|
|
+const seller_chart_top10_origin = ref()
|
|
|
+const seller_chart_top10_destination = ref()
|
|
|
+const seller_chart_CO2_origin = ref()
|
|
|
+const seller_chart_CO2_destination = ref()
|
|
|
+
|
|
|
+const ClickParams = (val: any) => {
|
|
|
+ const setEstimatedTime = (
|
|
|
+ type: 'ETD' | 'ETA',
|
|
|
+ value: string[],
|
|
|
+ formatType?: 'Container' | 'Revenue'
|
|
|
+ ) => {
|
|
|
+ const parseFormat = formatType === 'Container' ? 'MM/YYYY' : 'MM/DD/YYYY'
|
|
|
+
|
|
|
+ // 处理单个日期字符串的转换函数
|
|
|
+ const transformDate = (dateStr: string): string => {
|
|
|
+ let parsed = dayjs(dateStr, parseFormat, true) // 使用 strict 模式更安全
|
|
|
+
|
|
|
+ // 如果是 Container 格式(MM/YYYY),强制日期为 1 号
|
|
|
+ if (formatType === 'Container') {
|
|
|
+ parsed = parsed.date(1) // 设置为当月 1 日
|
|
|
+ }
|
|
|
+
|
|
|
+ return parsed.format(formatDate)
|
|
|
+ }
|
|
|
+ const config =
|
|
|
+ type === 'ETD'
|
|
|
+ ? {
|
|
|
+ title: 'ETD',
|
|
|
+ key: ['etd_start', 'etd_end']
|
|
|
+ }
|
|
|
+ : {
|
|
|
+ title: 'ETA',
|
|
|
+ key: ['eta_start', 'eta_end']
|
|
|
+ }
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ ...config,
|
|
|
+ value: [transformDate(value[0]), transformDate(value[1])],
|
|
|
+ keyType: 'dateRange'
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ const setTransportMode = (value: any) => {
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: 'Transport Mode',
|
|
|
+ key: 'transport_mode',
|
|
|
+ value: value,
|
|
|
+ keyType: 'array'
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ // KPI Departure点击跳转
|
|
|
+ if (val === 'KPI0') {
|
|
|
+ setEstimatedTime(dashboardObj.KPIDefaulteData.date_type, [
|
|
|
+ dashboardObj.KPIDefaulteData.date_start,
|
|
|
+ dashboardObj.KPIDefaulteData.date_end
|
|
|
+ ])
|
|
|
+ setTransportMode(dashboardObj.KPIDefaulteData.transportation)
|
|
|
+ // KPI Departure点击跳转
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: 'KPI Departure',
|
|
|
+ key: '_reportRef',
|
|
|
+ value: pie_chart_kpi_departure.value[0].paramsdata.name,
|
|
|
+ keyType: 'normal'
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportType',
|
|
|
+ key: '_reportType',
|
|
|
+ value: 'atd_r4',
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ } else if (val === 'KPI1') {
|
|
|
+ setEstimatedTime(dashboardObj.KPIDefaulteData.date_type, [
|
|
|
+ dashboardObj.KPIDefaulteData.date_start,
|
|
|
+ dashboardObj.KPIDefaulteData.date_end
|
|
|
+ ])
|
|
|
+ setTransportMode(dashboardObj.KPIDefaulteData.transportation)
|
|
|
+ // KPI Arrival点击跳转
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: 'KPI Arrival',
|
|
|
+ key: '_reportRef',
|
|
|
+ value: pie_chart_kpi_arrival.value[0]?.paramsdata?.name || '',
|
|
|
+ keyType: 'normal'
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportType',
|
|
|
+ key: '_reportType',
|
|
|
+ value: 'ata_r3',
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ } else if (val === 'Pending0') {
|
|
|
+ setTransportMode(dashboardObj.PendingDefaultData.transportation)
|
|
|
+ // PendingDeparture点击跳转
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: 'Pending Departure',
|
|
|
+ key: '_reportRef',
|
|
|
+ value: pie_chart_pending_departure.value[0].paramsdata.name,
|
|
|
+ keyType: 'normal'
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportType',
|
|
|
+ key: '_reportType',
|
|
|
+ value: 'r4',
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ } else if (val === 'Pending1') {
|
|
|
+ setTransportMode(dashboardObj.PendingDefaultData.transportation)
|
|
|
+ // PendingArrival点击跳转
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: 'Pending Arrival',
|
|
|
+ key: '_reportRef',
|
|
|
+ value: pie_chart_pending_arrival.value[0].paramsdata.name,
|
|
|
+ keyType: 'normal'
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportType',
|
|
|
+ key: '_reportType',
|
|
|
+ value: 'r3',
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ } else if (val === 'ETD to ETA (Days)') {
|
|
|
+ // ETD to ETA(DAYS)点击跳转
|
|
|
+ setEstimatedTime(
|
|
|
+ dashboardObj.ETDDefaultData.date_type,
|
|
|
+ [dashboardObj.ETDDefaultData.date_start, dashboardObj.ETDDefaultData.date_end],
|
|
|
+ 'Container'
|
|
|
+ )
|
|
|
+ setTransportMode(dashboardObj.ETDDefaultData.transportation)
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: 'ETD to ETA (Days)',
|
|
|
+ key: '_reportRef',
|
|
|
+ value: pie_chart_ETD.value[0].paramsdata.name,
|
|
|
+ keyType: 'normal'
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportType',
|
|
|
+ key: '_reportType',
|
|
|
+ value: 'r1',
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportRefe_date',
|
|
|
+ key: ['_reportRefe_date', '_reportRefb_date'],
|
|
|
+ value: [dayjs().startOf('year').format('MM/YYYY'), dayjs().endOf('year').format('MM/YYYY')],
|
|
|
+ keyType: 'dateRange',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ } else if (val === 'Top 10 Origin') {
|
|
|
+ // Top10 origin点击跳转
|
|
|
+ setEstimatedTime(dashboardObj.Top10faultData.date_type, [
|
|
|
+ dashboardObj.Top10faultData.date_start,
|
|
|
+ dashboardObj.Top10faultData.date_end
|
|
|
+ ])
|
|
|
+ setTransportMode(dashboardObj.Top10faultData.transportation)
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: 'Top 10 Origin',
|
|
|
+ key: '_reportRef',
|
|
|
+ value: seller_chart_top10_origin.value[0].paramsdata,
|
|
|
+ keyType: 'normal'
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportType',
|
|
|
+ key: '_reportType',
|
|
|
+ value: 'top',
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportStationType',
|
|
|
+ key: '_reportStationType',
|
|
|
+ value: toporiginType.value,
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: 'Origin',
|
|
|
+ key: 'shipper_city',
|
|
|
+ value: [seller_chart_top10_origin.value[0].paramscityname],
|
|
|
+ keyType: 'array'
|
|
|
+ })
|
|
|
+ } else if (val === 'Top 10 Destination') {
|
|
|
+ setEstimatedTime(dashboardObj.Top10faultData.date_type, [
|
|
|
+ dashboardObj.Top10faultData.date_start,
|
|
|
+ dashboardObj.Top10faultData.date_end
|
|
|
+ ])
|
|
|
+ setTransportMode(dashboardObj.Top10faultData.transportation)
|
|
|
+ // Top10 destination点击跳转
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: 'Top 10 Destination',
|
|
|
+ key: '_reportRef',
|
|
|
+ value: seller_chart_top10_destination.value[0].paramsdata,
|
|
|
+ keyType: 'normal'
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportType',
|
|
|
+ key: '_reportType',
|
|
|
+ value: 'top',
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportStationType',
|
|
|
+ key: '_reportStationType',
|
|
|
+ value: topdestinationinType.value,
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: 'Destination',
|
|
|
+ key: 'consignee_city',
|
|
|
+ value: [seller_chart_top10_destination.value[0].paramscityname],
|
|
|
+ keyType: 'array'
|
|
|
+ })
|
|
|
+ } else if (val === 'CO2e Emission by Origin (Top 10)') {
|
|
|
+ // CO2e Emission by Origin (Top 10)点击跳转
|
|
|
+ setEstimatedTime(dashboardObj.OriginCo2Top10faultData.date_type, [
|
|
|
+ dashboardObj.OriginCo2Top10faultData.date_start,
|
|
|
+ dashboardObj.OriginCo2Top10faultData.date_end
|
|
|
+ ])
|
|
|
+ setTransportMode(dashboardObj.OriginCo2Top10faultData.transportation)
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: 'CO2e Emission by Origin (Top 10)',
|
|
|
+ key: '_reportRef',
|
|
|
+ value: seller_chart_CO2_origin.value[0].paramsdata.name,
|
|
|
+ keyType: 'normal'
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportDataType',
|
|
|
+ key: '_reportDataType',
|
|
|
+ value: seller_chart_CO2_origin.value[0].paramsdata.type,
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportStationType',
|
|
|
+ key: '_reportStationType',
|
|
|
+ value: 'origin',
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportType',
|
|
|
+ key: '_reportType',
|
|
|
+ value: 'co2e',
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ } else if (val === 'CO2e Emission by Destination (Top 10)') {
|
|
|
+ // CO2e Emission by Origin (Top 10)点击跳转
|
|
|
+ setEstimatedTime(dashboardObj.DestinationCo2Top10faultData.date_type, [
|
|
|
+ dashboardObj.DestinationCo2Top10faultData.date_start,
|
|
|
+ dashboardObj.DestinationCo2Top10faultData.date_end
|
|
|
+ ])
|
|
|
+ setTransportMode(dashboardObj.DestinationCo2Top10faultData.transportation)
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: 'CO2e Emission by Destination (Top 10)',
|
|
|
+ key: '_reportRef',
|
|
|
+ value: seller_chart_CO2_destination.value[0].paramsdata.name,
|
|
|
+ keyType: 'normal'
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportDataType',
|
|
|
+ key: '_reportDataType',
|
|
|
+ value: seller_chart_CO2_destination.value[0].paramsdata.type,
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportType',
|
|
|
+ key: '_reportType',
|
|
|
+ value: 'co2e',
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ filtersStore.updateFilter({
|
|
|
+ title: '_reportStationType',
|
|
|
+ key: '_reportStationType',
|
|
|
+ value: 'agent',
|
|
|
+ keyType: 'normal',
|
|
|
+ isHide: true
|
|
|
+ })
|
|
|
+ }
|
|
|
+
|
|
|
+ router.push({
|
|
|
+ path: '/tracking'
|
|
|
+ })
|
|
|
+}
|
|
|
+
|
|
|
+import { useGuideStore } from '@/stores/modules/guide'
|
|
|
+import { useThemeStore } from '@/stores/modules/theme'
|
|
|
+
|
|
|
+import kpiChartTipLight from './tipsImage/kpi-chart-tip.png'
|
|
|
+import kpiChartTipDark from './tipsImage/dark-kpi-chart-tip.png'
|
|
|
+import pendingChartTipLight from './tipsImage/pending-chart-tip.png'
|
|
|
+import pendingChartTipDark from './tipsImage/dark-pending-chart-tip.png'
|
|
|
+import etdToEtaChartsTipLight from './tipsImage/etd-to-eta-chart-tip.png'
|
|
|
+import etdToEtaChartsTipDark from './tipsImage/dark-etd-to-eta-chart-tip.png'
|
|
|
+import containerChartTipLight from './tipsImage/container-count-chart-tip.png'
|
|
|
+import containerChartTipDark from './tipsImage/dark-container-count-chart-tip.png'
|
|
|
+import top10ChartTipLight from './tipsImage/top-10-chart-tip.png'
|
|
|
+import top10ChartTipDark from './tipsImage/dark-top-10-chart-tip.png'
|
|
|
+import co2eChartTipLight from './tipsImage/co2e-chart-tip.png'
|
|
|
+import co2eChartTipDark from './tipsImage/dark-co2e-chart-tip.png'
|
|
|
+import revenueSpentChartTipLight from './tipsImage/revenue-spent-chart-tip.png'
|
|
|
+import revenueSpentChartTipDark from './tipsImage/dark-revenue-spent-chart-tip.png'
|
|
|
+import recentStatusChartTipLight from './tipsImage/recent-status-chart-tip.png'
|
|
|
+import recentStatusChartTipDark from './tipsImage/dark-recent-status-chart-tip.png'
|
|
|
+
|
|
|
+// Guide 图片
|
|
|
+import viewManagementLight from './guideImage/view-management.png'
|
|
|
+import viewManagementDark from './guideImage/dark-view-management.png'
|
|
|
+import saveConfigLight from './guideImage/save-config-guide.png'
|
|
|
+import saveConfigDark from './guideImage/dark-save-config-guide.png'
|
|
|
+import kpiChartLight from './guideImage/kpi-chart-guide.png'
|
|
|
+import kpiChartDark from './guideImage/dark-kpi-chart-guide.png'
|
|
|
+import { set } from 'lodash'
|
|
|
+
|
|
|
+// ====== 2. 主题 store ======
|
|
|
+const themeStore = useThemeStore()
|
|
|
+const guideStore = useGuideStore()
|
|
|
+
|
|
|
+// ====== 3. 工具函数:根据主题返回对应图片 ======
|
|
|
+const getThemeImage = (light: string, dark: string) => {
|
|
|
+ return computed(() => (themeStore.theme === 'dark' ? dark : light))
|
|
|
+}
|
|
|
+
|
|
|
+// ====== 4. 自动生成 computed 图片引用 ======
|
|
|
+// Tips 图片
|
|
|
+const kpiChartTip = getThemeImage(kpiChartTipLight, kpiChartTipDark)
|
|
|
+const pendingChartTip = getThemeImage(pendingChartTipLight, pendingChartTipDark)
|
|
|
+const etdToEtaChartsTip = getThemeImage(etdToEtaChartsTipLight, etdToEtaChartsTipDark)
|
|
|
+const containerChartTip = getThemeImage(containerChartTipLight, containerChartTipDark)
|
|
|
+const top10ChartTip = getThemeImage(top10ChartTipLight, top10ChartTipDark)
|
|
|
+const co2eChartTip = getThemeImage(co2eChartTipLight, co2eChartTipDark)
|
|
|
+const revenueSpentChartTip = getThemeImage(revenueSpentChartTipLight, revenueSpentChartTipDark)
|
|
|
+const recentStatusChartTip = getThemeImage(recentStatusChartTipLight, recentStatusChartTipDark)
|
|
|
+
|
|
|
+// Guide 图片
|
|
|
+const viewManagementImg = getThemeImage(viewManagementLight, viewManagementDark)
|
|
|
+const saveConfigImg = getThemeImage(saveConfigLight, saveConfigDark)
|
|
|
+const kpiChartImg = getThemeImage(kpiChartLight, kpiChartDark)
|
|
|
+
|
|
|
+// ====== 5. 其他逻辑 ======
|
|
|
+const dashboardGuideRef = ref(null)
|
|
|
+const handleGuide = () => {
|
|
|
+ dashboardGuideRef.value?.startGuide()
|
|
|
+}
|
|
|
+</script>
|
|
|
+<template>
|
|
|
+ <div class="dashboard">
|
|
|
+ <!-- 评分 -->
|
|
|
+ <ScoringSystem></ScoringSystem>
|
|
|
+ <DashboardGuide ref="dashboardGuideRef"></DashboardGuide>
|
|
|
+ <!-- Title -->
|
|
|
+ <div class="Title">
|
|
|
+ <div>
|
|
|
+ <span>Dashboard</span>
|
|
|
+ <VDriverGuide style="margin-top: -1px" @click="handleGuide"></VDriverGuide>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <div style="position: relative">
|
|
|
+ <el-popover trigger="click" width="400" popper-style="border-radius: 12px">
|
|
|
+ <template #reference>
|
|
|
+ <el-button class="el-button--default">
|
|
|
+ <span class="iconfont_icon">
|
|
|
+ <svg class="iconfont" aria-hidden="true">
|
|
|
+ <use xlink:href="#icon-icon_view__management_b"></use>
|
|
|
+ </svg>
|
|
|
+ </span>
|
|
|
+ View Management
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+
|
|
|
+ <div class="Management">
|
|
|
+ <div class="title">View Management</div>
|
|
|
+ <div class="management-content">
|
|
|
+ <div class="management-item" v-for="(item, index) in Management" :key="index">
|
|
|
+ <div class="management_flex">
|
|
|
+ <div class="content_title">{{ item.title }}</div>
|
|
|
+ <div>
|
|
|
+ <el-switch
|
|
|
+ v-model="item.switchValue"
|
|
|
+ :disabled="
|
|
|
+ item.isRevenueDisplay != undefined && item.isRevenueDisplay == false
|
|
|
+ "
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <div class="content_text">{{ item.text }}</div>
|
|
|
+ <div
|
|
|
+ class="content_text_warining"
|
|
|
+ v-if="item.isRevenueDisplay != undefined && item.isRevenueDisplay == false"
|
|
|
+ >
|
|
|
+ *To ensure the accuracy of the data display, this report needs to be configured
|
|
|
+ and displayed after communicating clearly with Sales.
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <el-divider style="margin-top: 0; margin-bottom: 8px" />
|
|
|
+ <div class="tips">
|
|
|
+ <span class="iconfont_icon">
|
|
|
+ <svg class="iconfont iconfont_tips" aria-hidden="true">
|
|
|
+ <use xlink:href="#icon-icon_info_b"></use>
|
|
|
+ </svg>
|
|
|
+ </span>
|
|
|
+ <div class="tips_text">
|
|
|
+ Please remember to click the save button in order to keep the new dashboard layout
|
|
|
+ and widgets.
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </el-popover>
|
|
|
+
|
|
|
+ <img
|
|
|
+ id="view-management-guide"
|
|
|
+ v-if="guideStore.dashboard.isShowViewManagementGuidePhoto"
|
|
|
+ class="view-management-guide-class"
|
|
|
+ :class="{
|
|
|
+ 'view-management-guide-dark-class': themeStore.theme === 'dark'
|
|
|
+ }"
|
|
|
+ :src="viewManagementImg"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
+ <el-popover
|
|
|
+ :visible="SaveVisible"
|
|
|
+ :popper-style="{
|
|
|
+ display: 'flex',
|
|
|
+ flexDirection: 'column',
|
|
|
+ alignItems: 'center',
|
|
|
+ padding: '8px 4px',
|
|
|
+ borderRadius: '12px',
|
|
|
+ width: '142px',
|
|
|
+ minWidth: '140px',
|
|
|
+ backgroundColor: 'var(--management-bg-color)'
|
|
|
+ }"
|
|
|
+ >
|
|
|
+ <template #reference>
|
|
|
+ <el-button
|
|
|
+ class="el-button--default"
|
|
|
+ @blur="SaveVisible = false"
|
|
|
+ @click="SaveVisible = !SaveVisible"
|
|
|
+ >
|
|
|
+ <span class="iconfont_icon">
|
|
|
+ <svg class="iconfont" aria-hidden="true">
|
|
|
+ <use xlink:href="#icon-icon_save_b"></use>
|
|
|
+ </svg>
|
|
|
+ </span>
|
|
|
+ Save
|
|
|
+ <span class="iconfont_icon">
|
|
|
+ <svg class="iconfont" aria-hidden="true">
|
|
|
+ <use xlink:href="#icon-icon_dropdown_b"></use>
|
|
|
+ </svg>
|
|
|
+ </span>
|
|
|
+ </el-button>
|
|
|
+ </template>
|
|
|
+ <div class="Save_filters" @click="SaveFilters">
|
|
|
+ <span class="iconfont_icon iconfont_icon_save">
|
|
|
+ <svg class="iconfont" aria-hidden="true">
|
|
|
+ <use xlink:href="#icon-icon_save_b"></use>
|
|
|
+ </svg>
|
|
|
+ </span>
|
|
|
+ <div>Save Filters</div>
|
|
|
+ </div>
|
|
|
+ <div class="Save_filters" @click="SaveLayout">
|
|
|
+ <span class="iconfont_icon iconfont_icon_save">
|
|
|
+ <svg class="iconfont" aria-hidden="true">
|
|
|
+ <use xlink:href="#icon-icon_save_b"></use>
|
|
|
+ </svg>
|
|
|
+ </span>
|
|
|
+ <div>Save Layout</div>
|
|
|
+ </div>
|
|
|
+ </el-popover>
|
|
|
+
|
|
|
+ <!-- -->
|
|
|
+ <img
|
|
|
+ id="save-config-guide"
|
|
|
+ v-if="guideStore.dashboard.isShowSaveConfigGuidePhoto"
|
|
|
+ class="save-config-guide-class position-absolute-guide"
|
|
|
+ :src="saveConfigImg"
|
|
|
+ :class="{
|
|
|
+ 'save-config-guide-dark-class': themeStore.theme === 'dark'
|
|
|
+ }"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ <!-- 图表 -->
|
|
|
+ <div class="echarts">
|
|
|
+ <VueDraggable
|
|
|
+ style="
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 8px;
|
|
|
+ width: 100%;
|
|
|
+ "
|
|
|
+ ref="infoContentRef"
|
|
|
+ ghost-class="ghost-class"
|
|
|
+ :forceFallback="true"
|
|
|
+ fallback-class="fallback-class"
|
|
|
+ v-model="Management"
|
|
|
+ handle=".handle-draggable"
|
|
|
+ >
|
|
|
+ <template v-for="item in Management" :key="item">
|
|
|
+ <div v-if="item.title === 'KPI' && item.switchValue" class="filters_left">
|
|
|
+ <!-- KPI -->
|
|
|
+ <VBox_Dashboard
|
|
|
+ style="overflow: visible"
|
|
|
+ @changeCancel="changeCancel(item.id)"
|
|
|
+ :isShowDragIconGudie="true"
|
|
|
+ >
|
|
|
+ <template #header>
|
|
|
+ <div class="Title_flex" style="position: relative">
|
|
|
+ <img
|
|
|
+ id="kpi-chart-guide"
|
|
|
+ v-if="guideStore.dashboard.isShowKpiChartGuidePhoto"
|
|
|
+ class="kpi-chart-guide-class position-absolute-guide"
|
|
|
+ :src="kpiChartImg"
|
|
|
+ alt=""
|
|
|
+ />
|
|
|
+ <div>
|
|
|
+ {{ item.title }}
|
|
|
+ <VTipTooltip
|
|
|
+ :img="kpiChartTip"
|
|
|
+ :width="410"
|
|
|
+ :label="'KPI Report:Day difference between actual and estimate.'"
|
|
|
+ placement="bottom-start"
|
|
|
+ ></VTipTooltip>
|
|
|
+ </div>
|
|
|
+ <DashFilters
|
|
|
+ :defaultData="KPIDefaulteData"
|
|
|
+ :isShowTransportModeGuide="true"
|
|
|
+ @FilterSearch="GetKpiData"
|
|
|
+ ></DashFilters>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #content>
|
|
|
+ <div class="KPI_Pending">
|
|
|
+ <div class="kpi">
|
|
|
+ <PieChart
|
|
|
+ ref="pie_chart_kpi_departure"
|
|
|
+ @ClickParams="ClickParams(item.title + '0')"
|
|
|
+ :PieData="KPIobj"
|
|
|
+ v-vloading="KPILoading"
|
|
|
+ style="height: 300px"
|
|
|
+ ></PieChart>
|
|
|
+ </div>
|
|
|
+ <div class="kpi">
|
|
|
+ <PieChart
|
|
|
+ ref="pie_chart_kpi_arrival"
|
|
|
+ :PieData="Arrivalobj"
|
|
|
+ v-vloading="KPIArrivalLoading"
|
|
|
+ @ClickParams="ClickParams(item.title + '1')"
|
|
|
+ style="height: 300px"
|
|
|
+ ></PieChart>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </VBox_Dashboard>
|
|
|
+ </div>
|
|
|
+ <div v-else-if="item.title === 'Pending' && item.switchValue" class="filters_left">
|
|
|
+ <!-- Pending -->
|
|
|
+ <VBox_Dashboard @changeCancel="changeCancel(item.id)">
|
|
|
+ <template #header>
|
|
|
+ <div class="Title_flex">
|
|
|
+ <div>
|
|
|
+ {{ item.title }}
|
|
|
+ <VTipTooltip
|
|
|
+ :img="pendingChartTip"
|
|
|
+ :width="420"
|
|
|
+ :placement="'bottom-start'"
|
|
|
+ :label="'Pending Report:Showing shipments which are soon to depart/arrive.'"
|
|
|
+ ></VTipTooltip>
|
|
|
+ </div>
|
|
|
+ <DashFilters
|
|
|
+ :defaultData="PendingDefaulteData"
|
|
|
+ :radioisDisabled="true"
|
|
|
+ :img="'./image/kpi-chart-tip.png'"
|
|
|
+ @FilterSearch="GetPendingEcharts"
|
|
|
+ ></DashFilters>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #content>
|
|
|
+ <div class="KPI_Pending">
|
|
|
+ <div class="kpi">
|
|
|
+ <PieChart
|
|
|
+ ref="pie_chart_pending_departure"
|
|
|
+ :PieData="Pendingobj"
|
|
|
+ v-vloading="PendingLoading"
|
|
|
+ @ClickParams="ClickParams(item.title + '0')"
|
|
|
+ style="height: 300px"
|
|
|
+ ></PieChart>
|
|
|
+ </div>
|
|
|
+ <div class="kpi">
|
|
|
+ <PieChart
|
|
|
+ ref="pie_chart_pending_arrival"
|
|
|
+ @ClickParams="ClickParams(item.title + '1')"
|
|
|
+ :PieData="PendingArrivalobj"
|
|
|
+ v-vloading="PendingArrivalLoading"
|
|
|
+ style="height: 300px"
|
|
|
+ ></PieChart>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </VBox_Dashboard>
|
|
|
+ </div>
|
|
|
+ <!-- ETD to ETA -->
|
|
|
+ <div
|
|
|
+ v-else-if="item.title === 'ETD to ETA (Days)' && item.switchValue"
|
|
|
+ class="filters_left"
|
|
|
+ >
|
|
|
+ <VBox_Dashboard @changeCancel="changeCancel(item.id)">
|
|
|
+ <template #header>
|
|
|
+ <div class="Title_flex">
|
|
|
+ <div>
|
|
|
+ {{ item.title }}
|
|
|
+ <VTipTooltip
|
|
|
+ :img="etdToEtaChartsTip"
|
|
|
+ :width="430"
|
|
|
+ :placement="'bottom-start'"
|
|
|
+ :label="'ETD to ETA (Days):Distribution of Transit Time (ETA-ETD) for All Shipments in Last 12 Months.'"
|
|
|
+ ></VTipTooltip>
|
|
|
+ </div>
|
|
|
+ <DashFilters
|
|
|
+ :defaultData="ETDDefaulteData"
|
|
|
+ @FilterSearch="GetETDEcharts"
|
|
|
+ :isETDToETA="true"
|
|
|
+ :isContainer="true"
|
|
|
+ ></DashFilters>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #content>
|
|
|
+ <PieChart
|
|
|
+ ref="pie_chart_ETD"
|
|
|
+ @ClickParams="ClickParams(item.title)"
|
|
|
+ :PieData="ETDobj"
|
|
|
+ v-vloading="ETDLoading"
|
|
|
+ style="height: 300px"
|
|
|
+ ></PieChart>
|
|
|
+ </template>
|
|
|
+ </VBox_Dashboard>
|
|
|
+ </div>
|
|
|
+ <!-- Container Count -->
|
|
|
+ <div
|
|
|
+ v-else-if="item.title === 'Container Count' && item.switchValue"
|
|
|
+ class="filters_left"
|
|
|
+ >
|
|
|
+ <VBox_Dashboard @changeCancel="changeCancel(item.id)">
|
|
|
+ <template #header>
|
|
|
+ <div class="Title_flex">
|
|
|
+ <div>
|
|
|
+ {{ item.title }}
|
|
|
+ <VTipTooltip
|
|
|
+ :img="containerChartTip"
|
|
|
+ :placement="'bottom-start'"
|
|
|
+ :label="'Container Count:Total Container Volume by Month (Last 12 Months)'"
|
|
|
+ ></VTipTooltip>
|
|
|
+ </div>
|
|
|
+ <DashFilters
|
|
|
+ :defaultData="ContainerefaultData"
|
|
|
+ @FilterSearch="GetContainerCountEcharts"
|
|
|
+ :isContainer="true"
|
|
|
+ ></DashFilters>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #content>
|
|
|
+ <BarChart
|
|
|
+ ref="seller_chart_Container_count"
|
|
|
+ :BarData="containerObj"
|
|
|
+ v-vloading="containerLoading"
|
|
|
+ style="height: 300px"
|
|
|
+ :isRevenue="true"
|
|
|
+ save-image-name="Container Count"
|
|
|
+ :barHeight="{ height: '300px' }"
|
|
|
+ ></BarChart>
|
|
|
+ </template>
|
|
|
+ </VBox_Dashboard>
|
|
|
+ </div>
|
|
|
+ <!-- Top10 Origin/Top 10 Destination -->
|
|
|
+ <div
|
|
|
+ v-else-if="item.title === 'Top 10 Origin/Destination' && item.switchValue"
|
|
|
+ class="KPI_Pending"
|
|
|
+ >
|
|
|
+ <VBox_Dashboard @changeCancel="changeCancel(item.id)" style="width: 100%">
|
|
|
+ <template #header>
|
|
|
+ <div class="Title_flex" style="height: 48px">
|
|
|
+ <div style="display: flex">
|
|
|
+ <el-tabs
|
|
|
+ v-model="activeName"
|
|
|
+ class="demo-tabs"
|
|
|
+ style="height: 48px"
|
|
|
+ @tab-click="handleTabClick"
|
|
|
+ >
|
|
|
+ <el-tab-pane :label="item.title1" name="first"></el-tab-pane>
|
|
|
+ <el-tab-pane :label="item.title2" name="second"></el-tab-pane>
|
|
|
+ </el-tabs>
|
|
|
+ <VTipTooltip
|
|
|
+ style="margin-left: 4px"
|
|
|
+ :img="top10ChartTip"
|
|
|
+ :label="'Top 10 Origin & Destination: Last 12 Months Shipment Volume Rankings: Top 10 Origin Cities and Top 10 Destination Cities'"
|
|
|
+ :width="700"
|
|
|
+ ></VTipTooltip>
|
|
|
+ </div>
|
|
|
+ <DashFilters
|
|
|
+ :defaultData="Top10DefaultData"
|
|
|
+ @FilterSearch="GetTop10ODEcharts"
|
|
|
+ ></DashFilters>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-if="isShowtitle1" #content>
|
|
|
+ <div class="KPI_Pending">
|
|
|
+ <div class="seller_chart">
|
|
|
+ <SellerChart
|
|
|
+ ref="seller_chart_top10_origin"
|
|
|
+ @clickParams="ClickParams(item.title1)"
|
|
|
+ :SellerData="Top10Obj.OriginData"
|
|
|
+ v-vloading="TopOriginLoading"
|
|
|
+ :Interval="Top1OInterval"
|
|
|
+ saveImageName="Top 10 Origin"
|
|
|
+ ></SellerChart>
|
|
|
+ </div>
|
|
|
+ <div class="map">
|
|
|
+ <!-- <TopMap :obj="dashboardObj.Top10faultData" ref="Top10Originref"></TopMap> -->
|
|
|
+ <TopMap ref="Top10Originref"></TopMap>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template v-else #content2>
|
|
|
+ <div class="KPI_Pending">
|
|
|
+ <div class="seller_chart">
|
|
|
+ <SellerChart
|
|
|
+ ref="seller_chart_top10_destination"
|
|
|
+ @clickParams="ClickParams(item.title2)"
|
|
|
+ :SellerData="Top10Obj.DestinationData"
|
|
|
+ :Interval="Top1OInterval_dest"
|
|
|
+ v-vloading="TopOriginLoading"
|
|
|
+ saveImageName="Top 10 Destination"
|
|
|
+ style="height: 310px"
|
|
|
+ ></SellerChart>
|
|
|
+ </div>
|
|
|
+ <div class="map" style="height: 310px">
|
|
|
+ <!-- <TopMap :obj="dashboardObj.Top10faultData" ref="Top10Destinationref"></TopMap> -->
|
|
|
+ <TopMap ref="Top10Destinationref"></TopMap>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </VBox_Dashboard>
|
|
|
+ </div>
|
|
|
+ <!-- CO2e Emission by Origin (Top 10) -->
|
|
|
+ <div
|
|
|
+ v-else-if="item.title === 'CO2e Emission by Origin (Top 10)' && item.switchValue"
|
|
|
+ class="filters_left"
|
|
|
+ >
|
|
|
+ <VBox_Dashboard @changeCancel="changeCancel(item.id)">
|
|
|
+ <template #header>
|
|
|
+ <div class="Title_flex">
|
|
|
+ <div>
|
|
|
+ {{ item.title }}
|
|
|
+ <VTipTooltip
|
|
|
+ :img="co2eChartTip"
|
|
|
+ :label="'CO2e Emission by Origin or Destination: Last 12 Months CO2e Emission Rankings: Top 10 Origin Cities and Top 10 Destination Cities'"
|
|
|
+ :width="700"
|
|
|
+ :placement="'bottom-start'"
|
|
|
+ ></VTipTooltip>
|
|
|
+ </div>
|
|
|
+ <DashFilters
|
|
|
+ :defaultData="Co2OriginDefaultData"
|
|
|
+ @FilterSearch="GetCo2EmissionEcharts"
|
|
|
+ ></DashFilters>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #content>
|
|
|
+ <BarChart
|
|
|
+ ref="seller_chart_CO2_origin"
|
|
|
+ :BarData="EmissionObj"
|
|
|
+ save-image-name="CO2e Emission by Origin (Top 10)"
|
|
|
+ @clickParams="ClickParams(item.title)"
|
|
|
+ v-vloading="EmissionLoading"
|
|
|
+ style="height: 250px"
|
|
|
+ :isRevenue="true"
|
|
|
+ :barHeight="{ height: '250px' }"
|
|
|
+ ></BarChart>
|
|
|
+ </template>
|
|
|
+ </VBox_Dashboard>
|
|
|
+ </div>
|
|
|
+ <!-- CO2e Emission by Destination (Top 10) -->
|
|
|
+ <div
|
|
|
+ v-else-if="item.title === 'CO2e Emission by Destination (Top 10)' && item.switchValue"
|
|
|
+ class="filters_left"
|
|
|
+ >
|
|
|
+ <VBox_Dashboard @changeCancel="changeCancel(item.id)">
|
|
|
+ <template #header>
|
|
|
+ <div class="Title_flex">
|
|
|
+ <div>
|
|
|
+ {{ item.title }}
|
|
|
+ <!-- <VTipTooltip :img="co2eChartTip"></VTipTooltip> -->
|
|
|
+ </div>
|
|
|
+ <DashFilters
|
|
|
+ :defaultData="Co2DestinationDefaultData"
|
|
|
+ @FilterSearch="GetCo2DestinationEcharts"
|
|
|
+ ></DashFilters>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #content>
|
|
|
+ <BarChart
|
|
|
+ ref="seller_chart_CO2_destination"
|
|
|
+ :BarData="DestinationObj"
|
|
|
+ v-vloading="DestinationLoading"
|
|
|
+ style="height: 250px"
|
|
|
+ :isRevenue="true"
|
|
|
+ save-image-name="CO2e Emission by Destination (Top 10)"
|
|
|
+ @clickParams="ClickParams(item.title)"
|
|
|
+ :barHeight="{ height: '250px' }"
|
|
|
+ ></BarChart>
|
|
|
+ </template>
|
|
|
+ </VBox_Dashboard>
|
|
|
+ </div>
|
|
|
+ <!-- <div
|
|
|
+ v-else-if="item.title === 'Revenue' && item.switchValue"
|
|
|
+ class="KPI_Pending"
|
|
|
+ > -->
|
|
|
+ <div
|
|
|
+ v-else-if="
|
|
|
+ item.title === 'Recent Status' && item.switchValue && RecentStatusList.length != 0
|
|
|
+ "
|
|
|
+ class="KPI_Pending"
|
|
|
+ >
|
|
|
+ <!-- Recent Status -->
|
|
|
+ <VBox_Dashboard @changeCancel="changeCancel(item.id)" style="width: 100%">
|
|
|
+ <template #header>
|
|
|
+ <div class="Title_flex">
|
|
|
+ <div>
|
|
|
+ {{ item.title }}
|
|
|
+ <VTipTooltip
|
|
|
+ :img="recentStatusChartTip"
|
|
|
+ :label="'Recent Status: Active shipment list with ETD within the past three months and the next month.'"
|
|
|
+ :width="700"
|
|
|
+ :placement="'bottom-start'"
|
|
|
+ ></VTipTooltip>
|
|
|
+ </div>
|
|
|
+ <DashFilters
|
|
|
+ :defaultData="RecentDefaulteData"
|
|
|
+ @FilterSearch="getTableData"
|
|
|
+ :isRecent="true"
|
|
|
+ ></DashFilters>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #content>
|
|
|
+ <RecentStatus :RecentStatusList="RecentStatusList"></RecentStatus>
|
|
|
+ <div class="pagination">
|
|
|
+ <span>Total {{ formatNumber(pageInfo.total) }}</span>
|
|
|
+ <el-pagination
|
|
|
+ v-model:current-page="pageInfo.pageNo"
|
|
|
+ v-model:page-size="pageInfo.pageSize"
|
|
|
+ :page-sizes="[10, 50, 100, 200]"
|
|
|
+ layout="prev, pager, next"
|
|
|
+ :pager-count="3"
|
|
|
+ :total="pageInfo.total"
|
|
|
+ @size-change="getTableData(true, RecentDefaulteData)"
|
|
|
+ @current-change="getTableData(true, RecentDefaulteData)"
|
|
|
+ />
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </VBox_Dashboard>
|
|
|
+ </div>
|
|
|
+ <!-- Revenue -->
|
|
|
+ <div v-else-if="item.title === 'Revenue Spent' && item.switchValue" class="KPI_Pending">
|
|
|
+ <VBox_Dashboard @changeCancel="changeCancel(item.id)" style="width: 100%">
|
|
|
+ <template #header>
|
|
|
+ <div class="Title_flex">
|
|
|
+ <div>
|
|
|
+ Revenue Spent
|
|
|
+ <VTipTooltip
|
|
|
+ :img="revenueSpentChartTip"
|
|
|
+ :label="'Revenue Spent: Based on the billto object, display the corresponding revenue data. '"
|
|
|
+ :placement="'bottom-start'"
|
|
|
+ :width="700"
|
|
|
+ ></VTipTooltip>
|
|
|
+ </div>
|
|
|
+
|
|
|
+ <DashFilters
|
|
|
+ :defaultData="RevenueDefaultData"
|
|
|
+ @FilterSearch="GetRevenueEcharts"
|
|
|
+ :isRevenue="true"
|
|
|
+ :isContainer="true"
|
|
|
+ ></DashFilters>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ <template #content>
|
|
|
+ <RevenueChart
|
|
|
+ :BarData="RevenueObj"
|
|
|
+ v-vloading="RevenueLoading"
|
|
|
+ :RevenueStartDate="revenue_date_start"
|
|
|
+ :RevenueEndDate="revenue_date_end"
|
|
|
+ style="height: 300px"
|
|
|
+ :barHeight="{ height: '300px' }"
|
|
|
+ ></RevenueChart>
|
|
|
+ </template>
|
|
|
+ </VBox_Dashboard>
|
|
|
+ </div>
|
|
|
+ </template>
|
|
|
+ </VueDraggable>
|
|
|
+ </div>
|
|
|
+ </div>
|
|
|
+</template>
|
|
|
+<style lang="scss" scoped>
|
|
|
+.Title {
|
|
|
+ display: flex;
|
|
|
+ background-color: var(--color-mode);
|
|
|
+ height: 68px;
|
|
|
+ font-size: var(--font-size-6);
|
|
|
+ font-weight: 700;
|
|
|
+ padding: 0 24px;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+.iconfont {
|
|
|
+ vertical-align: -2px;
|
|
|
+}
|
|
|
+
|
|
|
+.view-management-guide-class {
|
|
|
+ position: absolute;
|
|
|
+ top: 0px;
|
|
|
+ right: 85px;
|
|
|
+ width: 437px;
|
|
|
+ height: 603px;
|
|
|
+ z-index: 1500;
|
|
|
+ &.view-management-guide-dark-class {
|
|
|
+ width: 439px;
|
|
|
+ height: 622px;
|
|
|
+ }
|
|
|
+}
|
|
|
+.save-config-guide-class {
|
|
|
+ position: absolute;
|
|
|
+ top: -1px;
|
|
|
+ right: -13px;
|
|
|
+ width: 183px;
|
|
|
+ height: 160px;
|
|
|
+ z-index: 1500;
|
|
|
+ transform: translate(-0.8px, 0px);
|
|
|
+ &.save-config-guide-dark-class {
|
|
|
+ width: 182px;
|
|
|
+ height: 157px;
|
|
|
+ right: -12px;
|
|
|
+ }
|
|
|
+}
|
|
|
+.kpi-chart-guide-class {
|
|
|
+ top: -2px;
|
|
|
+ left: -50px;
|
|
|
+ width: 589px;
|
|
|
+ height: 478px;
|
|
|
+ z-index: 3500;
|
|
|
+}
|
|
|
+
|
|
|
+.Management {
|
|
|
+ max-height: 640px;
|
|
|
+ overflow: hidden;
|
|
|
+ border-radius: 12px;
|
|
|
+ background-color: var(--management-bg-color);
|
|
|
+}
|
|
|
+
|
|
|
+.management-content {
|
|
|
+ overflow-y: auto;
|
|
|
+ max-height: 533px;
|
|
|
+}
|
|
|
+.title {
|
|
|
+ font-weight: 700;
|
|
|
+ font-size: var(--font-size-5);
|
|
|
+ background-color: var(--color-header-bg);
|
|
|
+ height: 48px;
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ padding-left: 16px;
|
|
|
+}
|
|
|
+.management-item {
|
|
|
+ width: 368px;
|
|
|
+ min-height: 54px;
|
|
|
+ margin: 10px auto;
|
|
|
+ background-color: var(--color-header-bg);
|
|
|
+ border-radius: var(--border-radius-6);
|
|
|
+ padding: 8px 16px;
|
|
|
+}
|
|
|
+.management_flex {
|
|
|
+ display: flex;
|
|
|
+ height: 20px;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+}
|
|
|
+.content_title {
|
|
|
+ font-weight: 700;
|
|
|
+ font-size: var(--font-size-3);
|
|
|
+}
|
|
|
+.content_text {
|
|
|
+ color: var(--color-neutral-2);
|
|
|
+ font-size: var(--font-size-2);
|
|
|
+ line-height: 16px;
|
|
|
+}
|
|
|
+.content_text_warining {
|
|
|
+ color: var(--color-warning);
|
|
|
+ font-size: var(--font-size-2);
|
|
|
+ line-height: 16px;
|
|
|
+}
|
|
|
+.tips {
|
|
|
+ display: flex;
|
|
|
+ justify-content: center;
|
|
|
+ padding-bottom: 8px;
|
|
|
+}
|
|
|
+.iconfont_tips {
|
|
|
+ fill: var(--color-neutral-2);
|
|
|
+}
|
|
|
+.tips_text {
|
|
|
+ width: 278.43px;
|
|
|
+ text-align: center;
|
|
|
+ font-size: var(--font-size-2);
|
|
|
+ color: var(--color-neutral-2);
|
|
|
+}
|
|
|
+
|
|
|
+.Save_filters {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: center;
|
|
|
+ height: 40px;
|
|
|
+ font-size: var(--font-size-3);
|
|
|
+ width: 126px;
|
|
|
+ border-radius: 6px;
|
|
|
+ cursor: pointer;
|
|
|
+}
|
|
|
+.iconfont_icon_save {
|
|
|
+ margin-right: 16px;
|
|
|
+ fill: var(--color-neutral-1);
|
|
|
+}
|
|
|
+.Save_filters:hover {
|
|
|
+ border-color: var(--color-btn-default-bg-hover);
|
|
|
+ background-color: var(--color-btn-default-bg-hover);
|
|
|
+ .iconfont_icon_save {
|
|
|
+ fill: var(--color-theme);
|
|
|
+ }
|
|
|
+ div {
|
|
|
+ color: var(--color-theme);
|
|
|
+ }
|
|
|
+}
|
|
|
+.filters {
|
|
|
+ display: flex;
|
|
|
+ padding: 0 24px;
|
|
|
+ height: 32px;
|
|
|
+ align-items: center;
|
|
|
+ margin-bottom: 8px;
|
|
|
+ justify-content: space-between;
|
|
|
+}
|
|
|
+.KPI_Pending {
|
|
|
+ display: flex;
|
|
|
+ width: 100%;
|
|
|
+}
|
|
|
+.filters_left {
|
|
|
+ border-radius: var(--border-radius-6);
|
|
|
+ width: calc(50% - 4px);
|
|
|
+ flex: 0 0 calc(50% - 4px);
|
|
|
+ min-width: 0;
|
|
|
+ box-sizing: border-box;
|
|
|
+}
|
|
|
+
|
|
|
+:deep(.ETD_title) {
|
|
|
+ margin-bottom: 0 !important;
|
|
|
+}
|
|
|
+:deep(:where(.css-dev-only-do-not-override-19iuou).ant-picker-range) {
|
|
|
+ height: 32px;
|
|
|
+}
|
|
|
+.echarts {
|
|
|
+ padding: 0 22px;
|
|
|
+ background-color: var(--color-mode);
|
|
|
+ :deep(> div) {
|
|
|
+ display: flex;
|
|
|
+ flex-wrap: wrap;
|
|
|
+ justify-content: space-between;
|
|
|
+ gap: 8px;
|
|
|
+ width: 100%;
|
|
|
+ > * {
|
|
|
+ box-sizing: border-box;
|
|
|
+ }
|
|
|
+ }
|
|
|
+}
|
|
|
+.kpi {
|
|
|
+ width: 50%;
|
|
|
+ border-right: 1px solid var(--color-border);
|
|
|
+}
|
|
|
+.kpi:last-child {
|
|
|
+ border-right: none;
|
|
|
+}
|
|
|
+.ghost-class {
|
|
|
+ opacity: 0;
|
|
|
+}
|
|
|
+.fallback-class {
|
|
|
+ opacity: 1 !important;
|
|
|
+ background-color: var(--color-v-box-content-drag-bg);
|
|
|
+ cursor: move !important;
|
|
|
+ box-shadow: 4px 4px 32px 0px rgba(0, 0, 0, 0.2);
|
|
|
+ border-radius: 12px;
|
|
|
+}
|
|
|
+.pagination {
|
|
|
+ display: flex;
|
|
|
+ justify-content: space-between;
|
|
|
+ align-items: center;
|
|
|
+ border-top: 1px solid var(--color-border);
|
|
|
+ padding: 4px 8px;
|
|
|
+}
|
|
|
+
|
|
|
+.seller_chart {
|
|
|
+ width: 30%;
|
|
|
+ border-right: 1px solid var(--color-border);
|
|
|
+}
|
|
|
+.map {
|
|
|
+ width: 70%;
|
|
|
+}
|
|
|
+.Title_flex {
|
|
|
+ display: flex;
|
|
|
+ align-items: center;
|
|
|
+ justify-content: space-between;
|
|
|
+ margin-right: 30px;
|
|
|
+}
|
|
|
+
|
|
|
+.dashboard {
|
|
|
+ z-index: 2014;
|
|
|
+ position: relative;
|
|
|
+ background-color: var(--color-mode);
|
|
|
+ padding-bottom: 40px;
|
|
|
+}
|
|
|
+:deep(.el-tabs__header) {
|
|
|
+ height: 48px;
|
|
|
+ margin-bottom: 0;
|
|
|
+}
|
|
|
+</style>
|
|
|
+<style lang="scss">
|
|
|
+:not(body):has(> img.driver-active-element) {
|
|
|
+ overflow: visible !important;
|
|
|
+}
|
|
|
+</style>
|