widgetBarchart.vue 14 KB

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