虫情监控

develop
ihzero 2023-08-31 14:30:23 +08:00
parent 4e93cf579a
commit 1ac3644155
6 changed files with 587 additions and 13 deletions

View File

@ -1000,7 +1000,7 @@ export function citydataEdit(data, mode: ErrorMessageMode = 'modal') {
)
}
/**
* @description:
* @description:
*/
export function getWormPhotos(device, params, mode: ErrorMessageMode = 'modal') {
return defHttp.get(
@ -1014,3 +1014,17 @@ export function getWormPhotos(device, params, mode: ErrorMessageMode = 'modal')
},
)
}
/**
* @description:
*/
export function getWormCount(device, params, mode: ErrorMessageMode = 'modal') {
return defHttp.get(
{
url: `/api/devices/${device}/worm-statics`,
params,
},
{
errorMessageMode: mode,
},
)
}

View File

@ -51,14 +51,14 @@ const main: AppRouteModule = {
title: '昆虫性诱监测',
},
},
// {
// path: 'pests',
// name: 'MainPests',
// component: () => import('/@/views/main/pests/index.vue'),
// meta: {
// title: '虫情监测',
// },
// },
{
path: 'pests',
name: 'MainPests',
component: () => import('/@/views/main/pests/index.vue'),
meta: {
title: '虫情监测',
},
},
{
path: 'insecticidal-lamp',
name: 'MainInsecticidalLamp',

View File

@ -222,7 +222,6 @@
const { data, meta } = await getWormPhotos(params.device_id, params)
pageTotal.value = meta.total
list.value = data
console.log(data)
}
onMounted(() => {

View File

@ -0,0 +1,295 @@
<template>
<Form ref="formRef" :model="formState">
<Row :gutter="[16, 16]">
<Col
:xs="{ span: 24 }"
:sm="{ span: 12 }"
:md="{ span: 8 }"
:lg="{ span: 6 }"
:xl="{ span: 6 }"
:xxl="{ span: 4 }"
>
<FormItem label="基地">
<Select
@select="onChange('base_id')"
:fieldNames="{ label: 'name', value: 'id' }"
:options="baseDate"
v-model:value="formState.base_id"
placeholder="请选择基地"
/>
</FormItem>
</Col>
<Col
:xs="{ span: 24 }"
:sm="{ span: 12 }"
:md="{ span: 8 }"
:lg="{ span: 6 }"
:xl="{ span: 6 }"
:xxl="{ span: 4 }"
>
<FormItem label="检测点">
<Select
@select="onChange('device_id')"
placeholder="请选择检测点"
:options="pointDate"
v-model:value="formState.device_id"
/>
</FormItem>
</Col>
<Col
:xs="{ span: 24 }"
:sm="{ span: 12 }"
:md="{ span: 8 }"
:lg="{ span: 6 }"
:xl="{ span: 6 }"
:xxl="{ span: 4 }"
>
<FormItem label="日期">
<RangePicker
:disabledDate="disabledDate"
@change="onChangTime"
v-model:value="formState.time"
/>
</FormItem>
</Col>
<Col
:xs="{ span: 24 }"
:sm="{ span: 12 }"
:md="{ span: 8 }"
:lg="{ span: 6 }"
:xl="{ span: 6 }"
:xxl="{ span: 4 }"
>
<FormItem>
<RadioGroup
@change="onChange('time_interval')"
button-style="solid"
v-model:value="formState.time_interval"
>
<RadioButton value="day">今天</RadioButton>
<RadioButton value="week">近一周</RadioButton>
<RadioButton value="month">近一个月</RadioButton>
</RadioGroup>
</FormItem>
</Col>
</Row>
</Form>
<div class="mt-20px">
<div class="h-450px" ref="pestsCountRef"></div>
</div>
</template>
<script lang="ts" setup>
import dayjs from 'dayjs'
import { useECharts } from '/@/hooks/web/useECharts'
import echarts from '/@/utils/lib/echarts'
import { formatDataByObject, getWeek, getMonth } from '/@/utils/index'
import {
getaGriculturalDevicePoint,
getGriculturalDeviceBasic,
getWormCount,
} from '/@/api/sys/user'
import { Form, FormItem, Select, Row, Col, RangePicker, Radio } from 'ant-design-vue'
import { reactive, ref, onMounted } from 'vue'
const RadioButton = Radio.Button
const RadioGroup = Radio.Group
const pestsCountRef = ref<Ref<HTMLDivElement>>(null)
const { setOptions } = useECharts(pestsCountRef as Ref<HTMLDivElement>)
const disabledDate = (current) => {
return current && current > dayjs().endOf('day')
}
const formState = reactive({
base_id: undefined, //
device_id: undefined, //
time: undefined, //
time_interval: 'week',
})
const statisData = ref<any>({})
const baseDate = ref<any>([])
const pointDate = ref<any>([])
const getBase = async () => {
const res = await getGriculturalDeviceBasic({ device_type: 5 })
if (res.length == 0) return
baseDate.value = res
if (!formState.base_id) formState.base_id = res?.[0]?.id ?? undefined
getPoint()
}
const onChangTime = (e) => {
if (e === null) formState.time_interval = 'day'
else formState.time_interval = ''
getPoint()
}
const onChange = (e: string | undefined) => {
if (e === 'base_id') formState.device_id = undefined
if (e === 'time') formState.time_interval = ''
if (e === 'time_interval') {
formState.time = undefined
return getDate()
}
getPoint()
}
//
const getPoint = async () => {
if (baseDate.value.length == 0) return
const res = await getaGriculturalDevicePoint({
device_type: 5,
agricultural_basic: formState.base_id,
})
pointDate.value = formatDataByObject(res)
if (!formState.device_id) formState.device_id = pointDate.value?.[0]?.value ?? undefined
getDate()
}
//
const getDate = async () => {
const params = {
device_id: formState.device_id,
start_time: '',
end_time: '',
}
if (formState.time) {
params.start_time = dayjs(formState.time?.[0]).format('YYYY-MM-DD')
params.end_time = dayjs(formState.time?.[1]).format('YYYY-MM-DD')
}
if (formState.time_interval === 'week') {
const { WeekStartDate, WeekEndDate } = getWeek()
params.start_time = WeekStartDate
params.end_time = WeekEndDate
} else if (formState.time_interval === 'month') {
const { MonthStartDate, MonthEndDate } = getMonth()
params.start_time = MonthStartDate
params.end_time = MonthEndDate
} else if (formState.time_interval === 'day') {
params.start_time = dayjs().endOf('day').format('YYYY-MM-DD')
params.end_time = dayjs().endOf('day').format('YYYY-MM-DD')
}
if (params.device_id == null) return (statisData.value = {})
console.log(params)
const res = await getWormCount(params.device_id, params)
statisData.value = res
chartsInit()
}
function chartsInit() {
const xAxis = []
const data = []
Object.keys(statisData.value ?? {}).forEach((key) => {
xAxis.push(key)
data.push(statisData.value[key])
})
setOptions({
tooltip: {
trigger: 'axis',
axisPointer: {
lineStyle: {
width: 1,
color: '#019680',
},
},
},
grid: {
left: '2%',
right: '4%',
bottom: '4%',
top: '16%',
containLabel: true,
},
xAxis: {
type: 'category',
data: xAxis,
axisLine: {
lineStyle: {
color: 'rgba(255, 255, 255, 0.1)',
},
},
axisLabel: {
textStyle: {
color: '#6F8290',
},
},
},
yAxis: {
type: 'value',
axisLine: {
show: false,
lineStyle: {
color: 'white',
},
},
splitLine: {
show: true,
lineStyle: {
color: 'rgba(255,255,255,0.3)',
},
},
axisLabel: {
textStyle: {
color: '#6F8290',
},
},
},
series: [
{
name: '1',
type: 'bar',
barWidth: '12px',
itemStyle: {
normal: {
color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
{
offset: 0,
color: 'rgba(166, 233, 215, 1)',
},
{
offset: 1,
color: 'rgba(72, 151, 94, 0)',
},
]),
barBorderRadius: 12,
},
},
data: data,
},
// {
// name: '2',
// type: 'bar',
// barWidth: '12px',
// itemStyle: {
// normal: {
// color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
// {
// offset: 0,
// color: 'rgba(229, 231, 89, 0.95)',
// },
// {
// offset: 1,
// color: 'rgba(134, 231, 89, 0)',
// },
// ]),
// barBorderRadius: 11,
// },
// },
// data: [400, 500, 500, 500, 500, 400, 200, 100],
// },
],
})
}
onMounted(() => {
getBase()
})
</script>

View File

@ -0,0 +1,230 @@
<template>
<PageWrapper>
<Card>
<Form ref="formRef" :model="formState">
<Row :gutter="[16, 16]">
<Col
:xs="{ span: 24 }"
:sm="{ span: 12 }"
:md="{ span: 8 }"
:lg="{ span: 6 }"
:xl="{ span: 6 }"
:xxl="{ span: 4 }"
>
<FormItem label="基地">
<Select
@select="onChange('base_id')"
:fieldNames="{ label: 'name', value: 'id' }"
:options="baseDate"
v-model:value="formState.base_id"
placeholder="请选择基地"
/>
</FormItem>
</Col>
<Col
:xs="{ span: 24 }"
:sm="{ span: 12 }"
:md="{ span: 8 }"
:lg="{ span: 6 }"
:xl="{ span: 6 }"
:xxl="{ span: 4 }"
>
<FormItem label="检测点">
<Select
@select="onChange('device_id')"
placeholder="请选择检测点"
:options="pointDate"
v-model:value="formState.device_id"
/>
</FormItem>
</Col>
<Col
:xs="{ span: 24 }"
:sm="{ span: 12 }"
:md="{ span: 8 }"
:lg="{ span: 6 }"
:xl="{ span: 6 }"
:xxl="{ span: 4 }"
>
<FormItem label="日期">
<RangePicker
:disabledDate="disabledDate"
@change="onChangTime"
v-model:value="formState.time"
/>
</FormItem>
</Col>
<Col
:xs="{ span: 24 }"
:sm="{ span: 12 }"
:md="{ span: 8 }"
:lg="{ span: 6 }"
:xl="{ span: 6 }"
:xxl="{ span: 4 }"
>
<FormItem>
<RadioGroup
@change="onChange('time_interval')"
button-style="solid"
v-model:value="formState.time_interval"
>
<RadioButton value="day">今天</RadioButton>
<RadioButton value="week">近一周</RadioButton>
<RadioButton value="month">近一个月</RadioButton>
</RadioGroup>
</FormItem>
</Col>
</Row>
</Form>
<List
:grid="{ gutter: 16, xs: 1, sm: 2, md: 2, lg: 3, xl: 4, xxl: 5, column: 8 }"
:data-source="list"
>
<template #renderItem="{ item }">
<List-item>
<Card :hoverable="true" class="card" :bodyStyle="{ padding: 0 }">
<div>
<a-image :src="item.url" />
</div>
<div class="text-gray-500 px-5 py-3"> 时间 {{ item.time }} </div>
</Card>
</List-item>
</template>
</List>
<div class="text-right">
<pagination
size="small"
v-model:current="pageCurrent"
v-model:page-size="pageSize"
:total="pageTotal"
show-less-items
showSizeChanger
:pageSizeOptions="['8']"
:show-total="(total) => `共 ${total} 条数据`"
@change="getData"
/>
</div>
</Card>
</PageWrapper>
</template>
<script lang="ts" setup>
import dayjs from 'dayjs'
import { formatDataByObject, getWeek, getMonth } from '/@/utils/index'
import {
getaGriculturalDevicePoint,
getGriculturalDeviceBasic,
getWormPhotos,
} from '/@/api/sys/user'
import { PageWrapper } from '/@/components/Page'
import {
Card,
Form,
FormItem,
Select,
Row,
Col,
RangePicker,
Radio,
List,
Image,
Pagination,
} from 'ant-design-vue'
import { reactive, ref, onMounted } from 'vue'
const RadioButton = Radio.Button
const RadioGroup = Radio.Group
const ListItem = List.Item
const AImage = Image
const disabledDate = (current) => {
return current && current > dayjs().endOf('day')
}
const formState = reactive({
base_id: undefined, //
device_id: undefined, //
time: undefined, //
time_interval: 'day',
})
const pageCurrent = ref(1)
const pageTotal = ref(0)
const pageSize = ref(20)
const baseDate = ref<any>([])
const pointDate = ref<any>([])
const list = ref<any>([])
const getBase = async () => {
const res = await getGriculturalDeviceBasic({ device_type: 5 })
if (res.length == 0) return
baseDate.value = res
if (!formState.base_id) formState.base_id = res?.[0]?.id ?? undefined
getPoint()
}
const onChangTime = (e) => {
if (e === null) formState.time_interval = 'day'
else formState.time_interval = ''
getPoint()
}
const onChange = (e: string | undefined) => {
if (e === 'base_id') formState.device_id = undefined
if (e === 'time') formState.time_interval = ''
if (e === 'time_interval') {
formState.time = undefined
return getData()
}
getPoint()
}
//
const getPoint = async () => {
if (baseDate.value.length == 0) return
const res = await getaGriculturalDevicePoint({
device_type: 5,
agricultural_basic: formState.base_id,
})
pointDate.value = formatDataByObject(res)
if (!formState.device_id) formState.device_id = pointDate.value?.[0]?.value ?? undefined
getData()
}
//
const getData = async () => {
const params = {
per_page: pageSize.value,
page: pageCurrent.value,
device_id: formState.device_id,
start_time: '',
end_time: '',
}
if (formState.time) {
params.start_time = dayjs(formState.time?.[0]).format('YYYY-MM-DD')
params.end_time = dayjs(formState.time?.[1]).format('YYYY-MM-DD')
}
if (formState.time_interval === 'week') {
const { WeekStartDate, WeekEndDate } = getWeek()
params.start_time = WeekStartDate
params.end_time = WeekEndDate
} else if (formState.time_interval === 'month') {
const { MonthStartDate, MonthEndDate } = getMonth()
params.start_time = MonthStartDate
params.end_time = MonthEndDate
} else if (formState.time_interval === 'day') {
params.start_time = dayjs().endOf('day').format('YYYY-MM-DD')
params.end_time = dayjs().endOf('day').format('YYYY-MM-DD')
}
if (params.device_id == null) return (list.value = [])
const { data, meta } = await getWormPhotos(params.device_id, params)
pageTotal.value = meta.total
list.value = data
}
onMounted(() => {
getBase()
})
</script>

View File

@ -1,9 +1,45 @@
<template>
<PageWrapper>
<Card>虫情监测</Card>
<Card>
<tabs :animated="false">
<template v-for="item in achieveList" :key="item.key">
<tab-pane>
<template #tab>
<span> {{ item.name }}</span>
</template>
<component :is="item.component" />
</tab-pane>
</template>
</tabs>
</Card>
</PageWrapper>
</template>
<script setup lang="ts">
import { Card } from 'ant-design-vue'
<script lang="ts" setup>
import { Card, Tabs } from 'ant-design-vue'
import { PageWrapper } from '/@/components/Page'
import CountChart from './components/CountChart.vue'
import Images from './components/Images.vue'
// import { ref } from 'vue'
const TabPane = Tabs.TabPane
export interface TabItem {
key: string
name: string
component: any
iconComponent: string
}
const achieveList: TabItem[] = [
{
key: '1',
name: '虫情统计',
component: CountChart,
iconComponent: 'VideoCameraOutlined',
},
{
key: '2',
name: '虫情图片',
component: Images,
iconComponent: 'PlayCircleOutlined',
},
]
</script>