useChartOptions.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. import type { EChartsOption } from "echarts";
  2. import { computed, watch, ref } from "vue";
  3. import { omit, defaultsDeep } from "lodash-es";
  4. import { useRequest } from "vue-hooks-plus";
  5. import { DataSourceType } from "../chartEnum";
  6. import { message } from "ant-design-vue";
  7. import { cllJsCode } from "../utils";
  8. type ExtOptions = {
  9. grid: EChartsOption["grid"];
  10. }
  11. export const useChartOptions = (chartProps: Record<string, any>, extOptions?: ExtOptions) => {
  12. const dataSource = chartProps.dataSource || {};
  13. const xAxis = ref<EChartsOption["xAxis"]>();
  14. const yAxis = ref<EChartsOption["yAxis"]>();
  15. const series = ref<EChartsOption["series"]>(dataSource?.data?.series);
  16. const server = computed(() => {
  17. return async () =>
  18. await fetch(chartProps.dataSource.url, {
  19. method: chartProps.dataSource.method,
  20. })
  21. .then((res) => res.json());
  22. });
  23. // 直接通过设置的接口请求数据
  24. const { run, refresh, cancel, data, loading } = useRequest(server.value, {
  25. defaultParams: chartProps.dataSource.params,
  26. manual: true,
  27. cacheKey: chartProps.dataSource.url,
  28. cacheTime: (chartProps.dataSource?.refreshTime || 0) * 1000,
  29. pollingInterval: (chartProps.dataSource?.refreshTime || 0) * 1000, // 刷新时间
  30. onError: (error) => {
  31. console.error(error);
  32. message.error(chartProps.dataSource.url + "请求失败");
  33. }
  34. });
  35. /* 初始请求 */
  36. if (chartProps.dataSource.sourceType === DataSourceType.API) {
  37. run();
  38. }
  39. watch(
  40. () => data.value,
  41. async (val) => {
  42. if (val && chartProps.dataSource.sourceType === DataSourceType.API) {
  43. let res = val;
  44. if(chartProps.dataSource.dataProcess) {
  45. // 请求后数据处理
  46. res = await cllJsCode(chartProps.dataSource.dataProcess, JSON.stringify(val));
  47. }
  48. xAxis.value = res.xAxis || res.xData ? { data: res.xData } : xAxis.value;
  49. yAxis.value = res.yAxis || res.yData ? { data: res.yData } : yAxis.value;
  50. series.value = res.series;
  51. }
  52. },
  53. {
  54. deep: true,
  55. }
  56. );
  57. // 数据源设置
  58. watch(
  59. () => [
  60. chartProps.dataSource.sourceType,
  61. chartProps.dataSource.method,
  62. chartProps.dataSource.data
  63. ],
  64. () => {
  65. // 请求接口
  66. if (chartProps.dataSource.sourceType === DataSourceType.API) {
  67. refresh();
  68. }
  69. // 静态数据
  70. if(chartProps.dataSource.sourceType === DataSourceType.STATIC) {
  71. cancel();
  72. const dataSource = chartProps.dataSource || {};
  73. const { xData, yData, series: seriesData } = dataSource?.data || {};
  74. if(xData) {
  75. xAxis.value = { data: xData };
  76. }
  77. if(yData) {
  78. yAxis.value = { data: yData };
  79. }
  80. series.value = seriesData;
  81. }
  82. // 根据视图或基础数据源获取数据
  83. if([DataSourceType.BASIC_PATH, DataSourceType.VIEW_CODE].includes(chartProps.dataSource.sourceType)) {
  84. const dataSource = chartProps.dataSource || {};
  85. const obj = {
  86. viewCode: dataSource.viewCode,
  87. basicPath: dataSource.basicPath,
  88. items: '',
  89. filter: '',
  90. key: '',
  91. isOne: '',
  92. };
  93. (window as Window & typeof globalThis & {mabp: any}).mabp &&
  94. (window as Window & typeof globalThis & {mabp: any}).mabp
  95. .$doLoadComponentData(obj).then(function (res: any) {
  96. series.value = res.data;
  97. });
  98. }
  99. },
  100. {
  101. deep: true,
  102. }
  103. );
  104. // 获取grid
  105. const getGrid = (opt: EChartsOption) => {
  106. // 试着从配置里读取
  107. let { bottom = 34, right = 20, left = 30, top = 20} = extOptions?.grid && !Array.isArray(extOptions?.grid) ? extOptions.grid : {};
  108. bottom = Number(bottom);
  109. top = Number(top);
  110. right = Number(right);
  111. left = Number(left);
  112. // 有标题
  113. if(!Array.isArray(opt.title) && opt.title?.show) {
  114. top += 20;
  115. }
  116. // 图例位置
  117. if(!Array.isArray(opt.legend) && opt.legend?.show) {
  118. if(opt.legend.left === 'center' && opt.legend.top !== 'auto') {
  119. top += 20;
  120. }
  121. if(opt.legend.left === 'center' && opt.legend.bottom !== 'auto') {
  122. bottom += 20;
  123. }
  124. if(opt.legend.top === 'center' && opt.legend.left !== 'auto') {
  125. left += 70;
  126. }
  127. if(opt.legend.top === 'center' && opt.legend.right !== 'auto') {
  128. right += 50;
  129. }
  130. }
  131. if(!Array.isArray(opt.xAxis) && opt.xAxis?.name) {
  132. bottom += 20;
  133. }
  134. if(!Array.isArray(opt.yAxis) && opt.yAxis?.name) {
  135. left += 20;
  136. }
  137. return {
  138. bottom,
  139. left,
  140. right,
  141. top
  142. }
  143. }
  144. const options = computed((): EChartsOption => {
  145. const opt = omit(chartProps, [
  146. "width",
  147. "height",
  148. "dataSource",
  149. ]) as EChartsOption;
  150. if(!Array.isArray(opt.title) && !opt.title?.show && !Array.isArray(opt.legend) && opt.legend) {
  151. opt.legend.top = 12;
  152. }
  153. // 通用标签
  154. const label = opt?.label || {};
  155. const result = defaultsDeep(
  156. {
  157. xAxis: xAxis.value,
  158. yAxis: yAxis.value,
  159. series: (series.value as any[])?.map((item: any) => {
  160. // 每个图单独的系列配置
  161. const seriesExtend = (opt.seriesExtend as EChartsOption) || {};
  162. return {
  163. ...label,
  164. ...item,
  165. ...seriesExtend,
  166. }
  167. }),
  168. grid: getGrid(opt)
  169. },
  170. opt
  171. );
  172. console.log('option result:', result)
  173. return result;
  174. });
  175. return {
  176. options,
  177. loading,
  178. };
  179. };