graph.vue 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325
  1. <template>
  2. <div :id="domId" :style="styleObj" class="chart_graph"></div>
  3. </template>
  4. <script>
  5. import { generateUUID } from '@/utils'
  6. export default {
  7. name: 'chartGraph',
  8. props: {
  9. h: {
  10. type: [Number, String],
  11. default: 300
  12. },
  13. w: {
  14. type: [Number, String],
  15. default: 300
  16. },
  17. nodes: {
  18. type: Array,
  19. default: () => [] // [{category: 0, id: '1', name: '张三', symbolSize: 10, value: 2}]
  20. },
  21. links: {
  22. type: Array,
  23. default: () => [] // [{source: '1', target: '0'}]
  24. },
  25. categories: {
  26. type: Array,
  27. default: () => [] // [{name: '员工'}]
  28. },
  29. name: {
  30. type: String
  31. },
  32. layout: {
  33. type: String,
  34. default: () => 'circular'
  35. },
  36. showlegend: {
  37. type: Boolean,
  38. default: false
  39. },
  40. top: {
  41. type: [Number, String],
  42. default: () => 20
  43. },
  44. bottom: {
  45. type: [Number, String],
  46. default: () => 20
  47. },
  48. roam: {
  49. type: Boolean,
  50. default: true
  51. },
  52. label: {
  53. type: Object,
  54. default: () => {
  55. return {
  56. position: 'right',
  57. formatter: '{b}'
  58. }
  59. }
  60. },
  61. force: {
  62. type: Object
  63. },
  64. circular: {
  65. type: Object,
  66. default: () => {
  67. return { rotateLabel: true }
  68. }
  69. },
  70. grid: {
  71. type: Object,
  72. default: () => {
  73. return { }
  74. }
  75. },
  76. itemStyle: {
  77. type: Object,
  78. default: () => {
  79. return { }
  80. }
  81. // 点颜色
  82. },
  83. emphasis: {
  84. // 线颜色
  85. type: Object,
  86. default: () => {
  87. return { }
  88. }
  89. },
  90. lineStyle: {
  91. type: Object,
  92. default: () => {
  93. return {
  94. color: 'target',
  95. curveness: 0.3
  96. }
  97. }
  98. },
  99. focusNodeAdjacency: {
  100. type: Boolean,
  101. default: false
  102. },
  103. isknowledgegraph: {
  104. type: Boolean,
  105. default: false
  106. },
  107. legendOrient: {
  108. type: String,
  109. default: 'horizontal'
  110. },
  111. legendLeft: {
  112. type: String,
  113. default: 'center'
  114. },
  115. draggable: {
  116. type: Boolean,
  117. default: false
  118. },
  119. legendType: {
  120. type: String,
  121. default: ''
  122. },
  123. edgeSymbol: {
  124. type: Array,
  125. default: () => { return [] }
  126. },
  127. edgeSymbolSize: {
  128. type: Array,
  129. default: () => { return [] }
  130. }
  131. },
  132. data () {
  133. return {
  134. zoom: 1,
  135. domId: generateUUID(),
  136. chart: null,
  137. timer: null,
  138. innerWidth: null,
  139. innerHeight: null
  140. }
  141. },
  142. computed: {
  143. styleObj () {
  144. const regPos = / ^\d+$/
  145. const style = {
  146. height: this.h || '300px',
  147. width: this.w || '300px'
  148. }
  149. if ((typeof this.h === 'string' && regPos.test(this.h)) || typeof this.h === 'number') {
  150. style.height = this.h + 'px'
  151. }
  152. if ((typeof this.w === 'string' && regPos.test(this.w)) || typeof this.w === 'number') {
  153. style.width = this.w + 'px'
  154. }
  155. style.zoom = this.zoom
  156. style.transform = `scale(${1 / this.zoom})`
  157. style.transformOrigin = '0 0'
  158. return style
  159. }
  160. },
  161. created () { },
  162. mounted () {
  163. const _this = this
  164. window.onresize = function () {
  165. _this.innerWidth = document.documentElement.clientWidth
  166. _this.innerHeight = document.documentElement.clientHeight
  167. }
  168. this.$nextTick(_ => this.initChart())
  169. },
  170. destroyed () {
  171. window.onresize = null
  172. },
  173. methods: {
  174. initChart () {
  175. const self = document.getElementById(this.domId)
  176. if (!self) return
  177. const setSelected = {}
  178. this.categories.map((item, index) => {
  179. if (index === 0) {
  180. setSelected[item.name] = true
  181. } else {
  182. setSelected[item.name] = false
  183. }
  184. return item
  185. })
  186. const option = {
  187. grid: this.grid,
  188. tooltip: this.isknowledgegraph
  189. ? {
  190. formatter: e => {
  191. if (e.name === '大') {
  192. const tooltipSrc = this.$store.state.statistics.epbigTooltip
  193. const str = '- ' + tooltipSrc.join('<br>- ')
  194. return str
  195. } else if (e.name === '中') {
  196. const tooltipSrc = this.$store.state.statistics.epmediTooltip
  197. const str = '- ' + tooltipSrc.join('<br>- ')
  198. return str
  199. } else if (e.name === '小') {
  200. const tooltipSrc = this.$store.state.statistics.epsmallTooltip
  201. const str = '- ' + tooltipSrc.join('<br>- ')
  202. return str
  203. }
  204. }
  205. }
  206. : {
  207. formatter: e => {
  208. if (e.data.pageName === 'staff') {
  209. return `<b>${e.name}</b> <br/>
  210. 所属机构: ${e.data.info.departmentName}<br/>
  211. 入职时间:${e.data.info.empEntryTime}<br/>
  212. 岗位:${e.data.info.empPostName}<br/>
  213. 学历:${e.data.info.empAcademicDegree}<br/>
  214. 出生日期:${e.data.info.empBirth}<br/>
  215. 性别:${e.data.info.empSex}<br/>
  216. `
  217. } else if (e.data.pageName === 'network' || e.data.pageName === 'subBranch') {
  218. return `<b>${e.name}</b>`
  219. } else {
  220. return ''
  221. }
  222. }
  223. },
  224. legend: [
  225. {
  226. show: this.showlegend,
  227. data: this.categories,
  228. orient: this.legendOrient,
  229. left: this.legendLeft,
  230. type: this.legendType
  231. }
  232. ],
  233. animationDurationUpdate: 1500,
  234. animationEasingUpdate: 'quinticInOut',
  235. series: [
  236. {
  237. draggable: this.draggable,
  238. name: this.name,
  239. type: 'graph',
  240. layout: this.layout,
  241. circular: this.circular,
  242. data: this.nodes,
  243. links: this.links,
  244. categories: this.categories,
  245. roam: this.roam,
  246. label: this.label,
  247. lineStyle: this.lineStyle,
  248. edgeSymbol: this.edgeSymbol || ['', ''],
  249. edgeSymbolSize: this.edgeSymbolSize || [],
  250. top: this.top,
  251. bottom: this.bottom,
  252. itemStyle: this.itemStyle,
  253. emphasis: this.emphasis,
  254. focusNodeAdjacency: this.focusNodeAdjacency
  255. }
  256. ]
  257. }
  258. if (this.force) Object.keys(this.force).length && (option.series[0].force = this.force)
  259. this.chart = this.$echarts.init(self)
  260. this.chart.on('click', event => this.$emit('click', event))
  261. this.chart.on('mousemove', this.onMousemove)
  262. this.chart.on('mouseout', this.onMouseout)
  263. this.chart.setOption(option)
  264. },
  265. updatedChart () {
  266. this.timer && clearTimeout(this.timer)
  267. this.timer = setTimeout(() => {
  268. this.chart && this.chart.dispose()
  269. this.initChart()
  270. this.timer = null
  271. }, 100)
  272. }
  273. },
  274. watch: {
  275. innerWidth: function (val) { // 监听屏幕宽度变化
  276. this.updatedChart()
  277. },
  278. innerHeight: function (val) {
  279. this.updatedChart()
  280. },
  281. styleObj: {
  282. handler () {
  283. if (this.chart) {
  284. this.chart.resize()
  285. }
  286. }
  287. },
  288. nodes: {
  289. handler (val) {
  290. if (val) {
  291. this.updatedChart()
  292. }
  293. },
  294. deep: true
  295. },
  296. links: {
  297. handler (val) {
  298. if (val) {
  299. this.updatedChart()
  300. }
  301. },
  302. deep: true
  303. },
  304. categories: {
  305. handler (val) {
  306. if (val) {
  307. this.updatedChart()
  308. }
  309. },
  310. deep: true
  311. }
  312. }
  313. }
  314. </script>
  315. <style lang="less" scoped>
  316. .chart_graph {
  317. height: 300px;
  318. width: 300px;
  319. }
  320. </style>