| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 |
- <template>
- <div class="chart-list">
- <div class="chart-item">
- <chart-box :name="`${props.areaName}作物种植面积占比`">
- <div class="box-content">
- <div class="chart-dom">
- <pie-chart :chartData="pieChartData" :totalArea="totalArea"></pie-chart>
- </div>
- <div class="box-bg">
- <div class="legend-list">
- <div class="legend-item" v-for="(item, index) in legendData" :key="index">
- <span class="dot" :style="{ background: item.color }"></span>
- <span class="text">
- {{ item.name }}
- <span class="percent">{{ item.percent }}%</span>
- <span class="line">|</span>
- <span class="value">{{ item.value }}亩</span>
- </span>
- </div>
- </div>
- </div>
- </div>
- </chart-box>
- </div>
- <div class="chart-item">
- <chart-box :name="twoTitle">
- <div class="box-content">
- <div class="chart-dom">
- <bar-chart :key="0" :chartData="regionChartData"></bar-chart>
- </div>
- <div class="box-bg">{{ regionSummaryText }}</div>
- </div>
- </chart-box>
- </div>
- <div class="chart-item" v-if="activeBaseTab === '作物分布'">
- <chart-box name="近三年主要作物种植面积变化趋势">
- <div class="box-content">
- <div class="chart-dom">
- <line-chart :chartData="areaTrendChartData"></line-chart>
- </div>
- <div class="box-bg">暂无数据</div>
- </div>
- </chart-box>
- </div>
- <div class="chart-item">
- <chart-box :name="threeTitle">
- <div class="box-content">
- <div class="chart-dom">
- <bar-chart :key="1" :chartData="yieldChartData" :yAxisFormatter="yAxisFormatter"></bar-chart>
- </div>
- <div class="box-bg">{{ yieldSummaryText }}</div>
- </div>
- </chart-box>
- </div>
- </div>
- </template>
- <script setup>
- import chartBox from "@/components/chartBox.vue";
- import pieChart from "./pieChart.vue";
- import lineChart from "./lineChart.vue";
- import { computed, onMounted, ref, watch } from "vue";
- import { pieOption } from "./chartOption.js";
- import barChart from "./barChart.vue";
- const props = defineProps({
- activeBaseTab: {
- type: String,
- default: "作物分布",
- },
- areaCode: {
- type: String,
- default: "156440000",
- },
- areaName: {
- type: String,
- default: "广东省",
- },
- });
- // 图表数据
- const pieChartData = ref([]);
- const totalArea = ref(0);
- // 区域占比图表数据
- const regionChartData = ref({
- categories: [], // 区域名称数组
- values: [], // 占比百分比数组
- });
- // 区域占比摘要文字
- const regionSummaryText = ref("暂无数据");
- // 预估产量图表数据
- const yieldChartData = ref({
- categories: [], // 作物名称数组
- values: [], // 预估产量数组(单位:吨)
- });
- // 预估产量摘要文字
- const yieldSummaryText = ref("暂无数据");
- // 根据 activeBaseTab 动态设置 y 轴单位
- const yAxisFormatter = computed(() => {
- return props.activeBaseTab === "物候期分布" ? "{value}亩" : "{value}吨";
- });
- // 种植面积趋势图表数据
- const areaTrendChartData = ref({
- xAxisData: [], // 时间轴数据
- series: [], // 系列数据
- });
- // 计算图例数据
- const legendData = computed(() => {
- if (!pieChartData.value.length || totalArea.value === 0) {
- return [];
- }
- return pieChartData.value.map((item, index) => {
- const percent = ((item.value / totalArea.value) * 100).toFixed(1);
- return {
- name: item.name,
- value: Math.round(item.value), // 显示整数
- percent: percent,
- color: pieOption.color[index % pieOption.color.length],
- };
- });
- });
- const twoTitle = ref(`${props.areaName}作物区域占比`);
- const threeTitle = ref(`${props.areaName}作物预估产量对比`);
- // 监听 activeBaseTab 变化
- watch(
- () => props.activeBaseTab,
- () => {
- initData();
- }
- );
- // 监听 areaCode 变化,当切换到物候期分布时重新获取数据
- watch(
- () => props.areaCode,
- (newVal) => {
- if (newVal) {
- initData();
- }
- }
- );
- const initData = () => {
- if (props.activeBaseTab === "物候期分布") {
- twoTitle.value = `${props.areaName}小麦物候进程分布`;
- threeTitle.value = `${props.areaName}小麦预告产量统计`;
- fetchStatPhenologyRatio();
- fetchStatRegionYieldRatio();
- } else {
- twoTitle.value = `${props.areaName}作物区域占比`;
- threeTitle.value = `${props.areaName}作物预估产量对比`;
- fetchStatSpeciesAreaYield();
- fetchStatRegionAreaRatio();
- fetchAreaTrend();
- }
- };
- //统计指定物种在下级区划中的预估产量占比
- const fetchStatRegionYieldRatio = () => {
- const params = {
- speciesId: 1,
- adminCode: props.areaCode,
- adminLevel: "province",
- };
- VE_API.warning
- .fetchStatRegionYieldRatio(params)
- .then((res) => {
- if (res.code === 0 && res.data && res.data.length > 0) {
- // 转换接口数据为图表格式
- const categories = res.data.map((item) => item.adminName);
- // 如果是物候期分布,使用 expectYield(但单位显示为亩),否则使用 expectYield(单位显示为吨)
- const values = res.data.map((item) => parseFloat(item.expectYield.toFixed(2)));
- // 更新图表数据
- yieldChartData.value = {
- categories,
- values,
- };
- // 找到最大值的区域
- let maxValue = 0;
- let maxRegion = "";
- res.data.forEach((item) => {
- if (item.expectYield > maxValue) {
- maxValue = item.expectYield;
- maxRegion = item.adminName;
- }
- });
- // 更新摘要文字
- if (maxRegion) {
- const maxValueFormatted = maxValue.toFixed(1);
- const unit = props.activeBaseTab === "物候期分布" ? "亩" : "吨";
- yieldSummaryText.value = `${maxRegion}的${
- props.activeBaseTab === "物候期分布" ? "种植面积" : "预估产量"
- }最大,为${maxValueFormatted}${unit}`;
- } else {
- yieldSummaryText.value = "暂无数据";
- }
- } else {
- yieldChartData.value = {
- categories: [],
- values: [],
- };
- yieldSummaryText.value = "暂无数据";
- }
- })
- .catch((error) => {
- console.error("获取区域产量占比数据失败:", error);
- yieldChartData.value = {
- categories: [],
- values: [],
- };
- yieldSummaryText.value = "暂无数据";
- });
- };
- //统计指定物种在不同物候期下的面积占比
- const fetchStatPhenologyRatio = () => {
- const params = {
- speciesId: 1,
- adminCode: props.areaCode,
- adminLevel: "province",
- };
- VE_API.warning
- .fetchStatPhenologyRatio(params)
- .then((res) => {
- if (res.code === 0 && res.data && res.data.length > 0) {
- console.log(res.data);
- // 转换接口数据为图表格式
- const categories = res.data.map((item) => item.phenologyName);
- const values = res.data.map((item) => parseFloat((item.areaRatio * 100).toFixed(2))); // 转换为百分比,保留两位小数
- // 更新图表数据
- regionChartData.value = {
- categories,
- values,
- };
- // 找到最大占比的物候期
- let maxRatio = 0;
- let maxPhenology = "";
- res.data.forEach((item) => {
- if (item.areaRatio > maxRatio) {
- maxRatio = item.areaRatio;
- maxPhenology = item.phenologyName;
- }
- });
- // 更新摘要文字
- if (maxPhenology) {
- const maxPercent = (maxRatio * 100).toFixed(1);
- regionSummaryText.value = `${maxPhenology}的种植面积最大,占比${maxPercent}%`;
- } else {
- regionSummaryText.value = "暂无数据";
- }
- } else {
- regionChartData.value = {
- categories: [],
- values: [],
- };
- regionSummaryText.value = "暂无数据";
- }
- })
- .catch((error) => {
- console.error("获取物候期占比数据失败:", error);
- regionChartData.value = {
- categories: [],
- values: [],
- };
- regionSummaryText.value = "暂无数据";
- });
- };
- const fetchAreaTrend = () => {
- const params = {
- speciesIds: [1, 222, 60876],
- adminCode: props.areaCode,
- adminLevel: "province",
- };
- VE_API.warning.fetchAreaTrend(params).then((res) => {
- if (res.code === 0 && res.data && res.data.length > 0) {
- // 收集所有唯一的时间点(year-quarter组合)
- const timePointSet = new Set();
- res.data.forEach((species) => {
- species.timeSeries.forEach((item) => {
- const timeKey = `${item.year}Q${item.quarter}`;
- timePointSet.add(timeKey);
- });
- });
- // 转换为数组并排序
- const xAxisData = Array.from(timePointSet).sort((a, b) => {
- const [yearA, quarterA] = a.split("Q").map(Number);
- const [yearB, quarterB] = b.split("Q").map(Number);
- if (yearA !== yearB) return yearA - yearB;
- return quarterA - quarterB;
- });
- // 定义颜色映射(可以根据需要调整)
- const colorMap = {
- 荔枝: "#2199F8",
- 籼稻: "#178B00",
- 小麦: "#FAA53D",
- };
- // 为每个作物创建系列数据
- const series = res.data.map((species) => {
- // 创建时间点到种植面积的映射
- const dataMap = new Map();
- species.timeSeries.forEach((item) => {
- const timeKey = `${item.year}Q${item.quarter}`;
- dataMap.set(timeKey, item.plantArea);
- });
- // 根据 xAxisData 顺序生成数据数组
- const data = xAxisData.map((timeKey) => {
- return dataMap.has(timeKey) ? parseFloat(dataMap.get(timeKey).toFixed(2)) : null;
- });
- return {
- name: species.speciesName,
- type: "line",
- smooth: true,
- showSymbol: false,
- data: data,
- itemStyle: {
- color: colorMap[species.speciesName] || "#2199F8",
- },
- lineStyle: {
- color: colorMap[species.speciesName] || "#2199F8",
- },
- };
- });
- // 更新图表数据
- areaTrendChartData.value = {
- xAxisData,
- series,
- };
- } else {
- console.log("空数据");
- // 接口返回空数据时,清空图表数据
- areaTrendChartData.value = {
- xAxisData: [],
- series: [],
- };
- }
- }).catch(() => {
- // 错误时也清空数据
- areaTrendChartData.value = {
- xAxisData: [],
- series: [],
- };
- });
- };
- const fetchStatRegionAreaRatio = () => {
- const params = {
- speciesId: "1",
- adminCode: props.areaCode,
- adminLevel: "",
- };
- VE_API.warning.fetchStatRegionAreaRatio(params).then((res) => {
- if (res.code === 0 && res.data && res.data.length > 0) {
- // 转换接口数据为图表格式
- const categories = res.data.map((item) => item.adminName);
- const values = res.data.map((item) => (item.areaRatio * 100).toFixed(2)); // 转换为百分比,保留两位小数
- // 更新图表数据
- regionChartData.value = {
- categories,
- values: values.map((v) => parseFloat(v)), // 转换为数字
- };
- // 找到最大占比的区域
- let maxRatio = 0;
- let maxRegion = "";
- res.data.forEach((item) => {
- if (item.areaRatio > maxRatio) {
- maxRatio = item.areaRatio;
- maxRegion = item.adminName;
- }
- });
- // 更新摘要文字
- if (maxRegion) {
- const maxPercent = (maxRatio * 100).toFixed(1);
- regionSummaryText.value = `${maxRegion}的作物种植面积最大,占比${maxPercent}%`;
- } else {
- regionSummaryText.value = "暂无数据";
- }
- } else {
- // 接口返回空数据时,清空图表数据
- regionChartData.value = {
- categories: [],
- values: [],
- };
- regionSummaryText.value = "暂无数据";
- }
- }).catch((error) => {
- console.error("获取区域面积占比数据失败:", error);
- // 错误时也清空数据
- regionChartData.value = {
- categories: [],
- values: [],
- };
- regionSummaryText.value = "暂无数据";
- });
- };
- const fetchStatSpeciesAreaYield = () => {
- const params = {
- year: 2025,
- adminCode: props.areaCode,
- adminLevel: null,
- };
- VE_API.warning.fetchStatSpeciesAreaYield(params).then((res) => {
- if (res.code === 0 && res.data && res.data.length > 0) {
- // 转换接口数据为图表格式(用于饼图)
- const chartData = res.data.map((item) => ({
- value: item.plantArea, // 种植面积
- name: item.speciesName, // 作物名称
- expectYield: item.expectYield, // 预估产量
- speciesId: item.speciesId, // 作物ID
- }));
- // 计算总种植面积
- const total = chartData.reduce((sum, item) => sum + item.value, 0);
- // 更新饼图数据
- pieChartData.value = chartData;
- totalArea.value = total;
- // 处理预估产量数据(用于柱状图)
- const categories = res.data.map((item) => item.speciesName);
- const values = res.data.map((item) => parseFloat(item.expectYield.toFixed(2))); // 保留两位小数
- // 更新预估产量图表数据
- yieldChartData.value = {
- categories,
- values,
- };
- // 找到最大预估产量的作物
- let maxYield = 0;
- let maxSpecies = "";
- res.data.forEach((item) => {
- if (item.expectYield > maxYield) {
- maxYield = item.expectYield;
- maxSpecies = item.speciesName;
- }
- });
- // 更新摘要文字
- if (maxSpecies) {
- const maxYieldFormatted = maxYield.toFixed(1);
- yieldSummaryText.value = `${maxSpecies}的预估产量最高,为${maxYieldFormatted}吨`;
- } else {
- yieldSummaryText.value = "暂无数据";
- }
- } else {
- // 接口返回空数据时,清空图表数据
- pieChartData.value = [];
- totalArea.value = 0;
- yieldChartData.value = {
- categories: [],
- values: [],
- };
- yieldSummaryText.value = "暂无数据";
- }
- }).catch((error) => {
- console.error("获取作物面积产量数据失败:", error);
- // 错误时也清空数据
- pieChartData.value = [];
- totalArea.value = 0;
- yieldChartData.value = {
- categories: [],
- values: [],
- };
- yieldSummaryText.value = "暂无数据";
- });
- };
- </script>
- <style lang="scss" scoped>
- .chart-list {
- width: 100%;
- height: 100%;
- .chart-item {
- width: 100%;
- height: 285px;
- box-sizing: border-box;
- margin-bottom: 10px;
- background: rgba(35, 35, 35, 1);
- border: 1px solid #444444;
- border-radius: 4px;
- .box-content {
- width: 100%;
- height: 100%;
- }
- .chart-dom {
- height: calc(100% - 61px);
- width: 100%;
- }
- .box-bg {
- border-radius: 2px 2px 0 0;
- font-size: 12px;
- padding: 6px 8px;
- box-sizing: border-box;
- height: 61px;
- overflow-y: auto;
- background: linear-gradient(180deg, rgb(85, 85, 85, 0.4) 0%, rgb(35, 35, 35, 1) 100%);
- .legend-list {
- display: grid;
- grid-template-columns: 1fr 1fr;
- gap: 8px 12px;
- height: 100%;
- font-size: 12px;
- .legend-item {
- display: flex;
- align-items: center;
- gap: 6px;
- line-height: 12px;
- .dot {
- width: 5px;
- height: 5px;
- border-radius: 50%;
- flex-shrink: 0;
- }
- .text {
- color: rgba(255, 255, 255, 1);
- font-size: 12px;
- white-space: nowrap;
- .percent {
- padding: 0 10px;
- }
- .line {
- color: rgba(255, 255, 255, 0.2);
- padding-right: 10px;
- }
- }
- }
- }
- }
- }
- }
- </style>
|