| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569 |
- <template>
- <view class="rodent-analysis">
- <!-- 活动节律分析 -->
- <view class="analysis-card">
- <view class="analysis-card__header">
- <view class="analysis-card__title">活动节律分析</view>
- <view class="analysis-card__extra">
- <text class="peak-label">活跃高峰</text>
- <text class="peak-value">{{ peakRange }}</text>
- </view>
- </view>
- <view class="chart-legend">
- <view class="chart-legend__dot chart-legend__dot--bar"></view>
- <text class="chart-legend__text">鼠害数量</text>
- </view>
- <view class="chart-wrap chart-wrap--rhythm">
- <qiun-data-charts
- type="column"
- :chartData="rhythmChart"
- :opts="rhythmOpts"
- :reshow="active"
- :canvas2d="true"
- :inScrollView="true"
- :ontouch="true"
- />
- </view>
- </view>
- <!-- 群落结构分析 -->
- <view class="analysis-card">
- <view class="analysis-card__header">
- <view class="analysis-card__title">群落结构分析</view>
- </view>
- <view class="community-content">
- <view class="chart-wrap chart-wrap--ring">
- <qiun-data-charts
- type="ring"
- :chartData="communityChart"
- :opts="communityOpts"
- :reshow="active"
- :canvas2d="true"
- :inScrollView="true"
- :ontouch="true"
- />
- </view>
- <view class="community-total">
- <text>总鼠害数量</text>
- <text class="total-value">{{ totalCount }}
- <text class="unit">只</text>
- </text>
- </view>
- <view class="community-list">
- <view
- class="community-item"
- v-for="(item, index) in communityList"
- :key="index"
- >
- <view class="community-item__dot" :style="{ background: item.color }"></view>
- <view class="community-item__name">{{ item.name }}</view>
- <view class="community-item__count">{{ item.count }}只</view>
- <view class="community-item__percent">{{ item.percent }}%</view>
- </view>
- </view>
- </view>
- </view>
- <!-- 鼠情发生量与气象关系 -->
- <view class="analysis-card">
- <view class="analysis-card__header">
- <view class="analysis-card__title">鼠情发生量与气象关系</view>
- <view class="range-tabs">
- <view
- class="range-tab"
- :class="{ active: weatherRange === 'week' }"
- @click="switchRange('week')"
- >周</view>
- <view
- class="range-tab"
- :class="{ active: weatherRange === 'month' }"
- @click="switchRange('month')"
- >月</view>
- <view
- class="range-tab"
- :class="{ active: weatherRange === 'year' }"
- @click="switchRange('year')"
- >年</view>
- </view>
- </view>
- <view class="chart-wrap chart-wrap--weather">
- <qiun-data-charts
- type="mix"
- :chartData="weatherChart"
- :opts="weatherOpts"
- :reshow="active"
- :canvas2d="true"
- :inScrollView="true"
- :ontouch="true"
- />
- </view>
- </view>
- </view>
- </template>
- <script>
- // 鼠情发生量与气象关系 mock 数据
- const WEATHER_MOCK = {
- month: {
- categories: ['8-1','8-16','8-20','8-29','9-1','9-28','10-1','10-28','11-1','11-28','12-9'],
- pest: [12, 18, 25, 15, 32, 28, 40, 35, 22, 45, 38],
- temp: [28, 30, 26, 22, 25, 18, 15, 20, 24, 12, 8],
- humidity: [45, 42, 48, 40, 38, 44, 46, 42, 37, 48, 43]
- },
- week: {
- categories: ['8-12','8-13','8-14','8-15','8-16','8-17','8-18'],
- pest: [8, 15, 22, 12, 28, 35, 20],
- temp: [26, 28, 30, 29, 27, 25, 26],
- humidity: [40, 36, 32, 45, 48, 46, 42]
- },
- year: {
- categories: ['1月','2月','3月','4月','5月','6月','7月','8月','9月','10月','11月','12月'],
- pest: [35, 28, 22, 18, 15, 20, 32, 45, 48, 42, 38, 30],
- temp: [5, 8, 14, 20, 26, 30, 32, 31, 26, 20, 12, 6],
- humidity: [30, 34, 40, 44, 48, 46, 48, 46, 42, 40, 36, 32]
- }
- };
- function buildWeatherChart(range) {
- const mock = WEATHER_MOCK[range];
- return {
- categories: mock.categories,
- series: [
- { name: '鼠害总数', type: 'area', style: 'curve', index: 0, data: mock.pest },
- { name: '温度', type: 'line', style: 'curve', index: 1, data: mock.temp },
- { name: '湿度', type: 'line', style: 'curve', index: 1, data: mock.humidity }
- ]
- };
- }
- export default {
- name: 'RodentAnalysis',
- props: {
- // 当前 tab 是否激活(tab 用 v-show 切换时,隐藏状态下 canvas 容器测量为 0,需激活后重绘)
- active: {
- type: Boolean,
- default: true
- }
- },
- data() {
- return {
- // 活动节律(mock)
- peakRange: '22:00',
- rhythmChart: null,
- rhythmOpts: {
- color: ['#FFC107'],
- dataLabel: false,
- // 背景轨道系列会进 uCharts 图例,改用卡片内自定义图例(见 template 的 chart-legend)
- legend: { show: false },
- xAxis: {
- disableGrid: true,
- fontSize: 9,
- fontColor: '#656565'
- },
- yAxis: {
- showTitle: true,
- disableGrid: false,
- gridType: 'dash',
- gridColor: '#EEEEEE',
- data: [{
- title: '数量:只',
- titleFontSize: 10,
- titleFontColor: '#656565',
- titleOffsetX: -10,
- titleOffsetY: -6,
- min: 0,
- max: 100,
- splitNumber: 5,
- tofix: 0
- }]
- },
- extra: {
- column: {
- // 温度计模式:系列[0]绘制为整柱浅色背景轨道,系列[1]叠加实际数据柱
- type: 'meter',
- meterBorder: 0,
- meterFillColor: '#d6dbed66',
- width: 14,
- barBorderCircle: false,
- linearType: 'none'
- }
- }
- },
- // 群落结构(mock)
- communityList: [
- { name: '褐家鼠', count: 91, percent: 25, color: '#E53935' },
- { name: '黄胸鼠', count: 91, percent: 25, color: '#FFC107' },
- { name: '小家鼠', count: 91, percent: 25, color: '#2196F3' },
- { name: '黑线姬鼠', count: 91, percent: 25, color: '#9E9E9E' }
- ],
- communityChart: null,
- communityOpts: {
- color: ['#E53935', '#FFC107', '#2196F3', '#9E9E9E'],
- legend: { show: false },
- // 环形图:中心显示当前占比最高的物种
- dataLabel: false,
- title: {
- name: '25%',
- fontSize: 16,
- color: '#E53935',
- offsetY: -6
- },
- subtitle: {
- name: '褐家鼠',
- fontSize: 10,
- color: '#333333',
- offsetY: 8
- },
- extra: {
- ring: {
- // 环粗细约为半径的三分之一
- ringWidth: 16,
- offsetAngle: 0,
- // 去掉分段之间的白色分隔线(qiun-data-charts 的 ring 默认 border: true)
- border: false,
- // 关闭点击分段时外扩+半透明的高亮效果(默认 activeRadius: 10 / activeOpacity: 0.5)
- activeRadius: 5,
- activeOpacity: 1
- }
- }
- },
- // 总量(mock)
- totalCount: 126,
- weekOverWeek: '+12.8%',
- alarmThreshold: 100,
- barMax: 130,
- // 鼠情与气象(mock)
- weatherRange: 'month',
- weatherChart: null,
- weatherOpts: {
- color: ['#FF5252', '#FFC107', '#2196F3'],
- dataLabel: false,
- legend: {
- show: true,
- position: 'bottom',
- fontSize: 10,
- fontColor: '#656565',
- itemGap: 15,
- lineHeight: 15
- },
- xAxis: {
- disableGrid: true,
- fontSize: 9,
- fontColor: '#656565'
- },
- yAxis: {
- showTitle: true,
- disableGrid: false,
- gridType: 'dash',
- gridColor: '#EEEEEE',
- data: [
- {
- title: '鼠害数量:只',
- titleFontSize: 10,
- titleFontColor: '#656565',
- titleOffsetX: -10,
- titleOffsetY: -6,
- position: 'left',
- min: 0,
- splitNumber: 5,
- tofix: 0
- },
- {
- title: '湿度:%',
- titleFontSize: 10,
- titleFontColor: '#656565',
- titleOffsetX: 10,
- titleOffsetY: -6,
- position: 'right',
- min: 0,
- splitNumber: 5,
- tofix: 0
- }
- ]
- },
- extra: {
- mix: {
- line: { width: 2 },
- area: { opacity: 0.15, gradient: true }
- },
- tooltip: {
- showBox: true
- }
- }
- }
- };
- },
- computed: {
- // 进度条填充:总量/量程
- fillPercent() {
- return Math.min((this.totalCount / this.barMax) * 100, 100);
- },
- // 告警阈值标记位置
- thresholdPercent() {
- return (this.alarmThreshold / this.barMax) * 100;
- }
- },
- mounted() {
- // 延迟赋值图表数据:等页面布局稳定后再初始化 canvas,避免容器尺寸测量为 0
- setTimeout(() => {
- this.initChartData();
- }, 300);
- },
- methods: {
- initChartData() {
- this.rhythmChart = {
- categories: ['00:00','02:00','04:00','06:00','08:00','10:00','12:00','14:00','16:00','18:00','20:00','22:00','24:00'],
- series: [
- // 背景轨道:满量程高度(meter 模式下系列[0]用 meterFillColor 填充)
- { name: '背景', color: '#D6DBED', data: Array(13).fill(100) },
- { name: '鼠害数量', color: '#FFC107', data: [42, 58, 66, 48, 22, 12, 8, 15, 28, 45, 95, 88, 52] }
- ]
- };
- this.communityChart = {
- series: [{
- data: [
- { name: '褐家鼠', value: 91 },
- { name: '黄胸鼠', value: 91 },
- { name: '小家鼠', value: 91 },
- { name: '黑线姬鼠', value: 91 }
- ]
- }]
- };
- this.weatherChart = buildWeatherChart(this.weatherRange);
- },
- switchRange(range) {
- if (this.weatherRange === range) return;
- this.weatherRange = range;
- this.weatherChart = buildWeatherChart(range);
- }
- }
- };
- </script>
- <style lang="scss" scoped>
- .rodent-analysis {
- width: 100%;
- }
- .analysis-card {
- width: 100%;
- padding: 32rpx;
- box-sizing: border-box;
- background: #fff;
- border-radius: 16rpx;
- margin-bottom: 24rpx;
- &:last-child {
- margin-bottom: 0;
- }
- }
- .analysis-card__header {
- display: flex;
- align-items: center;
- justify-content: space-between;
- margin-bottom: 20rpx;
- }
- .analysis-card__title {
- position: relative;
- font-size: 32rpx;
- color: #042118;
- font-family: 'Source Han Sans CN VF';
- font-weight: 700;
- }
- .analysis-card__extra {
- display: flex;
- align-items: center;
- .peak-label {
- font-size: 24rpx;
- color: #656565;
- font-family: 'Source Han Sans CN VF';
- margin-right: 8rpx;
- }
- .peak-value {
- font-size: 24rpx;
- color: #E53935;
- font-family: 'Source Han Sans CN VF';
- font-weight: 700;
- }
- }
- .chart-legend {
- display: flex;
- align-items: center;
- justify-content: flex-end;
- margin-bottom:-20rpx;
- .chart-legend__dot--bar {
- width: 16rpx;
- height: 16rpx;
- border-radius: 4rpx;
- background: #FFC107;
- margin-right: 8rpx;
- }
- .chart-legend__text {
- font-size: 20rpx;
- color: #656565;
- font-family: 'Source Han Sans CN VF';
- }
- }
- .chart-wrap {
- position: relative;
- width: 100%;
- }
- .chart-wrap--rhythm {
- height: 400rpx;
- }
- .chart-wrap--ring {
- width: 360rpx;
- height: 320rpx;
- flex-shrink: 0;
- }
- .chart-wrap--weather {
- height: 420rpx;
- }
- // 群落结构:上下布局,环形图在上,图例列表在下
- .community-content {
- display: flex;
- flex-direction: column;
- align-items: center;
- }
- .community-total{
- width: 90%;
- display: flex;
- align-items: center;
- justify-content: space-between;
- font-family: 'Source Han Sans CN VF';
- .total-value {
- font-size: 32rpx;
- color: #042118;
- font-weight: 700;
- line-height: 1;
- }
- .unit {
- font-size: 28rpx;
- font-weight: 400;
- color:#999999;
- margin-left: 8rpx;
- }
- }
- .community-list {
- width: 90%;
- margin-top: 16rpx;
- }
- .community-item {
- display: flex;
- align-items: center;
- padding: 12rpx 0;
- font-family: 'Source Han Sans CN VF';
- .community-item__dot {
- width: 16rpx;
- height: 16rpx;
- border-radius: 4rpx;
- margin-right: 12rpx;
- flex-shrink: 0;
- }
- .community-item__name {
- flex: 1;
- font-size: 26rpx;
- color: #042118;
- }
- .community-item__count {
- font-size: 26rpx;
- color: #042118;
- margin-right: 16rpx;
- }
- .community-item__percent {
- font-size: 26rpx;
- color: #656565;
- width: 72rpx;
- text-align: right;
- }
- }
- // 总量害虫数量
- .total-main {
- display: flex;
- align-items: flex-end;
- margin-bottom: 24rpx;
- font-family: 'Source Han Sans CN VF';
- .total-value {
- font-size: 56rpx;
- color: #042118;
- font-weight: 700;
- line-height: 1;
- .total-unit {
- font-size: 28rpx;
- font-weight: 500;
- margin-left: 8rpx;
- }
- }
- .total-compare {
- font-size: 24rpx;
- color: #656565;
- margin-left: 24rpx;
- padding-bottom: 4rpx;
- .total-compare__value {
- color: #E53935;
- font-weight: 700;
- }
- }
- }
- .total-bar {
- .total-bar__track {
- position: relative;
- height: 16rpx;
- border-radius: 8rpx;
- background: #F1F4F8;
- overflow: visible;
- }
- .total-bar__fill {
- height: 100%;
- border-radius: 8rpx;
- background: #0BBC58;
- }
- .total-bar__marker {
- position: absolute;
- top: -6rpx;
- width: 4rpx;
- height: 28rpx;
- border-radius: 2rpx;
- background: #E53935;
- transform: translateX(-50%);
- }
- .total-bar__scale {
- display: flex;
- justify-content: space-between;
- margin-top: 8rpx;
- font-size: 22rpx;
- color: #999999;
- font-family: 'Source Han Sans CN VF';
- }
- }
- // 周/月/年切换
- .range-tabs {
- display: flex;
- align-items: center;
- .range-tab {
- width: 64rpx;
- height: 48rpx;
- line-height: 44rpx;
- text-align: center;
- font-size: 24rpx;
- color: #042118;
- font-family: 'Source Han Sans CN VF';
- background: #fff;
- border: 2rpx solid #E4E7ED;
- box-sizing: border-box;
- &:first-child {
- border-radius: 8rpx 0 0 8rpx;
- }
- &:last-child {
- border-radius: 0 8rpx 8rpx 0;
- }
- &.active {
- background: #0BBC58;
- border-color: #0BBC58;
- color: #fff;
- font-weight: 700;
- }
- }
- }
- </style>
|