智慧种植模块一体育苗页面开发,new政务数据大屏路由调整

This commit is contained in:
2090205686@qq.com 2025-05-20 13:25:47 +08:00
parent 5909699ca8
commit c4304f8da7
17 changed files with 502 additions and 28 deletions

View File

@ -57,11 +57,11 @@ export const rightApps = [
}, },
{ {
// name: 'sub-government-screen-service', // name: 'sub-government-screen-service',
name: 'new-digital-agriculture-screen', name: 'new-digital-agriculture-screen/v2/land',
// entry: VITE_APP_SUB_GSS, // entry: VITE_APP_SUB_GSS,
entry: VITE_APP_SUB_GSR, entry: VITE_APP_SUB_GSR,
// activeRule: '/sub-government-screen-service', // activeRule: '/sub-government-screen-service',
activeRule: '/new-digital-agriculture-screen', activeRule: '/new-digital-agriculture-screen/v2/land',
title: '数据大屏', title: '数据大屏',
icon: 'images/platform/icon-screen.png', icon: 'images/platform/icon-screen.png',
}, },

View File

@ -28,7 +28,7 @@ const props = defineProps({
}); });
const titles = ref([ const titles = ref([
{ label: '首页', value: 'home' }, // { label: '', value: 'home' },
{ label: '土地资源', value: 'land' }, { label: '土地资源', value: 'land' },
{ label: '投入品', value: 'inputs' }, { label: '投入品', value: 'inputs' },
{ label: '生产经营主体', value: 'entities' }, { label: '生产经营主体', value: 'entities' },

View File

@ -54,7 +54,7 @@ const props = defineProps({
type: Array, type: Array,
default() { default() {
return [ return [
{ label: '首页', value: '/new-digital-agriculture-screen/v2/home' }, // { label: '', value: '/new-digital-agriculture-screen/v2/home' },
{ label: '土地资源', value: '/new-digital-agriculture-screen/v2/land' }, { label: '土地资源', value: '/new-digital-agriculture-screen/v2/land' },
{ label: '投入品监管', value: '/new-digital-agriculture-screen/v2/inputs' }, { label: '投入品监管', value: '/new-digital-agriculture-screen/v2/inputs' },
{ label: '产出品管理', value: '/new-digital-agriculture-screen/v2/entities' }, { label: '产出品管理', value: '/new-digital-agriculture-screen/v2/entities' },

View File

@ -58,10 +58,10 @@ onMounted(() => {
user-select: none; user-select: none;
box-sizing: border-box; box-sizing: border-box;
width: 100%; width: 100%;
height: 100; height: 100%;
background: background:
url('@/assets/images/basic/containerBG.png') no-repeat center 100%, url('../assets/images/basic/containerBG.png') no-repeat center 100%,
url('@/assets/images/basic/containerBotBG.png') no-repeat bottom center; url('../assets/images/basic/containerBotBG.png') no-repeat bottom center;
&-header { &-header {
width: 100%; width: 100%;
margin-bottom: 16px; margin-bottom: 16px;

View File

@ -17,21 +17,22 @@ export const constantRoutes = [
component: () => import('@/views/error/403.vue'), component: () => import('@/views/error/403.vue'),
hidden: true, hidden: true,
}, },
{ // {
path: '/new-digital-agriculture-screen', // // 原来的首页默认配置
name: 'layout', // path: '/new-digital-agriculture-screen',
component: Layout, // name: 'layout',
redirect: '/new-digital-agriculture-screen/v2/home', // component: Layout,
meta: { title: '首页', icon: 'House' }, // redirect: '/new-digital-agriculture-screen/v2/home',
children: [ // meta: { title: '首页', icon: 'House' },
{ // children: [
path: '/new-digital-agriculture-screen/v2/home', // {
component: () => import('@/views/home/index.vue'), // path: '/new-digital-agriculture-screen/v2/home',
name: 'home', // component: () => import('@/views/home/index.vue'),
meta: { title: '首页', icon: '' }, // name: 'home',
}, // meta: { title: '首页', icon: '' },
], // },
}, // ],
// },
// ...demoRouters, // ...demoRouters,
v2, v2,
// { // {

View File

@ -4,7 +4,7 @@ export default {
path: '/new-digital-agriculture-screen', path: '/new-digital-agriculture-screen',
name: 'layout', name: 'layout',
component: Layout, component: Layout,
redirect: '/new-digital-agriculture-screen/v2/home', redirect: '/new-digital-agriculture-screen/v2/land', //原home
meta: { title: '首页', icon: '' }, meta: { title: '首页', icon: '' },
children: [ children: [
{ {

View File

@ -23,6 +23,7 @@
"axios": "^1.6.5", "axios": "^1.6.5",
"echarts": "^5.6.0", "echarts": "^5.6.0",
"element-plus": "^2.7.2", "element-plus": "^2.7.2",
"hls.js": "^1.6.2",
"js-base64": "^3.7.6", "js-base64": "^3.7.6",
"lodash": "^4.17.21", "lodash": "^4.17.21",
"moment": "^2.30.1", "moment": "^2.30.1",

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -63,6 +63,12 @@ export const constantRoutes = [
name: 'fieldInspection', name: 'fieldInspection',
meta: { title: '田间检测' }, meta: { title: '田间检测' },
}, },
{
path: '/sub-operation-service/smartFarm/growSeedlings',
component: () => import('@/views/smartFarm/growSeedlings/index.vue'),
name: 'growSeedlings',
meta: { title: '一体育苗' },
},
], ],
}, },
{ {

View File

@ -48,12 +48,19 @@ const menus = reactive([
], ],
}, },
{ {
name: 'purchaser', name: 'control',
title: '生产管理控制', title: '生产管理控制',
icon: 'menu3.png', icon: 'menu3.png',
path: '/sub-operation-service/ecommerce-purchaser', path: '/sub-operation-service/ecommerce-purchaser',
isOpen: false, isOpen: false,
children: [], children: [
{
name: 'control',
title: '一体育苗',
icon: 'menu3.png',
path: '/sub-operation-service/smartFarm/growSeedlings',
},
],
}, },
]); ]);
</script> </script>

View File

@ -76,12 +76,19 @@ const leftMenu = reactive([
], ],
}, },
{ {
name: 'purchaser', name: 'control',
title: '生产管理控制', title: '生产管理控制',
icon: 'menu3.png', icon: 'menu3.png',
path: '/sub-operation-service/ecommerce-purchaser', path: '/sub-operation-service/smartFarm/main',
isOpen: false, isOpen: false,
children: [], children: [
{
name: 'control',
title: '一体育苗',
icon: 'menu3.png',
path: '/sub-operation-service/smartFarm/growSeedlings',
},
],
}, },
]); ]);
@ -108,9 +115,12 @@ const toLink = (index) => {
} }
}; };
const toLinkSub = (index, c) => { const toLinkSub = (index, c) => {
console.info('index', index);
console.info('c', c);
currentCIndex.value = c; currentCIndex.value = c;
let path = leftMenu[index].children[c].path; let path = leftMenu[index].children[c].path;
if (path) { if (path) {
console.info('path', path);
router.push(path); router.push(path);
} }
}; };

View File

@ -0,0 +1,79 @@
<script setup>
import { ref, reactive, onMounted, watch } from 'vue';
const props = defineProps({
column: {
type: Array,
required: true,
default: () => [],
},
data: {
type: Array,
required: true,
default: () => [],
},
title: {
type: String,
required: true,
default: () => '',
validator: (items) => {
return items;
},
},
});
onMounted(() => {
console.log(props.column);
});
</script>
<template>
<div>
<el-card style="border-radius: 16px">
<div class="my-table-title" style="">{{ title }}</div>
<div style="height: 170px">
<table border="0" cellspacing="0" cellpadding="8">
<tr class="my-table-th">
<th v-for="(item, index) in column" :key="item.prop || index">
{{ item?.label || '' }}
</th>
</tr>
<tr v-for="(item, index) in data" :key="item.id || index">
<td v-for="(cell, i) of item" :key="item.id || i">
<span style="color: #25bf82" v-if="cell == '开启'">{{ cell }}</span>
<span style="color: #fe4066" v-else-if="cell == '关闭'">{{ cell }}</span>
<span v-else>{{ cell }}</span>
</td>
</tr>
</table>
</div>
</el-card>
</div>
</template>
<style scoped lang="scss">
.my-table-title {
font-size: 16px;
font-weight: bold;
text-align: left;
color: #000;
margin-bottom: 16px;
}
table {
width: 100%;
display: table;
border-collapse: collapse;
}
td,
th {
display: table-cell;
width: auto;
padding: 5px;
text-align: left;
}
.my-table-th {
color: #999;
font-weight: 300;
background-color: rgba(37, 191, 130, 0.05);
}
</style>

View File

@ -0,0 +1,158 @@
<script setup>
import { ref, reactive, onMounted, watch } from 'vue';
import { isEmpty, getAssetsFile } from '@/utils';
import { useRoute, useRouter } from 'vue-router';
const route = useRoute();
const router = useRouter();
const props = defineProps({
devices: {
type: Array,
required: true,
default: () => [],
validator: (items) => {
return items.every((item) => {
return (
typeof item === 'object' &&
item !== null &&
typeof item.id === 'number' &&
typeof item.isOpen === 'number' &&
typeof item.isOperation === 'number' &&
typeof item.name === 'string' &&
typeof item.serial === 'string' &&
typeof item.icon === 'string' &&
(!item.status || typeof item.status === 'number')
);
});
},
},
title: {
type: String,
required: true,
default: () => '',
validator: (items) => {
return items;
},
},
});
</script>
<template>
<div>
<el-card style="border-radius: 16px">
<div class="device-list-title" style="">{{ title }}</div>
<div style="display: flex; justify-content: flex-start; flex-wrap: wrap; gap: 16px">
<div v-for="(item, index) in devices" :key="index" class="device">
<div v-if="item.status == 1" class="status" style="background-color: #25bf82">正常</div>
<div v-else-if="item.status == 0" class="status" style="background-color: #999999">离线</div>
<div v-else-if="item.status == -1" class="status" style="background-color: #fe4066">故障</div>
<div style="display: flex; flex-direction: column; justify-content: space-between; height: 100%">
<div style="display: flex; justify-content: flex-start">
<img v-if="item.icon === 'plant'" :src="getAssetsFile('images/smartFarm/育苗.png')" alt="" />
<img v-else-if="item.icon === 'gogga'" :src="getAssetsFile('images/smartFarm/病虫害.png')" alt="" />
<img v-else-if="item.icon === 'water'" :src="getAssetsFile('images/smartFarm/灌溉控制.png')" alt="" />
<div style="margin-left: 10px">
<div style="font-size: 16px; text-align: left">{{ item.name }}</div>
<div style="font-size: 12px; text-align: left">{{ item.serial }}</div>
</div>
</div>
<div style="text-align: left; font-size: 16px; display: flex; justify-content: space-between; padding-left: 6px">
<div style="width: 128px; height: 30px; border-radius: 15px; background-color: #ffffff">
<div v-if="item.status == '0'" :class="{ 'swich-box2': true, 'swich-box-close': item.isOpen == 0 }">
<span class="swich-btn" :style="{ color: item.isOpen == 0 ? '#999999' : '#ffffff' }">开启</span>
<span class="swich-btn" :style="{ color: item.isOpen == 1 ? '#999999' : '#ffffff' }">关闭</span>
</div>
<div v-else :class="{ 'swich-box': true, 'swich-box-close': item.isOpen == 0 }">
<span class="swich-btn" :style="{ color: item.isOpen == 0 ? '#25bf82' : '#ffffff' }" @click="item.isOpen = 1">开启</span>
<span class="swich-btn" :style="{ color: item.isOpen == 1 ? '#999999' : '#ffffff' }" @click="item.isOpen = 0">关闭</span>
</div>
</div>
<span v-if="item.isOperation == 0" style="color: #999999">待机中...</span>
<span v-else-if="item.isOperation == 1" style="color: #25bf82">运作中...</span>
</div>
</div>
</div>
</div>
</el-card>
</div>
</template>
<style scoped lang="scss">
.device-list-title {
font-size: 16px;
font-weight: bold;
text-align: left;
color: #000;
margin-bottom: 20px;
}
.device {
height: 150px;
flex: 0 0 calc(33.33% - 11px);
background-color: #f5f5f5;
border-radius: 16px;
position: relative;
cursor: pointer;
padding: 16px 16px 16px 10px;
img {
height: 64px;
width: 64px;
}
}
.status {
border-radius: 0 16px 0 16px;
height: 32px;
line-height: 26px;
width: 40px;
position: absolute;
right: 0;
top: 0;
display: flex;
justify-content: center;
align-items: center;
color: #ffffff;
font-size: 12px;
}
.swich-box,
.swich-box2 {
width: 128px;
height: 30px;
border-radius: 15px;
z-index: 0;
position: relative;
&::before {
display: inline-block;
position: absolute;
content: '';
top: 0;
left: 0;
z-index: -1;
width: 64px;
height: 30px;
background-color: #25bf82;
border-radius: 15px;
transition: all 0.3s ease-in-out;
}
&.swich-box-close::before {
left: 64px;
background-color: #999999;
}
::v-deep .swich-btn {
display: inline-block;
font-size: 16px;
width: 64px;
height: 30px;
line-height: 30px;
border-radius: 15px;
text-align: center;
transition: all 0.3s ease-in-out;
}
}
.swich-box2 {
&::before {
background-color: #999999;
}
}
</style>

View File

@ -0,0 +1,204 @@
<template>
<section>
<common>
<template #main>
<div>
<ProduceDevices :title="'育苗设备'" :devices="devices"></ProduceDevices>
</div>
<div style="display: flex; justify-content: space-between; margin-top: 20px">
<MyTable :title="'育苗策略'" :data="leftTableData" :column="leftTableTitle" style="width: 60%; margin-right: 20px"></MyTable>
<MyTable :title="'育苗记录'" :data="rightTableData" :column="rightTableTitle" style="flex: 1"></MyTable>
</div>
</template>
</common>
</section>
</template>
<script setup>
import { ref } from 'vue';
import Common from '../components/common.vue';
import MyTable from '@/views/smartFarm/components/myTable.vue';
import ProduceDevices from '@/views/smartFarm/components/produceDevices.vue';
const devices = ref([
{
name: 'A-001',
serial: 'YM20250101001', //
icon: 'plant', // plant gogga water
isOpen: 1, // 0: 1:
isOperation: 0, // 0: 1:
status: '1', // -1: 0:线 1:
id: 0,
},
{
name: 'A-002',
serial: 'YM20250101002',
icon: 'plant',
isOpen: 0,
isOperation: 1,
status: '1',
id: 1,
},
{
name: 'A-003',
serial: 'YM20250101003',
icon: 'gogga',
isOpen: 0,
isOperation: 0,
status: '-1',
id: 2,
},
{
name: 'A-004',
serial: 'YM20250101004',
icon: 'water',
isOpen: 1,
isOperation: 0,
status: '0',
id: 3,
},
{
name: 'A-005',
serial: 'YM20250101005',
icon: 'gogga',
isOpen: 0,
isOperation: 1,
status: '1',
id: 4,
},
{
name: 'A-006',
serial: 'YM20250101006',
icon: 'water',
isOpen: 1,
isOperation: 0,
status: '1',
id: 5,
},
]);
const leftTableData = ref([
{
name: '温度',
value: '>25',
device: '制冷机',
behavior: '开启',
time: 10,
},
{
name: '湿度',
value: '<24',
device: '喷洒机',
behavior: '关闭',
time: 15,
},
{
name: 'PH值',
value: '>8',
device: '配肥机',
behavior: '开启',
time: 5,
},
{
name: '风速',
value: '>中风',
device: '通风窗',
behavior: '关闭',
time: '/',
},
{
name: '光照',
value: '>强光',
device: '幕布',
behavior: '开启',
time: '/',
},
]);
const leftTableTitle = ref([
{
label: '参数名称',
prop: 'name',
width: 'auto',
},
{
label: '参数值',
prop: 'value',
width: 'auto',
},
{
label: '智能设备',
prop: 'device',
width: 'auto',
},
{
label: '机械行为',
prop: 'behavior',
width: 'auto',
},
{
label: '持续时间(min)',
prop: 'time',
width: 'auto',
},
]);
const rightTableData = ref([
{
date: '2025-01-01 10:36',
device: '制冷机',
behavior: '开启',
},
{
date: '2025-01-01 10:30',
device: '喷洒机',
behavior: '关闭',
},
{
date: '2025-01-01 10:22',
device: '配肥机',
behavior: '开启',
},
{
date: '2025-01-01 10:10',
device: '通风窗',
behavior: '关闭',
},
{
date: '2025-01-01 10:00',
device: '幕布',
behavior: '开启',
},
]);
const rightTableTitle = ref([
{
label: '执行时间',
prop: 'date',
width: 'auto',
},
{
label: '智能设备',
prop: 'device',
width: 'auto',
},
{
label: '机械行为',
prop: 'behavior',
width: 'auto',
},
]);
</script>
<style lang="scss" scoped>
.plantStatus {
display: flex;
justify-content: space-between;
font-size: 14px;
margin: 7px 0;
.leftKey {
color: #000000;
}
.rightValue {
color: #25bf82;
}
}
</style>

View File

@ -4417,6 +4417,13 @@ __metadata:
languageName: node languageName: node
linkType: hard linkType: hard
"hls.js@npm:^1.6.2":
version: 1.6.2
resolution: "hls.js@npm:1.6.2"
checksum: 10c0/c8700d88610afa85bf441cd624f6d548c1fea59c0e510fb05be02f9a33660b8a46cb17910ea5179b9d1307ce9242f4e904d8aa98d7f63d0df750d6d0f6e85134
languageName: node
linkType: hard
"hookified@npm:^1.6.0": "hookified@npm:^1.6.0":
version: 1.6.0 version: 1.6.0
resolution: "hookified@npm:1.6.0" resolution: "hookified@npm:1.6.0"
@ -8512,6 +8519,7 @@ __metadata:
eslint-config-prettier: "npm:^9.1.0" eslint-config-prettier: "npm:^9.1.0"
eslint-plugin-prettier: "npm:^5.1.3" eslint-plugin-prettier: "npm:^5.1.3"
eslint-plugin-vue: "npm:^9.20.1" eslint-plugin-vue: "npm:^9.20.1"
hls.js: "npm:^1.6.2"
js-base64: "npm:^3.7.6" js-base64: "npm:^3.7.6"
lodash: "npm:^4.17.21" lodash: "npm:^4.17.21"
mockjs: "npm:^1.1.0" mockjs: "npm:^1.1.0"