widgetLineStackChart.vue 14 KB

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