pestEchart.vue 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  1. <template>
  2. <view class="pest-echart">
  3. <view class="pest-echart__header">
  4. <view class="tab-list">
  5. <view
  6. v-for="(tab, index) in tabs"
  7. :key="index"
  8. class="tab-item"
  9. :class="{ active: activeTab === index }"
  10. @click="switchTab(index)"
  11. >
  12. {{ tab.name }}
  13. </view>
  14. </view>
  15. </view>
  16. <view class="pest-echart__content">
  17. <!-- 三个关键时期 -->
  18. <view class="period-section">
  19. <view class="period-item">
  20. <view class="period-label">始见期</view>
  21. <view class="period-value">{{ periodData.firstDate }}</view>
  22. </view>
  23. <view class="period-item">
  24. <view class="period-label">高峰期</view>
  25. <view class="period-value">{{ periodData.peakDate }}</view>
  26. </view>
  27. <view class="period-item">
  28. <view class="period-label">终见期</view>
  29. <view class="period-value">{{ periodData.lastDate }}</view>
  30. </view>
  31. </view>
  32. <!-- 图表区域 -->
  33. <view class="chart-container">
  34. <canvas
  35. canvas-id="pestChart"
  36. id="pestChart"
  37. class="chart-canvas"
  38. @touchstart="touchStart"
  39. @touchmove="touchMove"
  40. @touchend="touchEnd"
  41. />
  42. </view>
  43. </view>
  44. </view>
  45. </template>
  46. <script>
  47. import uCharts from '@/components/js_sdk/u-charts/u-charts/u-charts.js';
  48. let chartInstance = null;
  49. export default {
  50. name: 'PestEchart',
  51. data() {
  52. return {
  53. tabs: [
  54. { name: '叶蝉', id: 'yechan' },
  55. { name: '水龟虫', id: 'shuigui' },
  56. { name: '稻飞虱', id: 'daofeishi' },
  57. { name: '蝼蛄', id: 'lougou' },
  58. { name: '叶蝉', id: 'yechan' },
  59. { name: '蝼蛄', id: 'lougou' },
  60. { name: '叶蝉', id: 'yechan' },
  61. { name: '蝼蛄', id: 'lougou' },
  62. { name: '叶蝉', id: 'yechan' },
  63. { name: '甜菜', id: 'tiancai' }
  64. ],
  65. activeTab: 0,
  66. // 三个关键时期数据
  67. periodData: {
  68. firstDate: '2025-05-24',
  69. peakDate: '2025-06-24',
  70. lastDate: '2025-07-24'
  71. },
  72. chartData: {
  73. categories: ['05-29/00:00', '05-29/00:00', '05-29/00:00'],
  74. series: [
  75. {
  76. name: '虫量',
  77. data: [3, 7, 9]
  78. }
  79. ]
  80. },
  81. cWidth: 320,
  82. cHeight: 200,
  83. // 每个标签对应的数据
  84. tabData: [
  85. {
  86. periodData: {
  87. firstDate: '2025-05-24',
  88. peakDate: '2025-06-24',
  89. lastDate: '2025-07-24'
  90. },
  91. chartData: {
  92. categories: ['05-29/00:00', '05-29/00:00', '05-29/00:00'],
  93. series: [
  94. {
  95. name: '虫量',
  96. data: [3, 7, 9]
  97. }
  98. ]
  99. }
  100. },
  101. {
  102. periodData: {
  103. firstDate: '2025-06-01',
  104. peakDate: '2025-07-01',
  105. lastDate: '2025-08-01'
  106. },
  107. chartData: {
  108. categories: ['06-05', '06-12', '06-19', '06-26', '07-03', '07-10', '07-17', '07-24', '07-31'],
  109. series: [
  110. {
  111. name: '虫量',
  112. data: [1, 3, 6, 10, 12, 8, 5, 3, 2]
  113. }
  114. ]
  115. }
  116. },
  117. {
  118. periodData: {
  119. firstDate: '2025-05-15',
  120. peakDate: '2025-06-15',
  121. lastDate: '2025-07-15'
  122. },
  123. chartData: {
  124. categories: ['05-20', '05-27', '06-03', '06-10', '06-17', '06-24', '07-01', '07-08', '07-15'],
  125. series: [
  126. {
  127. name: '虫量',
  128. data: [3, 5, 7, 9, 11, 8, 6, 4, 2]
  129. }
  130. ]
  131. }
  132. },
  133. {
  134. periodData: {
  135. firstDate: '2025-05-20',
  136. peakDate: '2025-06-20',
  137. lastDate: '2025-07-20'
  138. },
  139. chartData: {
  140. categories: ['05-25', '06-01', '06-08', '06-15', '06-22', '06-29', '07-06', '07-13', '07-20'],
  141. series: [
  142. {
  143. name: '虫量',
  144. data: [1, 2, 5, 8, 10, 7, 5, 3, 1]
  145. }
  146. ]
  147. }
  148. },
  149. {
  150. periodData: {
  151. firstDate: '2025-06-05',
  152. peakDate: '2025-07-05',
  153. lastDate: '2025-08-05'
  154. },
  155. chartData: {
  156. categories: ['06-10', '06-17', '06-24', '07-01', '07-08', '07-15', '07-22', '07-29', '08-05'],
  157. series: [
  158. {
  159. name: '虫量',
  160. data: [2, 4, 6, 9, 12, 10, 7, 4, 2]
  161. }
  162. ]
  163. }
  164. }
  165. ]
  166. };
  167. },
  168. mounted() {
  169. this.initChart();
  170. },
  171. methods: {
  172. initChart() {
  173. this.cWidth = uni.upx2px(680);
  174. this.cHeight = uni.upx2px(400);
  175. this.$nextTick(() => {
  176. this.drawChart();
  177. });
  178. },
  179. drawChart() {
  180. const ctx = uni.createCanvasContext('pestChart', this);
  181. chartInstance = new uCharts({
  182. type: 'line',
  183. context: ctx,
  184. width: this.cWidth,
  185. height: this.cHeight,
  186. categories: this.chartData.categories,
  187. series: this.chartData.series,
  188. animation: true,
  189. background: '#FFFFFF',
  190. color: ['#0085FF'],
  191. padding: [10, 20, 10, 0],
  192. dataLabel: false,
  193. dataPointShape: true,
  194. enableScroll: false,
  195. legend: {
  196. show: false
  197. },
  198. xAxis: {
  199. disableGrid: true,
  200. boundaryGap: 'center',
  201. fontSize: 11,
  202. fontColor: '#999999',
  203. scrollShow: false
  204. },
  205. yAxis: {
  206. gridType: 'none',
  207. splitNumber: 4,
  208. min: 0,
  209. max: 12,
  210. fontSize: 11,
  211. fontColor: '#999999'
  212. },
  213. extra: {
  214. line: {
  215. type: 'curve',
  216. width: 2,
  217. activeType: 'hollow',
  218. linearType: 'none',
  219. onShadow: false,
  220. shadowColor: 'rgba(0, 133, 255, 0.3)',
  221. tension: 0.4
  222. }
  223. }
  224. });
  225. },
  226. switchTab(index) {
  227. this.activeTab = index;
  228. // 更新数据
  229. this.periodData = this.tabData[index].periodData;
  230. this.chartData = this.tabData[index].chartData;
  231. // 重新绘制图表
  232. this.$nextTick(() => {
  233. this.drawChart();
  234. });
  235. },
  236. touchStart(e) {
  237. if (chartInstance) {
  238. chartInstance.scrollStart(e);
  239. }
  240. },
  241. touchMove(e) {
  242. if (chartInstance) {
  243. chartInstance.scroll(e);
  244. }
  245. },
  246. touchEnd(e) {
  247. if (chartInstance) {
  248. chartInstance.scrollEnd(e);
  249. chartInstance.showToolTip(e);
  250. }
  251. }
  252. }
  253. };
  254. </script>
  255. <style lang="scss" scoped>
  256. .pest-echart {
  257. overflow: hidden;
  258. margin-top: 24rpx;
  259. }
  260. .pest-echart__header {
  261. padding-top: 24rpx;
  262. }
  263. .tab-list {
  264. width: 100%;
  265. padding-bottom: 24rpx;
  266. overflow-x: scroll;
  267. white-space: nowrap;
  268. overflow-y: hidden;
  269. box-sizing: border-box;
  270. // 去掉滚动条
  271. -ms-overflow-style: none;
  272. scrollbar-width: none;
  273. }
  274. .tab-item {
  275. margin-right: 16rpx;
  276. font-size: 28rpx;
  277. font-family: 'Source Han Sans CN VF', sans-serif;
  278. font-weight: 500;
  279. color: #999999;
  280. display: inline-block;
  281. box-sizing: border-box;
  282. background: #ffffff;
  283. font-family: "Source Han Sans CN VF";
  284. font-size: 28rpx;
  285. padding: 10rpx 32rpx;
  286. border-radius: 8rpx;
  287. &:last-child {
  288. margin-right: 0;
  289. }
  290. &.active {
  291. color: #0BBC58;
  292. font-weight: 700;
  293. }
  294. &:first-child.active {
  295. color: #0BBC58;
  296. }
  297. }
  298. .pest-echart__content {
  299. background: #FFFFFF;
  300. border-radius: 16rpx;
  301. padding: 0 32rpx 32rpx;
  302. }
  303. .period-section {
  304. display: flex;
  305. justify-content: space-between;
  306. padding: 24rpx;
  307. background: #ffffff;
  308. border-radius: 12rpx;
  309. }
  310. .period-item {
  311. flex: 1;
  312. display: flex;
  313. flex-direction: column;
  314. align-items: center;
  315. }
  316. .period-label {
  317. font-size: 28rpx;
  318. color: #303133;
  319. font-family: 'Source Han Sans CN VF', sans-serif;
  320. font-weight: 700;
  321. margin-bottom: 8rpx;
  322. }
  323. .period-value {
  324. font-size: 24rpx;
  325. color: #999999;
  326. font-family: 'Source Han Sans CN VF', sans-serif;
  327. font-weight: 400;
  328. }
  329. .chart-container {
  330. position: relative;
  331. width: 100%;
  332. height: 400rpx;
  333. border-radius: 12rpx;
  334. overflow: hidden;
  335. }
  336. .chart-canvas {
  337. width: 100%;
  338. height: 100%;
  339. }
  340. </style>