You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1521 lines
40 KiB
1521 lines
40 KiB
<template>
|
|
<div class="home-wrap" :style="cssVars">
|
|
<div class="wrap_all">
|
|
<!-- 左侧:行政执法 -->
|
|
<div class="wrap_left">
|
|
<div class="cont_left">
|
|
<h1 class="block_tit">行政执法</h1>
|
|
<div class="count_admin_wrap">
|
|
<div class="count_admin">
|
|
<label><img :src="imgPath('icon_jc2.png')" alt="单独执法" />单独执法</label>
|
|
<div class="count_admin_num">
|
|
<b>{{ coordination.singleNum.toLocaleString() }}</b>
|
|
<span class="number_percent">{{ coordination.singlePer }}<i>%</i></span>
|
|
</div>
|
|
<div class="percent_box">
|
|
<div class="percent-tag">
|
|
<span :class="coordination.singleYoy >= 0 ? 'data-rise' : 'data-fall'">
|
|
<i :class="coordination.singleYoy >= 0 ? 'fa fa-long-arrow-up' : 'fa fa-long-arrow-down'"></i>
|
|
</span>
|
|
<span class="data-change">{{ Math.abs(coordination.singleYoy) }}%</span>
|
|
<label>同比</label>
|
|
</div>
|
|
<div class="percent-tag">
|
|
<span :class="coordination.singleRr >= 0 ? 'data-rise' : 'data-fall'">
|
|
<i :class="coordination.singleRr >= 0 ? 'fa fa-long-arrow-up' : 'fa fa-long-arrow-down'"></i>
|
|
</span>
|
|
<span class="data-change">{{ Math.abs(coordination.singleRr) }}%</span>
|
|
<label>环比</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="count_admin">
|
|
<label><img :src="imgPath('icon_jc.png')" alt="联合执法" />联合执法</label>
|
|
<div class="count_admin_num">
|
|
<b>{{ coordination.unionNum.toLocaleString() }}</b>
|
|
<span class="number_percent">{{ coordination.unionPer }}<i>%</i></span>
|
|
</div>
|
|
<div class="percent_box">
|
|
<div class="percent-tag">
|
|
<span :class="coordination.unionYoy >= 0 ? 'data-rise' : 'data-fall'">
|
|
<i :class="coordination.unionYoy >= 0 ? 'fa fa-long-arrow-up' : 'fa fa-long-arrow-down'"></i>
|
|
</span>
|
|
<span class="data-change">{{ Math.abs(coordination.unionYoy) }}%</span>
|
|
<label>同比</label>
|
|
</div>
|
|
<div class="percent-tag">
|
|
<span :class="coordination.unionRr >= 0 ? 'data-rise' : 'data-fall'">
|
|
<i :class="coordination.unionRr >= 0 ? 'fa fa-long-arrow-up' : 'fa fa-long-arrow-down'"></i>
|
|
</span>
|
|
<span class="data-change">{{ Math.abs(coordination.unionRr) }}%</span>
|
|
<label>环比</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="count_admin">
|
|
<label><img :src="imgPath('icon_qy.png')" alt="被执法企业" />被执法企业</label>
|
|
<div class="count_admin_num">
|
|
<b>{{ enterprise.num.toLocaleString() }}</b>
|
|
</div>
|
|
<div class="percent_box">
|
|
<div class="percent-tag">
|
|
<span :class="enterprise.yoy >= 0 ? 'data-rise' : 'data-fall'">
|
|
<i :class="enterprise.yoy >= 0 ? 'fa fa-long-arrow-up' : 'fa fa-long-arrow-down'"></i>
|
|
</span>
|
|
<span class="data-change">{{ Math.abs(enterprise.yoy) }}%</span>
|
|
<label>同比</label>
|
|
</div>
|
|
<div class="percent-tag">
|
|
<span :class="enterprise.rr >= 0 ? 'data-rise' : 'data-fall'">
|
|
<i :class="enterprise.rr >= 0 ? 'fa fa-long-arrow-up' : 'fa fa-long-arrow-down'"></i>
|
|
</span>
|
|
<span class="data-change">{{ Math.abs(enterprise.rr) }}%</span>
|
|
<label>环比</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="count_admin">
|
|
<label><img :src="imgPath('icon_yj.png')" alt="入企压减率" />入企压减率</label>
|
|
<div class="count_admin_num">
|
|
<b>{{ coordination.cutNum.toLocaleString() }}</b>
|
|
</div>
|
|
<div class="percent_box">
|
|
<div class="percent-tag yjlv">
|
|
<span class="number_percent">{{ coordination.cutPer }}<i>%</i></span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div ref="adminPieRef" class="chartbox_right chartbox_admin"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 中间:概览 + 地图 -->
|
|
<div class="wrap_cent">
|
|
<div class="select_set">
|
|
<div class="select_item">
|
|
<span>深圳市</span>
|
|
<span class="time_wrap">
|
|
<el-date-picker
|
|
v-model="dateRange"
|
|
type="daterange"
|
|
range-separator="至"
|
|
start-placeholder="开始日期"
|
|
end-placeholder="结束日期"
|
|
value-format="YYYY-MM-DD"
|
|
clearable
|
|
@change="onDateChange"
|
|
/>
|
|
</span>
|
|
</div>
|
|
</div>
|
|
<div class="link_btn">
|
|
<a v-if="!hideLeftFlag" @click.prevent="goToAnalysis('city')">
|
|
各市直执法单位综合分析
|
|
</a>
|
|
<a @click.prevent="goToAnalysis('district')">
|
|
{{ rightFlagText }}
|
|
</a>
|
|
</div>
|
|
<div class="count_box">
|
|
<div class="count_item admin">
|
|
<div class="count_tit"><label>行政执法</label></div>
|
|
<div class="count_num">
|
|
<div class="count_num_all">{{ coordination.allNum.toLocaleString() }}</div>
|
|
<div class="count_num_sub">
|
|
<span>(市直:<b>{{ sJcNum }}</b></span>
|
|
<span>各区:<b>{{ qJcNum.toLocaleString() }}</b>)</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="count_item non_admin">
|
|
<div class="count_tit"><label>非行政执法</label></div>
|
|
<div class="count_num">
|
|
<div class="count_num_all">{{ njcAll.toLocaleString() }}</div>
|
|
<div class="count_num_sub">
|
|
<span>(市直:<b>{{ sNjcNum }}</b></span>
|
|
<span>各区:<b>{{ qNjcNum.toLocaleString() }}</b>)</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="map_box">
|
|
<img class="szmap" :src="imgPath('szmap_3d.png')" alt="深圳地图" />
|
|
<div class="label_wrap">
|
|
<div
|
|
v-for="config in districtConfigs"
|
|
:key="config.key"
|
|
:id="config.key"
|
|
class="label_item"
|
|
:style="{ top: config.top, left: config.left }"
|
|
>
|
|
<a
|
|
class="flag-c"
|
|
:class="{ active: activeDistrictIdx === config.idx }"
|
|
@click="toggleDistrictDetail(config)"
|
|
>
|
|
<label>{{ config.name }}</label>
|
|
</a>
|
|
<!-- 区域详情弹窗 -->
|
|
<div
|
|
v-show="activeDistrictIdx === config.idx"
|
|
class="fold_cont"
|
|
:class="config.key"
|
|
>
|
|
<div class="pop_tit">
|
|
<h5>{{ config.name }}</h5>
|
|
<div class="tab_switch">
|
|
<a
|
|
class="admin"
|
|
:class="{ active: districtTab === 'xzzf' }"
|
|
@click="switchDistrictTab(config.idx, 'xzzf')"
|
|
>行政执法</a>
|
|
<a
|
|
class="non-admin"
|
|
:class="{ active: districtTab === 'fxzzf' }"
|
|
@click="switchDistrictTab(config.idx, 'fxzzf')"
|
|
>非行政执法</a>
|
|
</div>
|
|
</div>
|
|
<div class="tab_inspect">
|
|
<div v-show="districtTab === 'xzzf'" class="tab_inspect_item">
|
|
<div class="inspect_count">(行政执法总数:<b>{{ districtData(config.name)?.allNum ?? 0 }}</b>)</div>
|
|
<ul>
|
|
<li><label>单独执法</label><span>{{ districtData(config.name)?.singleNum ?? 0 }}</span><span>{{ districtData(config.name)?.singlePer ?? '0.0' }}%</span></li>
|
|
<li><label>联合执法</label><span>{{ districtData(config.name)?.unionNum ?? 0 }}</span><span>{{ districtData(config.name)?.unionPer ?? '0.0' }}%</span></li>
|
|
<li><label>入企压减率</label><span>{{ districtData(config.name)?.cutNum ?? 0 }}</span><span>{{ districtData(config.name)?.cutPer ?? '0.0' }}%</span></li>
|
|
<li><label>被执法企业</label><span>{{ districtData(config.name)?.entNum ?? 0 }}</span><span></span></li>
|
|
<li><label>涉企投诉</label><span>{{ districtData(config.name)?.comNum ?? 0 }}</span><span></span></li>
|
|
</ul>
|
|
</div>
|
|
<div v-show="districtTab === 'fxzzf'" class="tab_inspect_item">
|
|
<div class="inspect_count">(非行政执法总数:<b>{{ districtData(config.name)?.njcNum ?? 0 }}</b>)</div>
|
|
<ul>
|
|
<li><label>日常巡查</label><span>{{ getNonTypeVal(config.name, 'key_4', 'num') }}</span><span>{{ getNonTypeVal(config.name, 'key_4', 'per') }}%</span></li>
|
|
<li><label>普法宣传</label><span>{{ getNonTypeVal(config.name, 'key_3', 'num') }}</span><span>{{ getNonTypeVal(config.name, 'key_3', 'per') }}%</span></li>
|
|
<li><label>企业服务</label><span>{{ getNonTypeVal(config.name, 'key_6', 'num') }}</span><span>{{ getNonTypeVal(config.name, 'key_6', 'per') }}%</span></li>
|
|
<li><label>技术指导</label><span>{{ getNonTypeVal(config.name, 'key_7', 'num') }}</span><span>{{ getNonTypeVal(config.name, 'key_7', 'per') }}%</span></li>
|
|
<li><label>检验检测</label><span>{{ getNonTypeVal(config.name, 'key_8', 'num') }}</span><span>{{ getNonTypeVal(config.name, 'key_8', 'per') }}%</span></li>
|
|
</ul>
|
|
<ul>
|
|
<li><label>诉求处理</label><span>{{ getNonTypeVal(config.name, 'key_5', 'num') }}</span><span>{{ getNonTypeVal(config.name, 'key_5', 'per') }}%</span></li>
|
|
<li><label>培训</label><span>{{ getNonTypeVal(config.name, 'key_9', 'num') }}</span><span>{{ getNonTypeVal(config.name, 'key_9', 'per') }}%</span></li>
|
|
<li><label>调研</label><span>{{ getNonTypeVal(config.name, 'key_10', 'num') }}</span><span>{{ getNonTypeVal(config.name, 'key_10', 'per') }}%</span></li>
|
|
<li><label>其他</label><span>{{ getNonTypeVal(config.name, 'key_0', 'num') }}</span><span>{{ getNonTypeVal(config.name, 'key_0', 'per') }}%</span></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 右侧:非行政执法 -->
|
|
<div class="wrap_right">
|
|
<div class="cont_left">
|
|
<h1 class="block_tit">非行政执法</h1>
|
|
<div class="count_wrap" id="nonRegistrationType">
|
|
<div
|
|
v-for="(item, index) in displayNonTypeList"
|
|
:key="item.dict_label"
|
|
class="count_item"
|
|
>
|
|
<label>
|
|
<img :src="getNonTypeIcon(index)" :alt="item.dict_label" />
|
|
{{ item.dict_label }}
|
|
</label>
|
|
<span class="number_count">{{ item.num.toLocaleString() }}</span>
|
|
</div>
|
|
</div>
|
|
<div ref="nonPieRef" class="chartbox_right chartbox_non"></div>
|
|
</div>
|
|
</div>
|
|
|
|
<!-- 底部:趋势图 -->
|
|
<div class="wrap_bottom">
|
|
<div class="cont_left">
|
|
<h3>涉企执法趋势</h3>
|
|
<div class="tab_tit">
|
|
<a :class="{ active: trendTab === 0 }" @click="switchTrendTab(0)">行政执法</a>
|
|
<a :class="{ active: trendTab === 1 }" @click="switchTrendTab(1)">非行政执法</a>
|
|
</div>
|
|
<div class="tab_chart">
|
|
<div v-show="trendTab === 0" ref="adminTrendRef" class="chartbox"></div>
|
|
<div v-show="trendTab === 1" ref="nonTrendRef" class="chartbox"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script setup lang="ts">
|
|
import { computed, nextTick, onMounted, onUnmounted, reactive, ref, watch } from 'vue';
|
|
import { useRouter } from 'vue-router';
|
|
import * as echarts from 'echarts';
|
|
import {
|
|
analysisEnterprises,
|
|
analysisEnterprisesCoordination,
|
|
analysisEnterprisesNonAll,
|
|
analysisNonRegistrationType,
|
|
analysisRegistrationType,
|
|
analysisTime,
|
|
areaRegistration,
|
|
nonAnalysisTime
|
|
} from '@/api/supervision/statistical/statisticalPanel';
|
|
import type { AreaRegistrationData, DictStatItem } from '@/api/supervision/statistical/types';
|
|
import {
|
|
normalizeAreaRegistration,
|
|
normalizeCoordination,
|
|
normalizeDictStatList,
|
|
normalizeEnterpriseStat,
|
|
normalizeTimeSeries,
|
|
toNum,
|
|
unwrapData
|
|
} from '@/api/supervision/statistical/adapters';
|
|
import { buildAdminPieOption, buildNonAdminPieOption, buildTrendLineOption } from '@/views/supervision/statistical/utils/chartOptions';
|
|
import { DISTRICT_CONFIGS, DISTRICT_LIST } from '@/views/supervision/statistical/utils/districtConfig';
|
|
|
|
async function safeLoad<T>(fn: () => Promise<T>): Promise<T | null> {
|
|
try {
|
|
return await fn();
|
|
} catch (e) {
|
|
console.warn('[首页大屏] 接口加载失败', e);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
const router = useRouter();
|
|
const districtConfigs = DISTRICT_CONFIGS;
|
|
|
|
const dateRange = ref<[string, string] | null>(null);
|
|
const trendTab = ref(0);
|
|
|
|
const activeDistrictIdx = ref(-1);
|
|
const districtTab = ref<'xzzf' | 'fxzzf'>('xzzf');
|
|
|
|
const coordination = reactive({
|
|
roleFlag: 1,
|
|
roleDept: '',
|
|
allNum: 0,
|
|
nonNum: 0,
|
|
unionNum: 0,
|
|
unionYoy: 0,
|
|
unionRr: 0,
|
|
unionPer: '0.0',
|
|
singleNum: 0,
|
|
singleYoy: 0,
|
|
singleRr: 0,
|
|
singlePer: '0.0',
|
|
cutNum: 0,
|
|
cutPer: '0.0'
|
|
});
|
|
|
|
const enterprise = reactive({ num: 0, yoy: 0, rr: 0 });
|
|
const nonTypeList = ref<DictStatItem[]>([]);
|
|
const njcAll = ref(0);
|
|
const qJcNum = ref(0);
|
|
const qNjcNum = ref(0);
|
|
|
|
const districtDataMap = ref<Record<string, AreaRegistrationData>>({});
|
|
|
|
const defaultNonTypes: DictStatItem[] = [
|
|
{ dict_label: '日常巡查', num: 49605, per: '84.04' },
|
|
{ dict_label: '普法宣传', num: 844, per: '1.43' },
|
|
{ dict_label: '企业服务', num: 3177, per: '5.39' },
|
|
{ dict_label: '技术指导', num: 3277, per: '5.56' },
|
|
{ dict_label: '检验检测', num: 210, per: '0.36' },
|
|
{ dict_label: '诉求处理', num: 377, per: '0.64' },
|
|
{ dict_label: '培训', num: 337, per: '0.57' },
|
|
{ dict_label: '调研', num: 73, per: '0.12' },
|
|
{ dict_label: '其他', num: 1129, per: '1.91' }
|
|
];
|
|
|
|
const displayNonTypeList = computed(() => {
|
|
if (nonTypeList.value.length > 0) return nonTypeList.value;
|
|
return defaultNonTypes;
|
|
});
|
|
|
|
const isDistrictUser = computed(() => coordination.roleFlag === 9 || coordination.roleFlag === 4 || coordination.roleFlag === 3);
|
|
|
|
const sJcNum = computed(() => {
|
|
if (isDistrictUser.value) return '-';
|
|
return (coordination.allNum - qJcNum.value).toLocaleString();
|
|
});
|
|
const sNjcNum = computed(() => {
|
|
if (isDistrictUser.value) return '-';
|
|
return (njcAll.value - qNjcNum.value).toLocaleString();
|
|
});
|
|
|
|
const hideLeftFlag = computed(() => isDistrictUser.value);
|
|
const rightFlagText = computed(() => {
|
|
if (isDistrictUser.value) {
|
|
return `${coordination.roleDept || '各区'}综合分析`;
|
|
}
|
|
return '各区综合分析';
|
|
});
|
|
|
|
function goToAnalysis(type: 'city' | 'district') {
|
|
const path = type === 'city'
|
|
? '/enforcement-code/statistical/city-direct'
|
|
: '/enforcement-code/statistical/district-direct';
|
|
router.push(path);
|
|
}
|
|
|
|
function districtData(name: string): AreaRegistrationData | undefined {
|
|
return districtDataMap.value[name];
|
|
}
|
|
|
|
function getNonTypeVal(areaName: string, key: string, field: 'num' | 'per') {
|
|
const data = districtDataMap.value[areaName];
|
|
if (!data) return field === 'num' ? 0 : '0.0';
|
|
const item = data.resNonTyps?.[key];
|
|
if (!item) return field === 'num' ? 0 : '0.0';
|
|
return field === 'num' ? (item.num ?? 0) : (item.per ?? '0.0');
|
|
}
|
|
|
|
function toggleDistrictDetail(config: { idx: number; name: string }) {
|
|
if (activeDistrictIdx.value === config.idx) {
|
|
activeDistrictIdx.value = -1;
|
|
} else {
|
|
activeDistrictIdx.value = config.idx;
|
|
districtTab.value = 'xzzf';
|
|
}
|
|
}
|
|
|
|
function switchDistrictTab(_idx: number, flag: 'xzzf' | 'fxzzf') {
|
|
districtTab.value = flag;
|
|
}
|
|
|
|
const BASE = import.meta.env.BASE_URL;
|
|
|
|
function imgPath(relativePath: string) {
|
|
return `${BASE}statistical/images/${relativePath}`;
|
|
}
|
|
|
|
const cssVars = computed(() => ({
|
|
'--bg-homebody': `url('${imgPath('bg_homebody.jpg')}')`,
|
|
'--bg-pie': `url('${imgPath('bg_pie.png')}')`,
|
|
'--bg-tip': `url('${imgPath('bg_tip.png')}')`,
|
|
'--bg-tip-line': `url('${imgPath('bg_tip_line.png')}')`,
|
|
'--bg-tit': `url('${imgPath('bg_tit.png')}')`,
|
|
'--bg-tit3': `url('${imgPath('bg_tit3.png')}')`,
|
|
'--bg-data-item': `url('${imgPath('bg_data_item.jpg')}')`,
|
|
'--icon-data1': `url('${imgPath('icon_data1.png')}')`,
|
|
'--icon-data2': `url('${imgPath('icon_data2.png')}')`,
|
|
'--icon-posit': `url('${imgPath('icon_posit.png')}')`,
|
|
'--icon-dept32': `url('${imgPath('icon_dept32.png')}')`,
|
|
'--icon-dist32': `url('${imgPath('icon_dist32.png')}')`
|
|
}));
|
|
|
|
function getNonTypeIcon(index: number) {
|
|
return imgPath(`icon_24_r${index + 1}.png`);
|
|
}
|
|
|
|
const adminPieRef = ref<HTMLElement>();
|
|
const nonPieRef = ref<HTMLElement>();
|
|
const adminTrendRef = ref<HTMLElement>();
|
|
const nonTrendRef = ref<HTMLElement>();
|
|
|
|
let adminPieChart: echarts.ECharts | null = null;
|
|
let nonPieChart: echarts.ECharts | null = null;
|
|
let adminTrendChart: echarts.ECharts | null = null;
|
|
let nonTrendChart: echarts.ECharts | null = null;
|
|
|
|
function getTimeParams() {
|
|
if (!dateRange.value) return { beginTime: undefined, endTime: undefined };
|
|
return { beginTime: dateRange.value[0], endTime: dateRange.value[1] };
|
|
}
|
|
|
|
async function loadCoordination() {
|
|
const res = await safeLoad(() => analysisEnterprisesCoordination(getTimeParams()));
|
|
if (res) {
|
|
const data = normalizeCoordination(unwrapData(res));
|
|
Object.assign(coordination, data);
|
|
coordination.singleYoy = parseFloat(data.singleYoy);
|
|
coordination.singleRr = parseFloat(data.singleRr);
|
|
coordination.unionYoy = parseFloat(data.unionYoy);
|
|
coordination.unionRr = parseFloat(data.unionRr);
|
|
} else {
|
|
// Mock data
|
|
Object.assign(coordination, {
|
|
roleFlag: 1,
|
|
roleDept: '',
|
|
allNum: 61125,
|
|
nonNum: 58902,
|
|
unionNum: 642,
|
|
unionYoy: -1.25,
|
|
unionRr: 1.05,
|
|
unionPer: '1.05',
|
|
singleNum: 59768,
|
|
singleYoy: 2.15,
|
|
singleRr: -0.77,
|
|
singlePer: '97.77',
|
|
cutNum: 715,
|
|
cutPer: '1.18'
|
|
});
|
|
}
|
|
}
|
|
|
|
async function loadEnterprise() {
|
|
const res = await safeLoad(() => analysisEnterprises(getTimeParams()));
|
|
if (res) {
|
|
const data = normalizeEnterpriseStat(unwrapData(res));
|
|
enterprise.num = data.num;
|
|
enterprise.yoy = parseFloat(data.yoy);
|
|
enterprise.rr = parseFloat(data.rr);
|
|
} else {
|
|
enterprise.num = 39028;
|
|
enterprise.yoy = 0;
|
|
enterprise.rr = 0;
|
|
}
|
|
}
|
|
|
|
async function loadNjcAll() {
|
|
const res = await safeLoad(() => analysisEnterprisesNonAll(getTimeParams()));
|
|
if (res) {
|
|
njcAll.value = toNum(unwrapData(res));
|
|
} else {
|
|
njcAll.value = 58902;
|
|
}
|
|
}
|
|
|
|
// Mock data for when API is unavailable
|
|
const MOCK_ADMIN_PIE = [
|
|
{ name: '行政检查', value: 59620 },
|
|
{ name: '行政处罚', value: 946 },
|
|
{ name: '行政许可', value: 358 },
|
|
{ name: '文书送达', value: 159 },
|
|
{ name: '行政强制', value: 67 },
|
|
{ name: '行政裁决', value: 3 },
|
|
{ name: '行政确认', value: 1 }
|
|
];
|
|
|
|
const MOCK_NON_PIE = [
|
|
{ name: '日常巡查', value: 49605 },
|
|
{ name: '普法宣传', value: 844 },
|
|
{ name: '企业服务', value: 3177 },
|
|
{ name: '技术指导', value: 3277 },
|
|
{ name: '检验检测', value: 210 },
|
|
{ name: '诉求处理', value: 377 },
|
|
{ name: '培训', value: 337 },
|
|
{ name: '调研', value: 73 },
|
|
{ name: '其他', value: 1129 }
|
|
];
|
|
|
|
async function loadAdminType() {
|
|
const res = await safeLoad(() => analysisRegistrationType(getTimeParams()));
|
|
const list = res ? normalizeDictStatList(unwrapData(res)) : [];
|
|
let chartData = list
|
|
.filter((item) => item.dict_label)
|
|
.map((item) => ({ value: item.num, name: item.dict_label }));
|
|
if (!chartData.length) {
|
|
chartData = MOCK_ADMIN_PIE;
|
|
}
|
|
await nextTick();
|
|
if (adminPieRef.value) {
|
|
if (!adminPieChart) {
|
|
adminPieChart = echarts.init(adminPieRef.value);
|
|
}
|
|
adminPieChart.setOption(buildAdminPieOption(chartData), true);
|
|
adminPieChart.resize();
|
|
}
|
|
}
|
|
|
|
async function loadNonType() {
|
|
const res = await safeLoad(() => analysisNonRegistrationType(getTimeParams()));
|
|
const list = res ? normalizeDictStatList(unwrapData(res)) : [];
|
|
nonTypeList.value = list;
|
|
let chartData = list
|
|
.filter((item) => item.dict_label)
|
|
.map((item) => ({ value: item.num, name: item.dict_label }));
|
|
if (!chartData.length) {
|
|
chartData = MOCK_NON_PIE;
|
|
}
|
|
await nextTick();
|
|
if (nonPieRef.value) {
|
|
if (!nonPieChart) {
|
|
nonPieChart = echarts.init(nonPieRef.value);
|
|
}
|
|
nonPieChart.setOption(buildNonAdminPieOption(chartData), true);
|
|
nonPieChart.resize();
|
|
}
|
|
}
|
|
|
|
async function loadAdminTrend() {
|
|
const res = await safeLoad(() => analysisTime(getTimeParams()));
|
|
let { times, ins, ent } = res ? normalizeTimeSeries(unwrapData(res)) : { times: [] as string[], ins: [] as number[], ent: [] as number[] };
|
|
if (!times.length) {
|
|
times = ['2024-08', '2024-10', '2024-12', '2025-02', '2025-04', '2025-06', '2025-08', '2025-10', '2025-12', '2026-02', '2026-04', '2026-06', '2026-08'];
|
|
ins = ['2800', '3200', '3800', '3500', '4200', '4800', '5200', '5800', '6400', '6000', '6800', '7200', '7600'];
|
|
ent = [1200, 1500, 1800, 1600, 2200, 2500, 2800, 3100, 3400, 3200, 3600, 3900, 4100];
|
|
}
|
|
await nextTick();
|
|
if (adminTrendRef.value) {
|
|
if (!adminTrendChart) {
|
|
adminTrendChart = echarts.init(adminTrendRef.value);
|
|
}
|
|
adminTrendChart.setOption(
|
|
buildTrendLineOption(times, ins.map(Number), ent.map(Number), '行政执法数量', '被检查企业数量', '行政执法数量(宗)', '被执法企业数量(家)'),
|
|
true
|
|
);
|
|
adminTrendChart.resize();
|
|
}
|
|
}
|
|
|
|
async function loadNonTrend() {
|
|
const res = await safeLoad(() => nonAnalysisTime(getTimeParams()));
|
|
let { times, ins, ent } = res ? normalizeTimeSeries(unwrapData(res)) : { times: [] as string[], ins: [] as number[], ent: [] as number[] };
|
|
if (!times.length) {
|
|
times = ['2024-08', '2024-10', '2024-12', '2025-02', '2025-04', '2025-06', '2025-08', '2025-10', '2025-12', '2026-02', '2026-04', '2026-06', '2026-08'];
|
|
ins = [800, 1200, 1500, 1800, 2200, 2500, 2800, 3200, 3500, 3800, 4200, 4500, 4800];
|
|
ent = [400, 600, 800, 1000, 1200, 1400, 1600, 1800, 2000, 2200, 2400, 2600, 2800];
|
|
}
|
|
await nextTick();
|
|
if (nonTrendRef.value) {
|
|
if (!nonTrendChart) {
|
|
nonTrendChart = echarts.init(nonTrendRef.value);
|
|
}
|
|
nonTrendChart.setOption(
|
|
buildTrendLineOption(times, ins.map(Number), ent.map(Number), '非行政执法数量', '被检查企业数量', '非行政执法数量(宗)', '被检查企业数量(家)'),
|
|
true
|
|
);
|
|
nonTrendChart.resize();
|
|
}
|
|
}
|
|
|
|
function onDateChange() {
|
|
refreshAll();
|
|
}
|
|
|
|
function switchTrendTab(tab: number) {
|
|
trendTab.value = tab;
|
|
nextTick(() => {
|
|
const chart = tab === 0 ? adminTrendChart : nonTrendChart;
|
|
chart?.resize();
|
|
});
|
|
}
|
|
|
|
function handleResize() {
|
|
adminPieChart?.resize();
|
|
nonPieChart?.resize();
|
|
adminTrendChart?.resize();
|
|
nonTrendChart?.resize();
|
|
}
|
|
|
|
async function loadAreaData() {
|
|
const params = getTimeParams();
|
|
let jcSum = 0;
|
|
let njcSum = 0;
|
|
const dataMap: Record<string, AreaRegistrationData> = {};
|
|
|
|
const results = await Promise.allSettled(
|
|
DISTRICT_LIST.map((area) => areaRegistration({ ...params, deptId: area }))
|
|
);
|
|
|
|
results.forEach((result) => {
|
|
if (result.status !== 'fulfilled') return;
|
|
const data = normalizeAreaRegistration(unwrapData(result.value));
|
|
const area = data.area || DISTRICT_LIST[results.indexOf(result)];
|
|
dataMap[area] = data;
|
|
jcSum += data.allNum;
|
|
njcSum += data.njcNum;
|
|
});
|
|
|
|
districtDataMap.value = dataMap;
|
|
qJcNum.value = jcSum;
|
|
qNjcNum.value = njcSum;
|
|
}
|
|
|
|
async function refreshAll() {
|
|
await Promise.allSettled([
|
|
loadCoordination(),
|
|
loadEnterprise(),
|
|
loadNjcAll(),
|
|
loadAdminType(),
|
|
loadNonType(),
|
|
loadAdminTrend(),
|
|
loadNonTrend(),
|
|
loadAreaData()
|
|
]);
|
|
}
|
|
|
|
let originalFontSize: string | null = null;
|
|
|
|
onMounted(async () => {
|
|
const html = document.documentElement;
|
|
originalFontSize = html.style.fontSize;
|
|
html.style.fontSize = '14px';
|
|
|
|
await nextTick();
|
|
|
|
// Wait for layout to settle before initializing charts
|
|
setTimeout(async () => {
|
|
if (adminPieRef.value && adminPieRef.value.clientHeight > 0) {
|
|
adminPieChart = echarts.init(adminPieRef.value);
|
|
}
|
|
if (nonPieRef.value && nonPieRef.value.clientHeight > 0) {
|
|
nonPieChart = echarts.init(nonPieRef.value);
|
|
}
|
|
if (adminTrendRef.value && adminTrendRef.value.clientHeight > 0) {
|
|
adminTrendChart = echarts.init(adminTrendRef.value);
|
|
}
|
|
if (nonTrendRef.value && nonTrendRef.value.clientHeight > 0) {
|
|
nonTrendChart = echarts.init(nonTrendRef.value);
|
|
}
|
|
|
|
// Load data and populate charts
|
|
await refreshAll();
|
|
|
|
nextTick(() => {
|
|
handleResize();
|
|
});
|
|
}, 100);
|
|
|
|
window.addEventListener('resize', handleResize);
|
|
});
|
|
|
|
onUnmounted(() => {
|
|
if (originalFontSize !== null) {
|
|
document.documentElement.style.fontSize = originalFontSize;
|
|
}
|
|
window.removeEventListener('resize', handleResize);
|
|
adminPieChart?.dispose();
|
|
nonPieChart?.dispose();
|
|
adminTrendChart?.dispose();
|
|
nonTrendChart?.dispose();
|
|
});
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
/* CSS reset for dark theme dashboard */
|
|
.home-wrap :deep(*) {
|
|
color: rgba(255, 255, 255, 0.8);
|
|
font-family: 'Microsoft Yahei', Arial, Verdana, sans-serif;
|
|
}
|
|
|
|
.home-wrap :deep(label) {
|
|
font-weight: normal;
|
|
}
|
|
|
|
.home-wrap :deep(b) {
|
|
font-weight: normal;
|
|
}
|
|
|
|
.home-wrap :deep(ul) {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
}
|
|
|
|
.home-wrap :deep(li) {
|
|
list-style: none;
|
|
}
|
|
|
|
.home-wrap :deep(a) {
|
|
text-decoration: none;
|
|
color: inherit;
|
|
}
|
|
|
|
.home-wrap :deep(img) {
|
|
border: none;
|
|
vertical-align: middle;
|
|
}
|
|
|
|
.home-wrap :deep(button) {
|
|
background: none;
|
|
border: none;
|
|
cursor: pointer;
|
|
color: inherit;
|
|
}
|
|
|
|
.home-wrap {
|
|
width: 100%;
|
|
height: calc(100vh - 50px);
|
|
font-size: 14px;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.wrap_all {
|
|
position: relative;
|
|
width: 100%;
|
|
height: calc(100vh - 80px);
|
|
background: var(--bg-homebody) no-repeat;
|
|
background-size: cover;
|
|
background-position: center center;
|
|
box-sizing: border-box;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.wrap_left,
|
|
.wrap_right,
|
|
.wrap_cent,
|
|
.wrap_bottom {
|
|
position: absolute;
|
|
top: 1%;
|
|
z-index: 99;
|
|
margin: 0;
|
|
height: 97%;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.wrap_left {
|
|
left: 0.5%;
|
|
width: 20.5%;
|
|
}
|
|
|
|
.wrap_right {
|
|
right: 0.5%;
|
|
left: auto;
|
|
width: 20.5%;
|
|
}
|
|
|
|
.wrap_cent {
|
|
left: 20%;
|
|
width: 60%;
|
|
}
|
|
|
|
.wrap_bottom {
|
|
top: auto;
|
|
bottom: 2%;
|
|
left: 21.5%;
|
|
width: 57%;
|
|
height: 25%;
|
|
}
|
|
|
|
.cont_left {
|
|
width: 100%;
|
|
height: 100%;
|
|
background: rgba(11, 59, 145, 0.6);
|
|
border-radius: 5px;
|
|
position: relative;
|
|
}
|
|
|
|
.block_tit {
|
|
margin: 0 0 1% 0;
|
|
padding: 0 0 0 4rem;
|
|
height: 2.5rem;
|
|
background: var(--bg-tit) no-repeat;
|
|
background-size: 100% 100%;
|
|
font-size: 1.2rem;
|
|
font-weight: 500;
|
|
line-height: 2;
|
|
text-shadow: 2px 1px 5px rgba(255, 255, 255, 0.5);
|
|
}
|
|
|
|
/* ========== 左侧 count_admin ========== */
|
|
.count_admin_wrap {
|
|
display: flex;
|
|
flex-direction: column;
|
|
height: 46.65%;
|
|
}
|
|
|
|
.count_admin {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-around;
|
|
margin: 3.5% 0 0;
|
|
width: 97%;
|
|
}
|
|
|
|
.count_admin > label {
|
|
width: 5.25rem;
|
|
height: 5.25rem;
|
|
background: linear-gradient(to bottom, transparent 50%, rgba(20, 138, 156, 0.5));
|
|
border: 1px solid rgba(20, 103, 103, 0.6);
|
|
border-radius: 5px;
|
|
color: rgba(255, 255, 255, 1);
|
|
font-size: 0.85rem;
|
|
line-height: 2;
|
|
text-align: center;
|
|
font-weight: normal;
|
|
}
|
|
|
|
.count_admin:nth-child(odd) > label {
|
|
background: linear-gradient(to bottom, transparent 50%, rgba(34, 125, 223, 0.5));
|
|
border: 1px solid rgba(26, 86, 151, 0.6);
|
|
}
|
|
|
|
.count_admin > label > img {
|
|
display: block;
|
|
margin: 10% auto 5%;
|
|
width: auto;
|
|
height: 50%;
|
|
}
|
|
|
|
.count_admin_num {
|
|
width: 35%;
|
|
text-align: center;
|
|
}
|
|
|
|
.count_admin_num > b {
|
|
display: block;
|
|
background-image: linear-gradient(to right, #d2f5ff, #0394f9);
|
|
-webkit-background-clip: text;
|
|
color: transparent;
|
|
font-size: 2.0rem;
|
|
font-weight: 550;
|
|
line-height: 1.5;
|
|
}
|
|
|
|
.number_percent {
|
|
color: rgba(243, 153, 98, 0.8);
|
|
font-size: 1.15rem;
|
|
}
|
|
|
|
.number_percent > i {
|
|
margin-left: 2%;
|
|
color: rgba(243, 153, 98, 0.75);
|
|
font-size: 0.85rem;
|
|
}
|
|
|
|
.percent_box {
|
|
width: 25%;
|
|
}
|
|
|
|
.percent-tag {
|
|
display: flex;
|
|
align-items: center;
|
|
margin: 20% 3%;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.percent-tag span {
|
|
margin: 0 5%;
|
|
color: rgba(255, 255, 255, 0.75);
|
|
font-size: 1rem;
|
|
line-height: 1;
|
|
}
|
|
|
|
.percent-tag span.data-rise,
|
|
.percent-tag span.data-fall {
|
|
margin: 0.75% 2% 1% 0.5%;
|
|
font-size: 1rem;
|
|
}
|
|
|
|
.percent-tag span.data-rise i {
|
|
color: #67dc53;
|
|
}
|
|
|
|
.percent-tag span.data-fall i {
|
|
color: #fd7c7c;
|
|
}
|
|
|
|
.percent-tag label {
|
|
margin: 0 2% 0 5%;
|
|
color: rgba(255, 255, 255, 0.65);
|
|
font-size: 0.85rem;
|
|
font-weight: normal;
|
|
}
|
|
|
|
.yjlv .number_percent {
|
|
color: rgba(243, 153, 98, 0.75);
|
|
font-size: 1.65rem;
|
|
}
|
|
|
|
.yjlv .number_percent > i {
|
|
font-size: 1rem;
|
|
}
|
|
|
|
/* ========== 饼图 ========== */
|
|
.chartbox_right {
|
|
margin: 0;
|
|
width: 100%;
|
|
height: 46%;
|
|
min-height: 120px;
|
|
background: var(--bg-pie) no-repeat center;
|
|
background-position-y: 50.5%;
|
|
background-size: 48.5%;
|
|
position: relative;
|
|
}
|
|
|
|
.chartbox_admin {
|
|
//margin-top: -10%;
|
|
}
|
|
|
|
.wrap_right .chartbox_right {
|
|
height: 47%;
|
|
min-height: 120px;
|
|
background-position-y: 30.5%;
|
|
}
|
|
|
|
.chartbox_non {
|
|
height: 47%;
|
|
background-position-y: 30.5%;
|
|
}
|
|
|
|
/* ========== 中间 select/link/count ========== */
|
|
.select_set {
|
|
float: left;
|
|
margin: 0.5% 0.5% 0.6% 5%;
|
|
padding-left: 2.5rem;
|
|
background: var(--icon-posit) no-repeat left;
|
|
background-size: auto 100%;
|
|
}
|
|
|
|
.select_item {
|
|
margin: 0 0 0 5px;
|
|
font-size: 1.2rem;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.select_item > span {
|
|
margin-right: 1rem;
|
|
}
|
|
|
|
.select_item .time_wrap {
|
|
display: inline-block;
|
|
position: relative;
|
|
width: 18rem;
|
|
height: 2.15rem;
|
|
}
|
|
|
|
.select_item .time_wrap :deep(.el-date-editor) {
|
|
--el-input-bg-color: transparent;
|
|
--el-input-border-color: transparent;
|
|
--el-input-text-color: rgba(255, 255, 255, 0.8);
|
|
--el-input-placeholder-color: rgba(255, 255, 255, 0.45);
|
|
width: 100%;
|
|
}
|
|
|
|
.select_item .time_wrap :deep(.el-input__wrapper) {
|
|
background: linear-gradient(to top, transparent 0, rgba(59, 145, 253, 0.3), rgba(59, 145, 253, 0.05));
|
|
box-shadow: none;
|
|
border-radius: 4px;
|
|
}
|
|
|
|
.select_item .time_wrap :deep(.el-range-separator) {
|
|
color: rgba(255, 255, 255, 0.6);
|
|
}
|
|
|
|
.select_item .time_wrap :deep(.el-input__inner) {
|
|
color: rgba(255, 255, 255, 0.8);
|
|
}
|
|
|
|
.link_btn {
|
|
float: right;
|
|
margin: 0.45% 5% 2% 0;
|
|
min-width: 31rem;
|
|
height: 2rem;
|
|
font-size: 1.2rem;
|
|
line-height: 2;
|
|
white-space: nowrap;
|
|
text-align: right;
|
|
}
|
|
|
|
.link_btn a {
|
|
position: relative;
|
|
display: inline-block;
|
|
margin: 0 3%;
|
|
padding-left: 2rem;
|
|
opacity: 0.8;
|
|
cursor: pointer;
|
|
color: rgba(255, 255, 255, 0.8);
|
|
text-decoration: none;
|
|
line-height: 20px;
|
|
}
|
|
|
|
.link_btn a:hover {
|
|
opacity: 1;
|
|
color: #fff;
|
|
}
|
|
|
|
.link_btn a::before {
|
|
position: absolute;
|
|
left: 0;
|
|
top: 0px;
|
|
content: '';
|
|
width: 1.75rem;
|
|
height: 1.75rem;
|
|
background: var(--icon-dept32) no-repeat;
|
|
background-size: 100% auto;
|
|
}
|
|
|
|
.link_btn a:last-child::before {
|
|
background: var(--icon-dist32) no-repeat;
|
|
background-size: 100% auto;
|
|
}
|
|
|
|
.link_btn a::after {
|
|
position: absolute;
|
|
top:0;
|
|
right: -16px;
|
|
content: '>';
|
|
color: #1ab5e0;
|
|
font-size: 1.25rem;
|
|
opacity: 0.75;
|
|
}
|
|
|
|
.count_box {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
margin: 2% 5%;
|
|
height: 8rem;
|
|
clear: both;
|
|
}
|
|
|
|
.count_box .count_item {
|
|
display: flex;
|
|
min-width: 37.5%;
|
|
height: 100%;
|
|
}
|
|
|
|
.count_box .count_item .count_tit {
|
|
position: relative;
|
|
width: 30%;
|
|
height: 100%;
|
|
background: var(--icon-data2) no-repeat;
|
|
background-size: auto 80%;
|
|
}
|
|
|
|
.count_box .count_item.non_admin .count_tit {
|
|
background: var(--icon-data1) no-repeat;
|
|
background-size: auto 80%;
|
|
}
|
|
|
|
.count_box .count_tit label {
|
|
position: absolute;
|
|
top: 5.65rem;
|
|
left: 0;
|
|
display: block;
|
|
margin: 0;
|
|
padding: 2% 5% 2% 18%;
|
|
width: auto;
|
|
background: var(--bg-tit3) no-repeat;
|
|
background-size: auto 100%;
|
|
color: rgba(255, 255, 255, 0.6);
|
|
font-size: 1.25rem;
|
|
font-weight: normal;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.count_num_all {
|
|
background-image: linear-gradient(to right, #d2f5ff, #0394f9);
|
|
-webkit-background-clip: text;
|
|
color: transparent;
|
|
font-size: 3.15rem;
|
|
font-weight: 550;
|
|
line-height: 1.75;
|
|
text-align: center;
|
|
}
|
|
|
|
.count_num_sub {
|
|
font-size: 1.25rem;
|
|
text-align: center;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.count_num_sub span {
|
|
margin: 0 10% 0 0;
|
|
line-height: 1.75;
|
|
text-align: center;
|
|
}
|
|
|
|
.count_num_sub span b {
|
|
background-image: linear-gradient(to right, #f7fbfd, #26bef9);
|
|
-webkit-background-clip: text;
|
|
color: transparent;
|
|
font-size: 1.25rem;
|
|
font-weight: 550;
|
|
line-height: 1.75;
|
|
text-align: center;
|
|
}
|
|
|
|
.count_box .count_item.admin .count_num {
|
|
margin-left: -3.5%;
|
|
}
|
|
|
|
.count_box .count_item.non_admin .count_num_all,
|
|
.count_box .count_item.non_admin .count_num_sub span b {
|
|
background-image: linear-gradient(to right, #f7fbfd, #2ba4b3);
|
|
}
|
|
|
|
/* ========== 地图 ========== */
|
|
.map_box {
|
|
position: relative;
|
|
top: -3%;
|
|
width: 100%;
|
|
}
|
|
|
|
.map_box > img.szmap {
|
|
margin-top: 0;
|
|
max-width: 100%;
|
|
height: auto;
|
|
display: block;
|
|
}
|
|
|
|
.label_wrap {
|
|
position: absolute;
|
|
top: 0;
|
|
left: 0;
|
|
z-index: 10;
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.label_item {
|
|
position: absolute;
|
|
display: inline-block;
|
|
}
|
|
|
|
.label_item > a {
|
|
cursor: pointer;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.label_item > a > label {
|
|
color: rgba(255, 255, 255, 0.9);
|
|
font-size: 1.15rem;
|
|
text-shadow: 0 0 5px #000;
|
|
cursor: pointer;
|
|
font-weight: normal;
|
|
}
|
|
|
|
/* ========== 弹窗 ========== */
|
|
.fold_cont {
|
|
display: block;
|
|
position: absolute;
|
|
top: -17.5rem;
|
|
left: -15.25rem;
|
|
z-index: 99;
|
|
min-width: 23rem;
|
|
height: 17.5rem;
|
|
background: var(--bg-tip) no-repeat;
|
|
background-size: 100% 100%;
|
|
}
|
|
|
|
.fold_cont::before {
|
|
position: absolute;
|
|
left: 9.25rem;
|
|
bottom: -3.65rem;
|
|
z-index: -1;
|
|
width: 6rem;
|
|
height: 5rem;
|
|
background: var(--bg-tip-line) no-repeat;
|
|
background-size: auto 80%;
|
|
background-position-y: -90%;
|
|
content: '';
|
|
}
|
|
|
|
:deep(#districtGM) .fold_cont {
|
|
left: -12.75rem;
|
|
}
|
|
|
|
:deep(#districtGM) .fold_cont::before {
|
|
left: 6.75rem;
|
|
}
|
|
|
|
:deep(#districtBA) .fold_cont {
|
|
left: -7.5rem;
|
|
}
|
|
|
|
:deep(#districtBA) .fold_cont::before {
|
|
left: 1.5rem;
|
|
}
|
|
|
|
:deep(#districtNS) .fold_cont {
|
|
left: -12.85rem;
|
|
}
|
|
|
|
:deep(#districtNS) .fold_cont::before {
|
|
left: 6.75rem;
|
|
}
|
|
|
|
:deep(#districtSS) .fold_cont {
|
|
left: -25.25rem;
|
|
}
|
|
|
|
:deep(#districtSS) .fold_cont::before {
|
|
left: 19.25rem;
|
|
}
|
|
|
|
:deep(#districtDP) .tab_inspect_item:last-child .inspect_count {
|
|
left: 6rem;
|
|
}
|
|
|
|
:deep(#districtSS) .tab_inspect_item:last-child .inspect_count {
|
|
left: 9.5rem;
|
|
}
|
|
|
|
.pop_tit {
|
|
display: flex;
|
|
align-items: center;
|
|
justify-content: space-between;
|
|
position: absolute;
|
|
top: 11%;
|
|
left: 7.25%;
|
|
right: 32%;
|
|
z-index: 999;
|
|
}
|
|
|
|
.pop_tit > h5 {
|
|
font-size: 1.15rem;
|
|
font-weight: normal;
|
|
margin: 0;
|
|
}
|
|
|
|
.inspect_count {
|
|
margin: 4% 0 3% -0.5rem;
|
|
color: rgba(255, 255, 255, 0.6);
|
|
}
|
|
|
|
.inspect_count b {
|
|
color: #06b8f8;
|
|
}
|
|
|
|
.tab_switch {
|
|
width: 35%;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.tab_switch a {
|
|
margin: 0 0.35rem;
|
|
padding: 1% 2%;
|
|
color: rgba(255, 255, 255, 0.5);
|
|
font-size: 1rem;
|
|
cursor: pointer;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.tab_switch a.active {
|
|
color: #2e82fd;
|
|
border-bottom: 2px solid #2e82fd;
|
|
}
|
|
|
|
.tab_inspect {
|
|
margin: 4rem 8% 0;
|
|
}
|
|
|
|
.tab_inspect_item {
|
|
width: 100%;
|
|
height: calc(100% - 8rem);
|
|
overflow-y: auto;
|
|
}
|
|
|
|
.tab_inspect_item > ul {
|
|
list-style: none;
|
|
padding: 0;
|
|
margin: 0;
|
|
}
|
|
|
|
.tab_inspect_item > ul > li {
|
|
display: flex;
|
|
justify-content: space-between;
|
|
position: relative;
|
|
margin: 0;
|
|
padding: 0 0 0 1.25rem;
|
|
}
|
|
|
|
.tab_inspect_item:last-child > ul > li {
|
|
margin: 2% 0;
|
|
}
|
|
|
|
.tab_inspect_item > ul > li::before {
|
|
position: absolute;
|
|
top: 0.35rem;
|
|
left: 0;
|
|
content: '\f111';
|
|
color: #7ca9fb;
|
|
font-size: 0.65rem;
|
|
}
|
|
|
|
.tab_inspect_item > ul > li > label {
|
|
width: 40%;
|
|
color: #92b3d3;
|
|
white-space: nowrap;
|
|
font-weight: normal;
|
|
}
|
|
|
|
.tab_inspect_item > ul > li > span {
|
|
width: 40%;
|
|
color: #06b8f8;
|
|
font-weight: 550;
|
|
text-align: right;
|
|
}
|
|
|
|
.tab_inspect_item > ul > li > span:last-child {
|
|
width: 35%;
|
|
color: rgba(243, 153, 98, 0.9);
|
|
font-weight: 500;
|
|
}
|
|
|
|
.tab_inspect_item:last-child {
|
|
display: flex;
|
|
justify-content: space-evenly;
|
|
position: relative;
|
|
top: 0;
|
|
left: -5%;
|
|
width: 36rem;
|
|
}
|
|
|
|
.tab_inspect_item:last-child .inspect_count {
|
|
position: absolute;
|
|
top: 3%;
|
|
left: 5rem;
|
|
margin-top: 0;
|
|
}
|
|
|
|
.tab_inspect_item:last-child > ul {
|
|
margin: 8% 5% 0 -5%;
|
|
width: 38%;
|
|
list-style: none;
|
|
padding: 0;
|
|
}
|
|
|
|
.tab_inspect_item:last-child > ul > li > label {
|
|
width: 30%;
|
|
font-weight: normal;
|
|
}
|
|
|
|
/* ========== 右侧 count_wrap ========== */
|
|
.count_wrap {
|
|
height: 46.65%;
|
|
width: 100%;
|
|
overflow: hidden;
|
|
}
|
|
|
|
.count_wrap .count_item {
|
|
display: flex;
|
|
float: left;
|
|
position: relative;
|
|
margin: 2.5% 0 1.5% 3%;
|
|
width: 45%;
|
|
height: 5rem;
|
|
background: linear-gradient(to bottom, transparent 50%, rgba(34, 125, 223, 0.35));
|
|
border: 1px solid rgba(26, 86, 151, 0.6);
|
|
border-radius: 5px;
|
|
font-size: 1rem;
|
|
text-align: center;
|
|
}
|
|
|
|
.count_wrap .count_item:nth-child(2),
|
|
.count_wrap .count_item:nth-child(3),
|
|
.count_wrap .count_item:nth-child(6),
|
|
.count_wrap .count_item:nth-child(7) {
|
|
background: linear-gradient(to bottom, transparent 50%, rgba(20, 138, 156, 0.35));
|
|
border: 1px solid rgba(20, 103, 103, 0.6);
|
|
}
|
|
|
|
.count_wrap .count_item:first-child {
|
|
width: 93%;
|
|
}
|
|
|
|
.count_wrap .count_item:nth-child(even) {
|
|
margin-left: 2.5%;
|
|
}
|
|
|
|
.count_wrap .count_item label {
|
|
display: flex;
|
|
flex-direction: column;
|
|
align-items: center;
|
|
justify-content: center;
|
|
margin: 0 2% 0 3%;
|
|
width: 36%;
|
|
height: 100%;
|
|
color: rgba(255, 255, 255, 0.7);
|
|
font-size: 0.85rem;
|
|
line-height: 1.5;
|
|
white-space: nowrap;
|
|
font-weight: normal;
|
|
}
|
|
|
|
.count_wrap .count_item:first-child label {
|
|
margin-top: 0;
|
|
width: 45%;
|
|
}
|
|
|
|
.count_wrap .count_item label > img {
|
|
display: block;
|
|
margin: 0 auto 8%;
|
|
width: 2.5rem;
|
|
height: 2.5rem;
|
|
object-fit: contain;
|
|
}
|
|
|
|
.count_wrap .count_item:first-child label > img {
|
|
margin: 0 auto 5%;
|
|
width: 3rem;
|
|
height: 3rem;
|
|
}
|
|
|
|
.number_count {
|
|
display: block;
|
|
margin: 0 5%;
|
|
width: 60%;
|
|
background-image: linear-gradient(to right, #f7fbfd, #2ba4b3);
|
|
-webkit-background-clip: text;
|
|
color: transparent;
|
|
font-size: 1.65rem;
|
|
font-weight: 550;
|
|
line-height: 3;
|
|
}
|
|
|
|
.count_wrap .count_item:first-child .number_count {
|
|
margin: 0 0 0 5%;
|
|
width: 50%;
|
|
}
|
|
|
|
/* ========== 底部 ========== */
|
|
.wrap_bottom h3 {
|
|
margin: 1% 0 -3% 1%;
|
|
height: 2.5rem;
|
|
font-size: 1.2rem;
|
|
font-weight: 500;
|
|
line-height: 2;
|
|
text-shadow: 2px 1px 5px rgba(255, 255, 255, 0.5);
|
|
}
|
|
|
|
.tab_chart {
|
|
position: relative;
|
|
margin: 2% 1%;
|
|
clear: both;
|
|
overflow: hidden;
|
|
width: 98%;
|
|
height: calc(96% - 3rem);
|
|
}
|
|
|
|
.chartbox {
|
|
width: 100%;
|
|
height: 100%;
|
|
}
|
|
|
|
.tab_tit {
|
|
position: absolute;
|
|
top: 8%;
|
|
left: 10rem;
|
|
font-size: 1rem;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.tab_tit a {
|
|
margin: 0 0.35rem;
|
|
padding: 1% 2%;
|
|
color: rgba(255, 255, 255, 0.5);
|
|
cursor: pointer;
|
|
text-decoration: none;
|
|
}
|
|
|
|
.tab_tit a.active {
|
|
color: #2e82fd;
|
|
border-bottom: 2px solid #2e82fd;
|
|
}
|
|
|
|
/* ========== 滚动条 ========== */
|
|
::-webkit-scrollbar {
|
|
width: 0.5rem;
|
|
height: 0.5rem;
|
|
}
|
|
|
|
::-webkit-scrollbar-thumb {
|
|
border-radius: 0.5rem;
|
|
background-color: #02206d;
|
|
box-shadow: inset 0 0 10px rgba(5, 172, 254, 0.6);
|
|
}
|
|
|
|
::-webkit-scrollbar-track {
|
|
box-shadow: inset 0 0 16px rgba(255, 255, 255, 0.2);
|
|
border-radius: 0;
|
|
background: rgba(0, 0, 0, 0.15);
|
|
}
|
|
</style>
|
|
|