widgetBarStackChart.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454
  1. <template>
  2. <div :style="styleObj">
  3. <v-chart :options="options" autoresize/>
  4. </div>
  5. </template>
  6. <script>
  7. export default {
  8. name: "WidgetBarStackchart",
  9. components: {},
  10. props: {
  11. value: Object,
  12. ispreview: Boolean
  13. },
  14. data() {
  15. return {
  16. options: {
  17. grid: {},
  18. legend: {
  19. textStyle: {
  20. color: "#fff"
  21. }
  22. },
  23. xAxis: {
  24. type: "category",
  25. data: [],
  26. axisLabel: {
  27. show: true,
  28. textStyle: {
  29. color: "#fff"
  30. }
  31. }
  32. },
  33. yAxis: {
  34. type: "value",
  35. data: [],
  36. axisLabel: {
  37. show: true,
  38. textStyle: {
  39. color: "#fff"
  40. }
  41. }
  42. },
  43. series: [
  44. {
  45. data: [],
  46. name: '',
  47. type: "bar",
  48. barGap: "0%",
  49. itemStyle: {
  50. barBorderRadius: null
  51. }
  52. }
  53. ]
  54. },
  55. optionsStyle: {}, // 样式
  56. optionsData: {}, // 数据
  57. optionsSetup: {},
  58. flagInter: null
  59. };
  60. },
  61. computed: {
  62. styleObj() {
  63. return {
  64. position: this.ispreview ? "absolute" : "static",
  65. width: this.optionsStyle.width + "px",
  66. height: this.optionsStyle.height + "px",
  67. left: this.optionsStyle.left + "px",
  68. top: this.optionsStyle.top + "px",
  69. background: this.optionsSetup.background
  70. };
  71. }
  72. },
  73. watch: {
  74. value: {
  75. handler(val) {
  76. this.optionsStyle = val.position;
  77. this.optionsData = val.data;
  78. this.optionsCollapse = val.setup;
  79. this.optionsSetup = val.setup;
  80. this.editorOptions();
  81. },
  82. deep: true
  83. }
  84. },
  85. mounted() {
  86. this.optionsStyle = this.value.position;
  87. this.optionsData = this.value.data;
  88. this.optionsCollapse = this.value.setup;
  89. this.optionsSetup = this.value.setup;
  90. this.editorOptions();
  91. },
  92. methods: {
  93. // 修改图标options属性
  94. editorOptions() {
  95. this.setOptionsTitle();
  96. this.setOptionsX();
  97. this.setOptionsY();
  98. this.setOptionsTooltip();
  99. this.setOptionsMargin();
  100. this.setOptionsLegend();
  101. this.setOptionsData();
  102. },
  103. // 标题修改
  104. setOptionsTitle() {
  105. const optionsSetup = this.optionsSetup;
  106. const title = {};
  107. title.text = optionsSetup.titleText;
  108. title.show = optionsSetup.isNoTitle;
  109. title.left = optionsSetup.textAlign;
  110. title.textStyle = {
  111. color: optionsSetup.textColor,
  112. fontSize: optionsSetup.textFontSize,
  113. fontWeight: optionsSetup.textFontWeight,
  114. fontStyle: optionsSetup.textFontStyle,
  115. };
  116. title.subtext = optionsSetup.subText;
  117. title.subtextStyle = {
  118. color: optionsSetup.subTextColor,
  119. fontWeight: optionsSetup.subTextFontWeight,
  120. fontSize: optionsSetup.subTextFontSize,
  121. fontStyle: optionsSetup.subTextFontStyle,
  122. };
  123. this.options.title = title;
  124. },
  125. // X轴设置
  126. setOptionsX() {
  127. const optionsSetup = this.optionsSetup;
  128. const xAxis = {
  129. type: "category",
  130. // 坐标轴是否显示
  131. show: optionsSetup.hideX,
  132. // 坐标轴名称
  133. name: optionsSetup.nameX,
  134. nameTextStyle: {
  135. color: optionsSetup.nameColorX,
  136. fontSize: optionsSetup.nameFontSizeX
  137. },
  138. // 轴反转
  139. inverse: optionsSetup.reversalX,
  140. axisLabel: {
  141. show: true,
  142. // 文字间隔
  143. interval: optionsSetup.textInterval,
  144. // 文字角度
  145. rotate: optionsSetup.textAngleX,
  146. textStyle: {
  147. // 坐标文字颜色
  148. color: optionsSetup.colorX,
  149. fontSize: optionsSetup.fontSizeX
  150. }
  151. },
  152. axisLine: {
  153. show: true,
  154. lineStyle: {
  155. color: optionsSetup.lineColorX
  156. }
  157. },
  158. splitLine: {
  159. show: optionsSetup.isShowSplitLineX,
  160. lineStyle: {
  161. color: optionsSetup.splitLineColorX
  162. }
  163. }
  164. };
  165. this.options.xAxis = xAxis;
  166. },
  167. // Y轴设置
  168. setOptionsY() {
  169. const optionsSetup = this.optionsSetup;
  170. const yAxis = {
  171. type: "value",
  172. scale: optionsSetup.scale,
  173. // 均分
  174. splitNumber: optionsSetup.splitNumberY,
  175. // 坐标轴是否显示
  176. show: optionsSetup.isShowY,
  177. // 坐标轴名称
  178. name: optionsSetup.textNameY,
  179. nameTextStyle: {
  180. color: optionsSetup.nameColorY,
  181. fontSize: optionsSetup.nameFontSizeY
  182. },
  183. // 轴反转
  184. inverse: optionsSetup.reversalY,
  185. axisLabel: {
  186. show: true,
  187. // 文字角度
  188. rotate: optionsSetup.textAngleY,
  189. textStyle: {
  190. // 坐标文字颜色
  191. color: optionsSetup.colorY,
  192. fontSize: optionsSetup.fontSizeY
  193. }
  194. },
  195. axisLine: {
  196. show: true,
  197. lineStyle: {
  198. color: optionsSetup.lineColorY
  199. }
  200. },
  201. splitLine: {
  202. show: optionsSetup.isShowSplitLineY,
  203. lineStyle: {
  204. color: optionsSetup.splitLineColorY
  205. }
  206. }
  207. };
  208. this.options.yAxis = yAxis;
  209. },
  210. // tooltip 提示语设置,鼠标放置显示
  211. setOptionsTooltip() {
  212. const optionsSetup = this.optionsSetup;
  213. const tooltip = {
  214. trigger: "item",
  215. show: true,
  216. textStyle: {
  217. color: optionsSetup.tipsColor,
  218. fontSize: optionsSetup.tipsFontSize
  219. }
  220. };
  221. this.options.tooltip = tooltip;
  222. },
  223. // 边距设置
  224. setOptionsMargin() {
  225. const optionsSetup = this.optionsSetup;
  226. const grid = {
  227. left: optionsSetup.marginLeft,
  228. right: optionsSetup.marginRight,
  229. bottom: optionsSetup.marginBottom,
  230. top: optionsSetup.marginTop,
  231. containLabel: true
  232. };
  233. this.options.grid = grid;
  234. },
  235. // 图例操作 legend
  236. setOptionsLegend() {
  237. const optionsSetup = this.optionsSetup;
  238. const legend = this.options.legend;
  239. legend.show = optionsSetup.isShowLegend;
  240. legend.left = optionsSetup.lateralPosition;
  241. legend.top = optionsSetup.longitudinalPosition;
  242. legend.bottom =
  243. optionsSetup.longitudinalPosition;
  244. legend.orient = optionsSetup.layoutFront;
  245. legend.textStyle = {
  246. color: optionsSetup.legendColor,
  247. fontSize: optionsSetup.legendFontSize
  248. };
  249. legend.itemWidth = optionsSetup.legendWidth;
  250. },
  251. // 图例名称设置
  252. setOptionsLegendName(name){
  253. const optionsSetup = this.optionsSetup;
  254. const series = this.options.series;
  255. const legendName = optionsSetup.legendName;
  256. // 图例没有手动写则显示原值,写了则显示新值
  257. if (null == legendName || legendName == '') {
  258. for (let i = 0; i < name.length; i++) {
  259. series[i].name = name[i];
  260. }
  261. this.options.legend['data'] = name;
  262. }else {
  263. const arr = legendName.split('|');
  264. for (let i = 0; i < arr.length; i++) {
  265. series[i].name = arr[i];
  266. }
  267. this.options.legend['data'] = arr
  268. }
  269. },
  270. // 数据解析
  271. setOptionsData() {
  272. const optionsSetup = this.optionsSetup;
  273. // 数据类型 静态 or 动态
  274. const optionsData = this.optionsData;
  275. optionsData.dataType == "staticData"
  276. ? this.staticDataFn(optionsData.staticData, optionsSetup)
  277. : this.dynamicDataFn(
  278. optionsData.dynamicData,
  279. optionsData.refreshTime,
  280. optionsSetup
  281. );
  282. },
  283. //去重
  284. setUnique(arr) {
  285. let newArr = [];
  286. arr.forEach(item => {
  287. return newArr.includes(item) ? '' : newArr.push(item);
  288. });
  289. return newArr;
  290. },
  291. //获取堆叠样式
  292. getStackStyle() {
  293. const optionsSetup = this.optionsSetup;
  294. let style = ""
  295. if (optionsSetup.stackStyle == "upDown") {
  296. style = "total"
  297. }
  298. return style
  299. },
  300. //静态数据
  301. staticDataFn(val) {
  302. const optionsSetup = this.optionsSetup;
  303. //颜色
  304. const customColor = optionsSetup.customColor;
  305. const arrColor = [];
  306. for (let i = 0; i < customColor.length; i++) {
  307. arrColor.push(customColor[i].color);
  308. }
  309. //数据
  310. const series = [];
  311. let xAxisList = [];
  312. let yAxisList = [];
  313. const legendName = [];
  314. for (const i in val) {
  315. xAxisList[i] = val[i].axis;
  316. yAxisList[i] = val[i].name;
  317. }
  318. xAxisList = this.setUnique(xAxisList);
  319. yAxisList = this.setUnique(yAxisList);
  320. for (const i in yAxisList) {
  321. const data = new Array(xAxisList.length).fill(0);
  322. for (const j in xAxisList) {
  323. for (const k in val) {
  324. if (val[k].name == yAxisList[i]) {
  325. if (val[k].axis == xAxisList[j]) {
  326. data[j] = val[k].data;
  327. }
  328. }
  329. }
  330. }
  331. series.push({
  332. name: yAxisList[i],
  333. type: "bar",
  334. data: data,
  335. barGap: "0%",
  336. stack: this.getStackStyle(),
  337. barWidth: optionsSetup.maxWidth,
  338. label: {
  339. show: optionsSetup.isShow,
  340. position: "top",
  341. distance: 10,
  342. fontSize: optionsSetup.fontSize,
  343. color: optionsSetup.subTextColor,
  344. fontWeight: optionsSetup.fontWeight,
  345. },
  346. //颜色,圆角属性
  347. itemStyle: {
  348. normal: {
  349. color: arrColor[i],
  350. barBorderRadius: optionsSetup.radius,
  351. }
  352. }
  353. })
  354. legendName.push(yAxisList[i]);
  355. }
  356. this.options.series = series;
  357. if (optionsSetup.verticalShow) {
  358. this.options.xAxis.data = [];
  359. this.options.yAxis.data = xAxisList;
  360. this.options.xAxis.type = "value";
  361. this.options.yAxis.type = "category";
  362. } else {
  363. this.options.xAxis.data = xAxisList;
  364. this.options.yAxis.data = [];
  365. this.options.xAxis.type = "category";
  366. this.options.yAxis.type = "value";
  367. }
  368. this.options.legend['data'] = legendName;
  369. this.setOptionsLegendName(legendName);
  370. },
  371. // 动态数据
  372. dynamicDataFn(val, refreshTime, optionsSetup) {
  373. if (!val) return;
  374. if (this.ispreview) {
  375. this.getEchartData(val, optionsSetup);
  376. this.flagInter = setInterval(() => {
  377. this.getEchartData(val, optionsSetup);
  378. }, refreshTime);
  379. } else {
  380. this.getEchartData(val, optionsSetup);
  381. }
  382. },
  383. getEchartData(val, optionsSetup) {
  384. const data = this.queryEchartsData(val);
  385. data.then(res => {
  386. this.renderingFn(optionsSetup, res);
  387. });
  388. },
  389. renderingFn(optionsSetup, val) {
  390. //颜色
  391. const customColor = optionsSetup.customColor;
  392. const arrColor = [];
  393. for (let i = 0; i < customColor.length; i++) {
  394. arrColor.push(customColor[i].color);
  395. }
  396. // x轴
  397. if (optionsSetup.verticalShow) {
  398. this.options.xAxis.data = [];
  399. this.options.yAxis.data = val.xAxis;
  400. this.options.xAxis.type = "value";
  401. this.options.yAxis.type = "category";
  402. } else {
  403. this.options.xAxis.data = val.xAxis;
  404. this.options.yAxis.data = [];
  405. this.options.xAxis.type = "category";
  406. this.options.yAxis.type = "value";
  407. }
  408. const series = [];
  409. const legendName = [];
  410. for (const i in val.series) {
  411. if (val.series[i].type == "bar") {
  412. series.push({
  413. name: val.series[i].name,
  414. type: "bar",
  415. data: val.series[i].data,
  416. barGap: "0%",
  417. stack: this.getStackStyle(),
  418. barWidth: optionsSetup.maxWidth,
  419. label: {
  420. show: optionsSetup.isShow,
  421. position: "top",
  422. distance: 10,
  423. fontSize: optionsSetup.fontSize,
  424. color: optionsSetup.subTextColor,
  425. fontWeight: optionsSetup.fontWeight,
  426. },
  427. //颜色,圆角属性
  428. itemStyle: {
  429. normal: {
  430. color: arrColor[i],
  431. barBorderRadius: optionsSetup.radius,
  432. }
  433. }
  434. })
  435. }
  436. legendName.push(val.series[i].name);
  437. }
  438. this.options.series = series;
  439. this.options.legend['data'] = legendName;
  440. this.setOptionsLegendName(legendName);
  441. }
  442. }
  443. };
  444. </script>
  445. <style scoped lang="scss">
  446. .echarts {
  447. width: 100%;
  448. height: 100%;
  449. overflow: hidden;
  450. }
  451. </style>