commonMixins.js 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. /*
  2. * @description: bigScreen公共方法
  3. * @Date: 2023-03-24 17:10:43
  4. * @Author: xing.heng
  5. */
  6. // import _ from 'lodash'
  7. import { mapMutations, mapState } from 'vuex'
  8. import { EventBus } from 'data-room-ui/js/utils/eventBus'
  9. import { getChatInfo, getUpdateChartInfo } from '../api/bigScreenApi'
  10. import axiosFormatting from '../../js/utils/httpParamsFormatting'
  11. import { settingToTheme } from 'data-room-ui/js/utils/themeFormatting'
  12. import cloneDeep from 'lodash/cloneDeep'
  13. export default {
  14. data () {
  15. return {
  16. filterList: [],
  17. treeParentId: 0,
  18. dataLoading: false
  19. }
  20. },
  21. watch: {
  22. 'config.expression': { // 表达式发生变化
  23. handler (val) {
  24. this.getDataByExpression(this.config)
  25. }
  26. },
  27. // 标题发生变化时需要及时更新表达式中的数据集库的字段名
  28. 'config.title': {
  29. handler (val, oldVal) {
  30. this.updateDataset({ code: this.config.code, title: val, data: [], oldTitle: oldVal, isChangeTitle: true })
  31. this.updateComputedDatas({ code: this.config.code, title: val, data: [], oldTitle: oldVal, isChangeTitle: true })
  32. }
  33. },
  34. currentDataset: { // 关联的数据发生变化
  35. handler (val, old) {
  36. if (val && Object.keys(val).length && JSON.stringify(val) !== JSON.stringify(old)) {
  37. this.getDataByExpression(this.config)
  38. }
  39. },
  40. deep: true,
  41. immediate: true
  42. },
  43. currentComputedDatas: { // 关联的数据发生变化
  44. handler (val, old) {
  45. if (val && Object.keys(val).length && JSON.stringify(val) !== JSON.stringify(old)) {
  46. this.getDataByExpression(this.config)
  47. }
  48. },
  49. deep: true,
  50. immediate: true
  51. }
  52. },
  53. computed: {
  54. ...mapState({
  55. pageCode: state => state.bigScreen.pageInfo.code,
  56. customTheme: state => state.bigScreen.pageInfo.pageConfig.customTheme,
  57. activeCode: state => state.bigScreen.activeCode
  58. // dataset: state => state.bigScreen.dataset
  59. }),
  60. // 所有组件的数据集合
  61. dataset () {
  62. return this.$store.state.bigScreen.dataset
  63. },
  64. // 所有组件的数据集合
  65. computedDatas () {
  66. return this.$store.state.bigScreen.computedDatas
  67. },
  68. // 跟当前组件计算表达式关联的组件的数据集合
  69. currentDataset () {
  70. const newDataset = {}
  71. this.config.expressionCodes?.forEach(item => {
  72. const code = item.split('_')[1]
  73. for (const key in this.dataset) {
  74. const objCode = key.split('_')[1]
  75. if (objCode === code) {
  76. newDataset[code] = this.dataset[key]
  77. }
  78. }
  79. })
  80. return newDataset
  81. },
  82. // 跟当前组件计算表达式关联的组件的数据集合
  83. currentComputedDatas () {
  84. const newDataset = {}
  85. this.config.expressionCodes?.forEach(item => {
  86. const code = item.split('_')[1]
  87. for (const key in this.computedDatas) {
  88. const objCode = key.split('_')[1]
  89. if (objCode === code) {
  90. newDataset[code] = this.computedDatas[key]
  91. }
  92. }
  93. })
  94. return newDataset
  95. },
  96. isPreview () {
  97. return (this.$route.path === window?.BS_CONFIG?.routers?.previewUrl) || (this.$route.path === '/big-screen/preview')
  98. }
  99. },
  100. mounted () {
  101. if (!['tables', 'flyMap', 'map'].includes(this.config.type)) {
  102. this.chartInit()
  103. }
  104. this.watchCacheData()
  105. },
  106. methods: {
  107. ...mapMutations({
  108. changeChartConfig: 'bigScreen/changeChartConfig',
  109. changeActiveItemConfig: 'bigScreen/changeActiveItemConfig',
  110. updateDataset: 'bigScreen/updateDataset',
  111. updateComputedDatas: 'bigScreen/updateComputedDatas'
  112. }),
  113. /**
  114. * 初始化组件
  115. */
  116. chartInit () {
  117. let config = this.config
  118. // key和code相等,说明是一进来刷新,调用list接口
  119. if (this.isPreview) {
  120. // 改变样式
  121. config = this.changeStyle(config) ? this.changeStyle(config) : config
  122. // 改变数据
  123. config = this.changeDataByCode(config)
  124. } else {
  125. // 否则说明是更新,这里的更新只指更新数据(改变样式时是直接调取changeStyle方法),因为更新数据会改变key,调用chart接口
  126. // eslint-disable-next-line no-unused-vars
  127. config = this.changeData(config)
  128. }
  129. },
  130. /**
  131. * 初始化组件时获取后端返回的数据, 返回数据和当前组件的配置_list
  132. * @param settingConfig 设置时的配置。不传则为当前组件的配置
  133. * @returns {Promise<unknown>}
  134. */
  135. changeDataByCode (config) {
  136. let currentPage = 1
  137. let size = 10
  138. if (config?.option?.pagination) {
  139. currentPage = config.option.pagination.currentPage
  140. size = config.option.pagination.pageSize
  141. }
  142. return new Promise((resolve, reject) => {
  143. config.loading = true
  144. getChatInfo({
  145. // innerChartCode: this.pageCode ? config.code : undefined,
  146. chartCode: config.code,
  147. current: currentPage,
  148. pageCode: this.pageCode,
  149. size: size,
  150. type: config.type
  151. }).then(async (res) => {
  152. config.loading = false
  153. let _res = cloneDeep(res)
  154. // 如果是http数据集的前端代理,则需要调封装的axios请求
  155. if (res.executionByFrontend) {
  156. if (res.data.datasetType === 'http') {
  157. _res = await axiosFormatting(res.data)
  158. _res = this.httpDataFormatting(res, _res)
  159. }
  160. if (res.data.datasetType === 'js') {
  161. try {
  162. const scriptAfterReplacement = res.data.script.replace(/\${(.*?)}/g, (match, p) => {
  163. const value = this.config.dataSource?.params[p]
  164. if (value === null || value === undefined || value === '') {
  165. return "''"
  166. } else if (!isNaN(value)) {
  167. return value || p
  168. } else {
  169. return `'${value}' || '${p}'`
  170. }
  171. })
  172. // eslint-disable-next-line no-new-func
  173. const scriptMethod = new Function(scriptAfterReplacement)
  174. _res.data = scriptMethod()
  175. } catch (error) {
  176. console.info('JS数据集脚本执行失败', error)
  177. }
  178. }
  179. }
  180. // 将后端返回的数据保存
  181. if (_res.success) {
  182. this.updateDataset({ code: config.code, title: config.title, data: _res?.data })
  183. }
  184. config = this.dataFormatting(config, _res)
  185. this.changeChartConfig(config)
  186. }).catch((err) => {
  187. console.info(err)
  188. }).finally(() => {
  189. resolve(config)
  190. })
  191. })
  192. },
  193. /**
  194. * @description: 更新chart
  195. * @param {Object} config
  196. * @param {Array} filterList
  197. */
  198. changeData (config, filterList) {
  199. const list = config?.paramsList?.map((item) => {
  200. if (item.value === '${level}') {
  201. return { ...item, value: config.customize.level }
  202. } else if (item.value === '${name}') {
  203. return { ...item, value: config.customize.scope }
  204. } else {
  205. return item
  206. }
  207. })
  208. const params = {
  209. chart: {
  210. ...config,
  211. paramsList: list ? [...list] : [],
  212. option: undefined
  213. },
  214. current: 1,
  215. pageCode: this.pageCode,
  216. type: config.type,
  217. filterList: filterList || this.filterList
  218. }
  219. return new Promise((resolve, reject) => {
  220. config.loading = true
  221. getUpdateChartInfo(params).then(async (res) => {
  222. config.loading = false
  223. let _res = cloneDeep(res)
  224. // 如果是http数据集的前端代理,则需要调封装的axios请求
  225. if (res.executionByFrontend) {
  226. if (res.data.datasetType === 'http') {
  227. _res = await axiosFormatting(res.data)
  228. _res = this.httpDataFormatting(res, _res)
  229. }
  230. if (res.data.datasetType === 'js') {
  231. try {
  232. params.filterList.forEach(item => {
  233. this.config.dataSource.params[item.column] = item.value
  234. })
  235. const scriptAfterReplacement = res.data.script.replace(/\${(.*?)}/g, (match, p) => {
  236. const value = this.config.dataSource?.params[p]
  237. if (value === null || value === undefined || value === '') {
  238. return "''"
  239. } else if (!isNaN(value)) {
  240. return value || p
  241. } else {
  242. return `'${value}' || '${p}'`
  243. }
  244. })
  245. // eslint-disable-next-line no-new-func
  246. const scriptMethod = new Function(scriptAfterReplacement)
  247. _res.data = scriptMethod()
  248. } catch (error) {
  249. console.info('JS数据集脚本执行失败', error)
  250. }
  251. }
  252. }
  253. // 将后端返回的数据保存
  254. if (_res.success) {
  255. this.updateDataset({ code: config.code, title: config.title, data: _res?.data })
  256. }
  257. config = this.dataFormatting(config, _res)
  258. if (this.chart) {
  259. // 单指标组件和多指标组件的changeData传参不同
  260. if (['Liquid', 'Gauge', 'RingProgress', 'Progress'].includes(config.chartType)) {
  261. this.chart.changeData(config.option.percent)
  262. } else {
  263. this.chart.changeData(config.option.data)
  264. }
  265. } if (this.config.type === 'candlestick' && this.charts) {
  266. this.updateChartData(config, _res)
  267. } else if (this.charts) {
  268. // 地图组件的被联动更新
  269. this.changeMapData(config.option.data)
  270. }
  271. }).catch(err => {
  272. console.info(err)
  273. }).finally(() => {
  274. if (config) {
  275. config.loading = false
  276. }
  277. resolve(config)
  278. })
  279. })
  280. },
  281. // 更新图表数据
  282. updateChartData () {
  283. },
  284. // http前台代理需要对返回的数据进行重新组装
  285. httpDataFormatting (chartRes, httpRes) {
  286. let result = {}
  287. result = {
  288. columnData: chartRes.columnData,
  289. data: httpRes,
  290. success: chartRes.success
  291. }
  292. return result
  293. },
  294. dataFormatting (config, data) {
  295. // 覆盖
  296. },
  297. newChart (option) {
  298. // 覆盖
  299. },
  300. // 通过表达式计算获取组件的值
  301. getDataByExpression (config) {
  302. // 覆盖
  303. },
  304. changeStyle (config) {
  305. config = { ...this.config, ...config }
  306. // 样式改变时更新主题配置
  307. config.theme = settingToTheme(cloneDeep(config), this.customTheme)
  308. this.changeChartConfig(config)
  309. if (config.code === this.activeCode) {
  310. this.changeActiveItemConfig(config)
  311. }
  312. },
  313. // 缓存组件数据监听
  314. watchCacheData () {
  315. EventBus.$on('cacheDataInit', (data, dataSetId) => {
  316. // 如果是缓存数据集
  317. // 且当前组件的businessKey和缓存的dataSetId相等时,更新组件
  318. if (
  319. this.config.dataSource.dataSetType === '2' &&
  320. this.config.dataSource.businessKey === dataSetId
  321. ) {
  322. const config = this.dataFormatting(this.config, data)
  323. config.key = new Date().getTime()
  324. this.changeChartConfig(config)
  325. this.newChart(config.option)
  326. }
  327. })
  328. }
  329. }
  330. }