widgetRadar.vue 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421
  1. <template>
  2. <div :style="styleObj">
  3. <v-chart ref="myVChart" :options="options" autoresize/>
  4. </div>
  5. </template>
  6. <script>
  7. import {targetWidgetLinkageLogic} from "@/views/bigscreenDesigner/designer/linkageLogic";
  8. import vue from "vue";
  9. import VueSuperSlide from "vue-superslide";
  10. vue.use(VueSuperSlide);
  11. export default {
  12. props: {
  13. value: Object,
  14. ispreview: Boolean,
  15. },
  16. data() {
  17. return {
  18. hackReset: true,
  19. options: {
  20. title: {},
  21. legend: {},
  22. radar: {
  23. indicator: [],
  24. },
  25. series: [],
  26. },
  27. optionsSetup: {},
  28. optionsPosition: {},
  29. optionsData: {},
  30. flagInter: null,
  31. };
  32. },
  33. computed: {
  34. styleObj() {
  35. const allStyle = this.optionsPosition;
  36. return {
  37. position: this.ispreview ? "absolute" : "static",
  38. width: allStyle.width + "px",
  39. height: allStyle.height + "px",
  40. left: allStyle.left + "px",
  41. top: allStyle.top + "px",
  42. background: this.optionsSetup.background,
  43. };
  44. },
  45. allComponentLinkage() {
  46. return this.$store.state.designer.allComponentLinkage;
  47. },
  48. },
  49. watch: {
  50. value: {
  51. handler(val) {
  52. this.optionsSetup = val.setup;
  53. this.optionsPosition = val.position;
  54. this.optionsData = val.data;
  55. this.editorOptions();
  56. },
  57. deep: true,
  58. },
  59. },
  60. mounted() {
  61. this.optionsSetup = this.value.setup;
  62. this.optionsPosition = this.value.position;
  63. this.optionsData = this.value.data;
  64. this.editorOptions();
  65. targetWidgetLinkageLogic(this); // 联动-目标组件逻辑
  66. },
  67. methods: {
  68. editorOptions() {
  69. this.setOptionsTitle();
  70. this.setOptionsRadar();
  71. this.setOptionsLegend();
  72. this.setOptionsTooltip();
  73. this.setOptionsMargin();
  74. this.setOptionsData();
  75. },
  76. // 标题修改
  77. setOptionsTitle() {
  78. const optionsSetup = this.optionsSetup;
  79. const title = {};
  80. title.text = optionsSetup.titleText;
  81. title.show = optionsSetup.isNoTitle;
  82. title.left = optionsSetup.textAlign;
  83. title.textStyle = {
  84. color: optionsSetup.textColor,
  85. fontSize: optionsSetup.textFontSize,
  86. fontWeight: optionsSetup.textFontWeight,
  87. fontStyle: optionsSetup.textFontStyle,
  88. };
  89. title.subtext = optionsSetup.subText;
  90. title.subtextStyle = {
  91. color: optionsSetup.subTextColor,
  92. fontWeight: optionsSetup.subTextFontWeight,
  93. fontSize: optionsSetup.subTextFontSize,
  94. fontStyle: optionsSetup.subTextFontStyle,
  95. };
  96. this.options.title = title;
  97. },
  98. // 雷达设置
  99. setOptionsRadar() {
  100. const optionsSetup = this.optionsSetup;
  101. const axisLine = {
  102. show: optionsSetup.axisLineShow,
  103. lineStyle: {
  104. color: optionsSetup.axisLineColor,
  105. opacity: optionsSetup.axisLineOpacity / 100,
  106. },
  107. };
  108. const axisName = {
  109. show: optionsSetup.axisNameShow,
  110. color: optionsSetup.axisNameColor,
  111. fontSize: optionsSetup.axisNameFontSize,
  112. fontStyle: optionsSetup.axisNamFontStyle,
  113. fontWeight: optionsSetup.axisNamFontWeight,
  114. };
  115. const splitLine = {
  116. show: optionsSetup.splitLineShow,
  117. lineStyle: {
  118. color: optionsSetup.splitLineColor,
  119. opacity: optionsSetup.splitLineOpacity / 100,
  120. },
  121. };
  122. this.options.radar.axisLine = axisLine;
  123. // echarts5.X以上,name属性被替换为axisName
  124. this.options.radar.name = axisName;
  125. this.options.radar.splitLine = splitLine;
  126. this.options.radar.shape = optionsSetup.radarShape;
  127. this.options.radar.splitNumber = optionsSetup.splitNumber;
  128. },
  129. // 图例配置
  130. setOptionsLegend() {
  131. const optionsSetup = this.optionsSetup;
  132. const legend = {
  133. show: optionsSetup.isShowLegend,
  134. left: optionsSetup.lateralPosition,
  135. top: optionsSetup.longitudinalPosition,
  136. bottom: optionsSetup.longitudinalPosition,
  137. orient: optionsSetup.layoutFront,
  138. textStyle: {
  139. color: optionsSetup.legendColor,
  140. fontSize: optionsSetup.legendFontSize,
  141. },
  142. itemWidth: optionsSetup.legendWidth,
  143. };
  144. this.options.legend = legend;
  145. },
  146. // 图例名称设置
  147. setOptionsLegendName(name) {
  148. const optionsSetup = this.optionsSetup;
  149. const series = this.options.series;
  150. const legendName = optionsSetup.legendName;
  151. // 图例没有手动写则显示原值,写了则显示新值
  152. if (null == legendName || legendName == "") {
  153. for (let i = 0; i < name.length; i++) {
  154. series[0].data[i].name = name[i];
  155. }
  156. this.options.legend["data"] = name;
  157. } else {
  158. const arr = legendName.split("|");
  159. for (let i = 0; i < arr.length; i++) {
  160. series[0].data[i].name = arr[i];
  161. }
  162. this.options.legend["data"] = arr;
  163. }
  164. },
  165. // tooltip 提示语设置,鼠标放置显示
  166. setOptionsTooltip() {
  167. const optionsSetup = this.optionsSetup;
  168. const tooltip = {
  169. trigger: "item",
  170. show: optionsSetup.isShowTooltip,
  171. textStyle: {
  172. color: optionsSetup.tooltipColor,
  173. fontSize: optionsSetup.tooltipFontSize,
  174. fontWeight: optionsSetup.tooltipFontWeight,
  175. fontStyle: optionsSetup.tooltipFontStyle,
  176. fontFamily: optionsSetup.tooltipFontFamily,
  177. },
  178. };
  179. this.options.tooltip = tooltip;
  180. },
  181. // 雷达大小设置
  182. setOptionsMargin() {
  183. this.options.radar.radius = "70%";
  184. },
  185. setOptionsData(e, paramsConfig) {
  186. const optionsData = this.optionsData; // 数据类型 静态 or 动态
  187. // 联动接收者逻辑开始
  188. optionsData.dynamicData = optionsData.dynamicData || {}; // 兼容 dynamicData undefined
  189. const myDynamicData = optionsData.dynamicData;
  190. clearInterval(this.flagInter); // 不管咋,先干掉上一次的定时任务,避免多跑
  191. if (
  192. e &&
  193. optionsData.dataType !== "staticData" &&
  194. Object.keys(myDynamicData.contextData).length
  195. ) {
  196. const keyArr = Object.keys(myDynamicData.contextData);
  197. paramsConfig.forEach((conf) => {
  198. if (keyArr.includes(conf.targetKey)) {
  199. myDynamicData.contextData[conf.targetKey] = e[conf.originKey];
  200. }
  201. });
  202. }
  203. // 联动接收者逻辑结束
  204. optionsData.dataType == "staticData"
  205. ? this.staticDataFn(optionsData.staticData)
  206. : this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);
  207. },
  208. //去重
  209. setUnique(arr) {
  210. let newArr = [];
  211. arr.forEach((item) => {
  212. return newArr.includes(item) ? "" : newArr.push(item);
  213. });
  214. return newArr;
  215. },
  216. staticDataFn(val) {
  217. const optionsSetup = this.optionsSetup;
  218. //颜色
  219. const customColor = optionsSetup.customColor;
  220. const arrColor = [];
  221. for (let i = 0; i < customColor.length; i++) {
  222. arrColor.push(customColor[i].color);
  223. }
  224. this.options.color = arrColor;
  225. // 雷达设置相关
  226. const indicator = optionsSetup.dynamicAddRadar;
  227. this.options.radar.indicator = indicator;
  228. // 雷达图key值
  229. const radarKeys = [];
  230. for (const i in indicator) {
  231. radarKeys[i] = indicator[i].key;
  232. }
  233. const name = [];
  234. const data = [];
  235. const legendName = [];
  236. for (const i in val) {
  237. name[i] = val[i].name;
  238. }
  239. for (const i in name) {
  240. const values = new Array(radarKeys.length).fill(0);
  241. for (const j in radarKeys) {
  242. for (const k in val) {
  243. if (val[k].name == name[i]) {
  244. values[j] = val[k][radarKeys[j]];
  245. }
  246. }
  247. }
  248. data.push({
  249. name: name[i],
  250. value: values,
  251. label: {
  252. show: optionsSetup.isShow,
  253. position: optionsSetup.fontPosition,
  254. distance: optionsSetup.fontDistance,
  255. fontSize: optionsSetup.fontSize,
  256. color: optionsSetup.fontColor == '' ? null : optionsSetup.fontColor,
  257. fontWeight: optionsSetup.fontWeight,
  258. fontStyle: optionsSetup.fontStyle,
  259. fontFamily: optionsSetup.fontFamily,
  260. },
  261. lineStyle: {
  262. normal: {
  263. width: optionsSetup.lineWidth,
  264. type: optionsSetup.lineType,
  265. color: arrColor[i],
  266. },
  267. },
  268. });
  269. legendName.push(name[i]);
  270. }
  271. this.options.series[0] = {
  272. type: "radar",
  273. data: data,
  274. symbolSize: optionsSetup.symbolSize,
  275. areaStyle: {
  276. normal: {
  277. opacity: optionsSetup.opacity / 100,
  278. },
  279. },
  280. };
  281. this.options.legend["data"] = legendName;
  282. this.setOptionsLegendName(legendName);
  283. },
  284. dynamicDataFn(data, refreshTime) {
  285. if (!data) return;
  286. if (this.ispreview) {
  287. this.getEchartData(data);
  288. this.flagInter = setInterval(() => {
  289. this.getEchartData(data);
  290. }, refreshTime);
  291. } else {
  292. this.getEchartData(data);
  293. }
  294. },
  295. getEchartData(val) {
  296. const data = this.queryEchartsData(val);
  297. data.then((res) => {
  298. this.renderingFn(res);
  299. });
  300. },
  301. renderingFn(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. this.options.color = arrColor;
  310. // 雷达设置相关
  311. const indicator = optionsSetup.dynamicAddRadar;
  312. this.options.radar.indicator = indicator;
  313. // 雷达图key值
  314. const radarKeys = [];
  315. for (const i in indicator) {
  316. radarKeys[i] = indicator[i].key;
  317. }
  318. const name = [];
  319. const data = [];
  320. const legendName = [];
  321. for (const i in val.value) {
  322. name.push(val.value[i][val.name]);
  323. }
  324. for (const i in name) {
  325. const values = new Array(radarKeys.length).fill(0);
  326. for (const j in radarKeys) {
  327. for (const k in val.value) {
  328. if (val.value[k][val.name] == name[i]) {
  329. values[j] = val.value[k][radarKeys[j]];
  330. }
  331. }
  332. }
  333. data.push({
  334. name: name[i],
  335. value: values,
  336. label: {
  337. show: optionsSetup.isShow,
  338. position: optionsSetup.fontPosition,
  339. distance: optionsSetup.fontDistance,
  340. fontSize: optionsSetup.fontSize,
  341. color: optionsSetup.fontColor == '' ? null : optionsSetup.fontColor,
  342. fontWeight: optionsSetup.fontWeight,
  343. fontStyle: optionsSetup.fontStyle,
  344. fontFamily: optionsSetup.fontFamily,
  345. },
  346. lineStyle: {
  347. normal: {
  348. type: optionsSetup.lineType,
  349. color: arrColor[i],
  350. },
  351. },
  352. });
  353. legendName.push(name[i]);
  354. }
  355. const series0 = {
  356. type: "radar",
  357. data: data,
  358. symbolSize: optionsSetup.symbolSize,
  359. areaStyle: {
  360. normal: {
  361. opacity: optionsSetup.opacity / 100,
  362. },
  363. },
  364. }
  365. this.$set(this.options.series, 0, series0);
  366. this.options.legend["data"] = legendName;
  367. this.setOptionsLegendName(legendName);
  368. },
  369. },
  370. };
  371. </script>
  372. <style lang="scss" scoped>
  373. .echarts {
  374. width: 100%;
  375. height: 100%;
  376. overflow: hidden;
  377. }
  378. /* 本例子css */
  379. .txtScroll-top {
  380. overflow: hidden;
  381. position: relative;
  382. }
  383. .title {
  384. display: flex;
  385. flex-direction: row;
  386. width: 100%;
  387. }
  388. .title > div {
  389. height: 50px;
  390. line-height: 50px;
  391. width: 100%;
  392. }
  393. .txtScroll-top .bd {
  394. width: 100%;
  395. }
  396. .txtScroll-top .infoList li {
  397. height: 50px;
  398. line-height: 50px;
  399. display: flex;
  400. flex-direction: row;
  401. }
  402. .txtScroll-top .infoList li > div {
  403. width: 100%;
  404. }
  405. /*.txtScroll-top .infoList li:nth-child(n) {
  406. background: rgb(0, 59, 81);
  407. }
  408. .txtScroll-top .infoList li:nth-child(2n) {
  409. background: rgb(10, 39, 50);
  410. }*/
  411. </style>