first commit
This commit is contained in:
@@ -0,0 +1,258 @@
|
||||
<template>
|
||||
<view class="business-data-page">
|
||||
<!-- 使用子头部组件 -->
|
||||
<sub-header
|
||||
title="业务数据总览"
|
||||
@goBack="goBack"
|
||||
@showMoreOptions="showMoreOptions"
|
||||
/>
|
||||
|
||||
<!-- 数据分类列表 -->
|
||||
<view class="data-categories">
|
||||
<view
|
||||
class="category-item"
|
||||
v-for="category in dataCategories"
|
||||
:key="category.id"
|
||||
@click="navigateToDetail(category)"
|
||||
>
|
||||
<view
|
||||
class="category-icon"
|
||||
:style="{ backgroundColor: category.bgColor }"
|
||||
>
|
||||
<i :class="category.icon"></i>
|
||||
</view>
|
||||
<view class="category-content">
|
||||
<view class="category-title">{{ category.title }}</view>
|
||||
<view class="category-desc">{{ category.description }}</view>
|
||||
<view class="category-stats">
|
||||
<text class="stat-item">{{ category.dataCount }}个数据源</text>
|
||||
<text class="stat-item">{{ category.updateTime }}</text>
|
||||
</view>
|
||||
</view>
|
||||
<view class="category-arrow">
|
||||
<i class="fas fa-chevron-right"></i>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref } from "vue";
|
||||
import SubHeader from "../components/subHeader.vue";
|
||||
|
||||
// 数据分类列表
|
||||
const dataCategories = ref([
|
||||
{
|
||||
id: 1,
|
||||
title: "港口数据",
|
||||
description: "港口吞吐量等相关数据",
|
||||
icon: "fas fa-chart-line",
|
||||
bgColor: "#4ECDC4",
|
||||
dataCount: 8,
|
||||
updateTime: "2小时前更新",
|
||||
},
|
||||
{
|
||||
id: 2,
|
||||
title: "财务数据",
|
||||
description: "收入、支出、报销、预算等财务相关数据",
|
||||
icon: "fas fa-money-bill-wave",
|
||||
bgColor: "#FECA57",
|
||||
dataCount: 12,
|
||||
updateTime: "1小时前更新",
|
||||
},
|
||||
{
|
||||
id: 3,
|
||||
title: "客户数据",
|
||||
description: "客户信息、满意度、活跃度等客户相关数据",
|
||||
icon: "fas fa-user-friends",
|
||||
bgColor: "#45B7D1",
|
||||
dataCount: 6,
|
||||
updateTime: "30分钟前更新",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: "运营数据",
|
||||
description: "访问量、转化率、用户行为等运营相关数据",
|
||||
icon: "fas fa-chart-bar",
|
||||
bgColor: "#FF6B6B",
|
||||
dataCount: 10,
|
||||
updateTime: "15分钟前更新",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: "人力资源数据",
|
||||
description: "员工信息、考勤、绩效等人力资源相关数据",
|
||||
icon: "fas fa-users",
|
||||
bgColor: "#96CEB4",
|
||||
dataCount: 15,
|
||||
updateTime: "1天前更新",
|
||||
},
|
||||
{
|
||||
id: 6,
|
||||
title: "项目数据",
|
||||
description: "项目进度、任务完成情况、资源分配等项目相关数据",
|
||||
icon: "fas fa-project-diagram",
|
||||
bgColor: "#A8E6CF",
|
||||
dataCount: 9,
|
||||
updateTime: "3小时前更新",
|
||||
},
|
||||
]);
|
||||
|
||||
// 导航到详情页面
|
||||
const navigateToDetail = (category) => {
|
||||
// 特殊处理港口数据,直接跳转到portData页面
|
||||
if (category.id === 1) {
|
||||
uni.navigateTo({
|
||||
url: "/pages/businessDatas/portData",
|
||||
});
|
||||
} else {
|
||||
// 其他数据跳转到通用详情页面
|
||||
uni.navigateTo({
|
||||
url: `/pages/businessDatas/detail?categoryId=${category.id}&title=${category.title}`,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 头部相关方法
|
||||
const goBack = () => {
|
||||
uni.navigateBack();
|
||||
};
|
||||
|
||||
const showMoreOptions = () => {
|
||||
uni.showActionSheet({
|
||||
itemList: ["刷新", "返回首页"],
|
||||
success: (res) => {
|
||||
switch (res.tapIndex) {
|
||||
case 0:
|
||||
// 刷新数据
|
||||
uni.reLaunch({
|
||||
url: "/pages/businessDatas/index",
|
||||
});
|
||||
uni.showToast({ title: "数据已刷新", icon: "success" });
|
||||
break;
|
||||
case 1:
|
||||
uni.reLaunch({
|
||||
url: "/pages/index/index",
|
||||
});
|
||||
uni.showToast({ title: "已返回工作台", icon: "success" });
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.business-data-page {
|
||||
background: #f9f9fb;
|
||||
min-height: 100vh;
|
||||
padding-top: calc(var(--status-bar-height) + 88rpx);
|
||||
padding-bottom: 40rpx;
|
||||
}
|
||||
|
||||
/* 支持安全区域的设备 */
|
||||
@supports (padding: max(0px)) {
|
||||
.business-data-page {
|
||||
padding-top: calc(
|
||||
var(--status-bar-height) + 88rpx + env(safe-area-inset-top)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
/* 数据分类列表 */
|
||||
.data-categories {
|
||||
padding: 24rpx;
|
||||
}
|
||||
|
||||
.category-item {
|
||||
background: #fff;
|
||||
border-radius: 16rpx;
|
||||
padding: 32rpx 24rpx;
|
||||
margin-bottom: 20rpx;
|
||||
box-shadow: 0 4rpx 12rpx rgba(0, 0, 0, 0.05);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
transition: all 0.3s ease;
|
||||
border: 1rpx solid #f0f0f0;
|
||||
|
||||
&:active {
|
||||
transform: scale(0.98);
|
||||
box-shadow: 0 2rpx 8rpx rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
&:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.category-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
border-radius: 20rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
margin-right: 24rpx;
|
||||
flex-shrink: 0;
|
||||
|
||||
i {
|
||||
font-size: 36rpx;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.category-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.category-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: #333;
|
||||
margin-bottom: 8rpx;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
.category-desc {
|
||||
font-size: 26rpx;
|
||||
color: #666;
|
||||
margin-bottom: 12rpx;
|
||||
line-height: 1.4;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
line-clamp: 2;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.category-stats {
|
||||
display: flex;
|
||||
gap: 20rpx;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
.stat-item {
|
||||
font-size: 22rpx;
|
||||
color: #999;
|
||||
background: #f5f5f5;
|
||||
padding: 4rpx 12rpx;
|
||||
border-radius: 12rpx;
|
||||
line-height: 1.2;
|
||||
}
|
||||
|
||||
.category-arrow {
|
||||
width: 40rpx;
|
||||
height: 40rpx;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
color: #ccc;
|
||||
flex-shrink: 0;
|
||||
|
||||
i {
|
||||
font-size: 24rpx;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
@@ -0,0 +1,810 @@
|
||||
<template>
|
||||
<view class="data-detail-page" :class="{ mobile: isMobile }">
|
||||
<!-- 页面头部 -->
|
||||
<sub-header
|
||||
title="港口数据"
|
||||
@goBack="goBack"
|
||||
@showMoreOptions="showMoreOptions"
|
||||
/>
|
||||
|
||||
<!-- 数据卡片 -->
|
||||
<view class="cards-section">
|
||||
<view class="section-title">数据概览</view>
|
||||
<view class="card-grid">
|
||||
<view v-for="card in cardData" :key="card.id" class="data-card">
|
||||
<view class="card-icon">
|
||||
<i :class="card.icon"></i>
|
||||
</view>
|
||||
<view class="card-content">
|
||||
<text class="card-value">{{ card.value }}</text>
|
||||
<text class="card-label">{{ card.title }}</text>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 图表分析 -->
|
||||
<view class="charts-section">
|
||||
<view class="section-title">图表分析</view>
|
||||
<view class="chart-tabs">
|
||||
<view
|
||||
class="chart-tab"
|
||||
:class="{ active: activeTab === 'cargo' }"
|
||||
@click="switchTab('cargo')"
|
||||
>
|
||||
船舶作业货物信息
|
||||
</view>
|
||||
<view
|
||||
class="chart-tab"
|
||||
:class="{ active: activeTab === 'customer' }"
|
||||
@click="switchTab('customer')"
|
||||
>
|
||||
客户排名
|
||||
</view>
|
||||
<view
|
||||
class="chart-tab"
|
||||
:class="{ active: activeTab === 'location' }"
|
||||
@click="switchTab('location')"
|
||||
>
|
||||
作业地点作业量
|
||||
</view>
|
||||
</view>
|
||||
<view class="chart-content">
|
||||
<!-- 船舶作业货物信息 -->
|
||||
<view v-show="activeTab === 'cargo'" class="charts-container">
|
||||
<view class="chartsMain">
|
||||
<l-echart ref="chartRef" type="2d" :height="'auto'" />
|
||||
</view>
|
||||
<view class="chartsMain">
|
||||
<l-echart ref="cargoChartRef" type="2d" :height="'auto'" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 客户排名 -->
|
||||
<view v-show="activeTab === 'customer'" class="charts-container">
|
||||
<view class="chartsMain">
|
||||
<l-echart ref="customerChartRef" type="2d" :height="'auto'" />
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 作业地点作业量 -->
|
||||
<view v-show="activeTab === 'location'" class="charts-container">
|
||||
<view class="chartsMain">
|
||||
<l-echart ref="locationChartRef" type="2d" :height="'auto'" />
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
|
||||
<!-- 数据表格 -->
|
||||
<view class="table-section">
|
||||
<view class="section-title">详细数据</view>
|
||||
<view class="table-container">
|
||||
<view class="data-table">
|
||||
<view class="table-header">
|
||||
<view
|
||||
v-for="header in tableHeaders"
|
||||
:key="header.key"
|
||||
class="table-cell header-cell"
|
||||
>
|
||||
{{ header.title }}
|
||||
</view>
|
||||
</view>
|
||||
<view
|
||||
v-for="(row, index) in tableData"
|
||||
:key="index"
|
||||
class="table-row"
|
||||
>
|
||||
<view
|
||||
v-for="header in tableHeaders"
|
||||
:key="header.key"
|
||||
class="table-cell"
|
||||
>
|
||||
{{ row[header.key] }}
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</view>
|
||||
</template>
|
||||
|
||||
<script setup lang="ts">
|
||||
import { ref, reactive, onMounted, nextTick } from "vue";
|
||||
import SubHeader from "../components/subHeader.vue";
|
||||
import * as echarts from "echarts";
|
||||
|
||||
// 声明uni全局对象
|
||||
declare const uni: any;
|
||||
|
||||
// 声明全局类型
|
||||
declare global {
|
||||
interface Window {
|
||||
uni: any;
|
||||
}
|
||||
}
|
||||
|
||||
// 类型定义
|
||||
interface CardData {
|
||||
id: number;
|
||||
title: string;
|
||||
value: string;
|
||||
icon: string;
|
||||
}
|
||||
|
||||
interface TableHeader {
|
||||
key: string;
|
||||
title: string;
|
||||
}
|
||||
|
||||
interface TableData {
|
||||
port: string;
|
||||
berth: string;
|
||||
ship: string;
|
||||
cargo: string;
|
||||
weight: string;
|
||||
status: string;
|
||||
}
|
||||
|
||||
// 响应式数据
|
||||
const pageTitle = ref("港口数据");
|
||||
const activeTab = ref("cargo");
|
||||
const chartRef = ref<any>(null);
|
||||
const cargoChartRef = ref<any>(null);
|
||||
const customerChartRef = ref<any>(null);
|
||||
const locationChartRef = ref<any>(null);
|
||||
|
||||
// 设备信息
|
||||
const isMobile = ref(false);
|
||||
|
||||
const cardData = ref<CardData[]>([
|
||||
{ id: 1, title: "报港次数", value: "173次", icon: "fas fa-ship" },
|
||||
{ id: 2, title: "完船次数", value: "197次", icon: "fas fa-anchor" },
|
||||
{
|
||||
id: 3,
|
||||
title: "作业票作业量",
|
||||
value: "260193.687吨",
|
||||
icon: "fas fa-weight",
|
||||
},
|
||||
{
|
||||
id: 4,
|
||||
title: "船舶报港吨数",
|
||||
value: "218928.400吨",
|
||||
icon: "fas fa-ship",
|
||||
},
|
||||
{
|
||||
id: 5,
|
||||
title: "完船作业吨数",
|
||||
value: "252643.653吨",
|
||||
icon: "fas fa-anchor",
|
||||
},
|
||||
]);
|
||||
|
||||
const tableHeaders = ref<TableHeader[]>([
|
||||
{ key: "port", title: "港口" },
|
||||
{ key: "berth", title: "泊位" },
|
||||
{ key: "ship", title: "船舶" },
|
||||
{ key: "cargo", title: "货物" },
|
||||
{ key: "weight", title: "重量(吨)" },
|
||||
{ key: "status", title: "状态" },
|
||||
]);
|
||||
|
||||
const tableData = ref<TableData[]>([
|
||||
{
|
||||
port: "上海港",
|
||||
berth: "A1",
|
||||
ship: "中远海运",
|
||||
cargo: "集装箱",
|
||||
weight: "50000",
|
||||
status: "作业中",
|
||||
},
|
||||
{
|
||||
port: "宁波港",
|
||||
berth: "B2",
|
||||
ship: "马士基",
|
||||
cargo: "散货",
|
||||
weight: "75000",
|
||||
status: "已完成",
|
||||
},
|
||||
{
|
||||
port: "青岛港",
|
||||
berth: "C3",
|
||||
ship: "长荣海运",
|
||||
cargo: "油品",
|
||||
weight: "30000",
|
||||
status: "待作业",
|
||||
},
|
||||
]);
|
||||
|
||||
// 方法
|
||||
|
||||
const goBack = () => {
|
||||
uni.navigateBack();
|
||||
};
|
||||
|
||||
const showMoreOptions = () => {
|
||||
uni.showActionSheet({
|
||||
itemList: ["刷新", "返回首页"],
|
||||
success: (res) => {
|
||||
switch (res.tapIndex) {
|
||||
case 0:
|
||||
// 刷新数据
|
||||
uni.reLaunch({
|
||||
url: "/pages/businessDatas/portData",
|
||||
});
|
||||
uni.showToast({ title: "数据已刷新", icon: "success" });
|
||||
break;
|
||||
//返回首页
|
||||
case 1:
|
||||
uni.reLaunch({
|
||||
url: "/pages/index/index",
|
||||
});
|
||||
uni.showToast({ title: "已返回工作台", icon: "success" });
|
||||
break;
|
||||
}
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
// 客户排名原始数据
|
||||
const customerRankingRawData = [
|
||||
{ name: "江苏鑫顺通新材料有限公司", value: 64641.52 },
|
||||
{ name: "连云港耀捷建设工程有限公司", value: 44569.54 },
|
||||
{ name: "江苏德邦兴华化工科技有限公司", value: 27887.37 },
|
||||
{ name: "连云港海鲲物流有限公司", value: 19028.98 },
|
||||
{ name: "张家港红喜物流有限公司", value: 16538.4 },
|
||||
{ name: "成忠", value: 15557.77 },
|
||||
{ name: "江苏米耘环保科技有限公司", value: 13952.03 },
|
||||
{ name: "南京恒之通船务有限公司", value: 12684 },
|
||||
{ name: "连云港市瑞豪贸易有限公司", value: 8098 },
|
||||
{ name: "佰鼎风禾(江苏)供应链管理有限公司", value: 6546.48 },
|
||||
];
|
||||
|
||||
// 作业地点作业量原始数据
|
||||
const locationWorkloadRawData = [
|
||||
{ name: "抓1", value: 12163.26 },
|
||||
{ name: "抓2", value: 11872.35 },
|
||||
{ name: "倒台", value: 93673.52 },
|
||||
{ name: "1#", value: 59712.06 },
|
||||
{ name: "2#", value: 9359.546 },
|
||||
{ name: "3#", value: 8825.58 },
|
||||
{ name: "4#", value: 14898.896 },
|
||||
{ name: "5#", value: 19450.075 },
|
||||
{ name: "6#", value: 17650.25 },
|
||||
{ name: "7#", value: 21368.56 },
|
||||
{ name: "8#", value: 35275.316 },
|
||||
{ name: "抓2对面", value: 222.0 },
|
||||
{ name: "二期大库", value: 9.1 },
|
||||
{ name: "调度室后", value: 679.966 },
|
||||
{ name: "直灌", value: 0 },
|
||||
];
|
||||
|
||||
// 自动排序客户排名数据
|
||||
const customerRankingData = (() => {
|
||||
// 按数值从小到大排序
|
||||
const sortedData = customerRankingRawData.sort((a, b) => a.value - b.value);
|
||||
|
||||
return {
|
||||
legend: ["10月"],
|
||||
yAxisData: sortedData.map((item) => item.name),
|
||||
seriesData: sortedData.map((item) => item.value),
|
||||
};
|
||||
})();
|
||||
|
||||
// 作业地点作业量数据(不排序,按原始顺序)
|
||||
const locationWorkloadData = {
|
||||
legend: ["10月"],
|
||||
yAxisData: locationWorkloadRawData.map((item) => item.name),
|
||||
seriesData: locationWorkloadRawData.map((item) => item.value),
|
||||
};
|
||||
|
||||
// 初始化客户排名图表
|
||||
const initCustomerChart = (chart: any) => {
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "shadow",
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
grid: {
|
||||
left: "3%",
|
||||
right: "8%",
|
||||
bottom: "3%",
|
||||
top: "5%",
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
type: "value",
|
||||
boundaryGap: [0, 0.01],
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: "category",
|
||||
data: customerRankingData.yAxisData,
|
||||
axisLabel: {
|
||||
fontSize: 12,
|
||||
width: 80,
|
||||
overflow: "truncate",
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: customerRankingData.legend[0],
|
||||
type: "bar",
|
||||
data: customerRankingData.seriesData,
|
||||
label: {
|
||||
show: true,
|
||||
position: "right",
|
||||
formatter: "{c}",
|
||||
fontSize: 11,
|
||||
color: "#333",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
chart.setOption(option);
|
||||
console.log("客户排名图表初始化成功");
|
||||
};
|
||||
|
||||
// 初始化作业地点作业量图表
|
||||
const initLocationChart = (chart: any) => {
|
||||
const option = {
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
axisPointer: {
|
||||
type: "shadow",
|
||||
},
|
||||
},
|
||||
legend: {
|
||||
show: false,
|
||||
},
|
||||
grid: {
|
||||
left: "3%",
|
||||
right: "8%",
|
||||
bottom: "3%",
|
||||
top: "5%",
|
||||
containLabel: true,
|
||||
},
|
||||
xAxis: {
|
||||
type: "value",
|
||||
boundaryGap: [0, 0.01],
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: "category",
|
||||
data: locationWorkloadData.yAxisData,
|
||||
axisLabel: {
|
||||
fontSize: 12,
|
||||
width: 80,
|
||||
overflow: "truncate",
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: locationWorkloadData.legend[0],
|
||||
type: "bar",
|
||||
data: locationWorkloadData.seriesData,
|
||||
label: {
|
||||
show: true,
|
||||
position: "right",
|
||||
formatter: "{c}",
|
||||
fontSize: 11,
|
||||
color: "#333",
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
chart.setOption(option);
|
||||
console.log("作业地点作业量图表初始化成功");
|
||||
};
|
||||
|
||||
// 切换tab
|
||||
const switchTab = (tab: string) => {
|
||||
activeTab.value = tab;
|
||||
|
||||
// 如果切换到客户排名tab,确保图表正确显示
|
||||
if (tab === "customer") {
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
if (customerChartRef.value) {
|
||||
customerChartRef.value.init(echarts, initCustomerChart);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
|
||||
// 如果切换到作业地点作业量tab,确保图表正确显示
|
||||
if (tab === "location") {
|
||||
nextTick(() => {
|
||||
setTimeout(() => {
|
||||
if (locationChartRef.value) {
|
||||
locationChartRef.value.init(echarts, initLocationChart);
|
||||
}
|
||||
}, 100);
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// 生命周期
|
||||
onMounted(() => {
|
||||
// 检测设备类型
|
||||
try {
|
||||
const systemInfo = uni.getSystemInfoSync();
|
||||
isMobile.value =
|
||||
systemInfo.platform !== "devtools" &&
|
||||
(systemInfo.platform === "ios" || systemInfo.platform === "android");
|
||||
} catch (e) {
|
||||
isMobile.value = false;
|
||||
}
|
||||
|
||||
// 初始化第一个图表 - 货物类型统计
|
||||
chartRef.value.init(echarts, (chart) => {
|
||||
const option = {
|
||||
title: {
|
||||
text: "货物类型统计",
|
||||
subtext: "各类型作业量分布",
|
||||
left: "center",
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
},
|
||||
legend: {
|
||||
orient: "horizontal",
|
||||
bottom: "bottom",
|
||||
itemGap: 10,
|
||||
itemWidth: 14,
|
||||
itemHeight: 14,
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "作业类型",
|
||||
type: "pie",
|
||||
radius: "50%",
|
||||
center: ["50%", "50%"],
|
||||
data: [
|
||||
{ value: 67187.753, name: "门机件杂货" },
|
||||
{ value: 26582.55, name: "门机散货" },
|
||||
{ value: 15576.03, name: "抓机散货" },
|
||||
{ value: 82319.55, name: "倒台散货" },
|
||||
{ value: 45963.8, name: "挖机散货" },
|
||||
],
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: "rgba(0, 0, 0, 0.5)",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
chart.setOption(option);
|
||||
});
|
||||
|
||||
// 初始化第二个图表 - 货物品类统计
|
||||
cargoChartRef.value.init(echarts, (chart) => {
|
||||
const option = {
|
||||
title: {
|
||||
text: "货物品类统计",
|
||||
subtext: "各类货物占比分布",
|
||||
left: "center",
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "item",
|
||||
},
|
||||
legend: {
|
||||
orient: "vertical",
|
||||
right: "right",
|
||||
itemGap: 5,
|
||||
itemWidth: 14,
|
||||
itemHeight: 14,
|
||||
textStyle: {
|
||||
fontSize: 12,
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
name: "货物品类",
|
||||
type: "pie",
|
||||
radius: "50%",
|
||||
center: ["50%", "55%"],
|
||||
data: [
|
||||
{ value: 64641.52, name: "铁精粉" },
|
||||
{ value: 44734.8, name: "PTA" },
|
||||
{ value: 44569.54, name: "粉质粘土" },
|
||||
{ value: 33427.37, name: "盐" },
|
||||
{ value: 15557.77, name: "石粉砂" },
|
||||
{ value: 13952.03, name: "低卡煤" },
|
||||
{ value: 4804.04, name: "氯化钾" },
|
||||
{ value: 4140.0, name: "元明粉" },
|
||||
{ value: 3664.0, name: "轻碱" },
|
||||
{ value: 23152.583, name: "其他" },
|
||||
],
|
||||
emphasis: {
|
||||
itemStyle: {
|
||||
shadowBlur: 10,
|
||||
shadowOffsetX: 0,
|
||||
shadowColor: "rgba(0, 0, 0, 0.5)",
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
chart.setOption(option);
|
||||
});
|
||||
|
||||
// 初始化客户排名图表 - 延迟初始化
|
||||
setTimeout(() => {
|
||||
if (customerChartRef.value) {
|
||||
customerChartRef.value.init(echarts, initCustomerChart);
|
||||
}
|
||||
}, 500);
|
||||
|
||||
// 初始化作业地点作业量图表 - 延迟初始化
|
||||
setTimeout(() => {
|
||||
if (locationChartRef.value) {
|
||||
locationChartRef.value.init(echarts, initLocationChart);
|
||||
}
|
||||
}, 500);
|
||||
});
|
||||
</script>
|
||||
|
||||
<style scoped>
|
||||
.data-detail-page {
|
||||
min-height: 100vh;
|
||||
background: var(--background);
|
||||
padding-top: 88rpx;
|
||||
}
|
||||
|
||||
/* 移动设备需要额外的状态栏高度 */
|
||||
.data-detail-page.mobile {
|
||||
padding-top: calc(var(--status-bar-height) + 88rpx);
|
||||
}
|
||||
|
||||
/* 支持安全区域的设备 */
|
||||
@supports (padding: max(0px)) {
|
||||
.data-detail-page.mobile {
|
||||
padding-top: calc(
|
||||
var(--status-bar-height) + 88rpx + env(safe-area-inset-top)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
.section-title {
|
||||
font-size: 32rpx;
|
||||
font-weight: 600;
|
||||
color: var(--title-color);
|
||||
margin-bottom: 24rpx;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
/* 卡片样式 */
|
||||
.cards-section {
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.card-grid {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(2, 1fr);
|
||||
gap: 20rpx;
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.data-card {
|
||||
background: var(--surface);
|
||||
border-radius: 16rpx;
|
||||
padding: 30rpx;
|
||||
box-shadow: var(--shadow);
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 20rpx;
|
||||
border: 1rpx solid var(--border-light);
|
||||
}
|
||||
|
||||
.card-icon {
|
||||
width: 80rpx;
|
||||
height: 80rpx;
|
||||
background: var(--gradient-primary);
|
||||
border-radius: 50%;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.card-icon i {
|
||||
font-size: 32rpx;
|
||||
color: var(--white);
|
||||
}
|
||||
|
||||
.card-content {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.card-value {
|
||||
display: block;
|
||||
font-size: 28rpx;
|
||||
font-weight: 600;
|
||||
color: var(--title-color);
|
||||
margin-bottom: 8rpx;
|
||||
}
|
||||
|
||||
.card-label {
|
||||
display: block;
|
||||
font-size: 24rpx;
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
/* 图表样式 */
|
||||
.charts-section {
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.chart-tabs {
|
||||
display: flex;
|
||||
padding: 0 30rpx;
|
||||
margin-bottom: 30rpx;
|
||||
overflow-x: auto;
|
||||
scrollbar-width: none; /* Firefox */
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.chart-tabs::-webkit-scrollbar {
|
||||
display: none; /* Chrome, Safari and Opera */
|
||||
}
|
||||
|
||||
.chart-tab {
|
||||
flex-shrink: 0;
|
||||
padding: 16rpx 32rpx;
|
||||
margin-right: 16rpx;
|
||||
background: var(--gray-light);
|
||||
border-radius: 32rpx;
|
||||
font-size: 28rpx;
|
||||
color: var(--text-color);
|
||||
transition: all 0.3s ease;
|
||||
cursor: pointer;
|
||||
user-select: none;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.chart-tab:last-child {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
.chart-tab.active {
|
||||
background: var(--primary-color);
|
||||
color: var(--white);
|
||||
box-shadow: var(--shadow-md);
|
||||
}
|
||||
|
||||
.chart-content {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
/* vchart样式 */
|
||||
.chartsMain {
|
||||
width: 100%;
|
||||
min-height: 400rpx;
|
||||
padding: 15rpx;
|
||||
background: var(--surface);
|
||||
margin-bottom: 24rpx;
|
||||
border-radius: 12rpx;
|
||||
box-shadow: var(--shadow-md);
|
||||
border: 1rpx solid var(--border-light);
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
/* 移动端优化 */
|
||||
@media screen and (max-width: 768px) {
|
||||
.chartsMain {
|
||||
min-height: 300rpx;
|
||||
}
|
||||
}
|
||||
|
||||
/* 柱状图特殊样式 - 支持横向滚动 */
|
||||
.chartsMain.bar-chart {
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
}
|
||||
|
||||
/* l-echart组件样式 */
|
||||
.chartsMain :deep(.l-echart) {
|
||||
width: 100% !important;
|
||||
height: auto !important;
|
||||
min-height: 300px !important;
|
||||
background-color: transparent !important;
|
||||
}
|
||||
|
||||
/* 柱状图横向滚动时的样式 */
|
||||
.chartsMain.bar-chart :deep(.l-echart) {
|
||||
min-width: 800rpx;
|
||||
width: auto !important;
|
||||
}
|
||||
|
||||
/* 表格样式 */
|
||||
.table-section {
|
||||
padding: 30rpx 0;
|
||||
}
|
||||
|
||||
.table-container {
|
||||
padding: 0 30rpx;
|
||||
}
|
||||
|
||||
.data-table {
|
||||
background: var(--surface);
|
||||
border-radius: 16rpx;
|
||||
overflow: hidden;
|
||||
box-shadow: var(--shadow);
|
||||
border: 1rpx solid var(--border-light);
|
||||
}
|
||||
|
||||
.table-header {
|
||||
background: var(--gray-lighter);
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.table-row {
|
||||
display: flex;
|
||||
border-bottom: 1rpx solid var(--border-light);
|
||||
}
|
||||
|
||||
.table-row:last-child {
|
||||
border-bottom: none;
|
||||
}
|
||||
|
||||
.table-cell {
|
||||
flex: 1;
|
||||
padding: 24rpx 16rpx;
|
||||
font-size: 26rpx;
|
||||
color: var(--text-color);
|
||||
text-align: center;
|
||||
border-right: 1rpx solid var(--border-light);
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
.table-cell:last-child {
|
||||
border-right: none;
|
||||
}
|
||||
|
||||
.header-cell {
|
||||
font-weight: 600;
|
||||
color: var(--title-color);
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user