widgetPieNightingaleRose.vue 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285
  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: "WidgetPieNightingaleRoseArea", //南丁格尔玫瑰图面积模式 参考:https://echarts.apache.org/examples/zh/editor.html?c=pie-roseType-simple
  13. components: {},
  14. props: {
  15. value: Object,
  16. ispreview: Boolean,
  17. },
  18. data() {
  19. return {
  20. options: {
  21. legend: {
  22. top: "bottom",
  23. },
  24. toolbox: {
  25. show: true,
  26. feature: {
  27. mark: {show: true},
  28. },
  29. },
  30. series: [
  31. {
  32. //name: "面积模式",
  33. type: "pie",
  34. radius: ["10%", "50%"],
  35. center: ["50%", "50%"],
  36. roseType: "area",
  37. itemStyle: {
  38. borderRadius: 8,
  39. },
  40. data: [],
  41. },
  42. ],
  43. },
  44. optionsStyle: {}, // 样式
  45. optionsData: {}, // 数据
  46. optionsCollapse: {}, // 图标属性
  47. optionsSetup: {},
  48. flagInter: null,
  49. };
  50. },
  51. computed: {
  52. styleObj() {
  53. return {
  54. position: this.ispreview ? "absolute" : "static",
  55. width: this.optionsStyle.width + "px",
  56. height: this.optionsStyle.height + "px",
  57. left: this.optionsStyle.left + "px",
  58. top: this.optionsStyle.top + "px",
  59. background: this.optionsSetup.background,
  60. };
  61. },
  62. allComponentLinkage() {
  63. return this.$store.state.designer.allComponentLinkage;
  64. },
  65. },
  66. watch: {
  67. value: {
  68. handler(val) {
  69. this.optionsStyle = val.position;
  70. this.optionsData = val.data;
  71. this.optionsCollapse = val.setup;
  72. this.optionsSetup = val.setup;
  73. this.editorOptions();
  74. },
  75. deep: true,
  76. },
  77. },
  78. mounted() {
  79. this.optionsStyle = this.value.position;
  80. this.optionsData = this.value.data;
  81. this.optionsCollapse = this.value.setup;
  82. this.optionsSetup = this.value.setup;
  83. this.editorOptions();
  84. targetWidgetLinkageLogic(this); // 联动-目标组件逻辑
  85. originWidgetLinkageLogic(this); // 联动-源组件逻辑
  86. },
  87. methods: {
  88. // 修改图标options属性
  89. editorOptions() {
  90. this.setOptionsTitle();
  91. this.setOptionsValue();
  92. this.setOptionsTooltip();
  93. this.setOptionsLegend();
  94. this.setOptionsColor();
  95. this.setOptionsPie();
  96. this.setOptionsData();
  97. },
  98. // 饼图设置
  99. setOptionsPie() {
  100. const optionsSetup = this.optionsSetup;
  101. const series = {
  102. type: "pie",
  103. // 饼图模式 面积模式"area" 半径模式"radius"//name: "面积模式",
  104. roseType: optionsSetup.nightingaleRoseType,
  105. radius: [optionsSetup.innerNumber + "%", optionsSetup.outerNumber + "%"],
  106. center: ["50%", "50%"],
  107. itemStyle: {
  108. borderRadius: [optionsSetup.borderRadius + "%", optionsSetup.borderRadius + "%"],
  109. },
  110. };
  111. this.options.series[0] = series;
  112. },
  113. // 标题修改
  114. setOptionsTitle() {
  115. const optionsSetup = this.optionsSetup;
  116. const title = {};
  117. title.text = optionsSetup.titleText;
  118. title.show = optionsSetup.isNoTitle;
  119. title.left = optionsSetup.textAlign;
  120. title.textStyle = {
  121. color: optionsSetup.textColor,
  122. fontSize: optionsSetup.textFontSize,
  123. fontWeight: optionsSetup.textFontWeight,
  124. fontStyle: optionsSetup.textFontStyle,
  125. };
  126. title.subtext = optionsSetup.subText;
  127. title.subtextStyle = {
  128. color: optionsSetup.subTextColor,
  129. fontWeight: optionsSetup.subTextFontWeight,
  130. fontSize: optionsSetup.subTextFontSize,
  131. fontStyle: optionsSetup.subTextFontStyle,
  132. };
  133. this.options.title = title;
  134. },
  135. // 数值设定
  136. setOptionsValue() {
  137. const optionsSetup = this.optionsSetup;
  138. const series = this.options.series;
  139. const numberValue = optionsSetup.numberValue ? "{c}" : "";
  140. const percentage = optionsSetup.percentage ? "({d})%" : "";
  141. const label = {
  142. show: optionsSetup.isShow,
  143. formatter: `{a|{b}:${numberValue} ${percentage}}`,
  144. rich: {
  145. a: {
  146. padding: [-30, 15, -20, 15],
  147. color: optionsSetup.dataColor,
  148. fontSize: optionsSetup.fontSize,
  149. fontWeight: optionsSetup.fontWeight,
  150. },
  151. },
  152. fontSize: optionsSetup.fontSize,
  153. fontWeight: optionsSetup.optionsSetup,
  154. };
  155. for (const key in series) {
  156. if (series[key].type == "pie") {
  157. series[key].label = label;
  158. series[key].labelLine = {show: optionsSetup.isShow};
  159. }
  160. }
  161. },
  162. // tooltip 设置
  163. setOptionsTooltip() {
  164. const optionsSetup = this.optionsSetup;
  165. const tooltip = {
  166. trigger: "item",
  167. show: true,
  168. textStyle: {
  169. color: optionsSetup.tipsColor,
  170. fontSize: optionsSetup.tipsFontSize,
  171. },
  172. };
  173. this.options.tooltip = tooltip;
  174. },
  175. // 边距设置
  176. setOptionsMargin() {
  177. const optionsSetup = this.optionsSetup;
  178. const grid = {
  179. left: optionsSetup.marginLeft,
  180. right: optionsSetup.marginRight,
  181. bottom: optionsSetup.marginBottom,
  182. top: optionsSetup.marginTop,
  183. containLabel: true,
  184. };
  185. this.options.grid = grid;
  186. },
  187. // 图例操作 legend
  188. setOptionsLegend() {
  189. const optionsSetup = this.optionsSetup;
  190. const legend = this.options.legend;
  191. legend.show = optionsSetup.isShowLegend;
  192. legend.left = optionsSetup.lateralPosition;
  193. legend.right = optionsSetup.lateralPosition;
  194. legend.top = optionsSetup.longitudinalPosition;
  195. legend.bottom =
  196. optionsSetup.longitudinalPosition;
  197. legend.orient = optionsSetup.layoutFront;
  198. legend.textStyle = {
  199. color: optionsSetup.legendColor,
  200. fontSize: optionsSetup.legendFontSize,
  201. };
  202. legend.itemWidth = optionsSetup.legendWidth;
  203. },
  204. // 图例颜色修改
  205. setOptionsColor() {
  206. const optionsSetup = this.optionsSetup;
  207. const customColor = optionsSetup.customColor;
  208. if (!customColor) return;
  209. const arrColor = [];
  210. for (let i = 0; i < customColor.length; i++) {
  211. arrColor.push(customColor[i].color);
  212. }
  213. this.options.color = arrColor;
  214. this.options = Object.assign({}, this.options);
  215. },
  216. // 数据解析
  217. setOptionsData(e, paramsConfig) {
  218. const optionsData = this.optionsData; // 数据类型 静态 or 动态
  219. // 联动接收者逻辑开始
  220. optionsData.dynamicData = optionsData.dynamicData || {}; // 兼容 dynamicData undefined
  221. const myDynamicData = optionsData.dynamicData;
  222. clearInterval(this.flagInter); // 不管咋,先干掉上一次的定时任务,避免多跑
  223. if (
  224. e &&
  225. optionsData.dataType !== "staticData" &&
  226. Object.keys(myDynamicData.contextData).length
  227. ) {
  228. const keyArr = Object.keys(myDynamicData.contextData);
  229. paramsConfig.forEach((conf) => {
  230. if (keyArr.includes(conf.targetKey)) {
  231. myDynamicData.contextData[conf.targetKey] = e[conf.originKey];
  232. }
  233. });
  234. }
  235. // 联动接收者逻辑结束
  236. optionsData.dataType == "staticData"
  237. ? this.staticDataFn(optionsData.staticData)
  238. : this.dynamicDataFn(optionsData.dynamicData, optionsData.refreshTime);
  239. },
  240. staticDataFn(val) {
  241. const staticData = typeof val == "string" ? JSON.parse(val) : val;
  242. for (const key in this.options.series) {
  243. if (this.options.series[key].type == "pie") {
  244. this.options.series[key].data = staticData;
  245. }
  246. }
  247. },
  248. dynamicDataFn(val, refreshTime) {
  249. if (!val) return;
  250. if (this.ispreview) {
  251. this.getEchartData(val);
  252. this.flagInter = setInterval(() => {
  253. this.getEchartData(val);
  254. }, refreshTime);
  255. } else {
  256. this.getEchartData(val);
  257. }
  258. },
  259. getEchartData(val) {
  260. const data = this.queryEchartsData(val);
  261. data.then((res) => {
  262. this.renderingFn(res);
  263. });
  264. },
  265. renderingFn(val) {
  266. for (const key in this.options.series) {
  267. if (this.options.series[key].type == "pie") {
  268. this.options.series[key].data = val;
  269. }
  270. }
  271. },
  272. },
  273. };
  274. </script>
  275. <style scoped lang="scss">
  276. .echarts {
  277. width: 100%;
  278. height: 100%;
  279. overflow: hidden;
  280. }
  281. </style>