123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499 |
- <template>
- <!-- 行业水平分布 - littlegreen - 补充form和label -->
- <div :class="className" :style="{ height: '100%', width: width }">
- <div class="select-container">
- <el-form
- style="
- display: grid;
- grid-template-columns: 1fr 1fr 1fr;
- align-items: center;
- grid-gap: 20px;
- "
- label-width="100px"
- >
- <el-form-item label="评估指标" style="margin-bottom: 0">
- <el-select v-model="selectedDataKey" style="width: 100%">
- <el-option
- v-for="key in dataKeys"
- :key="key"
- :value="key"
- :label="keyToChinese[key]"
- >
- {{ keyToChinese[key] }}
- </el-option>
- </el-select>
- </el-form-item>
- <el-form-item label="年度" style="margin-bottom: 0">
- <el-select v-model="selectedYear" style="width: 100%" >
- <el-option v-for="year in availableYears" :key="year" :value="year">
- {{ year }}
- </el-option>
- </el-select>
- </el-form-item>
- <el-form-item label="行业代码" style="margin-bottom: 0">
- <el-input
- v-model="selectedCode"
- placeholder="请输入行业代码"
- clearable
- style="width: 100%"
- />
- </el-form-item>
- <el-form-item label="数据分布区间" style="margin-bottom: 0">
- <el-input
- v-model="selectedRange"
- placeholder="请设置数据分布区间"
- clearable
- style="width: 100%"
- />
- </el-form-item>
- <el-form-item label="当前行业:" style="margin-bottom: 0">
- <div>
- {{ industryMap.get(selectedCode) }}
- </div>
- </el-form-item>
- <el-form-item style="margin-bottom: 0">
- <el-button type="primary" icon="el-icon-search" @click="updateChart" size="mini"
- >搜索</el-button
- >
- </el-form-item>
- </el-form>
- <!-- <el-select v-model="selectedDataKey" @change="updateChart">
- <el-option
- v-for="key in dataKeys"
- :key="key"
- :value="key"
- :label="keyToChinese[key]"
- >
- {{ keyToChinese[key] }}
- </el-option>
- </el-select>
- <el-select v-model="selectedYear" @change="updateChart">
- <el-option v-for="year in availableYears" :key="year" :value="year">
- {{ year }}
- </el-option>
- </el-select>
- <el-input
- v-model="selectedCode"
- placeholder="请输入行业代码"
- clearable
- style="width: 180px"
- />
- <el-input
- v-model="selectedRange"
- placeholder="请设置数据分布区间"
- clearable
- style="width: 180px"
- /> -->
- <!-- <div style="display: inline; padding-left: 10px">
- </div> -->
- </div>
- <div ref="chart" :style="{ height: height, width: width }"></div>
- <!-- littlegreen - 新增数据展示table -->
- <el-table :data="tableData" border style="width: 100%">
- <el-table-column
- prop="industryName"
- label="行业名称"
- width="200"
- ></el-table-column>
- <el-table-column prop="year" label="年度" width="200"> </el-table-column>
- <el-table-column prop="enterpriseId" label="企业ID"></el-table-column>
- <el-table-column
- prop="value"
- :label="label"
- width="200"
- ></el-table-column>
- </el-table>
- </div>
- </template>
- <script>
- import * as echarts from "echarts";
- import { listBase_data_year } from "@/api/base_data_year/base_data_year";
- import { listIndustry } from "@/api/industry/industry"; // 导入行业数据的接口
- require("echarts/theme/macarons"); // echarts theme
- import resize from "./mixins/resize";
- export default {
- mixins: [resize],
- props: {
- className: {
- type: String,
- default: "chart",
- },
- width: {
- type: String,
- default: "100%",
- },
- height: {
- type: String,
- default: "400px",
- },
- },
- data() {
- return {
- label: "评估指标值/万元",
- chart: null,
- chartData: [],
- industryData: [],
- industryMap: new Map(),
- selectedDataKey: "funding", // 默认选择的字段
- selectedCode: null,
- dataKeys: [
- "funding",
- "energyConsume",
- "paidTax",
- "taxableIncome",
- "totalIndustrialValue",
- "powerConsume",
- ], // 可选项
- keyToChinese: {
- landArea: "用地面积",
- totalIndustrialValue: "工业总产值",
- gdp: "工业增加值",
- taxableIncome: "应税收入",
- paidTax: "实缴税金",
- mainBusinessIncome: "主营业务收入",
- employeeNumber: "从业人员数",
- profit: "利润总额",
- ownerEquity: "所有者权益",
- funding: "研发经费",
- energyConsume: "能源消费量",
- powerConsume: "电力消费量",
- },
- keyToUnit: {
- landArea: "/亩",
- totalIndustrialValue: "/万元",
- gdp: "/万元",
- taxableIncome: "/万元",
- paidTax: "/万元",
- mainBusinessIncome: "/万元",
- employeeNumber: "/人",
- profit: "/万元",
- ownerEquity: "",
- funding: "/万元",
- energyConsume: "/万m³",
- powerConsume: "/万KW·h",
- },
- selectedYear: null,
- queryParams: {
- pageNum: 1,
- pageSize: 2000000, // 默认 2000000 条(全部一次性数据)
- enterpriseName: null,
- location: null,
- code: null,
- mainBusiness: null,
- landArea: null,
- totalIndustrialValue: null,
- gdp: null,
- taxableIncome: null,
- paidTax: null,
- mainBusinessIncome: null,
- employeeNumber: null,
- profit: null,
- ownerEquity: null,
- funding: null,
- energyConsume: null,
- year: null,
- month: null,
- },
- industryQueryParams: {
- pageNum: 1,
- pageSize: 2000000,
- industryName: null,
- code: null,
- }, // 查询行业信息
- availableYears: [],
- selectedRange: 300, // 不能为 0
- tableData: [],
- };
- },
- mounted() {
- this.$nextTick(() => {
- this.fetchData();
- });
- },
- beforeDestroy() {
- if (this.chart) {
- this.chart.dispose();
- }
- },
- methods: {
- fetchData() {
- listBase_data_year(this.queryParams)
- .then((response) => {
- this.chartData = response.rows;
- this.availableYears = [
- ...new Set(this.chartData.map((item) => item.year)),
- ];
- this.selectedYear = this.availableYears[0] || null;
- this.selectedCode = [
- ...new Set(this.chartData.map((item) => item.code)),
- ][0];
- this.initChart();
- })
- .catch((error) => {
- console.error("Error fetching data:", error);
- });
- listIndustry(this.industryQueryParams)
- .then((response) => {
- this.industryData = response.rows;
- // console.log("industry_info" + this.industryData);
- this.industryMap = this.industryData.reduce((map, item) => {
- const key = `${item.code}`; // 键是行业代码
- map.set(key, item.industryName); // 将键和对应的行业名称存储到Map中
- return map;
- }, new Map());
- })
- .catch((error) => {
- console.error("Error fetching data:", error);
- });
- },
- initChart() {
- if (this.chart) {
- this.chart.dispose();
- }
- this.chart = echarts.init(this.$refs.chart, "macarons");
- this.updateChart();
- },
- updateChart() {
- if (!this.chart) {
- return;
- }
- let filteredData = this.chartData;
- if (this.selectedYear) {
- filteredData = filteredData.filter(
- (item) =>
- item.year === this.selectedYear && item.code === this.selectedCode
- );
- }
- const values = filteredData.map((item) => item[this.selectedDataKey]);
- const minVal = 0;
- const maxVal = Math.max(...values);
- console.log(filteredData, values, this.selectedDataKey, 898);
- if (
- this.selectedRange === null ||
- this.selectedRange === "" ||
- isNaN(+this.selectedRange)
- )
- this.selectedRange = "100";
- else if (Number(this.selectedRange) <= 0) this.selectedRange = "100";
- const binCount = Math.ceil(
- (maxVal - minVal) / Number(this.selectedRange)
- );
- let maxNum = -1;
- // 生成区间标签和频次
- const histogramData = [];
- for (let i = 0; i < binCount; i++) {
- const x0 = minVal + i * Number(this.selectedRange);
- const x1 = Math.min(x0 + Number(this.selectedRange), maxVal);
- const label = `${x0}-${x1}`;
- let count = 0;
- count += values.filter((value) => value >= x0 && value < x1).length;
- if (x1 === maxVal) {
- count += values.filter((value) => value === maxVal).length;
- }
- if (count > 0) {
- if (count > maxNum) {
- maxNum = count;
- }
- histogramData.push({ name: label, value: count });
- }
- }
- const maxHistogramValue = Math.max(
- ...histogramData.map((item) => item.value)
- );
- const totalHistogramValue = histogramData.reduce(
- (sum, item) => sum + item.value,
- 0
- );
- // const quadraticData = this.generateQuadraticData(binCount, maxHistogramValue, totalHistogramValue);
- // littlegreen - 去掉line和scatter
- const option = {
- tooltip: {
- trigger: "axis",
- axisPointer: {
- type: "shadow",
- },
- formatter: (params) => {
- // 使用箭头函数来保持 this 的上下文
- const seriesName = params[0].name; // 系列名称
- const dataIndex = params[0].dataIndex; // 数据索引
- const value = params[0].data; // 实际的数据值
- const xAxisLabel = params[0].axisValueLabel; // x轴的标签
- const yAxisLabel = params[0].seriesName;
- // 构建自定义的 tooltip 内容,包含年份
- return `${xAxisLabel}<br> ${yAxisLabel}: ${value}`;
- },
- },
- legend: {
- data: [
- `${this.selectedYear}年 ${
- this.keyToChinese[this.selectedDataKey]
- }企业数统计`,
- ],
- },
- grid: {
- left: "3%",
- right: "4%",
- bottom: "3%",
- containLabel: true,
- },
- xAxis: {
- type: "category",
- name: "分布区间",
- data: histogramData.map((item) => item.name),
- axisLabel: {
- fontSize: 12,
- interval: 0,
- rotate: 30,
- },
- },
- yAxis: {
- name: "企业数",
- type: "value",
- minInterval: 1,
- },
- series: [
- {
- name: `${this.selectedYear}年 ${
- this.keyToChinese[this.selectedDataKey]
- }企业数统计`,
- type: "bar",
- barWidth: "30%",
- itemStyle: {
- color: "rgba(245,0,0,0.6)",
- },
- data: histogramData.map((item) => item.value),
- label: {
- show: false, // 将show属性设置为false,去掉柱子上的数字
- },
- },
- // {
- // type: "scatter",
- // symbol: "circle",
- // symbolSize: 10,
- // data: histogramData.map((item, index) => [index, item.value]),
- // itemStyle: {
- // color: "red",
- // },
- // },
- // {
- // type: "line",
- // data: histogramData.map((item, index) => [index, item.value]),
- // lineStyle: {
- // color: "#1a7cc8",
- // },
- // symbol: "none",
- // },
- ],
- };
- this.chart.setOption(option);
- const that = this;
- // littlegreen - chart增加点击事件,点击显示对应区间的企业列表
- this.chart.on("click", function (param) {
- //param参数包含的内容有:
- //param.name:X轴的值
- //param.data:Y轴的值
- //param.value:Y轴的值
- //param.type:点击事件均为click
- //param.seriesName:legend的名称
- //param.seriesIndex:系列序号(series中当前图形是第几个图形第几个)
- //param.dataIndex:数值序列(X轴上当前点是第几个点)
- //alert(param.seriesName); //legend的名称
- // console.log(param.name); //X轴的值 0-600 1.用-分割获得确定最小值和最大值 2.筛选filteredData中this.selectedDataKey的值符合要求的
- const result = param.name.split("-").map(Number);
- const filteredArray = filteredData.filter((item) => {
- const isMaxValEqual = result[1] === maxVal;
- const lowerBoundCheck = item[that.selectedDataKey] >= result[0];
- const upperBoundCheck = isMaxValEqual
- ? item[that.selectedDataKey] <= result[1]
- : item[that.selectedDataKey] < result[1];
- return lowerBoundCheck && upperBoundCheck;
- });
- that.tableData = filteredArray.map((item) => {
- return {
- industryName: item.code,
- enterpriseId: item.enterpriseName,
- year: item.year,
- value: item[that.selectedDataKey],
- };
- });
- // console.log(filteredData, result, that.selectedDataKey, filteredArray); //获取自定义的值
- });
- },
- generateQuadraticData(binCount, maxHistogramValue, totalHistogramValue) {
- const a = -0.01;
- const h = binCount / 2;
- const k = maxHistogramValue * 0.75;
- const sideValue = (maxHistogramValue * 0.15) / 2;
- const data = [];
- for (let i = 0; i < binCount; i++) {
- const x = i;
- const y = a * (x - h) ** 2 + k;
- // 调整两侧的值
- if (i === 0 || i === binCount - 1) {
- data.push([x, sideValue]);
- } else {
- data.push([x, y]);
- }
- }
- return data;
- },
- },
- watch: {
- // littlegreen - 关闭监测数值变化
- selectedDataKey() {
- this.label = "评估指标值"+this.keyToUnit[this.selectedDataKey]
- },
- // selectedYear() {
- // this.updateChart();
- // },
- // selectedRange() {
- // setTimeout(this.updateChart, 2500);
- // },
- // selectedCode() {
- // this.updateChart();
- // },
- },
- };
- </script>
- <style scoped>
- .select-container {
- margin: 10px 0;
- font-size: 16px; /* 调整字号大小 */
- }
- .select-container select {
- padding: 10px 20px; /* 增加内边距 */
- margin-right: 10px; /* 增加右边距 */
- border: 1px solid #121315; /* 蓝色边框 */
- border-radius: 4px; /* 圆角边框 */
- background-color: white; /* 背景色 */
- color: #121315; /* 文字颜色 */
- font-size: 16px; /* 调整字号大小 */
- cursor: pointer; /* 鼠标悬停时的指针样式 */
- outline: none; /* 移除焦点时的轮廓 */
- }
- .select-container select:hover {
- border-color: #1a7cc8; /* 鼠标悬停时的边框颜色 */
- }
- .select-container select:focus {
- border-color: #121315; /* 焦点时的边框颜色 */
- box-shadow: 0 0 0 2px rgba(64, 159, 255, 0.2); /* 焦点时的阴影效果 */
- }
- </style>
|