新增功能
parent
9c4d853f38
commit
c7a70e04ac
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 5.4 KiB |
@ -0,0 +1 @@
|
|||||||
|
<?xml version="1.0" standalone="no"?><!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"><svg t="1757476762111" class="icon" viewBox="0 0 1026 1024" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="4628" xmlns:xlink="http://www.w3.org/1999/xlink" width="128.25" height="128"><path d="M514.87164688 506.25670727m-502.53814919 0a502.53814918 502.53814918 0 1 0 1005.07629734 0 502.53814918 502.53814918 0 1 0-1005.07629734 0Z" fill="#3674AD" p-id="4629"></path><path d="M397.13413721 572.30457828c-25.84481881 20.1015261-43.07469803 48.81799179-43.07469803 83.2777502 0 43.07469803 25.84481881 80.40610333 66.047871 97.63598255 14.35823233 5.74329273 31.58811258 11.48658648 48.81799179 11.48658648l-71.79116476-192.40031923z" fill="#FFFFFF" p-id="4630"></path><path d="M503.3850604 891.05734679c-134.96738888 0-244.08995791-109.12256903-244.08995791-244.08995791 0-126.35244927 134.96738888-321.62441539 218.24513908-436.49027819l25.84481883-37.33140529 22.97317193 34.45975841c34.45975843 48.81799179 86.14939709 126.35244927 129.22409615 201.01525989 8.6149396 14.35823233 2.87164688 31.58811258-11.48658648 40.20305218-14.35823233 8.6149396-31.58811258 2.87164688-40.20305218-11.48658649-34.45975843-57.43293139-71.79116372-114.86586279-103.3792763-163.68385457-74.66281061 106.25092318-186.65702652 275.67807048-186.65702652 376.18569991 0 103.3792763 83.27775022 186.65702652 186.65702652 186.65702754 40.20305218 0 80.40610333-11.48658648 109.12257005-34.45975945 11.48658648-8.6149396 31.58811258-5.74329273 40.20305116 5.74329376 8.6149396 11.48658648 5.74329273 31.58811258-5.74329273 40.20305115-37.33140531 25.84481881-89.02104397 43.07469803-140.7106816 43.07469906z" fill="#FFFFFF" p-id="4631"></path><path d="M543.58811258 583.79116372c0-17.22987921 5.74329273-31.58811258 14.35823233-43.07469802s22.97317297-17.22987921 40.20305218-17.22987922 28.7164657 5.74329273 37.33140531 14.35823233 14.35823233 22.97317297 14.35823233 40.20305219-5.74329273 31.58811258-14.35823233 43.07469803-22.97317297 17.22987921-40.20305218 17.22988024c-14.35823233 0-28.7164657-5.74329273-37.33140531-14.35823336s-14.35823233-25.84481881-14.35823233-40.20305219z m28.7164657-2.87164584c0 20.1015261 8.6149396 28.7164657 22.97317194 28.71646569s22.97317297-11.48658648 22.97317296-31.58811257-8.6149396-31.58811258-22.97317296-31.58811257c-14.35823233 2.87164688-22.97317297 14.35823233-22.97317194 34.45975945z m178.0420869-54.56128555l-140.71068161 218.2451391h-34.45975945l140.71068161-218.2451391h34.45975945z m-71.79116476 166.55550146c0-17.22987921 5.74329273-31.58811258 14.35823337-43.07469906s22.97317297-17.22987921 40.20305218-17.22987922 28.7164657 5.74329273 37.33140531 14.35823337 14.35823233 22.97317297 14.35823233 40.20305115-5.74329273 31.58811258-14.35823233 43.07469906-22.97317297 17.22987921-40.20305219 17.22987921c-14.35823233 0-28.7164657-5.74329273-37.3314053-14.35823233-11.48658648-11.48658648-14.35823233-22.97317297-14.35823337-40.20305218z m28.7164657 0c0 20.1015261 8.6149396 31.58811258 22.97317297 31.58811154s22.97317297-11.48658648 22.97317194-31.58811154c0-8.6149396-2.87164688-17.22987921-5.74329273-22.97317297-2.87164688-5.74329273-8.6149396-8.6149396-17.22987921-8.61493961-14.35823233 0-22.97317297 8.6149396-22.97317297 31.58811258z" fill="#FFFFFF" p-id="4632"></path></svg>
|
After Width: | Height: | Size: 3.3 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 14 KiB |
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 7.9 KiB |
@ -1,11 +1,24 @@
|
|||||||
<script name="DeviceList">
|
<!--
|
||||||
|
* @Author: chris
|
||||||
|
* @Date: 2025-09-05 09:39:28
|
||||||
|
* @LastEditors: chris
|
||||||
|
* @LastEditTime: 2025-09-08 09:37:55
|
||||||
|
-->
|
||||||
|
<script setup name="DeviceList">
|
||||||
|
import DeviceFlatList from '@/components/deviceFlatList'
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<el-card class="device-tree-card" title="设备列表">
|
<el-card class="device-tree-card">
|
||||||
设备列表
|
<template #header>
|
||||||
|
<div class="list-header">
|
||||||
|
<span>设备列表</span>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
<device-flat-list />
|
||||||
</el-card>
|
</el-card>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
|
|
||||||
</style>
|
</style>
|
@ -0,0 +1,39 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: chris
|
||||||
|
* @Date: 2025-08-18 09:24:37
|
||||||
|
* @LastEditors: chris
|
||||||
|
* @LastEditTime: 2025-08-18 14:41:04
|
||||||
|
-->
|
||||||
|
<script setup name="DeviceList">
|
||||||
|
const props = defineProps({
|
||||||
|
devices: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['selected'])
|
||||||
|
|
||||||
|
const checkList = ref([]);
|
||||||
|
|
||||||
|
watch(() => checkList, (val) => {
|
||||||
|
emits('selected', val);
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="device-list">
|
||||||
|
<el-card>
|
||||||
|
<template #header>设备列表</template>
|
||||||
|
<el-checkbox-group size="large" v-model="checkList">
|
||||||
|
<el-checkbox v-for="item in props.devices" :label="item.name" :value="item.id" />
|
||||||
|
</el-checkbox-group>
|
||||||
|
</el-card>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
:deep(.el-checkbox-group) {
|
||||||
|
@apply flex flex-col
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,67 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: chris
|
||||||
|
* @Date: 2025-08-18 09:27:23
|
||||||
|
* @LastEditors: chris
|
||||||
|
* @LastEditTime: 2025-08-18 17:18:54
|
||||||
|
-->
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
params: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
deviceId: null,
|
||||||
|
dateRange: []
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['update:params'])
|
||||||
|
|
||||||
|
const queryRef = ref()
|
||||||
|
const queryParams = reactive({...props.params});
|
||||||
|
const pestOpts = ref([])
|
||||||
|
|
||||||
|
watch(() => queryParams, (newVal) => {
|
||||||
|
emits('update:params', newVal)
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => props.params, (newVal) => {
|
||||||
|
Object.assign(queryParams, newVal)
|
||||||
|
})
|
||||||
|
|
||||||
|
function resetQuery() {
|
||||||
|
emits('reset')
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleQuery() {
|
||||||
|
emits('query')
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportData() {
|
||||||
|
emits('export')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-form :model="queryParams" ref="queryRef" :inline="true" label-width="68px">
|
||||||
|
<el-form-item label="创建时间">
|
||||||
|
<el-date-picker
|
||||||
|
style="width: 240px"
|
||||||
|
v-model="queryParams.dateRange"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
></el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button type="warning" icon="Download" @click="exportData">导出</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
@ -0,0 +1,47 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: chris
|
||||||
|
* @Date: 2025-08-20 17:06:41
|
||||||
|
* @LastEditors: chris
|
||||||
|
* @LastEditTime: 2025-08-21 10:47:52
|
||||||
|
-->
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
params: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
pestTypes: []
|
||||||
|
})
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
type: Array,
|
||||||
|
default: () => []
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['update:params'])
|
||||||
|
|
||||||
|
const queryParams = ref({...props.params});
|
||||||
|
|
||||||
|
watch(() => queryParams.value, (newVal) => {
|
||||||
|
emits('update:params', newVal)
|
||||||
|
})
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-row class="chart-action">
|
||||||
|
<el-col :span="12" :offset="18">
|
||||||
|
<el-select v-model="queryParams.pestTypes" placeholder="请选择" style="width: 240px;">
|
||||||
|
<el-option
|
||||||
|
v-for="item in options"
|
||||||
|
multiple
|
||||||
|
:key="item.value"
|
||||||
|
:label="item.label"
|
||||||
|
:value="item.value"
|
||||||
|
/>
|
||||||
|
</el-select>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
@ -0,0 +1,63 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: chris
|
||||||
|
* @Date: 2025-08-18 09:24:26
|
||||||
|
* @LastEditors: chris
|
||||||
|
* @LastEditTime: 2025-09-08 11:35:38
|
||||||
|
-->
|
||||||
|
<script setup name="PestStatistics">
|
||||||
|
import { useSettings } from "@/hooks/useSettings";
|
||||||
|
import DeviceList from './components/DeviceList.vue';
|
||||||
|
import SearchForm from './components/SearchForm.vue';
|
||||||
|
import TrendChart from './components/TrendChart.vue';
|
||||||
|
import ChartAction from "./components/chartAction.vue";
|
||||||
|
import { devices } from './mockData'
|
||||||
|
|
||||||
|
const { hasTags } = useSettings()
|
||||||
|
|
||||||
|
const deviceList = ref(devices);
|
||||||
|
const tableData = ref([]);
|
||||||
|
const queryParams = ref({});
|
||||||
|
|
||||||
|
function getList () {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelect(items) {
|
||||||
|
console.log(items);
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportView() {
|
||||||
|
console.log('导出视图')
|
||||||
|
}
|
||||||
|
|
||||||
|
function resetQuery() {
|
||||||
|
console.log('重置查询')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div :class="['pest-statistics-page', 'page-height', { 'hasTagsView': hasTags }]">
|
||||||
|
<el-row :gutter="40" class="h-100%">
|
||||||
|
<el-col :span="4">
|
||||||
|
<device-list :devices="deviceList" @select="handleSelect"></device-list>
|
||||||
|
</el-col>
|
||||||
|
<el-col :span="20">
|
||||||
|
<search-form v-model:params="queryParams" @reset="resetQuery" @query="getList" @export="exportView" />
|
||||||
|
<chart-action v-model:params="queryParams" :options="options" class="action" />
|
||||||
|
<trend-chart :tableData="tableData" class="chart"/>
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.pest-statistics-page {
|
||||||
|
@apply p-20px
|
||||||
|
}
|
||||||
|
.action {
|
||||||
|
@apply mt-20px;
|
||||||
|
}
|
||||||
|
.chart {
|
||||||
|
@apply h-88% w-100% mt-10px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,10 @@
|
|||||||
|
export const devices = [
|
||||||
|
{
|
||||||
|
id: "1",
|
||||||
|
name: "设备1",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "2",
|
||||||
|
name: "设备2",
|
||||||
|
},
|
||||||
|
];
|
@ -0,0 +1,42 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: chris
|
||||||
|
* @Date: 2025-08-08 16:17:54
|
||||||
|
* @LastEditors: chris
|
||||||
|
* @LastEditTime: 2025-09-09 16:50:46
|
||||||
|
-->
|
||||||
|
<template>
|
||||||
|
<el-table
|
||||||
|
v-loading="loading"
|
||||||
|
:data="dataList"
|
||||||
|
@selection-change="handleSelectionChange"
|
||||||
|
row-key="orchardId"
|
||||||
|
border
|
||||||
|
highlight-current-row
|
||||||
|
style="width: 100%"
|
||||||
|
>
|
||||||
|
<el-table-column type="selection" width="50" align="center" />
|
||||||
|
<el-table-column label="参数名" align="center" prop="name" v-if="columns[0].visible"/>
|
||||||
|
<el-table-column label="数值" align="center" prop="value" v-if="columns[1].visible" :show-overflow-tooltip="true" />
|
||||||
|
<el-table-column label="创建时间" align="center" prop="createTime" v-if="columns[2].visible">
|
||||||
|
<template #default="scope">
|
||||||
|
<span>{{ parseTime(scope.row.createTime) }}</span>
|
||||||
|
</template>
|
||||||
|
</el-table-column>
|
||||||
|
</el-table>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script setup>
|
||||||
|
import { parseTime } from '@/utils/ruoyi'
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
dataList: { type: Array, required: true },
|
||||||
|
loading: { type: Boolean, required: true },
|
||||||
|
columns: { type: Array, required: true }
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['selection-change', 'view', 'update', 'delete'])
|
||||||
|
|
||||||
|
function handleSelectionChange(selection) {
|
||||||
|
emits('selection-change', selection)
|
||||||
|
}
|
||||||
|
</script>
|
@ -0,0 +1,75 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: chris
|
||||||
|
* @Date: 2025-08-18 09:27:23
|
||||||
|
* @LastEditors: chris
|
||||||
|
* @LastEditTime: 2025-09-09 16:54:23
|
||||||
|
-->
|
||||||
|
<script setup>
|
||||||
|
const props = defineProps({
|
||||||
|
params: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ({
|
||||||
|
nodeId: null,
|
||||||
|
dateRange: []
|
||||||
|
})
|
||||||
|
},
|
||||||
|
weatherOptions: {
|
||||||
|
type: Object,
|
||||||
|
default: () => ([])
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const emits = defineEmits(['update:params'])
|
||||||
|
|
||||||
|
const queryRef = ref()
|
||||||
|
const queryParams = reactive({...props.params});
|
||||||
|
|
||||||
|
watch(() => queryParams, (newVal) => {
|
||||||
|
emits('update:params', newVal)
|
||||||
|
})
|
||||||
|
|
||||||
|
watch(() => props.params, (newVal) => {
|
||||||
|
Object.assign(queryParams, newVal)
|
||||||
|
})
|
||||||
|
|
||||||
|
function resetQuery() {
|
||||||
|
emits('reset')
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleQuery() {
|
||||||
|
emits('query')
|
||||||
|
}
|
||||||
|
|
||||||
|
function exportData() {
|
||||||
|
emits('export')
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<el-form :model="queryParams" ref="queryRef" :inline="true" label-width="68px">
|
||||||
|
<el-form-item label="参数" style="width: 260px;">
|
||||||
|
<el-select v-model="queryParams.nodeId" placeholder="请选择参数">
|
||||||
|
<el-option v-for="value in weatherOptions" :key="value.id" :label="value.name" :value="value.id"></el-option>
|
||||||
|
</el-select>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item label="记录时间">
|
||||||
|
<el-date-picker
|
||||||
|
style="width: 300px"
|
||||||
|
v-model="queryParams.dateRange"
|
||||||
|
value-format="YYYY-MM-DD"
|
||||||
|
type="daterange"
|
||||||
|
range-separator="至"
|
||||||
|
start-placeholder="开始日期"
|
||||||
|
end-placeholder="结束日期"
|
||||||
|
></el-date-picker>
|
||||||
|
</el-form-item>
|
||||||
|
<el-form-item>
|
||||||
|
<el-button type="primary" icon="Search" @click="handleQuery">搜索</el-button>
|
||||||
|
<el-button type="warning" icon="Download" @click="exportData">导出</el-button>
|
||||||
|
<el-button icon="Refresh" @click="resetQuery">重置</el-button>
|
||||||
|
</el-form-item>
|
||||||
|
</el-form>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
</style>
|
@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* @Author: chris
|
||||||
|
* @Date: 2025-09-05 10:12:41
|
||||||
|
* @LastEditors: chris
|
||||||
|
* @LastEditTime: 2025-09-09 16:17:59
|
||||||
|
*/
|
||||||
|
// 列配置
|
||||||
|
export const columnsConfig = [
|
||||||
|
{ key: 0, label: "参数名称", visible: true },
|
||||||
|
{ key: 1, label: "数值", visible: true },
|
||||||
|
{ key: 2, label: "记录时间", visible: true },
|
||||||
|
];
|
||||||
|
|
||||||
|
// 状态颜色映射
|
||||||
|
export const statusColorMap = {
|
||||||
|
0: "success",
|
||||||
|
1: "danger",
|
||||||
|
};
|
@ -0,0 +1,39 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: chris
|
||||||
|
* @Date: 2025-09-11 17:11:16
|
||||||
|
* @LastEditors: chris
|
||||||
|
* @LastEditTime: 2025-09-11 17:21:28
|
||||||
|
-->
|
||||||
|
<script setup>
|
||||||
|
import HistoryTable from './components/HistoryTable.vue';
|
||||||
|
import SearchForm from './components/SearchForm.vue';
|
||||||
|
import { columnsConfig } from './config';
|
||||||
|
import { useSettings } from '@/hooks/useSettings';
|
||||||
|
|
||||||
|
const { hasTags } = useSettings();
|
||||||
|
|
||||||
|
const historyList = ref([]);
|
||||||
|
const queryParams = ref({});
|
||||||
|
|
||||||
|
getHistoryList();
|
||||||
|
|
||||||
|
function getHistoryList() {
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelectionChange(selection) {
|
||||||
|
console.log(selection)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div :class="['weather-history-page', 'page-height', { 'hasTagsView': hasTags }]">
|
||||||
|
<search-form v-model:params="queryParams" class="mb-12px" />
|
||||||
|
<history-table :dataList="historyList" :columns="columnsConfig" @selection-change="handleSelectionChange" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.weather-history-page {
|
||||||
|
@apply p-20px;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,227 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: chris
|
||||||
|
* @Date: 2025-09-09 15:30:24
|
||||||
|
* @LastEditors: chris
|
||||||
|
* @LastEditTime: 2025-09-11 17:27:00
|
||||||
|
-->
|
||||||
|
<script setup>
|
||||||
|
import weatherImg from '@/assets/images/devices/weather.png'
|
||||||
|
|
||||||
|
const testDataList = [
|
||||||
|
{
|
||||||
|
id: 1,
|
||||||
|
title: '温度',
|
||||||
|
type: 'temperature',
|
||||||
|
value: '25',
|
||||||
|
icon: 'temperature2',
|
||||||
|
color: '#FF6B6B',
|
||||||
|
unit: '°C',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
title: '湿度',
|
||||||
|
type: 'humidity',
|
||||||
|
value: '60',
|
||||||
|
icon: 'humidity',
|
||||||
|
color: '#4ECDC4',
|
||||||
|
unit: '%',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 3,
|
||||||
|
title: '光照',
|
||||||
|
type: 'light',
|
||||||
|
value: '10000',
|
||||||
|
icon: 'light',
|
||||||
|
color: '#FFD166',
|
||||||
|
unit: 'lux',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 4,
|
||||||
|
title: '降雨量',
|
||||||
|
type: 'rainfall',
|
||||||
|
value: '10',
|
||||||
|
icon: 'rain',
|
||||||
|
color: '#6A0572',
|
||||||
|
unit: 'mm',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 5,
|
||||||
|
title: '风向',
|
||||||
|
type: 'windDirection',
|
||||||
|
value: '东南风',
|
||||||
|
icon: 'wind',
|
||||||
|
color: '#1A535C',
|
||||||
|
unit: '°',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 6,
|
||||||
|
title: '风速',
|
||||||
|
type: 'windSpeed',
|
||||||
|
value: '2',
|
||||||
|
icon: 'windPower',
|
||||||
|
color: '#77DD77',
|
||||||
|
unit: 'm/s',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: 7,
|
||||||
|
title: '气压',
|
||||||
|
type: 'pressure',
|
||||||
|
value: '1013',
|
||||||
|
icon: 'hpa',
|
||||||
|
color: '#845EC2',
|
||||||
|
unit: 'hPa',
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
const emits = defineEmits([ 'select' ])
|
||||||
|
|
||||||
|
function handleSelect(item) {
|
||||||
|
console.log('Selected item:', item);
|
||||||
|
emits('select', item)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="weather-dashboard">
|
||||||
|
<!-- 顶部标题区域 -->
|
||||||
|
<div class="dashboard-header">
|
||||||
|
<h2 class="dashboard-title">气象监测数据</h2>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 数据卡片区域 -->
|
||||||
|
<div class="data-cards">
|
||||||
|
<div
|
||||||
|
v-for="item in testDataList"
|
||||||
|
:key="item.id"
|
||||||
|
class="data-card"
|
||||||
|
:style="{ '--card-color': item.color }"
|
||||||
|
@click="handleSelect(item)"
|
||||||
|
>
|
||||||
|
<div class="card-icon-wrapper">
|
||||||
|
<svg-icon :icon-class="item.icon" class="card-icon"></svg-icon>
|
||||||
|
</div>
|
||||||
|
<div class="card-info">
|
||||||
|
<div class="card-label">{{ item.title }}</div>
|
||||||
|
<div class="card-value-container">
|
||||||
|
<span class="card-value">{{ item.value }}</span>
|
||||||
|
<span v-if="item.unit" class="card-unit">{{ item.unit }}</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- 图片区域 -->
|
||||||
|
<div class="weather-photo">
|
||||||
|
<el-image
|
||||||
|
:src="weatherImg"
|
||||||
|
fit="contain"
|
||||||
|
class="weather-photo-img"
|
||||||
|
lazy
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
// 主题颜色变量
|
||||||
|
$bg-primary: #ffffff;
|
||||||
|
$bg-secondary: #f5f7fa;
|
||||||
|
$text-primary: #333333;
|
||||||
|
$text-secondary: #666666;
|
||||||
|
$shadow-normal: 0 2px 12px rgba(0, 0, 0, 0.05);
|
||||||
|
$transition-base: all 0.3s ease;
|
||||||
|
|
||||||
|
.weather-dashboard {
|
||||||
|
@apply flex flex-col justify-center item-center w-full h-full overflow-hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 顶部标题区域
|
||||||
|
.dashboard-header {
|
||||||
|
@apply text-center mb-24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.dashboard-title {
|
||||||
|
@apply text-24px font-weight-600 m-0 tracking-[0.5px];
|
||||||
|
color: $text-primary;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 图片区域样式
|
||||||
|
.weather-photo {
|
||||||
|
@apply w-full h-480px rounded-8px overflow-hidden;
|
||||||
|
box-shadow: $shadow-normal;
|
||||||
|
transition: $transition-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-photo:hover {
|
||||||
|
@apply translate-y-[-2px] shadow-[0_4px_16px_rgba(0,0,0,0.1)];
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-photo-img {
|
||||||
|
@apply h-full w-full transition-[transform] duration-500 ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.weather-photo-img:hover {
|
||||||
|
transform: scale(1.03);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据卡片网格布局
|
||||||
|
.data-cards {
|
||||||
|
@apply grid grid-cols-[repeat(auto-fill,minmax(160px,1fr))] gap-16px flex-1 mb-24px;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 数据卡片样式 - 横向排列
|
||||||
|
.data-card {
|
||||||
|
@apply rounded-8px p-16px flex items-center relative border-[1px] border-style-solid border-[transparent] min-h-[100px] cursor-pointer;
|
||||||
|
background: $bg-secondary;
|
||||||
|
transition: $transition-base;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-3px);
|
||||||
|
box-shadow: 0 6px 16px rgba(0, 0, 0, 0.08);
|
||||||
|
border-color: var(--card-color);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 背景光效点缀
|
||||||
|
&::before {
|
||||||
|
@apply content-[''] absolute top-[-20px] right-[-20px] w-60px h-60px rounded-[50%] bg-[radial-gradient(circle,rgba(var(--card-color-rgb),0.1)_0%,transparent_70%)] z-0;
|
||||||
|
background: radial-gradient(circle, rgba(var(--card-color-rgb), 0.1) 0%, transparent 70%);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 卡片图标样式
|
||||||
|
.card-icon-wrapper {
|
||||||
|
@apply w-48px h-48px rounded-50% flex items-center justify-center flex-shrink-0 mr-16px bg-[rgba(var(--card-color-rgb),0.1)] z-1;
|
||||||
|
transition: $transition-base;
|
||||||
|
}
|
||||||
|
|
||||||
|
.data-card:hover .card-icon-wrapper {
|
||||||
|
@apply bg-[rgba(var(--card-color-rgb),0.15)] transform scale-105;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-icon {
|
||||||
|
@apply w-36px h-36px color-[var(--card-color)];
|
||||||
|
}
|
||||||
|
|
||||||
|
// 卡片信息样式
|
||||||
|
.card-info {
|
||||||
|
@apply relative z-1 flex-1;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-label {
|
||||||
|
@apply text-14px mb-10px font-500;
|
||||||
|
color: $text-secondary;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-value-container {
|
||||||
|
@apply flex items-baseline gap-4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-value {
|
||||||
|
@apply text-22px font-600 color-[var(--card-color)] line-height-[1] whitespace-nowrap overflow-hidden text-ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-unit {
|
||||||
|
@apply text-14px font-400 whitespace-nowrap;
|
||||||
|
color: $text-secondary;
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,71 @@
|
|||||||
|
<!--
|
||||||
|
* @Author: chris
|
||||||
|
* @Date: 2025-09-05 09:29:59
|
||||||
|
* @LastEditors: chris
|
||||||
|
* @LastEditTime: 2025-09-11 17:11:53
|
||||||
|
-->
|
||||||
|
<script setup>
|
||||||
|
import LiveData from './components/LiveData.vue'
|
||||||
|
import WeatherChart from './components/WeatherChart.vue';
|
||||||
|
import { useSettings } from '@/hooks/useSettings';
|
||||||
|
import { getFormattedWeatherData } from './mock';
|
||||||
|
|
||||||
|
const { hasTags } = useSettings()
|
||||||
|
|
||||||
|
const liveData = ref({})
|
||||||
|
const chartData = ref({ dates: [], values: []})
|
||||||
|
const weatherType = ref('temperature')
|
||||||
|
const selectedTimeRange = ref(7)
|
||||||
|
const chartLoading = ref(false)
|
||||||
|
|
||||||
|
getChartData()
|
||||||
|
|
||||||
|
function getChartData() {
|
||||||
|
chartLoading.value = true
|
||||||
|
setTimeout(() => {
|
||||||
|
console.log(getFormattedWeatherData(weatherType.value, selectedTimeRange.value))
|
||||||
|
chartData.value = getFormattedWeatherData(weatherType.value, selectedTimeRange.value)
|
||||||
|
chartLoading.value = false
|
||||||
|
}, 300)
|
||||||
|
return chartData.value
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelectionChange(selection) {
|
||||||
|
console.log(selection)
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleSelectWeatherItem(item) {
|
||||||
|
weatherType.value = item.type
|
||||||
|
getChartData()
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTimeRangeChange(range) {
|
||||||
|
selectedTimeRange.value = range
|
||||||
|
getChartData()
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div :class="['weather-monitor-page', 'page-height', { 'hasTagsView': hasTags }]">
|
||||||
|
<el-row :gutter="20">
|
||||||
|
<el-col class="real-time-data" :span="6">
|
||||||
|
<live-data :data="liveData" @select="handleSelectWeatherItem"/>
|
||||||
|
</el-col>
|
||||||
|
<el-col class="history-data" :span="18">
|
||||||
|
<weather-chart :weather-type="weatherType" :chart-data="chartData" :selected-time-range="selectedTimeRange" :loading="chartLoading" @time-range-change="handleTimeRangeChange" />
|
||||||
|
<!-- <search-form v-model:params="queryParams" class="mb-12px" />
|
||||||
|
<history-table :dataList="historyList" :columns="columnsConfig" @selection-change="handleSelectionChange" /> -->
|
||||||
|
</el-col>
|
||||||
|
</el-row>
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.weather-monitor-page {
|
||||||
|
@apply p-20px;
|
||||||
|
|
||||||
|
> .el-row {
|
||||||
|
@apply h-full;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
Loading…
Reference in New Issue