feat
This commit is contained in:
commit
6ed519564a
BIN
src/assets/images/business/bg_title.png
Normal file
BIN
src/assets/images/business/bg_title.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
src/assets/images/vsualized/mapopup1.png
Normal file
BIN
src/assets/images/vsualized/mapopup1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 66 KiB |
@ -8,7 +8,8 @@
|
||||
<el-dialog
|
||||
v-model="isShow"
|
||||
:title="currentMap.name + dialogTitle"
|
||||
width="360"
|
||||
:width="dialogWidth"
|
||||
:style="{ 'background-image': 'url(' + getAssetsFile(bgImageVal) + ')' }"
|
||||
:show-close="false"
|
||||
:before-close="handleClose"
|
||||
custom-class="map-info-dialog"
|
||||
@ -22,7 +23,7 @@
|
||||
</template>
|
||||
<script setup>
|
||||
import { isEmpty, getAssetsFile } from '@/utils';
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { ref, reactive, onMounted, computed } from 'vue';
|
||||
import { useRoute } from 'vue-router';
|
||||
import geoJsonData from '../components/530926geo.json'; // 根据实际情况调整路径
|
||||
const route = useRoute();
|
||||
@ -37,9 +38,19 @@ const props = defineProps({
|
||||
return [];
|
||||
},
|
||||
},
|
||||
bgImage: {
|
||||
type: String,
|
||||
default: 'images/vsualized/mapopup.png',
|
||||
},
|
||||
dialogWidth: {
|
||||
type: Number,
|
||||
default: 360,
|
||||
},
|
||||
});
|
||||
var iconUrl = getAssetsFile('images/vsualized/gmmap2.png').href;
|
||||
|
||||
let bgImageVal = computed(() => {
|
||||
return props.bgImage;
|
||||
});
|
||||
const isShow = ref(false);
|
||||
let geoData = geoJsonData;
|
||||
let mapName = ref('ZJ' + route.name);
|
||||
@ -174,7 +185,7 @@ const chartsData = reactive({
|
||||
scale: 3, // 波纹缩放比例
|
||||
brushType: 'stroke', // 波纹绘制方式:'stroke' 或 'fill'
|
||||
},
|
||||
hoverAnimation: false,
|
||||
hoverAnimation: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
@ -183,16 +194,21 @@ const chartsData = reactive({
|
||||
let currentMap = reactive({});
|
||||
|
||||
const mapClick = (data) => {
|
||||
isShow.value = true;
|
||||
currentMap = data;
|
||||
emit('mapclick', currentMap);
|
||||
if (props.markerData.length && props.markerData.length > 0) {
|
||||
if (data.seriesType == 'effectScatter') {
|
||||
isShow.value = true;
|
||||
currentMap = data;
|
||||
emit('mapclick', currentMap);
|
||||
}
|
||||
} else {
|
||||
isShow.value = true;
|
||||
currentMap = data;
|
||||
emit('mapclick', currentMap);
|
||||
}
|
||||
};
|
||||
const handleClose = () => {
|
||||
isShow.value = false;
|
||||
};
|
||||
onMounted(() => {
|
||||
console.info('iconUrl', iconUrl);
|
||||
});
|
||||
|
||||
const emit = defineEmits(['mapclick']);
|
||||
</script>
|
||||
@ -203,7 +219,10 @@ div {
|
||||
|
||||
::v-deep() {
|
||||
.el-dialog {
|
||||
background: url('@/assets/images/vsualized/mapopup.png') no-repeat left top;
|
||||
background: url(iconUrl) no-repeat left top;
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
border-radius: 8px !important;
|
||||
min-height: 200px;
|
||||
max-height: 500px;
|
||||
overflow-y: auto;
|
||||
|
@ -7,7 +7,7 @@ import { cloneDeep } from 'lodash';
|
||||
import { useEcharts } from '@/hooks/useEcharts';
|
||||
|
||||
export default {
|
||||
name: 'customEchartWaterDroplet',
|
||||
name: 'CustomEchartWaterDroplet',
|
||||
props: {
|
||||
chartData: {
|
||||
type: Array,
|
||||
|
@ -54,14 +54,14 @@ const props = defineProps({
|
||||
type: Array,
|
||||
default() {
|
||||
return [
|
||||
{ label: '首页', value: 'home' },
|
||||
{ label: '土地资源', value: 'land' },
|
||||
{ label: '投入品监管', value: 'inputs' },
|
||||
{ label: '产出品管理', value: 'entities' },
|
||||
{ label: '首页', value: '/v2/home' },
|
||||
{ label: '土地资源', value: '/v2/land' },
|
||||
{ label: '投入品监管', value: '/v2/inputs' },
|
||||
{ label: '产出品管理', value: '/v2/entities' },
|
||||
// { label: '智慧种植监测', value: 'plant' },
|
||||
// { label: '智慧养殖监测', value: 'breed' },
|
||||
{ label: '生产经营主体', value: 'business' },
|
||||
{ label: '农产品溯源', value: 'trace' },
|
||||
{ label: '生产经营主体', value: '/v2/business' },
|
||||
{ label: '农产品溯源', value: '/v2/trace' },
|
||||
// { label: '产业预警决策', value: 'early' },
|
||||
];
|
||||
},
|
||||
@ -122,7 +122,7 @@ function handleTitleBtn(t = -1) {
|
||||
function handleTitleClick(val) {
|
||||
activeTitle.value = val;
|
||||
// emit('changeTitle', val);
|
||||
router.push({ name: val });
|
||||
router.push({ path: val });
|
||||
}
|
||||
</script>
|
||||
|
||||
|
@ -171,10 +171,14 @@ const handleCommand = (data) => {
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
z-index: 2;
|
||||
border: 1px solid $color-custom-main;
|
||||
border-radius: 4px;
|
||||
padding: 6px;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
|
||||
.el-dropdown {
|
||||
border: 1px solid $color-custom-main;
|
||||
padding: 6px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
@ -20,13 +20,13 @@ export default {
|
||||
meta: { title: '土地资源', icon: '' },
|
||||
},
|
||||
{
|
||||
path: 'inputs',
|
||||
path: '/v2/inputs',
|
||||
name: 'inputs',
|
||||
component: () => import('@/views/inputs/index.vue'),
|
||||
meta: { title: '投入品监管', icon: '' },
|
||||
},
|
||||
{
|
||||
path: 'entities',
|
||||
path: '/v2/entities',
|
||||
name: 'entities',
|
||||
component: () => import('@/views/entities/index.vue'),
|
||||
meta: { title: '产出品管理', icon: '' },
|
||||
@ -44,7 +44,7 @@ export default {
|
||||
// meta: { title: '', icon: '' },
|
||||
// },
|
||||
{
|
||||
path: 'business',
|
||||
path: '/v2/business',
|
||||
name: 'business',
|
||||
component: () => import('@/views/business/index.vue'),
|
||||
meta: { title: '生产经营主体', icon: '' },
|
||||
|
109
src/views/business/components/businessFive.vue
Normal file
109
src/views/business/components/businessFive.vue
Normal file
@ -0,0 +1,109 @@
|
||||
<template>
|
||||
<div class="rank">
|
||||
<custom-rank-List :chart-config="state" />
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
import { isEmpty } from '@/utils';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
attr: { w: '100%', h: 240 },
|
||||
option: {
|
||||
// 数据
|
||||
dataset: [],
|
||||
type: 'column',
|
||||
rowNum: 6,
|
||||
isAnimation: true,
|
||||
waitTime: 5,
|
||||
unit: '万元',
|
||||
sort: true,
|
||||
height: 12,
|
||||
color: 'linear-gradient(90deg,rgba(53,208,192,0.00), #35d0c0)',
|
||||
textColor: '#fff',
|
||||
borderRadius: '12px',
|
||||
carousel: 'single',
|
||||
indexPrefix: 'TOP',
|
||||
indexFontSize: 12,
|
||||
leftFontSize: 14,
|
||||
rightFontSize: 14,
|
||||
valueFormatter: (item) => {
|
||||
return item.value;
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(val) => {
|
||||
if (!isEmpty(val)) {
|
||||
state.option.dataset = val;
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style scoped lang="scss">
|
||||
.rank {
|
||||
padding: 10px 20px;
|
||||
|
||||
&:deep(.row-item) {
|
||||
.ranking-info {
|
||||
color: #35d0c0 !important;
|
||||
font-family: 'DingTalk JinBuTi, DingTalk JinBuTi-Regular';
|
||||
font-weight: 700;
|
||||
}
|
||||
|
||||
.inside-column {
|
||||
border-radius: 8px;
|
||||
}
|
||||
}
|
||||
|
||||
&:deep(.row-item-1) {
|
||||
.ranking-info {
|
||||
color: #fe7f03 !important;
|
||||
}
|
||||
.ranking-value {
|
||||
color: #fe7f03 !important;
|
||||
}
|
||||
.inside-column {
|
||||
background: linear-gradient(90deg, rgba(254, 127, 3, 0), #fe7f03) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:deep(.row-item-2) {
|
||||
.ranking-info {
|
||||
color: #fef906 !important;
|
||||
}
|
||||
.ranking-value {
|
||||
color: #fef906 !important;
|
||||
}
|
||||
.inside-column {
|
||||
background: linear-gradient(90deg, rgba(254, 249, 6, 0), #fef906) !important;
|
||||
}
|
||||
}
|
||||
|
||||
&:deep(.row-item-3) {
|
||||
.ranking-info {
|
||||
color: #02fd94 !important;
|
||||
}
|
||||
.ranking-value {
|
||||
color: #02fd94 !important;
|
||||
}
|
||||
.inside-column {
|
||||
background: linear-gradient(90deg, rgba(2, 253, 148, 0), #02fd94) !important;
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
210
src/views/business/components/businessFour.vue
Normal file
210
src/views/business/components/businessFour.vue
Normal file
@ -0,0 +1,210 @@
|
||||
<template>
|
||||
<div class="business">
|
||||
<div class="business-left">
|
||||
<custom-echart-water-droplet width="100%" height="100%" :option="state.option" />
|
||||
<div class="business-title">证件齐全率</div>
|
||||
</div>
|
||||
<div class="business-right">
|
||||
<div class="business-title">临期预警</div>
|
||||
<ul class="business-info">
|
||||
<li class="success">
|
||||
<b>正常</b>
|
||||
<span>253家</span>
|
||||
</li>
|
||||
<li class="warning">
|
||||
<b>临期</b>
|
||||
<span>5家</span>
|
||||
</li>
|
||||
<li class="danger">
|
||||
<b>已过期</b>
|
||||
<span>0家</span>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, ref, watch } from 'vue';
|
||||
import { isEmpty } from '@/utils';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Object,
|
||||
default: () => {},
|
||||
},
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
option: {
|
||||
backgroundColor: 'transparent', //背景色
|
||||
series: [
|
||||
{
|
||||
name: '',
|
||||
type: 'liquidFill',
|
||||
radius: '80%',
|
||||
center: ['50%', '50%'],
|
||||
backgroundStyle: {
|
||||
color: 'transparent',
|
||||
},
|
||||
data: [],
|
||||
amplitude: 12, //水波振幅
|
||||
label: {
|
||||
position: ['50%', '45%'],
|
||||
// formatter: 0.3998 * 100 + '%', //显示文本,
|
||||
textStyle: {
|
||||
fontSize: '20px', //文本字号,
|
||||
color: '#fff',
|
||||
},
|
||||
},
|
||||
outline: {
|
||||
borderDistance: 2,
|
||||
itemStyle: {
|
||||
borderWidth: 2,
|
||||
borderColor: {
|
||||
type: 'linear',
|
||||
x: 1,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: 'rgba(71, 202, 219, 0.5)',
|
||||
},
|
||||
{
|
||||
offset: 0.6,
|
||||
color: 'rgba(45, 209, 185, 0.5)',
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: 'rgba(13, 204, 163, 0.5)',
|
||||
},
|
||||
],
|
||||
globalCoord: false,
|
||||
},
|
||||
},
|
||||
},
|
||||
itemStyle: {
|
||||
color: {
|
||||
type: 'linear', // 线性渐变
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(13, 204, 163, 0.6)' },
|
||||
{ offset: 1, color: 'rgba(71, 202, 219, 1)' },
|
||||
],
|
||||
global: false, // 默认为 false
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(val) => {
|
||||
if (!isEmpty(val)) {
|
||||
state.option.series[0].data = [0, val.percent];
|
||||
state.option.series[0].label.formatter = val.percent * 100 + '%';
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.business {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
@include flex-row();
|
||||
|
||||
&-title {
|
||||
width: 160px;
|
||||
margin: 0 auto;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
text-shadow: 2px 0px 10px 0px #01eeff;
|
||||
background: url('@/assets/images/business/bg_title.png');
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
text-shadow:
|
||||
0 0 10px #01eeff,
|
||||
0 0 20px #01eeff,
|
||||
0 0 30px #01eeff,
|
||||
0 0 40px #01eeff;
|
||||
}
|
||||
|
||||
&-left,
|
||||
&-right {
|
||||
@include flex-column();
|
||||
flex: 1;
|
||||
}
|
||||
|
||||
&-info {
|
||||
width: 100%;
|
||||
@include flex-column();
|
||||
text-align: center;
|
||||
|
||||
li {
|
||||
@include flex-column();
|
||||
font-size: 16px;
|
||||
font-weight: 400;
|
||||
color: #fff;
|
||||
margin-top: 16px;
|
||||
|
||||
b {
|
||||
margin-bottom: 10px;
|
||||
|
||||
&::before {
|
||||
display: inline-block;
|
||||
content: '';
|
||||
width: 12px;
|
||||
height: 12px;
|
||||
border-radius: 6px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
&.success {
|
||||
span {
|
||||
color: #02fd94;
|
||||
}
|
||||
b {
|
||||
&::before {
|
||||
background-color: #02fd94;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.warning {
|
||||
span {
|
||||
color: #fef906;
|
||||
}
|
||||
b {
|
||||
&::before {
|
||||
background-color: #fef906;
|
||||
}
|
||||
}
|
||||
}
|
||||
&.danger {
|
||||
span {
|
||||
color: #fc0003;
|
||||
}
|
||||
b {
|
||||
&::before {
|
||||
background-color: #fc0003;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
@ -1,19 +1,89 @@
|
||||
<template>
|
||||
<centerMap :dialog-title="'投入品'" :marker-data="markerData" @mapclick="doMapclick">
|
||||
<centerMap
|
||||
:dialog-title="'经营主体'"
|
||||
:marker-data="markerData"
|
||||
:bg-image="'images/vsualized/mapopup1.png'"
|
||||
:dialog-width="240"
|
||||
@mapclick="doMapclick"
|
||||
>
|
||||
<template #header>
|
||||
<div class="land-map-pop-header">
|
||||
<div class="title">{{ currentRegion && currentRegion.name ? currentRegion.name : '投入品' }}</div>
|
||||
<div class="buiness-map-pop-header">
|
||||
<div class="title">{{ currentRegion && currentRegion.name ? currentRegion.name : '经营主体' }}</div>
|
||||
</div>
|
||||
</template>
|
||||
<template #dialogContent>
|
||||
<!-- <div class="land-map-pop-content">
|
||||
<div v-for="(n, index) in list" :key="index" class="list-item">
|
||||
<div class="title">
|
||||
<span class="title-val"> {{ n.title }}</span>
|
||||
</div>
|
||||
<div class="value">{{ n.value }}{{ n.unit }}</div>
|
||||
<div class="buiness-map-pop-content">
|
||||
<div class="addr">
|
||||
<el-icon :size="'18px'" :color="'#fff'">
|
||||
<LocationFilled />
|
||||
</el-icon>
|
||||
{{ testInfo.addr || ' --' }}
|
||||
</div>
|
||||
</div> -->
|
||||
<div class="tips-warp">
|
||||
<div class="label">负责人:</div>
|
||||
<div class="val">{{ testInfo.user || '--' }}</div>
|
||||
</div>
|
||||
<div class="tips-warp">
|
||||
<div class="label">联系方式:</div>
|
||||
<div class="val">{{ testInfo.tel || '--' }}</div>
|
||||
</div>
|
||||
<div class="tips-warp">
|
||||
<div class="label">注册资本:</div>
|
||||
<div class="val">{{ testInfo.capital || '--' }}</div>
|
||||
</div>
|
||||
<div class="tips-warp">
|
||||
<div class="label">成立时间:</div>
|
||||
<div class="val">{{ testInfo.time || '--' }}</div>
|
||||
</div>
|
||||
<div class="tips-warp">
|
||||
<div class="label">信用等级:</div>
|
||||
<div class="val">{{ testInfo.credit || '--' }}</div>
|
||||
</div>
|
||||
<div class="img-list">
|
||||
<div class="img-item">
|
||||
<el-image
|
||||
style="width: 80px; height: 60px; cursor: pointer"
|
||||
:preview-src-list="
|
||||
testInfo.imglist.map((m) => {
|
||||
return getAssetsFile(m);
|
||||
})
|
||||
"
|
||||
:src="getAssetsFile(testInfo.imglist[0])"
|
||||
fit="cover"
|
||||
lazy
|
||||
/>
|
||||
<div class="img-name">营业执照</div>
|
||||
</div>
|
||||
<div class="img-item">
|
||||
<el-image
|
||||
style="width: 80px; height: 60px; cursor: pointer"
|
||||
:preview-src-list="
|
||||
testInfo.imglist.map((m) => {
|
||||
return getAssetsFile(m);
|
||||
})
|
||||
"
|
||||
:src="getAssetsFile(testInfo.imglist[1])"
|
||||
fit="cover"
|
||||
lazy
|
||||
/>
|
||||
<div class="img-name">经营许可证</div>
|
||||
</div>
|
||||
<div class="img-item">
|
||||
<el-image
|
||||
style="width: 80px; height: 60px; cursor: pointer"
|
||||
:preview-src-list="
|
||||
testInfo.imglist.map((m) => {
|
||||
return getAssetsFile(m);
|
||||
})
|
||||
"
|
||||
:src="getAssetsFile(testInfo.imglist[2])"
|
||||
fit="cover"
|
||||
lazy
|
||||
/>
|
||||
<div class="img-name">其他整数</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</centerMap>
|
||||
</template>
|
||||
@ -26,37 +96,57 @@ const list = reactive([
|
||||
{ title: '年总产值', value: 3.49, color: '#01FEFD', unit: '亿元' },
|
||||
{ title: '年人均收入', value: 6.98, color: '#FEF906', unit: '万元' },
|
||||
]);
|
||||
|
||||
let testInfo = reactive({});
|
||||
let currentRegion = ref(null);
|
||||
const doMapclick = (data) => {
|
||||
currentRegion.value = data;
|
||||
if (data.name == '永星食品加工厂') {
|
||||
testInfo = {
|
||||
addr: '云南省临沧市耿马傣族佤族自治县孟定镇101号',
|
||||
user: '张强',
|
||||
tel: '15331683325',
|
||||
capital: '500万',
|
||||
time: '2018年12月1日',
|
||||
credit: 'AA',
|
||||
imglist: ['images/vsualized/home1.png', 'images/vsualized/home1.png', 'images/vsualized/home1.png'],
|
||||
};
|
||||
}
|
||||
if (data.name == '欣欣种源企业') {
|
||||
testInfo = {
|
||||
addr: '云南省临沧市耿马傣族佤族自治耿马镇102号',
|
||||
user: '李欣',
|
||||
tel: '13713575206',
|
||||
capital: '600万',
|
||||
time: '2020年10月1日',
|
||||
credit: 'AA',
|
||||
imglist: ['images/vsualized/home1.png', 'images/vsualized/home1.png', 'images/vsualized/home1.png'],
|
||||
};
|
||||
}
|
||||
};
|
||||
|
||||
let markerData = reactive([
|
||||
[
|
||||
// 示例数据点,实际应用中应替换为真实的数据
|
||||
{
|
||||
name: '永星食品加工厂',
|
||||
value: [99.081993, 23.554045, 150], // 经度, 纬度, 数值
|
||||
symbol: 'image://' + getAssetsFile('images/vsualized/marker.png'),
|
||||
itemStyle: {
|
||||
color: '#4bffb4', //
|
||||
},
|
||||
// 示例数据点,实际应用中应替换为真实的数据
|
||||
{
|
||||
name: '永星食品加工厂',
|
||||
value: [99.081993, 23.524045, 150], // 经度, 纬度, 数值
|
||||
symbol: 'image://' + getAssetsFile('images/vsualized/marker.png'),
|
||||
itemStyle: {
|
||||
color: '#4bffb4', //
|
||||
},
|
||||
{
|
||||
name: '耿马镇',
|
||||
value: [99.402267, 23.538889, 150], // 经度, 纬度, 数值
|
||||
symbol: 'image://' + getAssetsFile('images/vsualized/marker.png'),
|
||||
itemStyle: {
|
||||
color: '#4bffb4', // 勐永镇的颜色
|
||||
},
|
||||
},
|
||||
{
|
||||
name: '欣欣种源企业',
|
||||
value: [99.402267, 23.538889, 150], // 经度, 纬度, 数值
|
||||
symbol: 'image://' + getAssetsFile('images/vsualized/marker.png'),
|
||||
itemStyle: {
|
||||
color: '#4bffb4', // 勐永镇的颜色
|
||||
},
|
||||
],
|
||||
},
|
||||
]);
|
||||
</script>
|
||||
|
||||
<style lang="scss" scoped>
|
||||
.land-map-pop-header {
|
||||
.buiness-map-pop-header {
|
||||
display: inline-flex;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
@ -74,45 +164,43 @@ let markerData = reactive([
|
||||
font-size: 14px;
|
||||
}
|
||||
}
|
||||
.land-map-pop-content {
|
||||
.buiness-map-pop-content {
|
||||
width: 100%;
|
||||
gap: 10px;
|
||||
display: inline-flex;
|
||||
justify-content: flex-start;
|
||||
flex-wrap: wrap;
|
||||
.list-item {
|
||||
width: calc((100% - 10px) / 1);
|
||||
.addr {
|
||||
width: 100%;
|
||||
display: inline-flex;
|
||||
color: #fff;
|
||||
text-align: left;
|
||||
}
|
||||
.tips-warp {
|
||||
width: 100%;
|
||||
display: inline-flex;
|
||||
justify-content: space-between;
|
||||
padding: 6px 0;
|
||||
.title {
|
||||
display: inline-flex;
|
||||
justify-content: flex-start;
|
||||
.before {
|
||||
display: inline-flex;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
}
|
||||
.b-content {
|
||||
width: 8px;
|
||||
height: 8px;
|
||||
border-radius: 50%;
|
||||
display: inline-block;
|
||||
}
|
||||
.before,
|
||||
.title-val {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
padding: 0 5px 0 2px;
|
||||
color: $color-custom-main;
|
||||
}
|
||||
text-align: left;
|
||||
margin: 6px 0;
|
||||
.label {
|
||||
color: #fef906;
|
||||
}
|
||||
|
||||
.value {
|
||||
display: inline-block;
|
||||
text-align: right;
|
||||
color: $color-white;
|
||||
font-size: 12px;
|
||||
.val {
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.img-list {
|
||||
width: 100%;
|
||||
display: inline-flex;
|
||||
justify-content: space-between;
|
||||
gap: 10;
|
||||
flex-wrap: wrap;
|
||||
.img-item {
|
||||
width: calc((100% - 10px) / 2);
|
||||
margin-bottom: 8px;
|
||||
.el-image {
|
||||
background: transparent !important;
|
||||
}
|
||||
.img-name {
|
||||
color: #fff;
|
||||
padding: 6px 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
302
src/views/business/components/businessOne.vue
Normal file
302
src/views/business/components/businessOne.vue
Normal file
@ -0,0 +1,302 @@
|
||||
<template>
|
||||
<custom-echart-pie-3d :chart-data="state.data" height="100%" :option="state.option" />
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
import { isEmpty } from '@/utils';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
option: {},
|
||||
data: [],
|
||||
text: '',
|
||||
});
|
||||
|
||||
function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
|
||||
// 计算
|
||||
let midRatio = (startRatio + endRatio) / 2;
|
||||
let startRadian = startRatio * Math.PI * 2;
|
||||
let endRadian = endRatio * Math.PI * 2;
|
||||
let midRadian = midRatio * Math.PI * 2;
|
||||
// 如果只有一个扇形,则不实现选中效果。
|
||||
if (startRatio === 0 && endRatio === 1) {
|
||||
isSelected = false;
|
||||
}
|
||||
// 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
|
||||
k = typeof k !== 'undefined' ? k : 1 / 3;
|
||||
// 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
|
||||
let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
|
||||
let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
|
||||
// 计算高亮效果的放大比例(未高亮,则比例为 1)
|
||||
let hoverRate = isHovered ? 1.05 : 1;
|
||||
// 返回曲面参数方程
|
||||
return {
|
||||
u: {
|
||||
min: -Math.PI,
|
||||
max: Math.PI * 3,
|
||||
step: Math.PI / 32,
|
||||
},
|
||||
v: {
|
||||
min: 0,
|
||||
max: Math.PI * 2,
|
||||
step: Math.PI / 20,
|
||||
},
|
||||
x: function (u, v) {
|
||||
if (u < startRadian) {
|
||||
return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
}
|
||||
if (u > endRadian) {
|
||||
return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
}
|
||||
return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
},
|
||||
y: function (u, v) {
|
||||
if (u < startRadian) {
|
||||
return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
}
|
||||
if (u > endRadian) {
|
||||
return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
}
|
||||
return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
},
|
||||
z: function (u, v) {
|
||||
if (u < -Math.PI * 0.5) {
|
||||
return Math.sin(u);
|
||||
}
|
||||
if (u > Math.PI * 2.5) {
|
||||
return Math.sin(u) * h * 0.1;
|
||||
}
|
||||
return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function fomatFloat(num, n) {
|
||||
var f = parseFloat(num);
|
||||
if (isNaN(f)) {
|
||||
return false;
|
||||
}
|
||||
f = Math.round(num * Math.pow(10, n)) / Math.pow(10, n); // n 幂
|
||||
var s = f.toString();
|
||||
var rs = s.indexOf('.');
|
||||
if (rs < 0) {
|
||||
rs = s.length;
|
||||
s += '.';
|
||||
}
|
||||
while (s.length <= rs + n) {
|
||||
s += '0';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function getHeight3D(series, height) {
|
||||
series.sort((a, b) => {
|
||||
return b.pieData.value - a.pieData.value;
|
||||
});
|
||||
return (height * 20) / series[0].pieData.value;
|
||||
}
|
||||
|
||||
function getPie3D(pieData, internalDiameterRatio) {
|
||||
let series = [];
|
||||
let sumValue = 0;
|
||||
let startValue = 0;
|
||||
let endValue = 0;
|
||||
let legendData = [];
|
||||
let legendBfb = [];
|
||||
let k = 1 - internalDiameterRatio;
|
||||
pieData.sort((a, b) => {
|
||||
return b.value - a.value;
|
||||
});
|
||||
for (let i = 0; i < pieData.length; i++) {
|
||||
sumValue += pieData[i].value;
|
||||
let seriesItem = {
|
||||
//名称
|
||||
name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
|
||||
type: 'surface',
|
||||
//是否为参数曲面(是)
|
||||
parametric: true,
|
||||
//曲面图网格线(否)上面一根一根的
|
||||
wireframe: {
|
||||
show: false,
|
||||
},
|
||||
pieData: pieData[i],
|
||||
pieStatus: {
|
||||
selected: false,
|
||||
hovered: false,
|
||||
k: k,
|
||||
},
|
||||
|
||||
//设置饼图在容器中的位置(目前没发现啥用)
|
||||
// center: ['50%', '100%']
|
||||
};
|
||||
|
||||
//曲面的颜色、不透明度等样式。
|
||||
if (typeof pieData[i].itemStyle != 'undefined') {
|
||||
let itemStyle = {};
|
||||
typeof pieData[i].itemStyle.color != 'undefined' ? (itemStyle.color = pieData[i].itemStyle.color) : null;
|
||||
typeof pieData[i].itemStyle.opacity != 'undefined' ? (itemStyle.opacity = pieData[i].itemStyle.opacity) : null;
|
||||
seriesItem.itemStyle = itemStyle;
|
||||
}
|
||||
series.push(seriesItem);
|
||||
}
|
||||
|
||||
legendData = [];
|
||||
legendBfb = [];
|
||||
for (let i = 0; i < series.length; i++) {
|
||||
endValue = startValue + series[i].pieData.value * 1;
|
||||
series[i].pieData.startRatio = startValue / sumValue;
|
||||
series[i].pieData.endRatio = endValue / sumValue;
|
||||
series[i].parametricEquation = getParametricEquation(
|
||||
series[i].pieData.startRatio,
|
||||
series[i].pieData.endRatio,
|
||||
false,
|
||||
false,
|
||||
k,
|
||||
series[i].pieData.value
|
||||
);
|
||||
startValue = endValue;
|
||||
let bfb = fomatFloat(series[i].pieData.value / sumValue, 4);
|
||||
legendData.push({
|
||||
name: series[i].name,
|
||||
value: bfb,
|
||||
});
|
||||
legendBfb.push({
|
||||
name: series[i].name,
|
||||
value: bfb,
|
||||
});
|
||||
}
|
||||
|
||||
let boxHeight = getHeight3D(series, 15);
|
||||
let option = {
|
||||
legendSuffix: '%',
|
||||
legend: {
|
||||
data: legendData,
|
||||
// color: ['#8FD7FC', '#466BE7', '#F4BB29', '#49C384', '#8FD7FC', '#466BE7', '#F4BB29', '#49C384'],
|
||||
orient: 'vertical',
|
||||
right: 10,
|
||||
top: 'center',
|
||||
itemGap: 20,
|
||||
show: true,
|
||||
icon: 'rect',
|
||||
itemHeight: 16,
|
||||
itemWidth: 16,
|
||||
textStyle: {
|
||||
fontSize: 14,
|
||||
color: '#B8DDFF',
|
||||
lineHeight: 20,
|
||||
},
|
||||
formatter: (name) => {
|
||||
if (state.data.length) {
|
||||
const item = state.data.filter((item) => item.name === name)[0];
|
||||
return `${name} ${item.pieData.value}${state.option.legendSuffix ?? ''}`;
|
||||
}
|
||||
},
|
||||
},
|
||||
tooltip: {
|
||||
backgroundColor: 'rgba(18, 55, 85, 0.8);',
|
||||
borderColor: '#35d0c0',
|
||||
color: '#fff',
|
||||
position: function (point, params, dom, rect, size) {
|
||||
var x = point[0];
|
||||
var y = point[1];
|
||||
var viewWidth = size.viewSize[0];
|
||||
var viewHeight = size.viewSize[1];
|
||||
var boxWidth = size.contentSize[0];
|
||||
var boxHeight = size.contentSize[1];
|
||||
// 判断 tooltip 位置,调整其位置使其不会超出图表边界
|
||||
if (x + boxWidth > viewWidth) {
|
||||
x = x - boxWidth;
|
||||
}
|
||||
if (y + boxHeight > viewHeight) {
|
||||
y = y - boxHeight;
|
||||
}
|
||||
// 保证 tooltip 始终在图表内部
|
||||
if (x < 0) {
|
||||
x = 0;
|
||||
}
|
||||
if (y < 0) {
|
||||
y = 0;
|
||||
}
|
||||
|
||||
return [x, y];
|
||||
},
|
||||
formatter: (params) => {
|
||||
if (params.seriesName !== 'mouseoutSeries') {
|
||||
return `
|
||||
<span style="color:#FFF">
|
||||
${params.seriesName}<br/>
|
||||
<span style="display:inline-block;
|
||||
margin-right:5px;
|
||||
border-radius:10px;
|
||||
width:10px;
|
||||
height:10px;
|
||||
background-color:${params.color};"></span>
|
||||
${option.series[params.seriesIndex].pieData.value}
|
||||
</span>
|
||||
`;
|
||||
}
|
||||
return '';
|
||||
},
|
||||
},
|
||||
xAxis3D: {
|
||||
min: -1,
|
||||
max: 1,
|
||||
},
|
||||
yAxis3D: {
|
||||
min: -1,
|
||||
max: 1,
|
||||
},
|
||||
zAxis3D: {
|
||||
min: -1,
|
||||
max: 1,
|
||||
},
|
||||
grid3D: {
|
||||
show: false,
|
||||
boxHeight: boxHeight,
|
||||
left: '-20%',
|
||||
top: -20,
|
||||
viewControl: {
|
||||
alpha: 30, //角度(这个很重要 调节角度的)
|
||||
distance: 150, //调整视角到主体的距离,类似调整zoom(这是整体大小)
|
||||
rotateSensitivity: 1, //设置为0无法旋转
|
||||
zoomSensitivity: 0, //设置为0无法缩放
|
||||
panSensitivity: 0, //设置为0无法平移
|
||||
autoRotate: true, //自动旋转
|
||||
},
|
||||
},
|
||||
series: series,
|
||||
};
|
||||
return option;
|
||||
}
|
||||
|
||||
const initData = (pieData = []) => {
|
||||
const option = getPie3D(pieData, 0.8);
|
||||
state.option = option;
|
||||
state.data = option.series;
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(val) => {
|
||||
if (!isEmpty(val)) {
|
||||
const pieData = val.map((row) => {
|
||||
return {
|
||||
name: row.name,
|
||||
value: row.value,
|
||||
};
|
||||
});
|
||||
initData(pieData);
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
274
src/views/business/components/businessSix.vue
Normal file
274
src/views/business/components/businessSix.vue
Normal file
@ -0,0 +1,274 @@
|
||||
<template>
|
||||
<custom-echart-pie-3d :chart-data="state.data" height="100%" :option="state.option" @click="handleClick" />
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
import { isEmpty } from '@/utils';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
option: {},
|
||||
data: [],
|
||||
text: '',
|
||||
});
|
||||
|
||||
function getParametricEquation(startRatio, endRatio, isSelected, isHovered, k, h) {
|
||||
// 计算
|
||||
let midRatio = (startRatio + endRatio) / 2;
|
||||
let startRadian = startRatio * Math.PI * 2;
|
||||
let endRadian = endRatio * Math.PI * 2;
|
||||
let midRadian = midRatio * Math.PI * 2;
|
||||
// 如果只有一个扇形,则不实现选中效果。
|
||||
if (startRatio === 0 && endRatio === 1) {
|
||||
isSelected = false;
|
||||
}
|
||||
// 通过扇形内径/外径的值,换算出辅助参数 k(默认值 1/3)
|
||||
k = typeof k !== 'undefined' ? k : 1 / 3;
|
||||
// 计算选中效果分别在 x 轴、y 轴方向上的位移(未选中,则位移均为 0)
|
||||
let offsetX = isSelected ? Math.cos(midRadian) * 0.1 : 0;
|
||||
let offsetY = isSelected ? Math.sin(midRadian) * 0.1 : 0;
|
||||
// 计算高亮效果的放大比例(未高亮,则比例为 1)
|
||||
let hoverRate = isHovered ? 1.05 : 1;
|
||||
// 返回曲面参数方程
|
||||
return {
|
||||
u: {
|
||||
min: -Math.PI,
|
||||
max: Math.PI * 3,
|
||||
step: Math.PI / 32,
|
||||
},
|
||||
v: {
|
||||
min: 0,
|
||||
max: Math.PI * 2,
|
||||
step: Math.PI / 20,
|
||||
},
|
||||
x: function (u, v) {
|
||||
if (u < startRadian) {
|
||||
return offsetX + Math.cos(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
}
|
||||
if (u > endRadian) {
|
||||
return offsetX + Math.cos(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
}
|
||||
return offsetX + Math.cos(u) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
},
|
||||
y: function (u, v) {
|
||||
if (u < startRadian) {
|
||||
return offsetY + Math.sin(startRadian) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
}
|
||||
if (u > endRadian) {
|
||||
return offsetY + Math.sin(endRadian) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
}
|
||||
return offsetY + Math.sin(u) * (1 + Math.cos(v) * k) * hoverRate;
|
||||
},
|
||||
z: function (u, v) {
|
||||
if (u < -Math.PI * 0.5) {
|
||||
return Math.sin(u);
|
||||
}
|
||||
if (u > Math.PI * 2.5) {
|
||||
return Math.sin(u) * h * 0.1;
|
||||
}
|
||||
return Math.sin(v) > 0 ? 1 * h * 0.1 : -1;
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function fomatFloat(num, n) {
|
||||
var f = parseFloat(num);
|
||||
if (isNaN(f)) {
|
||||
return false;
|
||||
}
|
||||
f = Math.round(num * Math.pow(10, n)) / Math.pow(10, n); // n 幂
|
||||
var s = f.toString();
|
||||
var rs = s.indexOf('.');
|
||||
if (rs < 0) {
|
||||
rs = s.length;
|
||||
s += '.';
|
||||
}
|
||||
while (s.length <= rs + n) {
|
||||
s += '0';
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
function getHeight3D(series, height) {
|
||||
series.sort((a, b) => {
|
||||
return b.pieData.value - a.pieData.value;
|
||||
});
|
||||
return (height * 20) / series[0].pieData.value;
|
||||
}
|
||||
|
||||
function getPie3D(pieData, internalDiameterRatio) {
|
||||
let series = [];
|
||||
let sumValue = 0;
|
||||
let startValue = 0;
|
||||
let endValue = 0;
|
||||
let legendData = [];
|
||||
let legendBfb = [];
|
||||
let k = 1 - internalDiameterRatio;
|
||||
pieData.sort((a, b) => {
|
||||
return b.value - a.value;
|
||||
});
|
||||
for (let i = 0; i < pieData.length; i++) {
|
||||
sumValue += pieData[i].value;
|
||||
let seriesItem = {
|
||||
//名称
|
||||
name: typeof pieData[i].name === 'undefined' ? `series${i}` : pieData[i].name,
|
||||
type: 'surface',
|
||||
//是否为参数曲面(是)
|
||||
parametric: true,
|
||||
//曲面图网格线(否)上面一根一根的
|
||||
wireframe: {
|
||||
show: false,
|
||||
},
|
||||
pieData: pieData[i],
|
||||
pieStatus: {
|
||||
selected: false,
|
||||
hovered: false,
|
||||
k: k,
|
||||
},
|
||||
|
||||
//设置饼图在容器中的位置(目前没发现啥用)
|
||||
// center: ['50%', '100%']
|
||||
};
|
||||
|
||||
//曲面的颜色、不透明度等样式。
|
||||
if (typeof pieData[i].itemStyle != 'undefined') {
|
||||
let itemStyle = {};
|
||||
typeof pieData[i].itemStyle.color != 'undefined' ? (itemStyle.color = pieData[i].itemStyle.color) : null;
|
||||
typeof pieData[i].itemStyle.opacity != 'undefined' ? (itemStyle.opacity = pieData[i].itemStyle.opacity) : null;
|
||||
seriesItem.itemStyle = itemStyle;
|
||||
}
|
||||
series.push(seriesItem);
|
||||
}
|
||||
|
||||
legendData = [];
|
||||
legendBfb = [];
|
||||
for (let i = 0; i < series.length; i++) {
|
||||
endValue = startValue + series[i].pieData.value * 1;
|
||||
series[i].pieData.startRatio = startValue / sumValue;
|
||||
series[i].pieData.endRatio = endValue / sumValue;
|
||||
series[i].parametricEquation = getParametricEquation(
|
||||
series[i].pieData.startRatio,
|
||||
series[i].pieData.endRatio,
|
||||
false,
|
||||
false,
|
||||
k,
|
||||
series[i].pieData.value
|
||||
);
|
||||
startValue = endValue;
|
||||
let bfb = fomatFloat(series[i].pieData.value / sumValue, 4);
|
||||
legendData.push({
|
||||
name: series[i].name,
|
||||
value: bfb,
|
||||
});
|
||||
legendBfb.push({
|
||||
name: series[i].name,
|
||||
value: bfb,
|
||||
});
|
||||
}
|
||||
|
||||
let boxHeight = getHeight3D(series, 15);
|
||||
let option = {
|
||||
legend: {
|
||||
data: legendData,
|
||||
color: ['#8FD7FC', '#466BE7', '#F4BB29', '#49C384', '#8FD7FC', '#466BE7', '#F4BB29', '#49C384'],
|
||||
orient: 'vertical',
|
||||
right: 10,
|
||||
top: 'center',
|
||||
itemGap: 20,
|
||||
show: true,
|
||||
icon: 'rect',
|
||||
itemHeight: 16,
|
||||
itemWidth: 16,
|
||||
textStyle: {
|
||||
fontSize: 14,
|
||||
color: '#B8DDFF',
|
||||
lineHeight: 20,
|
||||
},
|
||||
},
|
||||
title: {
|
||||
text: '',
|
||||
x: '35%',
|
||||
y: '30%',
|
||||
textStyle: {
|
||||
rich: {
|
||||
a: {
|
||||
fontSize: 20,
|
||||
color: '#fff',
|
||||
},
|
||||
c: {
|
||||
fontSize: 12,
|
||||
color: '#fff',
|
||||
padding: [15, 0],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
xAxis3D: {
|
||||
min: -1,
|
||||
max: 1,
|
||||
},
|
||||
yAxis3D: {
|
||||
min: -1,
|
||||
max: 1,
|
||||
},
|
||||
zAxis3D: {
|
||||
min: -1,
|
||||
max: 1,
|
||||
},
|
||||
grid3D: {
|
||||
show: false,
|
||||
boxHeight: boxHeight,
|
||||
left: '-10%',
|
||||
top: -20,
|
||||
viewControl: {
|
||||
alpha: 55, //角度(这个很重要 调节角度的)
|
||||
distance: 150, //调整视角到主体的距离,类似调整zoom(这是整体大小)
|
||||
rotateSensitivity: 1, //设置为0无法旋转
|
||||
zoomSensitivity: 0, //设置为0无法缩放
|
||||
panSensitivity: 0, //设置为0无法平移
|
||||
autoRotate: true, //自动旋转
|
||||
},
|
||||
},
|
||||
series: series,
|
||||
};
|
||||
return option;
|
||||
}
|
||||
|
||||
const initData = (pieData = []) => {
|
||||
const option = getPie3D(pieData, 0.8);
|
||||
const { name, value } = option.series[0].pieData;
|
||||
option.title.text = `{a|${value}%}{c|\n${name}}`;
|
||||
state.option = option;
|
||||
state.data = option.series;
|
||||
};
|
||||
|
||||
const handleClick = (params) => {
|
||||
const findItem = state.data.find((el) => el.name === params.seriesName);
|
||||
state.option.title.text = `{a|${findItem?.pieData?.value}%}{c|\n${params.seriesName}}`;
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(val) => {
|
||||
if (!isEmpty(val)) {
|
||||
const pieData = val.map((row) => {
|
||||
return {
|
||||
name: row.name,
|
||||
value: row.value,
|
||||
};
|
||||
});
|
||||
initData(pieData);
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
77
src/views/business/components/businessThere.vue
Normal file
77
src/views/business/components/businessThere.vue
Normal file
@ -0,0 +1,77 @@
|
||||
<template>
|
||||
<custom-echart-line :chart-data="state.data" height="100%" :option="state.option" />
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
import { isEmpty } from '@/utils';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
option: {
|
||||
color: ['#35D0C0'],
|
||||
grid: {
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
bottom: '5%',
|
||||
top: '10%',
|
||||
containLabel: true,
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
},
|
||||
backgroundColor: 'rgba(18, 55, 85, 0.8);',
|
||||
borderColor: '#35d0c0',
|
||||
formatter: (data) => {
|
||||
const params = data[0];
|
||||
let str = `<div class="custom-echarts-tips">
|
||||
<span>${params.name}</span><br/>
|
||||
<span>${params.marker} ${params.data} 万亩</span>
|
||||
</div>`;
|
||||
return str;
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
// name: '年份',
|
||||
axisTick: {
|
||||
show: false,
|
||||
alignWithLabel: false,
|
||||
interval: 'auto',
|
||||
inside: false,
|
||||
length: 5,
|
||||
lineStyle: {
|
||||
type: 'solid',
|
||||
width: 1,
|
||||
color: 'rgba(28, 158, 222, 1)',
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
// name: '',
|
||||
},
|
||||
},
|
||||
data: [],
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(val) => {
|
||||
if (!isEmpty(val)) {
|
||||
state.data = val;
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
139
src/views/business/components/businessTwo.vue
Normal file
139
src/views/business/components/businessTwo.vue
Normal file
@ -0,0 +1,139 @@
|
||||
<template>
|
||||
<custom-echart-bar :chart-data="state.data" height="100%" :option="state.option" />
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
import { isEmpty, sleep } from '@/utils';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
},
|
||||
query: {
|
||||
type: String,
|
||||
default: '',
|
||||
},
|
||||
});
|
||||
|
||||
const state = reactive({
|
||||
option: {
|
||||
grid: {
|
||||
left: '5%',
|
||||
right: '5%',
|
||||
bottom: '5%',
|
||||
top: '10%',
|
||||
containLabel: true,
|
||||
},
|
||||
tooltip: {
|
||||
trigger: 'axis',
|
||||
axisPointer: {
|
||||
type: 'shadow',
|
||||
},
|
||||
backgroundColor: 'rgba(18, 55, 85, 0.8);',
|
||||
borderColor: '#35d0c0',
|
||||
formatter: (data) => {
|
||||
const params = data[0];
|
||||
let str = `<div class="custom-echarts-tips">
|
||||
<span>${params.name}</span><br/>
|
||||
<span>${params.marker} ${params.data} 个</span>
|
||||
</div>`;
|
||||
return str;
|
||||
},
|
||||
},
|
||||
barStyle: {
|
||||
barWidth: 15,
|
||||
itemStyle: {
|
||||
borderRadius: [8, 8, 0, 0],
|
||||
},
|
||||
color: {
|
||||
type: 'linear',
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: '#35D0C0' },
|
||||
{ offset: 1, color: '#35D0C0' },
|
||||
],
|
||||
global: false,
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: 'category',
|
||||
// name: '面积',
|
||||
axisTick: {
|
||||
show: false,
|
||||
alignWithLabel: false,
|
||||
interval: 'auto',
|
||||
inside: false,
|
||||
length: 5,
|
||||
lineStyle: {
|
||||
type: 'solid',
|
||||
width: 1,
|
||||
color: 'rgba(28, 158, 222, 1)',
|
||||
},
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: 'value',
|
||||
// name: '面积(万亩)',
|
||||
},
|
||||
},
|
||||
data: [],
|
||||
});
|
||||
|
||||
const loadData = async (code = '') => {
|
||||
state.loading = true;
|
||||
// GetInputsInfo()
|
||||
// .then((res) => {
|
||||
// if (res.code === 200) {
|
||||
// state.data = res.data;
|
||||
// }
|
||||
// })
|
||||
// .catch((err) => {
|
||||
// app.$message.error(err.msg);
|
||||
// });
|
||||
await sleep(500);
|
||||
state.data = [
|
||||
{ name: '耿马镇', value: 70 },
|
||||
{ name: '勐撒镇', value: 203 },
|
||||
{ name: '勐永镇', value: 54 },
|
||||
{ name: '孟定镇', value: 35 },
|
||||
{ name: '勐简乡', value: 95 },
|
||||
{ name: '贺派乡', value: 62 },
|
||||
{ name: '四排山乡', value: 84 },
|
||||
{ name: '芒洪乡', value: 82 },
|
||||
{ name: '大兴乡', value: 64 },
|
||||
{ name: '信阳', value: 55 },
|
||||
{ name: '新乡', value: 32 },
|
||||
{ name: '大同', value: 51 },
|
||||
];
|
||||
};
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(val) => {
|
||||
if (!isEmpty(val)) {
|
||||
state.data = val;
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
|
||||
watch(
|
||||
() => props.query,
|
||||
(val) => {
|
||||
if (!isEmpty(val)) {
|
||||
loadData(val);
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
@ -2,18 +2,40 @@
|
||||
<el-row class="data-home-index">
|
||||
<el-col :span="6" class="left-charts">
|
||||
<div class="left-charts-item">
|
||||
<customBack top-title=" " :top-postion="'left'">
|
||||
<template #back> </template>
|
||||
<customBack top-title="生产经营主体数量统计" :top-postion="'left'">
|
||||
<template #back>
|
||||
<businessOne :data="state.data.one" />
|
||||
</template>
|
||||
</customBack>
|
||||
</div>
|
||||
<div class="left-charts-item">
|
||||
<customBack top-title=" " :top-postion="'left'">
|
||||
<template #back> </template>
|
||||
<customBack
|
||||
top-title="生产经营主体数量"
|
||||
:top-postion="'left'"
|
||||
:down-title="'农资企业'"
|
||||
:label-field="'label'"
|
||||
:value-field="'value'"
|
||||
:down-width="'100px'"
|
||||
:options="[
|
||||
{ value: 1, label: '农企/合作社' },
|
||||
{ value: 2, label: '农资企业' },
|
||||
{ value: 3, label: '种源企业' },
|
||||
{ value: 4, label: '生产加工企业' },
|
||||
{ value: 5, label: '农户' },
|
||||
]"
|
||||
:is-down="true"
|
||||
@command="handleCommand"
|
||||
>
|
||||
<template #back>
|
||||
<businessTwo :data="state.data.two" :query="state.queryCode" />
|
||||
</template>
|
||||
</customBack>
|
||||
</div>
|
||||
<div class="left-charts-item">
|
||||
<customBack top-title=" " :top-postion="'left'">
|
||||
<template #back> </template>
|
||||
<customBack top-title="近三年用地规模曲线" :top-postion="'left'">
|
||||
<template #back>
|
||||
<businessThere :data="state.data.there" />
|
||||
</template>
|
||||
</customBack>
|
||||
</div>
|
||||
</el-col>
|
||||
@ -22,18 +44,24 @@
|
||||
</el-col>
|
||||
<el-col :span="6" class="right-charts">
|
||||
<div class="right-charts-item">
|
||||
<customBack top-title=" " :top-postion="'right'">
|
||||
<template #back> </template>
|
||||
<customBack top-title="证件状态看板" :top-postion="'right'">
|
||||
<template #back>
|
||||
<businessFour :data="state.data.four" />
|
||||
</template>
|
||||
</customBack>
|
||||
</div>
|
||||
<div class="right-charts-item">
|
||||
<customBack top-title=" " :top-postion="'right'">
|
||||
<template #back> </template>
|
||||
<customBack top-title="生产经营主体年收益排行" :top-postion="'right'">
|
||||
<template #back>
|
||||
<businessFive :data="state.data.five" />
|
||||
</template>
|
||||
</customBack>
|
||||
</div>
|
||||
<div class="right-charts-item">
|
||||
<customBack top-title=" " :top-postion="'right'">
|
||||
<template #back> </template>
|
||||
<customBack top-title="生产经营主体用地情况" :top-postion="'right'">
|
||||
<template #back>
|
||||
<businessSix :data="state.data.six" />
|
||||
</template>
|
||||
</customBack>
|
||||
</div>
|
||||
</el-col>
|
||||
@ -42,10 +70,114 @@
|
||||
<script setup>
|
||||
import { nextTick, reactive, ref } from 'vue';
|
||||
import { useApp } from '@/hooks';
|
||||
import { sleep } from '@/utils';
|
||||
import businessMap from './components/businessMap.vue';
|
||||
import businessOne from './components/businessOne.vue';
|
||||
import businessTwo from './components/businessTwo.vue';
|
||||
import businessThere from './components/businessThere.vue';
|
||||
import businessFour from './components/businessFour.vue';
|
||||
import businessFive from './components/businessFive.vue';
|
||||
import businessSix from './components/businessSix.vue';
|
||||
|
||||
const app = useApp();
|
||||
const fiveRef = ref(null);
|
||||
const state = reactive({
|
||||
loading: false,
|
||||
data: {},
|
||||
queryCode: '',
|
||||
});
|
||||
|
||||
// 加载
|
||||
const loadData = async () => {
|
||||
state.loading = true;
|
||||
// GetInputsInfo()
|
||||
// .then((res) => {
|
||||
// if (res.code === 200) {
|
||||
// state.data = res.data;
|
||||
// }
|
||||
// })
|
||||
// .catch((err) => {
|
||||
// app.$message.error(err.msg);
|
||||
// });
|
||||
await sleep(500);
|
||||
state.data = {
|
||||
one: [
|
||||
{ value: 13.8, name: '农企/合作社' },
|
||||
{ value: 23.8, name: '农资企业' },
|
||||
{ value: 24.1, name: '种源企业' },
|
||||
{ value: 29.8, name: '生产加工企业' },
|
||||
{ value: 8.5, name: '农户' },
|
||||
],
|
||||
two: [
|
||||
{ name: '耿马镇', value: 870 },
|
||||
{ name: '勐撒镇', value: 603 },
|
||||
{ name: '勐永镇', value: 854 },
|
||||
{ name: '孟定镇', value: 635 },
|
||||
{ name: '勐简乡', value: 795 },
|
||||
{ name: '贺派乡', value: 662 },
|
||||
{ name: '四排山乡', value: 584 },
|
||||
{ name: '芒洪乡', value: 682 },
|
||||
{ name: '大兴乡', value: 664 },
|
||||
{ name: '信阳', value: 555 },
|
||||
{ name: '新乡', value: 532 },
|
||||
{ name: '大同', value: 511 },
|
||||
],
|
||||
there: [
|
||||
{ value: 66, name: '2021' },
|
||||
{ value: 100, name: '2022' },
|
||||
{ value: 50, name: '2023' },
|
||||
{ value: 150, name: '2024' },
|
||||
{ value: 80, name: '2025' },
|
||||
],
|
||||
four: {
|
||||
percent: 0.3998,
|
||||
success: 253,
|
||||
warning: 5,
|
||||
danger: 0,
|
||||
},
|
||||
five: [
|
||||
{ name: '耿马镇', value: 87.84 },
|
||||
{ name: '勐撒镇', value: 60.7 },
|
||||
{ name: '勐永镇', value: 85.84 },
|
||||
{ name: '孟定镇', value: 63.25 },
|
||||
{ name: '勐简乡', value: 79.45 },
|
||||
{ name: '贺派乡', value: 66.22 },
|
||||
{ name: '四排山乡', value: 58.34 },
|
||||
{ name: '芒洪乡', value: 68.12 },
|
||||
{ name: '大兴乡', value: 66.34 },
|
||||
{ name: '信阳', value: 55.75 },
|
||||
{ name: '新乡', value: 53.32 },
|
||||
{ name: '大同', value: 51.11 },
|
||||
],
|
||||
six: [
|
||||
{
|
||||
name: '农企/合作社',
|
||||
value: 25,
|
||||
},
|
||||
{
|
||||
name: '农资企业',
|
||||
value: 40,
|
||||
},
|
||||
{
|
||||
name: '种源企业',
|
||||
value: 24,
|
||||
},
|
||||
{
|
||||
name: '生产加工企业',
|
||||
value: 32,
|
||||
},
|
||||
{
|
||||
name: '农户',
|
||||
value: 32,
|
||||
},
|
||||
],
|
||||
};
|
||||
state.loading = false;
|
||||
};
|
||||
|
||||
loadData();
|
||||
|
||||
const handleCommand = (data) => {
|
||||
state.queryCode = data.value;
|
||||
};
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
.data-home-index {
|
||||
|
@ -54,8 +54,8 @@ const datalist = reactive([
|
||||
{ label: '农药使用(吨)', value: 5000, icon: 'pesticide.png' },
|
||||
{ label: '化肥使用(吨)', value: 9000, icon: 'fertilizer.png' },
|
||||
{ label: '饲料(吨)', value: 88943, icon: 'feeduse.png' },
|
||||
{ label: '兽药(吨)', value: 10, icon: 'animalm.png' },
|
||||
{ label: '农机使用(台)', value: 8000, icon: 'farmuse.png' },
|
||||
//{ label: '兽药(吨)', value: 10, icon: 'animalm.png' },
|
||||
//{ label: '农机使用(台)', value: 8000, icon: 'farmuse.png' },
|
||||
]);
|
||||
|
||||
onMounted(() => {
|
||||
|
@ -26,6 +26,7 @@
|
||||
<el-col :span="12">
|
||||
<inputsMap></inputsMap>
|
||||
</el-col>
|
||||
|
||||
<el-col :span="6" class="right-charts">
|
||||
<div class="right-charts-item">
|
||||
<customBack top-title="生产主体统计" :top-postion="'right'">
|
||||
|
@ -2,13 +2,106 @@
|
||||
<custom-echart-bar :chart-data="state.data" height="100%" :option="state.option" />
|
||||
</template>
|
||||
<script setup>
|
||||
import { reactive, watch } from 'vue';
|
||||
import { isEmpty } from '@/utils';
|
||||
|
||||
const props = defineProps({
|
||||
data: {
|
||||
type: Array,
|
||||
default: () => [],
|
||||
import { ref, reactive, onMounted } from 'vue';
|
||||
import { isEmpty, getAssetsFile } from '@/utils';
|
||||
let valData = reactive([
|
||||
{ value: 658, name: '生产溯源码' },
|
||||
{ value: 526, name: '有效溯源码' },
|
||||
]);
|
||||
const chartsData = reactive({
|
||||
option: {
|
||||
backgroundColor: 'transparent',
|
||||
title: {
|
||||
zlevel: 0,
|
||||
text: 806,
|
||||
subtext: '设备管理',
|
||||
top: '38%',
|
||||
left: '80%',
|
||||
textAlign: 'center',
|
||||
textStyle: {
|
||||
color: '#fff',
|
||||
fontSize: 14,
|
||||
},
|
||||
subtextStyle: {
|
||||
fontSize: 10,
|
||||
color: '#fff',
|
||||
},
|
||||
show: false,
|
||||
},
|
||||
color: [
|
||||
{
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(40, 218, 239, 1)' },
|
||||
{ offset: 1, color: 'rgba(130, 249, 255, 0.8)' },
|
||||
],
|
||||
},
|
||||
{
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 1,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{ offset: 0, color: 'rgba(198, 201, 24, 1)' },
|
||||
{ offset: 1, color: 'rgba(198, 201, 24, 0.8)' },
|
||||
],
|
||||
},
|
||||
{
|
||||
x: 1,
|
||||
y: 1,
|
||||
x2: 0,
|
||||
y2: 0,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: 'rgba(15, 44, 88, 1)', // 0% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 0.7,
|
||||
color: 'rgba(40, 55, 255, 1)', // 100% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: 'rgba(244, 245, 255, 1)', // 100% 处的颜色
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
x: 1,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: 'rgba(75, 238, 114, 0.2)', // 0% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: 'rgba(75, 238, 114, 1)', // 100% 处的颜色
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{
|
||||
offset: 0,
|
||||
color: 'rgba(255, 19, 0, 0.2)', // 0% 处的颜色
|
||||
},
|
||||
{
|
||||
offset: 1,
|
||||
color: 'rgba(251, 95, 79, 1)', // 100% 处的颜色
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
@ -106,17 +199,4 @@ const state = reactive({
|
||||
],
|
||||
},
|
||||
});
|
||||
|
||||
watch(
|
||||
() => props.data,
|
||||
(val) => {
|
||||
if (!isEmpty(val)) {
|
||||
state.data = val;
|
||||
}
|
||||
},
|
||||
{
|
||||
deep: true,
|
||||
immediate: true,
|
||||
}
|
||||
);
|
||||
</script>
|
||||
|
Loading…
x
Reference in New Issue
Block a user