market.vue 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334
  1. <template>
  2. <div class="market-container">
  3. <div class="market-title">
  4. <img src="@/assets/images/shb.png" class="title-icon" />
  5. 市场拓展
  6. </div>
  7. <div class="legend">
  8. <div class="legend-item">上月</div>
  9. <div class="legend-item">本月</div>
  10. </div>
  11. <div class="chart-wrap">
  12. <div id="marketChart" class="chart"></div>
  13. <div id="marketChart2" class="chart2"></div>
  14. </div>
  15. </div>
  16. </template>
  17. <script>
  18. import { mapState } from "vuex"
  19. import { api } from "@/api"
  20. import * as echarts from "echarts"
  21. export default {
  22. name: "MarketExpansion",
  23. props: {
  24. data: {
  25. type: Object,
  26. default: () => ({}),
  27. },
  28. },
  29. data() {
  30. return {
  31. chartInstanceA: null,
  32. chartInstanceB: null,
  33. chartData: {
  34. categories: [
  35. "新增户数",
  36. "新增项目",
  37. "新增合同",
  38. "新增联系人",
  39. "跟进企业",
  40. "新增企业",
  41. ],
  42. },
  43. }
  44. },
  45. computed: {
  46. ...mapState(["entCode", "communityId"]),
  47. },
  48. watch: {
  49. data: {
  50. handler(newVal, oldVal) {
  51. if (newVal) {
  52. this.initChart()
  53. }
  54. },
  55. deep: true,
  56. },
  57. },
  58. mounted() {
  59. this.init()
  60. window.addEventListener("resize", this.handleResize)
  61. },
  62. beforeDestroy() {
  63. if (this.chartInstanceA) {
  64. this.chartInstanceA.dispose()
  65. }
  66. window.removeEventListener("resize", this.handleResize)
  67. },
  68. methods: {
  69. // 初始化组件
  70. init() {
  71. this.initChart()
  72. },
  73. // 初始化图表
  74. initChart() {
  75. this.chartInstanceA = echarts.init(
  76. document.getElementById("marketChart")
  77. )
  78. this.chartInstanceB = echarts.init(
  79. document.getElementById("marketChart2")
  80. )
  81. const lastMonthData = Object.keys(this.data)
  82. .map((key, index) => {
  83. return -this.data[key].last_month
  84. })
  85. .reverse()
  86. const thisMonthData = Object.keys(this.data)
  87. .map((key, index) => {
  88. return this.data[key].this_month
  89. })
  90. .reverse()
  91. const optionA = {
  92. tooltip: {
  93. trigger: "axis",
  94. axisPointer: {
  95. type: "shadow",
  96. },
  97. backgroundColor: "rgba(17, 28, 49, 0.9)",
  98. borderColor: "rgba(64, 158, 255, 0.2)",
  99. textStyle: {
  100. color: "#ffffff",
  101. },
  102. formatter: (params) => {
  103. // 自定义tooltip格式
  104. let result = params[0].name + "<br/>"
  105. params.forEach((item) => {
  106. result +=
  107. item.marker +
  108. item.seriesName +
  109. ": " +
  110. Math.abs(item.value) +
  111. "<br/>"
  112. })
  113. return result
  114. },
  115. },
  116. grid: {
  117. left: "10%",
  118. right: "1%",
  119. bottom: "5%",
  120. top: "5%",
  121. containLabel: true,
  122. },
  123. xAxis: {
  124. type: "value",
  125. axisLabel: {
  126. formatter: (value) => {
  127. if (value < 0) return -value //这里是针对取负值
  128. else return value
  129. },
  130. },
  131. show: false, // 隐藏x轴
  132. },
  133. yAxis: [
  134. {
  135. type: "category",
  136. data: this.chartData.categories,
  137. axisLine: {
  138. show: false,
  139. },
  140. axisTick: {
  141. show: false,
  142. },
  143. axisLabel: {
  144. show: false,
  145. },
  146. },
  147. ],
  148. series: [
  149. {
  150. name: "上月",
  151. type: "bar",
  152. // barMinHeight: 20,
  153. data: lastMonthData,
  154. itemStyle: {
  155. // 左侧渐变色:从#F66757到#FCE2B4
  156. color: new echarts.graphic.LinearGradient(1, 0, 0, 0, [
  157. { offset: 0, color: "#FCE2B4" },
  158. { offset: 1, color: "#F66757" },
  159. ]),
  160. borderRadius: [20, 0, 0, 20],
  161. },
  162. label: {
  163. show: true,
  164. position: "left",
  165. formatter: "{c}",
  166. color: "#ffffff",
  167. fontSize: 12,
  168. formatter: (value) => {
  169. return -value.data
  170. },
  171. },
  172. },
  173. ],
  174. }
  175. const optionB = {
  176. tooltip: {
  177. trigger: "axis",
  178. axisPointer: {
  179. type: "shadow",
  180. },
  181. backgroundColor: "rgba(17, 28, 49, 0.9)",
  182. borderColor: "rgba(64, 158, 255, 0.2)",
  183. textStyle: {
  184. color: "#ffffff",
  185. },
  186. formatter: (params) => {
  187. // 自定义tooltip格式
  188. let result = params[0].name + "<br/>"
  189. params.forEach((item) => {
  190. result +=
  191. item.marker +
  192. item.seriesName +
  193. ": " +
  194. Math.abs(item.value) +
  195. "<br/>"
  196. })
  197. return result
  198. },
  199. },
  200. grid: {
  201. left: "1%",
  202. right: "10%",
  203. bottom: "5%",
  204. top: "5%",
  205. containLabel: true,
  206. },
  207. xAxis: {
  208. type: "value",
  209. axisLabel: {
  210. formatter: (value) => {
  211. if (value < 0) return -value //这里是针对取负值
  212. else return value
  213. },
  214. },
  215. show: false, // 隐藏x轴
  216. },
  217. yAxis: [
  218. {
  219. type: "category",
  220. data: this.chartData.categories,
  221. axisLine: {
  222. show: false,
  223. },
  224. axisTick: {
  225. show: false,
  226. },
  227. axisLabel: {
  228. show: true,
  229. color: "#a0b3d6",
  230. fontSize: 14,
  231. align: "right",
  232. },
  233. },
  234. ],
  235. series: [
  236. {
  237. name: "本月",
  238. type: "bar",
  239. // barMinHeight: 20,
  240. data: thisMonthData,
  241. itemStyle: {
  242. // 右侧渐变色:从#1620D4到#3AB3E3
  243. color: new echarts.graphic.LinearGradient(0, 0, 1, 0, [
  244. { offset: 0, color: "#3AB3E3" },
  245. { offset: 1, color: "#1620D4" },
  246. ]),
  247. borderRadius: [0, 20, 20, 0],
  248. },
  249. label: {
  250. show: true,
  251. position: "right",
  252. formatter: "{c}",
  253. color: "#ffffff",
  254. fontSize: 12,
  255. },
  256. },
  257. ],
  258. }
  259. this.chartInstanceA.setOption(optionA)
  260. this.chartInstanceA.resize()
  261. this.chartInstanceB.setOption(optionB)
  262. this.chartInstanceB.resize()
  263. },
  264. // 处理窗口大小变化
  265. handleResize() {
  266. if (this.chartInstanceA) {
  267. this.chartInstanceA.resize()
  268. }
  269. if (this.chartInstanceB) {
  270. this.chartInstanceB.resize()
  271. }
  272. },
  273. },
  274. }
  275. </script>
  276. <style lang="scss" scoped>
  277. @import "@/assets/css/theme.scss";
  278. .market-container {
  279. background: #0d1629;
  280. border-radius: halfW(4);
  281. height: 100%;
  282. display: flex;
  283. flex-direction: column;
  284. background: var(--content-bg);
  285. }
  286. .market-title {
  287. border-radius: halfW(4);
  288. background: var(--title-bg);
  289. padding: halfH(4) halfW(10);
  290. font-size: halfW(16);
  291. color: var(--title-primary);
  292. display: flex;
  293. align-items: center;
  294. }
  295. .legend {
  296. display: flex;
  297. justify-content: space-around;
  298. align-items: center;
  299. padding: halfH(10) halfW(20);
  300. font-size: halfW(14);
  301. font-weight: 500;
  302. color: #fff;
  303. border-bottom: 1px solid rgba(64, 158, 255, 0.2);
  304. }
  305. .chart-wrap {
  306. display: flex;
  307. align-items: center;
  308. width: 100%;
  309. height: 100%;
  310. .chart {
  311. width: 40%;
  312. height: 100%;
  313. background: var(--content-bg);
  314. }
  315. .chart2 {
  316. width: 60%;
  317. height: 100%;
  318. background: var(--content-bg);
  319. }
  320. }
  321. </style>