widgetBarStackChart.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449
  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. };
  115. title.subtext = optionsSetup.subText;
  116. title.subtextStyle = {
  117. color: optionsSetup.subTextColor,
  118. fontWeight: optionsSetup.subTextFontWeight,
  119. fontSize: optionsSetup.subTextFontSize
  120. };
  121. this.options.title = title;
  122. },
  123. // X轴设置
  124. setOptionsX() {
  125. const optionsSetup = this.optionsSetup;
  126. const xAxis = {
  127. type: "category",
  128. // 坐标轴是否显示
  129. show: optionsSetup.hideX,
  130. // 坐标轴名称
  131. name: optionsSetup.xName,
  132. nameTextStyle: {
  133. color: optionsSetup.xNameColor,
  134. fontSize: optionsSetup.xNameFontSize
  135. },
  136. // 轴反转
  137. inverse: optionsSetup.reversalX,
  138. axisLabel: {
  139. show: true,
  140. // 文字间隔
  141. interval: optionsSetup.textInterval,
  142. // 文字角度
  143. rotate: optionsSetup.textAngleX,
  144. textStyle: {
  145. // 坐标文字颜色
  146. color: optionsSetup.Xcolor,
  147. fontSize: optionsSetup.fontSizeX
  148. }
  149. },
  150. axisLine: {
  151. show: true,
  152. lineStyle: {
  153. color: optionsSetup.lineColorX
  154. }
  155. },
  156. splitLine: {
  157. show: optionsSetup.isShowSplitLineX,
  158. lineStyle: {
  159. color: optionsSetup.splitLineColorX
  160. }
  161. }
  162. };
  163. this.options.xAxis = xAxis;
  164. },
  165. // Y轴设置
  166. setOptionsY() {
  167. const optionsSetup = this.optionsSetup;
  168. const yAxis = {
  169. type: "value",
  170. // 坐标轴是否显示
  171. show: optionsSetup.isShowY,
  172. // 坐标轴名称
  173. name: optionsSetup.textNameY,
  174. nameTextStyle: {
  175. color: optionsSetup.NameColorY,
  176. fontSize: optionsSetup.NameFontSizeY
  177. },
  178. // y轴反转
  179. inverse: optionsSetup.reversalY,
  180. axisLabel: {
  181. show: true,
  182. // 文字角度
  183. rotate: optionsSetup.textAngleY,
  184. textStyle: {
  185. // 坐标文字颜色
  186. color: optionsSetup.colorY,
  187. fontSize: optionsSetup.fontSizeY
  188. }
  189. },
  190. axisLine: {
  191. show: true,
  192. lineStyle: {
  193. color: optionsSetup.lineColorY
  194. }
  195. },
  196. splitLine: {
  197. show: optionsSetup.isShowSplitLineY,
  198. lineStyle: {
  199. color: optionsSetup.splitLineColorY
  200. }
  201. }
  202. };
  203. this.options.yAxis = yAxis;
  204. },
  205. // tooltip 提示语设置,鼠标放置显示
  206. setOptionsTooltip() {
  207. const optionsSetup = this.optionsSetup;
  208. const tooltip = {
  209. trigger: "item",
  210. show: true,
  211. textStyle: {
  212. color: optionsSetup.tipsColor,
  213. fontSize: optionsSetup.tipsFontSize
  214. }
  215. };
  216. this.options.tooltip = tooltip;
  217. },
  218. // 边距设置
  219. setOptionsMargin() {
  220. const optionsSetup = this.optionsSetup;
  221. const grid = {
  222. left: optionsSetup.marginLeft,
  223. right: optionsSetup.marginRight,
  224. bottom: optionsSetup.marginBottom,
  225. top: optionsSetup.marginTop,
  226. containLabel: true
  227. };
  228. this.options.grid = grid;
  229. },
  230. // 图例操作 legend
  231. setOptionsLegend() {
  232. const optionsSetup = this.optionsSetup;
  233. const legend = this.options.legend;
  234. legend.show = optionsSetup.isShowLegend;
  235. legend.left = optionsSetup.lateralPosition;
  236. legend.top = optionsSetup.longitudinalPosition;
  237. legend.bottom =
  238. optionsSetup.longitudinalPosition;
  239. legend.orient = optionsSetup.layoutFront;
  240. legend.textStyle = {
  241. color: optionsSetup.legendColor,
  242. fontSize: optionsSetup.legendFontSize
  243. };
  244. legend.itemWidth = optionsSetup.legendWidth;
  245. },
  246. // 图例名称设置
  247. setOptionsLegendName(name){
  248. const optionsSetup = this.optionsSetup;
  249. const series = this.options.series;
  250. const legendName = optionsSetup.legendName;
  251. // 图例没有手动写则显示原值,写了则显示新值
  252. if (null == legendName || legendName == '') {
  253. for (let i = 0; i < name.length; i++) {
  254. series[i].name = name[i];
  255. }
  256. this.options.legend['data'] = name;
  257. }else {
  258. const arr = legendName.split('|');
  259. for (let i = 0; i < arr.length; i++) {
  260. series[i].name = arr[i];
  261. }
  262. this.options.legend['data'] = arr
  263. }
  264. },
  265. // 数据解析
  266. setOptionsData() {
  267. const optionsSetup = this.optionsSetup;
  268. // 数据类型 静态 or 动态
  269. const optionsData = this.optionsData;
  270. optionsData.dataType == "staticData"
  271. ? this.staticDataFn(optionsData.staticData, optionsSetup)
  272. : this.dynamicDataFn(
  273. optionsData.dynamicData,
  274. optionsData.refreshTime,
  275. optionsSetup
  276. );
  277. },
  278. //去重
  279. setUnique(arr) {
  280. let newArr = [];
  281. arr.forEach(item => {
  282. return newArr.includes(item) ? '' : newArr.push(item);
  283. });
  284. return newArr;
  285. },
  286. //获取堆叠样式
  287. getStackStyle() {
  288. const optionsSetup = this.optionsSetup;
  289. let style = ""
  290. if (optionsSetup.stackStyle == "upDown") {
  291. style = "total"
  292. }
  293. return style
  294. },
  295. //静态数据
  296. staticDataFn(val) {
  297. const optionsSetup = this.optionsSetup;
  298. //颜色
  299. const customColor = optionsSetup.customColor;
  300. const arrColor = [];
  301. for (let i = 0; i < customColor.length; i++) {
  302. arrColor.push(customColor[i].color);
  303. }
  304. //数据
  305. const series = [];
  306. let xAxisList = [];
  307. let yAxisList = [];
  308. const legendName = [];
  309. for (const i in val) {
  310. xAxisList[i] = val[i].axis;
  311. yAxisList[i] = val[i].name;
  312. }
  313. xAxisList = this.setUnique(xAxisList);
  314. yAxisList = this.setUnique(yAxisList);
  315. for (const i in yAxisList) {
  316. const data = new Array(xAxisList.length).fill(0);
  317. for (const j in xAxisList) {
  318. for (const k in val) {
  319. if (val[k].name == yAxisList[i]) {
  320. if (val[k].axis == xAxisList[j]) {
  321. data[j] = val[k].data;
  322. }
  323. }
  324. }
  325. }
  326. series.push({
  327. name: yAxisList[i],
  328. type: "bar",
  329. data: data,
  330. barGap: "0%",
  331. stack: this.getStackStyle(),
  332. barWidth: optionsSetup.maxWidth,
  333. label: {
  334. show: optionsSetup.isShow,
  335. position: "top",
  336. distance: 10,
  337. fontSize: optionsSetup.fontSize,
  338. color: optionsSetup.subTextColor,
  339. fontWeight: optionsSetup.fontWeight,
  340. },
  341. //颜色,圆角属性
  342. itemStyle: {
  343. normal: {
  344. color: arrColor[i],
  345. barBorderRadius: optionsSetup.radius,
  346. }
  347. }
  348. })
  349. legendName.push(yAxisList[i]);
  350. }
  351. this.options.series = series;
  352. if (optionsSetup.verticalShow) {
  353. this.options.xAxis.data = [];
  354. this.options.yAxis.data = xAxisList;
  355. this.options.xAxis.type = "value";
  356. this.options.yAxis.type = "category";
  357. } else {
  358. this.options.xAxis.data = xAxisList;
  359. this.options.yAxis.data = [];
  360. this.options.xAxis.type = "category";
  361. this.options.yAxis.type = "value";
  362. }
  363. this.options.legend['data'] = legendName;
  364. this.setOptionsLegendName(legendName);
  365. },
  366. // 动态数据
  367. dynamicDataFn(val, refreshTime, optionsSetup) {
  368. if (!val) return;
  369. if (this.ispreview) {
  370. this.getEchartData(val, optionsSetup);
  371. this.flagInter = setInterval(() => {
  372. this.getEchartData(val, optionsSetup);
  373. }, refreshTime);
  374. } else {
  375. this.getEchartData(val, optionsSetup);
  376. }
  377. },
  378. getEchartData(val, optionsSetup) {
  379. const data = this.queryEchartsData(val);
  380. data.then(res => {
  381. this.renderingFn(optionsSetup, res);
  382. });
  383. },
  384. renderingFn(optionsSetup, val) {
  385. //颜色
  386. const customColor = optionsSetup.customColor;
  387. const arrColor = [];
  388. for (let i = 0; i < customColor.length; i++) {
  389. arrColor.push(customColor[i].color);
  390. }
  391. // x轴
  392. if (optionsSetup.verticalShow) {
  393. this.options.xAxis.data = [];
  394. this.options.yAxis.data = val.xAxis;
  395. this.options.xAxis.type = "value";
  396. this.options.yAxis.type = "category";
  397. } else {
  398. this.options.xAxis.data = val.xAxis;
  399. this.options.yAxis.data = [];
  400. this.options.xAxis.type = "category";
  401. this.options.yAxis.type = "value";
  402. }
  403. const series = [];
  404. const legendName = [];
  405. for (const i in val.series) {
  406. if (val.series[i].type == "bar") {
  407. series.push({
  408. name: val.series[i].name,
  409. type: "bar",
  410. data: val.series[i].data,
  411. barGap: "0%",
  412. stack: this.getStackStyle(),
  413. barWidth: optionsSetup.maxWidth,
  414. label: {
  415. show: optionsSetup.isShow,
  416. position: "top",
  417. distance: 10,
  418. fontSize: optionsSetup.fontSize,
  419. color: optionsSetup.subTextColor,
  420. fontWeight: optionsSetup.fontWeight,
  421. },
  422. //颜色,圆角属性
  423. itemStyle: {
  424. normal: {
  425. color: arrColor[i],
  426. barBorderRadius: optionsSetup.radius,
  427. }
  428. }
  429. })
  430. }
  431. legendName.push(val.series[i].name);
  432. }
  433. this.options.series = series;
  434. this.options.legend['data'] = legendName;
  435. this.setOptionsLegendName(legendName);
  436. }
  437. }
  438. };
  439. </script>
  440. <style scoped lang="scss">
  441. .echarts {
  442. width: 100%;
  443. height: 100%;
  444. overflow: hidden;
  445. }
  446. </style>