options.ts 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463
  1. import { reactive, watch } from 'vue'
  2. import { ECOption } from '@/components/base/echarts/core'
  3. import { ChartCycleType } from '@/constants/chart'
  4. import { useGlobalStore } from '@/stores'
  5. import { EchartsDataset, EchartsOptions, Colors } from './types'
  6. import moment from 'moment'
  7. const globalStore = useGlobalStore()
  8. const { appTheme } = globalStore.$toRefs()
  9. function getColors() {
  10. // 默认主题色配置
  11. const defaultColors: Colors = {
  12. upColor: '#ff3333',
  13. downColor: '#0aab62',
  14. xAxisLineColor: 'rgba(128,128,128,.1)',
  15. yAxisLineColor: 'rgba(128,128,128,.1)',
  16. }
  17. const colors = {
  18. default: defaultColors,
  19. dark: defaultColors,
  20. light: {
  21. ...defaultColors,
  22. xAxisLineColor: '#dae5ec',
  23. yAxisLineColor: '#dae5ec',
  24. }
  25. }
  26. return colors[appTheme.value];
  27. }
  28. export function useOptions(dataset: EchartsDataset) {
  29. // 图表配置项
  30. const options = reactive<EchartsOptions>({
  31. cycleType: ChartCycleType.Minutes,
  32. colors: getColors(),
  33. candlestick: {},
  34. macd: {},
  35. vol: {},
  36. kdj: {},
  37. cci: {},
  38. })
  39. const getDefaultOption = (): ECOption => {
  40. const { source } = dataset.candlestick;
  41. const { xAxisLineColor, yAxisLineColor } = options.colors;
  42. return {
  43. grid: {
  44. left: '25px',
  45. right: '25px',
  46. top: '20px',
  47. bottom: '15px',
  48. containLabel: true,
  49. },
  50. dataZoom: {
  51. type: 'inside',
  52. startValue: source.length - 60, // 起始显示K线条数(最新60条)
  53. end: 100,
  54. minValueSpan: 30, // 限制窗口缩放显示最少数据条数
  55. maxValueSpan: 200, // 限制窗口缩放显示最大数据条数
  56. },
  57. axisPointer: {
  58. label: {
  59. backgroundColor: 'rgba(72,72,72,.75)'
  60. }
  61. },
  62. xAxis: {
  63. type: 'category',
  64. axisLabel: {
  65. color: '#777',
  66. margin: 12,
  67. formatter: (val: string) => {
  68. switch (options.cycleType) {
  69. case ChartCycleType.Day: {
  70. return moment(val).format('YYYY-MM-DD')
  71. }
  72. default: {
  73. return moment(val).format('HH:mm')
  74. }
  75. }
  76. },
  77. // interval: (index) => {
  78. // return index % 8 === 0
  79. // }
  80. },
  81. axisLine: {
  82. lineStyle: {
  83. color: xAxisLineColor, // 坐标轴线线的颜色
  84. }
  85. },
  86. axisPointer: {
  87. label: {
  88. formatter: (params) => {
  89. switch (options.cycleType) {
  90. case ChartCycleType.Day: {
  91. return moment(params.value).format('YYYY-MM-DD')
  92. }
  93. default: {
  94. return moment(params.value).format('YYYY-MM-DD HH:mm:ss')
  95. }
  96. }
  97. },
  98. }
  99. },
  100. axisTick: {
  101. show: false,
  102. },
  103. // splitLine: {
  104. // show: true,
  105. // lineStyle: {
  106. // color: xAxisLineColor,
  107. // },
  108. // },
  109. },
  110. yAxis: {
  111. scale: true,
  112. splitLine: {
  113. lineStyle: {
  114. // 坐标分隔线颜色
  115. color: yAxisLineColor,
  116. },
  117. },
  118. },
  119. }
  120. }
  121. // K线配置项
  122. const setCandlestickOption = () => {
  123. const { dimensions, source } = dataset.candlestick;
  124. const { upColor, downColor } = options.colors;
  125. options.candlestick = {
  126. ...getDefaultOption(),
  127. dataset: {
  128. dimensions,
  129. source,
  130. },
  131. series: [
  132. {
  133. name: 'K线',
  134. type: 'candlestick',
  135. barWidth: '80%',
  136. itemStyle: {
  137. color: upColor,
  138. color0: downColor,
  139. borderColor: upColor,
  140. borderColor0: downColor,
  141. },
  142. // 最新价标线
  143. markLine: {
  144. symbol: 'none',
  145. // 标线标签样式
  146. label: {
  147. show: false,
  148. color: '#fff',
  149. backgroundColor: 'rgba(72,72,72,.75)',
  150. padding: 5,
  151. borderRadius: 3,
  152. position: 'insideStartTop',
  153. },
  154. // 标线样式
  155. lineStyle: {
  156. type: 'dashed',
  157. color: 'rgba(102,102,102,.7)'
  158. },
  159. data: [
  160. {
  161. // 收盘价
  162. yAxis: source.length ? source[source.length - 1].close : 0,
  163. },
  164. ],
  165. },
  166. },
  167. {
  168. name: 'MA5',
  169. type: 'line',
  170. sampling: 'average', //折线图在数据量远大于像素点时候的降采样策略,开启后可以有效的优化图表的绘制效率
  171. smooth: true,
  172. symbol: 'none',
  173. lineStyle: {
  174. width: 1,
  175. opacity: 0.8,
  176. },
  177. },
  178. {
  179. name: 'MA10',
  180. type: 'line',
  181. sampling: 'average',
  182. smooth: true,
  183. symbol: 'none',
  184. lineStyle: {
  185. width: 1,
  186. opacity: 0.8,
  187. },
  188. },
  189. {
  190. name: 'MA15',
  191. type: 'line',
  192. sampling: 'average',
  193. smooth: true,
  194. symbol: 'none',
  195. lineStyle: {
  196. width: 1,
  197. opacity: 0.8,
  198. },
  199. },
  200. ],
  201. }
  202. }
  203. // MACD配置项
  204. const setMacdOption = () => {
  205. const { upColor, downColor, yAxisLineColor } = options.colors;
  206. const { dimensions, source } = dataset.macd;
  207. options.macd = {
  208. ...getDefaultOption(),
  209. yAxis: {
  210. scale: true,
  211. splitNumber: 2,
  212. splitLine: {
  213. lineStyle: {
  214. // 坐标分隔线颜色
  215. color: yAxisLineColor,
  216. },
  217. },
  218. },
  219. dataset: {
  220. dimensions,
  221. source,
  222. },
  223. series: [
  224. {
  225. name: 'MACD',
  226. type: 'bar',
  227. sampling: 'average',
  228. barWidth: '60%',
  229. itemStyle: {
  230. color: ({ data }) => {
  231. const { macd } = data as { macd: number };
  232. if (macd > 0) {
  233. return upColor;
  234. } else {
  235. return downColor;
  236. }
  237. },
  238. }
  239. },
  240. {
  241. name: 'DIF',
  242. type: 'line',
  243. sampling: 'average',
  244. smooth: true,
  245. symbol: 'none',
  246. lineStyle: {
  247. width: 1,
  248. opacity: 0.8,
  249. },
  250. },
  251. {
  252. name: 'DEA',
  253. type: 'line',
  254. sampling: 'average',
  255. smooth: true,
  256. symbol: 'none',
  257. lineStyle: {
  258. width: 1,
  259. opacity: 0.8,
  260. },
  261. },
  262. ],
  263. }
  264. }
  265. // VOL配置项
  266. const setVolOption = () => {
  267. const { yAxisLineColor } = options.colors;
  268. const { dimensions, source } = dataset.vol;
  269. options.vol = {
  270. ...getDefaultOption(),
  271. yAxis: {
  272. scale: true,
  273. splitNumber: 2,
  274. splitLine: {
  275. lineStyle: {
  276. // 坐标分隔线颜色
  277. color: yAxisLineColor,
  278. },
  279. },
  280. },
  281. dataset: {
  282. dimensions,
  283. source,
  284. },
  285. series: [
  286. {
  287. name: 'VOL',
  288. type: 'bar',
  289. sampling: 'average',
  290. barWidth: '60%',
  291. },
  292. ],
  293. }
  294. }
  295. // KDJ配置项
  296. const setKdjOption = () => {
  297. const { yAxisLineColor } = options.colors;
  298. const { dimensions, source } = dataset.kdj;
  299. options.kdj = {
  300. ...getDefaultOption(),
  301. yAxis: {
  302. scale: true,
  303. splitNumber: 2,
  304. splitLine: {
  305. lineStyle: {
  306. // 坐标分隔线颜色
  307. color: yAxisLineColor,
  308. },
  309. },
  310. },
  311. dataset: {
  312. dimensions,
  313. source,
  314. },
  315. series: [
  316. {
  317. name: 'K',
  318. type: 'line',
  319. sampling: 'average',
  320. smooth: true,
  321. symbol: 'none',
  322. lineStyle: {
  323. width: 1,
  324. opacity: 0.8,
  325. },
  326. },
  327. {
  328. name: 'D',
  329. type: 'line',
  330. sampling: 'average',
  331. smooth: true,
  332. symbol: 'none',
  333. lineStyle: {
  334. width: 1,
  335. opacity: 0.8,
  336. },
  337. },
  338. {
  339. name: 'J',
  340. type: 'line',
  341. sampling: 'average',
  342. smooth: true,
  343. symbol: 'none',
  344. lineStyle: {
  345. width: 1,
  346. opacity: 0.8,
  347. },
  348. },
  349. ],
  350. }
  351. }
  352. // CCI配置项
  353. const setCciOption = () => {
  354. const { yAxisLineColor } = options.colors;
  355. const { dimensions, source } = dataset.cci;
  356. options.cci = {
  357. ...getDefaultOption(),
  358. yAxis: {
  359. scale: true,
  360. splitNumber: 2,
  361. splitLine: {
  362. lineStyle: {
  363. // 坐标分隔线颜色
  364. color: yAxisLineColor,
  365. },
  366. },
  367. },
  368. dataset: {
  369. dimensions,
  370. source,
  371. },
  372. series: [
  373. {
  374. name: 'CCI',
  375. type: 'line',
  376. sampling: 'average',
  377. smooth: true,
  378. symbol: 'none',
  379. lineStyle: {
  380. width: 1,
  381. opacity: 0.8,
  382. },
  383. },
  384. ],
  385. }
  386. }
  387. const initOptions = () => {
  388. setCandlestickOption();
  389. setMacdOption();
  390. setVolOption();
  391. setKdjOption();
  392. setCciOption();
  393. }
  394. // 动态更新数据
  395. const updateOptions = () => {
  396. const { candlestick, macd, vol, kdj, cci } = dataset;
  397. options.candlestick = {
  398. dataset: {
  399. source: candlestick.source,
  400. },
  401. series: [
  402. {
  403. name: 'K线',
  404. markLine: {
  405. data: [
  406. {
  407. yAxis: candlestick.source[candlestick.source.length - 1].close,
  408. },
  409. ],
  410. },
  411. },
  412. ],
  413. }
  414. options.macd = {
  415. dataset: {
  416. source: macd.source,
  417. },
  418. }
  419. options.vol = {
  420. dataset: {
  421. source: vol.source,
  422. },
  423. }
  424. options.kdj = {
  425. dataset: {
  426. source: kdj.source,
  427. },
  428. }
  429. options.cci = {
  430. dataset: {
  431. source: cci.source,
  432. },
  433. }
  434. }
  435. // 监听主题变化
  436. watch(appTheme, () => {
  437. options.colors = getColors();
  438. initOptions();
  439. })
  440. return {
  441. options,
  442. initOptions,
  443. updateOptions,
  444. }
  445. }