在vue中如何封裝G2圖表
vue封裝G2圖表
<template> ? ? <div id="id"></div> </template>
<script> import G2 from '@antv/g2' import { DataSet } from '@antv/data-set' export default { ? ? name: 'pie', ? ? data () { ? ? ? ? return { ? ? ? ? ? ? chart: null ? ? ? ? }; ? ? }, ? ? props:{ ? ? ? ? gtwopiedata:{ ? ? ? ? ? ? type: Array ? ? ? ? }, ? ? ? ? // gtwopiecolor:{ ? ? ? ? // ? ? type: Array ? ? ? ? // }, ? ? }, ? ? methods:{ ? ? ? ? g2pie(){ ? ? ? ? ? ? if(this.chart){ ? ? // 如果存在的話就刪除圖表再重新生成 ? ? ? ? ? ? ? ? this.chart.destroy() ? ? ? ? ? ? } ? ? ? ? ? ? var startAngle = - Math.PI / 2 - Math.PI / 4; ? ? ? ? ? ? var data = this.gtwopiedata.data; ? ? ? ? ? ? var ds = new DataSet(); ? ? ? ? ? ? var dv = ds.createView().source(data); ? ? ? ? ? ? dv.transform({ ? ? ? ? ? ? ? ? type: 'percent', ? ? ? ? ? ? ? ? field: 'value', ? ? ? ? ? ? ? ? dimension: 'type', ? ? ? ? ? ? ? ? as: 'percent' ? ? ? ? ? ? }); ? ? ? ? ? ? this.chart = new G2.Chart({ ? ? ? ? ? ? ? ? container: 'id', ? ? ? ? ? ? ? ? forceFit: true, ? ? ? ? ? ? ? ? height: this.gtwopiedata.height, ? ? ? ? ? ? ? ? padding: 'auto' ? ? ? ? ? ? }); ? ? ? ? ? ? this.chart.source(dv); ? ? ? ? ? ? this.chart.legend(false); ? ? ? ? ? ? this.chart.coord('theta', { ? ? ? ? ? ? ? ? radius: 0.75, ? ? ? ? ? ? ? ? innerRadius: 0.5, ? ? ? ? ? ? ? ? startAngle: startAngle, ? ? ? ? ? ? ? ? endAngle: startAngle + Math.PI * 2 ? ? ? ? ? ? }); ? ? ? ? ? ? this.chart.intervalStack().position('value').color('type', this.gtwopiedata.color).opacity(1).label('percent', { ? ? ? ? ? ? ? ? offset: -20, ? ? ? ? ? ? ? ? textStyle: { ? ? ? ? ? ? ? ? ? ? fill: 'white', ? ? ? ? ? ? ? ? ? ? fontSize: 12, ? ? ? ? ? ? ? ? ? ? shadowBlur: 2, ? ? ? ? ? ? ? ? ? ? shadowColor: 'rgba(0, 0, 0, .45)' ? ? ? ? ? ? ? ? }, ? ? ? ? ? ? ? ? formatter: function formatter(val) { ? ? ? ? ? ? ? ? ? ? return parseInt(val * 100) + '%'; ? ? ? ? ? ? ? ? } ? ? ? ? ? ? }); ? ? ? ? ? ? this.chart.guide().html({ ? ? ? ? ? ? ? ? position: ['50%', '50%'], ? ? ? ? ? ? ? ? html: '<div class="g2-guide-html"><p class="title">'+this.gtwopiedata.title+'</p></div>' ? ? ? ? ? ? }); ? ? ? ? ? ? this.chart.render(); ? ? ? ? ? ? //draw label ? ? ? ? ? ? var OFFSET = 20; ? ? ? ? ? ? var APPEND_OFFSET = 50; ? ? ? ? ? ? var LINEHEIGHT = 60; ? ? ? ? ? ? var coord = this.chart.get('coord'); // 獲取坐標(biāo)系對(duì)象 ? ? ? ? ? ? var center = coord.center; // 極坐標(biāo)圓心坐標(biāo) ? ? ? ? ? ? var r = coord.radius; // 極坐標(biāo)半徑 ? ? ? ? ? ? var canvas = this.chart.get('canvas'); ? ? ? ? ? ? var canvasWidth = this.chart.get('width'); ? ? ? ? ? ? var canvasHeight = this.chart.get('height'); ? ? ? ? ? ? var labelGroup = canvas.addGroup(); ? ? ? ? ? ? var labels = []; ? ? ? ? ? ? // addPieLabel(this.chart); ? ? ? ? ? ? var halves = [[], []]; ? ? ? ? ? ? var data = dv.rows; ? ? ? ? ? ? var angle = startAngle; ? ? ? ?? ? ? ? ? ? ? for (var i = 0; i < data.length; i++) { ? ? ? ? ? ? ? ? var percent = data[i].percent; ? ? ? ? ? ? ? ? var targetAngle = angle + Math.PI * 2 * percent; ? ? ? ? ? ? ? ? var middleAngle = angle + (targetAngle - angle) / 2; ? ? ? ? ? ? ? ? angle = targetAngle; ? ? ? ? ? ? ? ? var edgePoint = this.getEndPoint(center, middleAngle, r); ? ? ? ? ? ? ? ? var routerPoint = this.getEndPoint(center, middleAngle, r + OFFSET); ? ? ? ? ? ? ? ? //label ? ? ? ? ? ? ? ? var label = { ? ? ? ? ? ? ? ? ? ? _anchor: edgePoint, ? ? ? ? ? ? ? ? ? ? _router: routerPoint, ? ? ? ? ? ? ? ? ? ? _data: data[i], ? ? ? ? ? ? ? ? ? ? x: routerPoint.x, ? ? ? ? ? ? ? ? ? ? y: routerPoint.y, ? ? ? ? ? ? ? ? ? ? r: r + OFFSET, ? ? ? ? ? ? ? ? ? ? fill: '#bfbfbf' ? ? ? ? ? ? ? ? }; ? ? ? ? ? ? ? ? // 判斷文本的方向 ? ? ? ? ? ? ? ? if (edgePoint.x < center.x) { ? ? ? ? ? ? ? ? ? ? label._side = 'left'; ? ? ? ? ? ? ? ? ? ? halves[0].push(label); ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? label._side = 'right'; ? ? ? ? ? ? ? ? ? ? halves[1].push(label); ? ? ? ? ? ? ? ? } ? ? ? ? ? ? } // end of for ? ? ? ?? ? ? ? ? ? ? var maxCountForOneSide = parseInt(canvasHeight / LINEHEIGHT, 10); ? ? ? ? ? ? halves.forEach(function(half, index) { ? ? ? ? ? ? ? ? // step 2: reduce labels ? ? ? ? ? ? ? ? if (half.length > maxCountForOneSide) { ? ? ? ? ? ? ? ? ? ? half.sort(function(a, b) { ? ? ? ? ? ? ? ? ? ? return b._percent - a._percent; ? ? ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? ? ? ? ? half.splice(maxCountForOneSide, half.length - maxCountForOneSide); ? ? ? ? ? ? ? ? } ? ? ? ? ? ?? ? ? ? ? ? ? ? ? // step 3: distribute position (x and y) ? ? ? ? ? ? ? ? half.sort(function(a, b) { ? ? ? ? ? ? ? ? ? ? return a.y - b.y; ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? ? ? // antiCollision(half, index); ? ? ? ? ? ? ? ? var startY = center.y - r - OFFSET - LINEHEIGHT; ? ? ? ? ? ? ? ? var overlapping = true; ? ? ? ? ? ? ? ? var totalH = canvasHeight; ? ? ? ? ? ? ? ? var i = void 0; ? ? ? ? ? ?? ? ? ? ? ? ? ? ? var maxY = 0; ? ? ? ? ? ? ? ? var minY = Number.MIN_VALUE; ? ? ? ? ? ? ? ? var boxes = half.map(function(label) { ? ? ? ? ? ? ? ? ? ? var labelY = label.y; ? ? ? ? ? ? ? ? ? ? if (labelY > maxY) { ? ? ? ? ? ? ? ? ? ? maxY = labelY; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? if (labelY < minY) { ? ? ? ? ? ? ? ? ? ? minY = labelY; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? return { ? ? ? ? ? ? ? ? ? ? size: LINEHEIGHT, ? ? ? ? ? ? ? ? ? ? targets: [labelY - startY] ? ? ? ? ? ? ? ? ? ? }; ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? ? ? if (maxY - startY > totalH) { ? ? ? ? ? ? ? ? ? ? totalH = maxY - startY; ? ? ? ? ? ? ? ? } ? ? ? ? ? ?? ? ? ? ? ? ? ? ? while (overlapping) { ? ? ? ? ? ? ? ? ? ? boxes.forEach(function(box) { ? ? ? ? ? ? ? ? ? ? var target = (Math.min.apply(minY, box.targets) + Math.max.apply(minY, box.targets)) / 2; ? ? ? ? ? ? ? ? ? ? box.pos = Math.min(Math.max(minY, target - box.size / 2), totalH - box.size); ? ? ? ? ? ? ? ? ? ? }); ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? // detect overlapping and join boxes ? ? ? ? ? ? ? ? ? ? overlapping = false; ? ? ? ? ? ? ? ? ? ? i = boxes.length; ? ? ? ? ? ? ? ? ? ? while (i--) { ? ? ? ? ? ? ? ? ? ? if (i > 0) { ? ? ? ? ? ? ? ? ? ? ? ? var previousBox = boxes[i - 1]; ? ? ? ? ? ? ? ? ? ? ? ? var box = boxes[i]; ? ? ? ? ? ? ? ? ? ? ? ? if (previousBox.pos + previousBox.size > box.pos) { ? ? ? ? ? ? ? ? ? ? ? ? // overlapping ? ? ? ? ? ? ? ? ? ? ? ? previousBox.size += box.size; ? ? ? ? ? ? ? ? ? ? ? ? previousBox.targets = previousBox.targets.concat(box.targets); ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? ? ? // overflow, shift up ? ? ? ? ? ? ? ? ? ? ? ? if (previousBox.pos + previousBox.size > totalH) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? previousBox.pos = totalH - previousBox.size; ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? ? ? boxes.splice(i, 1); // removing box ? ? ? ? ? ? ? ? ? ? ? ? overlapping = true; ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? } ? ? ? ? ? ?? ? ? ? ? ? ? ? ? // step 4: normalize y and adjust x ? ? ? ? ? ? ? ? i = 0; ? ? ? ? ? ? ? ? boxes.forEach(function(b) { ? ? ? ? ? ? ? ? ? ? var posInCompositeBox = startY; // middle of the label ? ? ? ? ? ? ? ? ? ? b.targets.forEach(function() { ? ? ? ? ? ? ? ? ? ? half[i].y = b.pos + posInCompositeBox + LINEHEIGHT / 2; ? ? ? ? ? ? ? ? ? ? posInCompositeBox += LINEHEIGHT; ? ? ? ? ? ? ? ? ? ? i++; ? ? ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? ? ? }); ? ? ? ? ? ?? ? ? ? ? ? ? ? ? // (x - cx)^2 + (y - cy)^2 = totalR^2 ? ? ? ? ? ? ? ? half.forEach(function(label) { ? ? ? ? ? ? ? ? ? ? var rPow2 = label.r * label.r; ? ? ? ? ? ? ? ? ? ? var dyPow2 = Math.pow(Math.abs(label.y - center.y), 2); ? ? ? ? ? ? ? ? ? ? if (rPow2 < dyPow2) { ? ? ? ? ? ? ? ? ? ? ? ? label.x = center.x; ? ? ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? ? ? var dx = Math.sqrt(rPow2 - dyPow2); ? ? ? ? ? ? ? ? ? ? ? ? if (!index) { ? ? ? ? ? ? ? ? ? ? ? ? ? ? // left ? ? ? ? ? ? ? ? ? ? ? ? ? ? label.x = center.x - dx; ? ? ? ? ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? ? ? ? ? // right ? ? ? ? ? ? ? ? ? ? ? ? ? ? label.x = center.x + dx; ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? // drawLabel(label); ? ? ? ? ? ? ? ? ? ? var _anchor = label._anchor, ? ? ? ? ? ? ? ? ? ? _router = label._router, ? ? ? ? ? ? ? ? ? ? fill = label.fill, ? ? ? ? ? ? ? ? ? ? y = label.y; ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? var labelAttrs = { ? ? ? ? ? ? ? ? ? ? ? ? y: y, ? ? ? ? ? ? ? ? ? ? ? ? fontSize: 12, // 字體大小 ? ? ? ? ? ? ? ? ? ? ? ? fill: '#808080', ? ? ? ? ? ? ? ? ? ? ? ? text: label._data.type + '\n' + label._data.value, ? ? ? ? ? ? ? ? ? ? ? ? textBaseline: 'bottom' ? ? ? ? ? ? ? ? ? ? }; ? ? ? ? ? ? ? ? ? ? var lastPoint = { ? ? ? ? ? ? ? ? ? ? ? ? y: y ? ? ? ? ? ? ? ? ? ? }; ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? if (label._side === 'left') { ? ? ? ? ? ? ? ? ? ? ? ? // 具體文本的位置 ? ? ? ? ? ? ? ? ? ? ? ? lastPoint.x = APPEND_OFFSET; ? ? ? ? ? ? ? ? ? ? ? ? labelAttrs.x = APPEND_OFFSET; // 左側(cè)文本左對(duì)齊并貼著畫布最左側(cè)邊緣 ? ? ? ? ? ? ? ? ? ? ? ? labelAttrs.textAlign = 'left'; ? ? ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? ? ? lastPoint.x = canvasWidth - APPEND_OFFSET; ? ? ? ? ? ? ? ? ? ? ? ? labelAttrs.x = canvasWidth - APPEND_OFFSET; // 右側(cè)文本右對(duì)齊并貼著畫布最右側(cè)邊緣 ? ? ? ? ? ? ? ? ? ? ? ? labelAttrs.textAlign = 'right'; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? // 繪制文本 ? ? ? ? ? ? ? ? ? ? var text = labelGroup.addShape('Text', { ? ? ? ? ? ? ? ? ? ? ? ? attrs: labelAttrs ? ? ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? ? ? ? ? labels.push(text); ? ? ? ? ? ? ? ? ? ? // 繪制連接線 ? ? ? ? ? ? ? ? ? ? var points = void 0; ? ? ? ? ? ? ? ? ? ? if (_router.y !== y) { ? ? ? ? ? ? ? ? ? ? ? ? // 文本位置做過調(diào)整 ? ? ? ? ? ? ? ? ? ? ? ? points = [[_anchor.x, _anchor.y], [_router.x, y], [lastPoint.x, lastPoint.y]]; ? ? ? ? ? ? ? ? ? ? } else { ? ? ? ? ? ? ? ? ? ? ? ? points = [[_anchor.x, _anchor.y], [_router.x, _router.y], [lastPoint.x, lastPoint.y]]; ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ?? ? ? ? ? ? ? ? ? ? ? labelGroup.addShape('polyline', { ? ? ? ? ? ? ? ? ? ? ? ? attrs: { ? ? ? ? ? ? ? ? ? ? ? ? ? ? points: points, ? ? ? ? ? ? ? ? ? ? ? ? ? ? lineWidth: 1, ? ? ? ? ? ? ? ? ? ? ? ? ? ? stroke: fill ? ? ? ? ? ? ? ? ? ? ? ? } ? ? ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? ? ? }); ? ? ? ? ? ? }); ? ? ? ? ? ? canvas.draw(); ? ? ? ? ? ? // this.chart.on('afterpaint', function() { ? ? ? ? ? ? // ? addPieLabel(this.chart); ? ? ? ? ? ? // }); ? ? ? ? }, ? ? ? ? // g2獲取餅圖點(diǎn)位置 ? ? ? ? getEndPoint(center, angle, r) { ? ? ? ? ? ? return { ? ? ? ? ? ? ? ? x: center.x + r * Math.cos(angle), ? ? ? ? ? ? ? ? y: center.y + r * Math.sin(angle) ? ? ? ? ? ? }; ? ? ? ? } ? ? }, ? ? watch: { ? ? ? ? gtwopiedata: function (val, oldVal) { ? ?// 監(jiān)聽數(shù)據(jù),當(dāng)發(fā)生變化時(shí),觸發(fā)回調(diào)函數(shù)繪制圖表,使用mounted無(wú)法正常繪制 ? ? ? ? ? ? // if(this.dothisfun){ ? ? ? ? ? ? ? ? this.g2pie(val); ? ? ? ? ? ? // ? ? this.dothisfun = false ? ? ? ? ? ? // } ? ? ? ? } ? ? }, ? ? // mounted(){ ? ? // ? ? this.g2pie(); ? ? // } } </script>
<style scoped> ? ? #id{ ? ? ? ? width: 100%; ? ? ? ? height: 100%; ? ? } </style>
本來(lái)是想將生成的方法封裝到j(luò)s文件中的,但是不知道為什么,import G2 進(jìn)入js文件之后,vue便會(huì)卡在92%無(wú)法繼續(xù)熱更新,node的cpu占用率也會(huì)飽滿,所以只好封裝在.vue文件中,以子組件的形式被父組件調(diào)用。
本處需要注意的第一個(gè)問題,即為data中定義的chart,如果不定義,直接用let chart = new G2.chart(),也確實(shí)能夠正常生成圖表,但是當(dāng)數(shù)據(jù)更新的時(shí)候,便會(huì)重新渲染生成新的圖表,此時(shí)頁(yè)面上會(huì)同時(shí)存在多個(gè)圖表,所以需要提前定義chart,并使用this.chart = new G2.chart()。
本處需要注意的第二個(gè)問題,即為使用mounted鉤子函數(shù)運(yùn)行此函數(shù)時(shí),因?yàn)椴⑽礄z測(cè)到數(shù)據(jù)變化,所以不會(huì)生成有效圖表,所以需要使用watch監(jiān)聽數(shù)據(jù)變化,當(dāng)發(fā)生變化的時(shí)候,執(zhí)行方法渲染圖表。
vue引入G2圖表
G2 是一套基于圖形語(yǔ)法理論的可視化底層引擎,以數(shù)據(jù)驅(qū)動(dòng),提供圖形語(yǔ)法與交互語(yǔ)法,具有高度的易用性和擴(kuò)展性。使用 G2,你可以無(wú)需關(guān)注圖表各種繁瑣的實(shí)現(xiàn)細(xì)節(jié),一條語(yǔ)句即可使用 Canvas 或 SVG 構(gòu)建出各種各樣的可交互的統(tǒng)計(jì)圖表;
官網(wǎng)地址:https://antv.gitee.io/zh
線上示例
特性
- ?? 完善的圖形語(yǔ)法:數(shù)據(jù)到圖形的映射,能夠繪制出所有的圖表;
- ?? 全新的交互語(yǔ)法:通過觸發(fā)和反饋機(jī)制可以組合出各種交互行為,對(duì)數(shù)據(jù)進(jìn)行探索;
- ?? 強(qiáng)大的 View 模塊:可支持開發(fā)個(gè)性化的數(shù)據(jù)多維分析圖形;
- ?? 雙引擎渲染:Canvas 或 SVG 任意切換;
- ?? 可視化組件體系:面向交互、體驗(yàn)優(yōu)雅;
- ?全面擁抱 TypeScript:提供完整的類型定義文件;
介紹一下在vue中使用G2
安裝G2依賴:
npm instal @antv/g2
在繪圖前我們需要為 G2 準(zhǔn)備一個(gè) DOM 容器:
<div id="c1"></div>
執(zhí)行代碼:
import * as G2 from '@antv/g2'; export default { mounted() { const data = [ { genre: 'Sports', sold: 275 }, { genre: 'Strategy', sold: 115 }, { genre: 'Action', sold: 120 }, { genre: 'Shooter', sold: 350 }, { genre: 'Other', sold: 150 }, ]; // Step 1: 創(chuàng)建 Chart 對(duì)象 const chart = new G2.Chart({ container: 'c1', // 指定圖表容器 ID width: 600, // 指定圖表寬度 height: 300, // 指定圖表高度 }); // Step 2: 載入數(shù)據(jù)源 chart.data(data); // Step 3:創(chuàng)建圖形語(yǔ)法,繪制柱狀圖 chart.interval().position('genre*sold'); // Step 4: 渲染圖表 chart.render(); } }
效果展示:
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
vue el-select綁定對(duì)象時(shí),回顯內(nèi)容不正確,始終是最后一項(xiàng)的解決
這篇文章主要介紹了vue el-select綁定對(duì)象時(shí),回顯內(nèi)容不正確,始終是最后一項(xiàng)的問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-07-07vue3+vite assets動(dòng)態(tài)引入圖片的三種方法及解決打包后圖片路徑錯(cuò)誤不顯示的問題
這篇文章主要介紹了vue3+vite assets動(dòng)態(tài)引入圖片的幾種方式,解決打包后圖片路徑錯(cuò)誤不顯示的問題,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-03-03vue中 el-table每個(gè)單元格包含多個(gè)數(shù)據(jù)項(xiàng)處理
vue項(xiàng)目中,我們需要在el-table中顯示數(shù)組數(shù)據(jù),有的時(shí)候,需要在一個(gè)單元格中顯示多條數(shù)據(jù),如何實(shí)現(xiàn)呢,對(duì)vue el-table單元格相關(guān)知識(shí)感興趣的朋友一起看看吧2023-11-11vue axios post發(fā)送復(fù)雜對(duì)象問題
現(xiàn)在vue項(xiàng)目中,一般使用axios發(fā)送請(qǐng)求去后臺(tái)拉取數(shù)據(jù)。這篇文章主要介紹了vue axios post發(fā)送復(fù)雜對(duì)象的一點(diǎn)思考,需要的朋友可以參考下2019-06-06vue-router3.x和vue-router4.x相互影響的問題分析
這篇文章主要介紹了vue-router3.x和vue-router4.x相互影響的問題分析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-04-04vue2.0 element-ui中el-select選擇器無(wú)法顯示選中的內(nèi)容(解決方法)
這篇文章主要介紹了vue2.0 element-ui中的el-select選擇器無(wú)法顯示選中的內(nèi)容,在文中小編使用的是element-ui V2.2.3。具體解決方法及示例代碼大家參考下本文2018-08-08vue前端優(yōu)雅展示后端十萬(wàn)條數(shù)據(jù)面試點(diǎn)剖析
這篇文章主要為大家介紹了vue前端優(yōu)雅展示后端十萬(wàn)條數(shù)據(jù)的考點(diǎn)剖析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07