widgetMoreBarLineChart.vue 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579
  1. <template>
  2. <div :style='styleObj'>
  3. <v-chart :options='options' autoresize/>
  4. </div>
  5. </template>
  6. <script>
  7. import echarts from 'echarts';
  8. export default {
  9. name: 'widgetMoreBarLineChart',
  10. components: {},
  11. props: {
  12. value: Object,
  13. ispreview: Boolean
  14. },
  15. data() {
  16. return {
  17. options: {
  18. tooltip: {
  19. trigger: 'item',
  20. axisPointer: {
  21. type: 'shadow'
  22. }
  23. },
  24. grid: {
  25. left: '2%',
  26. right: '4%',
  27. bottom: '14%',
  28. top: '16%',
  29. containLabel: true
  30. },
  31. legend: {
  32. data: ['调解成功', '调解失败', '调解终止', '调解成功率'],
  33. left: '7%',
  34. top: '5%',
  35. textStyle: {
  36. color: '#666666'
  37. },
  38. itemWidth: 15,
  39. itemHeight: 10,
  40. itemGap: 25
  41. },
  42. xAxis: {
  43. type: 'category',
  44. data: ['2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019'],
  45. axisLine: {
  46. lineStyle: {
  47. color: '#cdd5e2'
  48. }
  49. },
  50. axisLabel: {
  51. textStyle: {
  52. color: '#666666'
  53. }
  54. },
  55. },
  56. yAxis: [
  57. {
  58. type: 'value',
  59. axisLine: {
  60. show: true,
  61. lineStyle: {
  62. color: '#cdd5e2'
  63. }
  64. },
  65. splitLine: {
  66. show: false,
  67. },
  68. axisLabel: {
  69. textStyle: {
  70. color: '#666666'
  71. }
  72. },
  73. },
  74. {
  75. type: 'value',
  76. nameTextStyle: {
  77. color: '#666666'
  78. },
  79. position: 'right',
  80. axisLine: {
  81. lineStyle: {
  82. color: '#cdd5e2'
  83. }
  84. },
  85. splitLine: {
  86. show: false,
  87. },
  88. axisLabel: {
  89. show: true,
  90. textStyle: {
  91. color: '#666666'
  92. }
  93. }
  94. }
  95. ],
  96. series: [
  97. {
  98. name: '调解成功',
  99. type: 'bar',
  100. itemStyle: {
  101. normal: {
  102. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
  103. offset: 0,
  104. color: '#29acff'
  105. }, {
  106. offset: 1,
  107. color: '#4bdfff'
  108. }]),
  109. barBorderRadius: 6,
  110. },
  111. },
  112. data: []
  113. },
  114. {
  115. name: '调解失败',
  116. type: 'bar',
  117. itemStyle: {
  118. normal: {
  119. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
  120. offset: 0,
  121. color: '#3d93f2'
  122. }, {
  123. offset: 1,
  124. color: '#5dc1fd'
  125. }]),
  126. barBorderRadius: 6,
  127. }
  128. },
  129. data: []
  130. },
  131. {
  132. name: '调解终止',
  133. type: 'bar',
  134. itemStyle: {
  135. normal: {
  136. color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{
  137. offset: 0,
  138. color: '#01c871'
  139. }, {
  140. offset: 1,
  141. color: '#55f49c'
  142. }]),
  143. barBorderRadius: 6,
  144. }
  145. },
  146. data: []
  147. },
  148. {
  149. name: '调解成功率',
  150. type: 'line',
  151. yAxisIndex: 1, //使用的 y 轴的 index,在单个图表实例中存在多个 y轴的时候有用
  152. smooth: false, //平滑曲线显示
  153. symbol: 'circle', //标记的图形为实心圆
  154. symbolSize: 8, //标记的大小
  155. itemStyle: {
  156. normal: {
  157. color: '#ffa43a',
  158. borderColor: 'rgba(255, 234, 0, 0.5)', //圆点透明 边框
  159. borderWidth: 5
  160. },
  161. },
  162. lineStyle: {
  163. color: '#ffa43a'
  164. },
  165. data: []
  166. }
  167. ]
  168. }
  169. }
  170. },
  171. computed: {
  172. styleObj() {
  173. return {
  174. position: this.ispreview ? 'absolute' : 'static',
  175. width: this.optionsStyle.width + 'px',
  176. height: this.optionsStyle.height + 'px',
  177. left: this.optionsStyle.left + 'px',
  178. top: this.optionsStyle.top + 'px',
  179. background: this.optionsSetup.background
  180. };
  181. }
  182. },
  183. watch: {
  184. value: {
  185. handler(val) {
  186. this.optionsStyle = val.position;
  187. this.optionsData = val.data;
  188. this.optionsCollapse = val.collapse;
  189. this.optionsSetup = val.setup;
  190. this.editorOptions();
  191. },
  192. deep: true
  193. }
  194. },
  195. created() {
  196. this.optionsStyle = this.value.position;
  197. this.optionsData = this.value.data;
  198. this.optionsCollapse = this.value.collapse;
  199. this.optionsSetup = this.value.setup;
  200. this.editorOptions();
  201. },
  202. methods: {
  203. // 修改图标options属性
  204. editorOptions() {
  205. this.setOptionsTitle();
  206. this.setOptionsX();
  207. this.setOptionsY();
  208. this.setOptionsLegend();
  209. this.setOptionsTooltip();
  210. this.setOptionsMargin();
  211. this.setOptionsColor();
  212. this.setOptionsData();
  213. },
  214. // 标题修改
  215. setOptionsTitle() {
  216. const optionsSetup = this.optionsSetup;
  217. const title = {};
  218. title.text = optionsSetup.titleText;
  219. title.show = optionsSetup.isNoTitle;
  220. title.left = optionsSetup.textAlign;
  221. title.textStyle = {
  222. color: optionsSetup.textColor,
  223. fontSize: optionsSetup.textFontSize,
  224. fontWeight: optionsSetup.textFontWeight
  225. };
  226. title.subtext = optionsSetup.subText;
  227. title.subtextStyle = {
  228. color: optionsSetup.subTextColor,
  229. fontWeight: optionsSetup.subTextFontWeight,
  230. fontSize: optionsSetup.subTextFontSize
  231. };
  232. this.options.title = title;
  233. },
  234. // X轴设置
  235. setOptionsX() {
  236. const optionsSetup = this.optionsSetup;
  237. const xAxis = {
  238. type: 'category',
  239. show: optionsSetup.hideX, // 坐标轴是否显示
  240. name: optionsSetup.xName, // 坐标轴名称
  241. nameTextStyle: {
  242. color: optionsSetup.nameColorX,
  243. fontSize: optionsSetup.nameFontSizeX
  244. },
  245. nameRotate: optionsSetup.textAngle, // 文字角度
  246. inverse: optionsSetup.reversalX, // 轴反转
  247. axisLabel: {
  248. show: true,
  249. interval: optionsSetup.textInterval, // 文字间隔
  250. rotate: optionsSetup.textAngle, // 文字角度
  251. textStyle: {
  252. color: optionsSetup.Xcolor, // x轴 坐标文字颜色
  253. fontSize: optionsSetup.fontSizeX
  254. }
  255. },
  256. axisLine: {
  257. show: true,
  258. lineStyle: {
  259. color: optionsSetup.lineColorX
  260. }
  261. },
  262. splitLine: {
  263. show: optionsSetup.isShowSplitLineX,
  264. lineStyle: {
  265. color: optionsSetup.splitLineColorX
  266. }
  267. }
  268. };
  269. this.options.xAxis = xAxis;
  270. },
  271. // Y轴设置
  272. setOptionsY() {
  273. const optionsSetup = this.optionsSetup;
  274. const yAxis = [
  275. {
  276. type: 'value',
  277. show: optionsSetup.isShowYLeft, // 坐标轴是否显示
  278. name: optionsSetup.textNameYLeft, // 坐标轴名称
  279. nameTextStyle: { // 别名
  280. color: optionsSetup.nameColorYLeft,
  281. fontSize: optionsSetup.namefontSizeYLeft
  282. },
  283. axisLabel: {
  284. show: true,
  285. textStyle: {
  286. color: optionsSetup.colorY, // y轴 坐标文字颜色
  287. fontSize: optionsSetup.fontSizeY
  288. }
  289. },
  290. axisLine: {
  291. show: optionsSetup.isShowYLeft,
  292. lineStyle: {
  293. color: optionsSetup.lineColorY
  294. }
  295. },
  296. splitLine: {
  297. show: false,
  298. }
  299. },
  300. {
  301. type: 'value',
  302. position: 'right',
  303. show: optionsSetup.isShowYRight, // 坐标轴是否显示
  304. name: optionsSetup.textNameYRight, // 坐标轴名称
  305. nameTextStyle: { // 别名
  306. color: optionsSetup.nameColorYRight,
  307. fontSize: optionsSetup.namefontSizeYRight
  308. },
  309. axisLabel: {
  310. show: true,
  311. textStyle: {
  312. color: optionsSetup.colorY, // y轴 坐标文字颜色
  313. fontSize: optionsSetup.fontSizeY
  314. }
  315. },
  316. axisLine: {
  317. show: optionsSetup.isShowYRight,
  318. lineStyle: {
  319. color: optionsSetup.lineColorY
  320. }
  321. },
  322. splitLine: {
  323. show: false,
  324. }
  325. }
  326. ];
  327. this.options.yAxis = yAxis;
  328. },
  329. // tooltip 设置
  330. setOptionsTooltip() {
  331. const optionsSetup = this.optionsSetup;
  332. const tooltip = {
  333. trigger: 'item',
  334. show: true,
  335. textStyle: {
  336. color: optionsSetup.lineColor,
  337. fontSize: optionsSetup.tipFontSize
  338. }
  339. };
  340. this.options.tooltip = tooltip;
  341. },
  342. // 边距设置
  343. setOptionsMargin() {
  344. const optionsSetup = this.optionsSetup;
  345. const grid = {
  346. left: optionsSetup.marginLeft,
  347. right: optionsSetup.marginRight,
  348. bottom: optionsSetup.marginBottom,
  349. top: optionsSetup.marginTop,
  350. containLabel: true
  351. };
  352. this.options.grid = grid;
  353. },
  354. setOptionsLegend() {
  355. const optionsSetup = this.optionsSetup;
  356. const legend = this.options.legend;
  357. legend.show = optionsSetup.isShowLegend;
  358. legend.left = optionsSetup.lateralPosition;
  359. legend.top = optionsSetup.longitudinalPosition;
  360. legend.bottom =
  361. optionsSetup.longitudinalPosition;
  362. legend.orient = optionsSetup.layoutFront;
  363. legend.textStyle = {
  364. color: optionsSetup.lengedColor,
  365. fontSize: optionsSetup.lengedFontSize
  366. };
  367. legend.itemWidth = optionsSetup.lengedWidth;
  368. },
  369. // 图例名称设置
  370. setOptionsLegendName(name){
  371. const optionsSetup = this.optionsSetup;
  372. const series = this.options.series;
  373. const legendName = optionsSetup.legendName;
  374. // 图例没有手动写则显示原值,写了则显示新值
  375. if (null == legendName || legendName == '') {
  376. for (let i = 0; i < name.length; i++) {
  377. series[i].name = name[i];
  378. }
  379. this.options.legend['data'] = name;
  380. }else {
  381. const arr = legendName.split('|');
  382. for (let i = 0; i < arr.length; i++) {
  383. series[i].name = arr[i];
  384. }
  385. this.options.legend['data'] = arr
  386. }
  387. },
  388. // 颜色修改
  389. setOptionsColor() {
  390. const optionsSetup = this.optionsSetup;
  391. const customColor = optionsSetup.customColor;
  392. const series = this.options.series;
  393. if (!customColor) return;
  394. const arrColor = [];
  395. for (let i = 0; i < customColor.length; i++) {
  396. arrColor.push(customColor[i].color);
  397. }
  398. for (const i in series) {
  399. if (series[i].type == 'bar') {
  400. series[i].itemStyle.normal['color'] = arrColor[i];
  401. } else {
  402. series[i].lineStyle['color'] = arrColor[i];
  403. }
  404. }
  405. },
  406. // 数据处理
  407. setOptionsData() {
  408. const optionsData = this.optionsData; // 数据类型 静态 or 动态
  409. optionsData.dataType == 'staticData'
  410. ? this.staticDataFn(optionsData.staticData)
  411. : this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);
  412. },
  413. staticDataFn(val) {
  414. const optionsSetup = this.optionsSetup;
  415. const series = this.options.series;
  416. let axis = [];
  417. let bar1 = [];
  418. let bar2 = [];
  419. let bar3 = [];
  420. let line = [];
  421. for (const i in val) {
  422. axis[i] = val[i].date;
  423. bar1[i] = val[i].unsales;
  424. bar2[i] = val[i].manus;
  425. bar3[i] = val[i].rework;
  426. line[i] = val[i].sales;
  427. }
  428. // x轴
  429. this.options.xAxis.data = axis;
  430. // series
  431. for (const i in series) {
  432. if (series[i].type == 'bar') {
  433. series[i].label = {
  434. show: optionsSetup.isShowBar,
  435. position: 'top',
  436. distance: optionsSetup.distanceBar,
  437. fontSize: optionsSetup.fontSizeBar,
  438. color: optionsSetup.subTextColorBar,
  439. fontWeight: optionsSetup.fontWeightBar
  440. };
  441. series[i].barWidth = optionsSetup.maxWidth;
  442. series[i].itemStyle.normal['barBorderRadius'] = optionsSetup.radius;
  443. } else if (series[i].type == 'line') {
  444. series[i].yAxisIndex = 1;
  445. series[i].showSymbol = optionsSetup.markPoint;
  446. series[i].symbolSize = optionsSetup.pointSize;
  447. series[i].smooth = optionsSetup.smoothCurve;
  448. if (optionsSetup.area) {
  449. series[i].areaStyle = {
  450. opacity: optionsSetup.areaThickness / 100
  451. };
  452. } else {
  453. series[i].areaStyle = {
  454. opacity: 0
  455. };
  456. }
  457. series[i].lineStyle = {
  458. width: optionsSetup.lineWidth
  459. };
  460. series[i].label = {
  461. show: optionsSetup.isShowLine,
  462. position: 'top',
  463. distance: optionsSetup.distanceLine,
  464. fontSize: optionsSetup.fontSizeLine,
  465. color: optionsSetup.subTextColorLine,
  466. fontWeight: optionsSetup.fontWeightLine
  467. };
  468. }
  469. }
  470. series[0].data = bar1;
  471. series[1].data = bar2;
  472. series[2].data = bar3;
  473. series[3].data = line;
  474. const legendName = [];
  475. legendName.push('调解成功');
  476. legendName.push('调解失败');
  477. legendName.push('调解终止');
  478. legendName.push('调解成功率');
  479. this.options.legend['data'] = legendName;
  480. this.setOptionsLegendName(legendName);
  481. },
  482. dynamicDataFn(val, refreshTime) {
  483. if (!val) return;
  484. if (this.ispreview) {
  485. this.getEchartData(val);
  486. this.flagInter = setInterval(() => {
  487. this.getEchartData(val);
  488. }, refreshTime);
  489. } else {
  490. this.getEchartData(val);
  491. }
  492. },
  493. getEchartData(val) {
  494. const data = this.queryEchartsData(val);
  495. data.then(res => {
  496. this.renderingFn(res);
  497. });
  498. },
  499. renderingFn(val) {
  500. const optionsSetup = this.optionsSetup;
  501. this.options.xAxis.data = val.xAxis;
  502. const series = [];
  503. const legendName = [];
  504. for (const i in val.series) {
  505. const obj = {};
  506. if (val.series[i].type == 'bar') {
  507. obj.name = val.series[i].name;
  508. obj.type = val.series[i].type;
  509. obj.label = {
  510. show: optionsSetup.isShowBar,
  511. position: 'top',
  512. distance: optionsSetup.distanceBar,
  513. fontSize: optionsSetup.fontSizeBar,
  514. color: optionsSetup.subTextColorBar,
  515. fontWeight: optionsSetup.fontWeightBar
  516. };
  517. obj.barWidth = optionsSetup.maxWidth;
  518. obj.itemStyle = {
  519. normal: {
  520. barBorderRadius: optionsSetup.radius,
  521. }
  522. };
  523. obj.data = val.series[i].data;
  524. series.push(obj);
  525. } else if (val.series[i].type == 'line') {
  526. obj.name = val.series[i].name;
  527. obj.type = val.series[i].type;
  528. obj.yAxisIndex = 1;
  529. obj.showSymbol = optionsSetup.markPoint;
  530. obj.symbolSize = optionsSetup.pointSize;
  531. obj.smooth = optionsSetup.smoothCurve;
  532. if (optionsSetup.area) {
  533. obj.areaStyle = {
  534. opacity: optionsSetup.areaThickness / 100
  535. };
  536. } else {
  537. obj.areaStyle = {
  538. opacity: 0
  539. };
  540. }
  541. obj.lineStyle = {
  542. width: optionsSetup.lineWidth
  543. };
  544. obj.label = {
  545. show: optionsSetup.isShowLine,
  546. position: 'top',
  547. distance: optionsSetup.distanceLine,
  548. fontSize: optionsSetup.fontSizeLine,
  549. color: optionsSetup.subTextColorLine,
  550. fontWeight: optionsSetup.fontWeightLine
  551. };
  552. obj.data = val.series[i].data;
  553. series.push(obj);
  554. }
  555. legendName.push(val.series[i].name);
  556. }
  557. this.options.series = series;
  558. this.options.legend['data'] = legendName;
  559. this.setOptionsLegendName(legendName);
  560. },
  561. }
  562. };
  563. </script>
  564. <style scoped lang='scss'>
  565. .echarts {
  566. width: 100%;
  567. height: 100%;
  568. overflow: hidden;
  569. }
  570. </style>