右侧模块增加

This commit is contained in:
王兴凯 2026-05-12 08:47:27 +08:00
parent 7ab91f158e
commit 48262cc162
34 changed files with 2525 additions and 7516 deletions

View File

@ -9,9 +9,9 @@ VITE_APP_BASE_API = '/dev-api'
# 本地环境 # 本地环境
# VITE_APP_BASE_URL = 'http://localhost:8093' # VITE_APP_BASE_URL = 'http://localhost:8093'
# 测试环境 # 测试环境
# VITE_APP_BASE_URL = 'http://172.16.21.142:8096' VITE_APP_BASE_URL = 'http://172.16.21.142:8096'
# 汤伟 # 汤伟
VITE_APP_BASE_URL = 'http://10.84.121.21:8093' # VITE_APP_BASE_URL = 'http://10.84.121.21:8093'
# 开发环境导入预览地址 # 开发环境导入预览地址

View File

@ -3,7 +3,7 @@
"version": "1.2.0", "version": "1.2.0",
"scripts": { "scripts": {
"dev": "vite serve --mode development", "dev": "vite serve --mode development",
"build": "vue-tsc --noEmit && vite build --mode production", "build": "vite build --mode production",
"build:mvn": "vite build --mode production", "build:mvn": "vite build --mode production",
"serve": "vite preview", "serve": "vite preview",
"lint": "eslint src/**/*.{ts,js,vue} --fix", "lint": "eslint src/**/*.{ts,js,vue} --fix",

File diff suppressed because it is too large Load Diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 353 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 478 B

View File

@ -18,9 +18,9 @@
</div> </div>
<div class="title_right"> <div class="title_right">
<div v-if="select.show"> <div v-if="select.show">
<a-select v-model:value="selectValue" show-search placeholder="请选择" :size="'small'" <a-select v-model:value="selectValue" show-search placeholder="请选择" :size="'small'"
:options="select.options" :filter-option="filterOption" @focus="handleFocus" @blur="handleBlur" style="width: 120px" :options="select.options" :filter-option="filterOption"
@change="handleChange"></a-select> @focus="handleFocus" @blur="handleBlur" @change="handleChange"></a-select>
</div> </div>
<div v-if="shrink" class="title_shrink" @click="isExpand = !isExpand"> <div v-if="shrink" class="title_shrink" @click="isExpand = !isExpand">
<img v-if="isExpand" src="@/assets/components/arrow-up.png" alt=""> <img v-if="isExpand" src="@/assets/components/arrow-up.png" alt="">
@ -36,14 +36,20 @@
<div v-if="datetimePicker.show"> <div v-if="datetimePicker.show">
<!-- 添加 locale 属性来设置语言 --> <!-- 添加 locale 属性来设置语言 -->
<a-date-picker v-model:value="datetimeValue" show-time <a-date-picker v-model:value="datetimeValue" show-time
:style="{ width: datetimePicker.picker === 'year' ? '80px' : '' }"
:format="datetimePicker.format !== null ? datetimePicker.format : undefined" :format="datetimePicker.format !== null ? datetimePicker.format : undefined"
:picker="datetimePicker.picker" placeholder="请选择时间" :picker="datetimePicker.picker" placeholder=" " @change="handleDateTimeChange"
@change="handleDateTimeChange" :size="'small'" /> :size="'small'" />
<!-- 修改为 locale 变量 --> <!-- 修改为 locale 变量 -->
</div> </div>
<div v-if="scopeDate.show"> <div v-if="scopeDate.show" class="title_scopeDate">
<a-range-picker v-model:value="scopeDateValue" :picker="scopeDate.picker" <a-range-picker v-model:value="scopeDateValue" :picker="scopeDate.picker"
:format="'YYYY-MM-DD'" :range-separator="' 至 '" style="width: 200px" /> :style="{ width: scopeDate.picker === 'year' ? '80px' : (scopeDate.picker === 'month' ? '150px' : '') }"
:format="scopeDate.format" :range-separator="' 至 '" :size="'small'" />
</div>
<div v-if="tabs.show" class="typeOne">
<div @click="handleTabClick('one')" :class="tabsValue == 'one' ? 'typezhong' : ''">图片</div>
<div @click="handleTabClick('two')" :class="tabsValue == 'two' ? 'typezhong' : ''">视频</div>
</div> </div>
</div> </div>
</div> </div>
@ -136,16 +142,29 @@ const props = defineProps({
default: () => ({ default: () => ({
show: false, show: false,
value: undefined, value: undefined,
format: null, //YYYY-MM-DD HH
picker: 'month' //date | week | month | quarter | year picker: 'month' //date | week | month | quarter | year
}) })
}, },
tabs: {
type: Object,
default: () => ({
show: false,
value: 'one',
})
}
}); });
const emit = defineEmits(['tab-change']);
const isExpand = ref(true); const isExpand = ref(true);
const selectValue = ref(props.select.value) const selectValue = ref(props.select.value)
const moreSelectValue = ref(props.select.value) const moreSelectValue = ref(props.select.value)
const datetimeValue = ref<Dayjs | null>(props.datetimePicker.value ? dayjs(props.datetimePicker.value) : null); const datetimeValue = ref<Dayjs | null>(props.datetimePicker.value ? dayjs(props.datetimePicker.value) : null);
const scopeDateValue = ref(props.scopeDate.value); const scopeDateValue = ref<[Dayjs, Dayjs] | undefined>(
props.scopeDate.value && Array.isArray(props.scopeDate.value)
? [dayjs(props.scopeDate.value[0]), dayjs(props.scopeDate.value[1])]
: undefined
);
const tabsValue = ref(props.tabs.value)
// // locale // // locale
// const locale = zhCN; // const locale = zhCN;
@ -178,6 +197,14 @@ const handleDateTimeChange = (date: any | null, dateString: string) => {
console.log('Selected DateTime:', date, dateString); console.log('Selected DateTime:', date, dateString);
}; };
const handleTabClick = (value: string) => {
tabsValue.value = value;
//
emit('tab-change', {
tabValue: value,
tabLabel: value === 'one' ? '图片' : '视频'
});
};
// //
onMounted(() => { onMounted(() => {
console.log(props.select); console.log(props.select);
@ -212,10 +239,12 @@ onMounted(() => {
.title_left { .title_left {
display: flex; display: flex;
align-items: center; align-items: center;
.texttitle{
.texttitle {
display: inline-block; display: inline-block;
width:180px; //width:180px;
} }
.title_icon { .title_icon {
display: inline-block; display: inline-block;
margin-left: 5px; margin-left: 5px;
@ -227,11 +256,36 @@ onMounted(() => {
.title_right { .title_right {
display: flex; display: flex;
align-items: center; align-items: center;
div{
div {
margin-right: 2px; margin-right: 2px;
} }
} }
.typeOne {
display: flex;
// width: 84px;
height: 24px;
box-sizing: border-box;
cursor: pointer;
div {
width: 38px;
height: 24px;
font-size: 14px;
line-height: 24px;
text-align: center;
background: #fff;
margin: 0px;
color: rgba(0, 0, 0, .85);
}
.typezhong {
background: #40a9ff;
color: #fff;
}
}
} }
.qgc_title:before { .qgc_title:before {
@ -263,4 +317,10 @@ onMounted(() => {
} }
} }
} }
.title_scopeDate {
:deep(.ant-picker-range-separator) {
padding: 0px !important;
}
}
</style> </style>

View File

@ -48,7 +48,7 @@ const props = defineProps({
}); });
const datetimePicker = ref({ const datetimePicker = ref({
show: true, show: true,
value: undefined, value: `${new Date().getFullYear() - 1}`, //
format: 'YYYY', format: 'YYYY',
picker: 'year' as const, picker: 'year' as const,
options: [] options: []
@ -61,7 +61,8 @@ interface ChartDataItem {
} }
// //
const originalChartData = ref<ChartDataItem[]>([ const originalChartData = ref<ChartDataItem[]>(
[
{ {
title: '过鱼总量统计 - 2025年', title: '过鱼总量统计 - 2025年',
data: [ data: [

View File

@ -0,0 +1,320 @@
<!-- SidePanelItem.vue -->
<template>
<SidePanelItem title="野生动物监测" :select="select" :datetimePicker="datetimePicker" :tabs="tabs"
@tab-change="handleTabChange">
<div v-if="tabsa == 'one'" class="container" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
<!-- 跑马灯轨道容器 -->
<div class="carousel-track" :class="{ 'no-transition': isTransitioning }"
:style="{ transform: `translateX(-${currentIndex * 100}%)` }">
<!-- 遍历所有媒体项包含克隆项 -->
<div v-for="(item, index) in renderMediaData" :key="index" class="carousel-item">
<!-- 图片 -->
<a-image :src="item.url" />
<!-- 说明文字 -->
<div class="text">{{ item.text }}</div>
</div>
</div>
</div>
<div v-else class="container video-carousel-container" @mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave">
<!-- 跑马灯轨道容器 -->
<div class="carousel-track" :class="{ 'no-transition': isTransitioning }"
:style="{ transform: `translateX(-${currentIndex * 30}%)` }">
<!-- 遍历所有媒体项包含克隆项 -->
<div v-for="(item, index) in renderMediaData" :key="index" class="carousel-item1">
<!-- 图片 -->
<a-image :src="item.url" />
<div class="biaozji">
<span class="icon iconfont icon-play" ></span>
</div>
</div>
</div>
</div>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted } from 'vue';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
// 便
defineOptions({
name: 'ZhiWuYuanJianSheJiJieRuQingKuangBar'
});
// ==================== ====================//
const select = ref({
show: true,
value: undefined,
options: [],
picker: undefined,
format: undefined
});
//
const datetimePicker = ref({
show: true,
value: `2024`,
format: 'YYYY',
picker: 'year' as const,
options: []
});
const tabs = ref({
show: true,
value: 'one',
});
//
interface MediaItem {
type: 'image' | 'video';
url: string;
text: string;
}
// 5
const originalMediaData = ref<MediaItem[]>([
{
type: 'image',
url: 'https://211.99.26.225:12125/?20250709001636453909987812803850&view=jpg&token=bearer 0a2549fe-9bc6-4bef-b098-1344e569c395',
text: '糯扎渡动物救护站 2025-04-11 15'
},
{
type: 'image',
url: 'https://211.99.26.225:12125/?20250709001636453909987812803850&view=jpg&token=bearer 0a2549fe-9bc6-4bef-b098-1344e569c395',
text: '糯扎渡动物救护站 2025-04-11 15'
},
{
type: 'image',
url: 'https://211.99.26.225:12125/?20250709001636453909987812803850&view=jpg&token=bearer 0a2549fe-9bc6-4bef-b098-1344e569c395',
text: '糯扎渡动物救护站 2025-04-11 15'
},
{
type: 'image',
url: 'https://211.99.26.225:12125/?20250709001636453909987812803850&view=jpg&token=bearer 0a2549fe-9bc6-4bef-b098-1344e569c395',
text: '糯扎渡动物救护站 2025-04-11 15'
},
]);
const tabsa = ref('one')
//
// [, ..., ]
const renderMediaData = ref<MediaItem[]>([]);
// renderMediaData
const currentIndex = ref(1); // 1
//
let timer: any = null;
//
const isHovering = ref(false);
// transition
const isTransitioning = ref(false);
//
const initRenderData = () => {
const length = originalMediaData.value.length;
if (length === 0) return;
renderMediaData.value = [
originalMediaData.value[length - 1], //
...originalMediaData.value, //
originalMediaData.value[0] //
];
};
//
const startAutoPlay = () => {
if (timer) clearInterval(timer);
timer = setInterval(() => {
if (!isHovering.value && !isTransitioning.value) {
nextSlide();
}
}, 2000);
};
//
const nextSlide = () => {
currentIndex.value++;
//
setTimeout(() => {
checkSeamlessJump();
}, 500); // transition
};
//
const checkSeamlessJump = () => {
const realLength = originalMediaData.value.length;
// = realLength + 1
if (currentIndex.value >= realLength + 1) {
// 1.
isTransitioning.value = true;
// 2. 1
currentIndex.value = 1;
// 3. DOM
requestAnimationFrame(() => {
requestAnimationFrame(() => {
isTransitioning.value = false;
});
});
}
};
//
const handleMouseEnter = () => {
isHovering.value = true;
};
//
const handleMouseLeave = () => {
isHovering.value = false;
};
const handleTabChange = (data: { tabValue: string; tabLabel: string }) => {
console.log('当前选中标签:', data.tabValue);
console.log('标签名称:', data.tabLabel);
//
tabsa.value = data.tabValue;
};
//
onMounted(() => {
initRenderData();
startAutoPlay();
});
//
onUnmounted(() => {
if (timer) clearInterval(timer);
});
</script>
<style lang="scss" scoped>
.container {
width: 100%;
height: 290px;
border: 1px solid #7fd6ff;
border-radius: 5px;
position: relative;
overflow: hidden; //
//
.carousel-track {
display: flex; //
width: 100%;
height: 100%;
transition: transform 0.5s ease-in-out; // 0.5
//
&.no-transition {
transition: none;
}
//
.carousel-item {
width: 100% !important; //
height: 100%;
position: relative;
flex-shrink: 0; //
img,
video {
width: 100%;
height: 100%;
object-fit: cover; //
}
// Ant Design Vue a-image
:deep(.ant-image) {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.text {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 40px;
align-items: center;
line-height: 40px;
background: rgba(0, 0, 0, 0.4);
color: #fff;
padding-left: 10px;
}
}
}
}
.video-carousel-container {
border: 0px solid #7fd6ff !important;
border-radius: 0px !important;
.carousel-item1 {
position: relative;
width: 40% !important; //
height: 100%;
position: relative;
flex-shrink: 0; //
// margin-right: 10px;
padding: 6px;
border-top:#f0f0f0 solid 1px;
border-bottom:#f0f0f0 solid 1px;
border-right:#f0f0f0 solid 1px;
img,
video {
width: 100%;
height: 100%;
object-fit: cover; //
}
// Ant Design Vue a-image
:deep(.ant-image) {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.biaozji{
position: absolute;
width:40px;
height:40px;
border-radius:50%;
background:#0c33586c;
z-index: 9999;
top: 50%;
left: 50%;
transform: translate(-50%,-50%);
display:flex;
align-items: center;
justify-content: center;
cursor: pointer;
span{
width:16px;
height:16px;
font-size: 16px;
color: #abacad;
display: inline-block;
text-align: center;
line-height: 16px;
}
}
}
}
</style>

View File

@ -1,40 +1,14 @@
<!-- SidePanelItem.vue --> <!-- SidePanelItem.vue -->
<template> <template>
<SidePanelItem title="动物救助情况"> <SidePanelItem title="动物救助情况">
<div <div class="container" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
class="container"
@mouseenter="handleMouseEnter"
@mouseleave="handleMouseLeave"
>
<!-- 跑马灯轨道容器 --> <!-- 跑马灯轨道容器 -->
<div <div class="carousel-track" :class="{ 'no-transition': isTransitioning }"
class="carousel-track" :style="{ transform: `translateX(-${currentIndex * 100}%)` }">
:class="{ 'no-transition': isTransitioning }"
:style="{ transform: `translateX(-${currentIndex * 100}%)` }"
>
<!-- 遍历所有媒体项包含克隆项 --> <!-- 遍历所有媒体项包含克隆项 -->
<div <div v-for="(item, index) in renderMediaData" :key="index" class="carousel-item">
v-for="(item, index) in renderMediaData"
:key="index"
class="carousel-item"
>
<!-- 图片 --> <!-- 图片 -->
<img <a-image :src="item.url" />
v-if="item.type === 'image'"
:src="item.url"
alt=""
/>
<!-- 视频 -->
<video
v-else
:src="item.url"
autoplay
muted
loop
playsinline
></video>
<!-- 说明文字 --> <!-- 说明文字 -->
<div class="text">{{ item.text }}</div> <div class="text">{{ item.text }}</div>
</div> </div>
@ -67,8 +41,8 @@ const originalMediaData = ref<MediaItem[]>([
text: '糯扎渡动物救护站 2025-04-11 15' text: '糯扎渡动物救护站 2025-04-11 15'
}, },
{ {
type: 'video', type: 'image',
url: 'https://example.com/video1.mp4', // URL url: 'https://211.99.26.225:12125/?20250508094042468361071230016027&view=jpg&token=bearer fee092f0-b748-4019-bcbb-1386fa8c4fa4', // URL
text: '野生动物救助中心 2025-04-12 10' text: '野生动物救助中心 2025-04-12 10'
}, },
{ {
@ -192,17 +166,30 @@ onUnmounted(() => {
// //
.carousel-item { .carousel-item {
min-width: 100%; // width: 100% !important; //
height: 100%; height: 100%;
position: relative; position: relative;
flex-shrink: 0; // flex-shrink: 0; //
img, video { img,
video {
width: 100%; width: 100%;
height: 100%; height: 100%;
object-fit: cover; // object-fit: cover; //
} }
// Ant Design Vue a-image
:deep(.ant-image) {
width: 100%;
height: 100%;
img {
width: 100%;
height: 100%;
object-fit: cover;
}
}
.text { .text {
position: absolute; position: absolute;
bottom: 0; bottom: 0;

View File

@ -0,0 +1,209 @@
<!-- SidePanelItem.vue -->
<template>
<SidePanelItem title="水生生态调查" :select="select" :datetimePicker="datetimePicker">
<div ref="chartRef" class="chart-container"></div>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
//
defineOptions({
name: 'shuiShengShengTaiDiaoCha'
});
// ==================== ====================
const chartRef = ref<HTMLDivElement>();
let chartInstance: any = null;
//
const select = ref({
show: true,
value: undefined,
options: [],
picker: undefined,
format: undefined
});
//
const datetimePicker = ref({
show: true,
value: '2020',
format: 'YYYY',
picker: 'year' as const,
options: []
});
//
const initChart = () => {
if (!chartRef.value) return;
//
if (chartInstance) {
chartInstance.dispose();
}
//
chartInstance = echarts.init(chartRef.value);
//
const option: EChartsOption = {
tooltip: {
trigger: 'axis',
axisPointer: {
type: 'shadow'
},
backgroundColor: 'rgba(0, 0, 0, 0.5)',
borderColor: 'transparent',
textStyle: {
color: '#ffffff'
}
},
grid: {
top: 30,
left: '2%',
right: '4%',
bottom: 30,
containLabel: true
},
legend: {
bottom: 0,
itemWidth: 10,
itemHeight: 10
},
yAxis: {
type: 'value',
minInterval: 1,
name: '种',
axisLine: {
lineStyle: {
color: '#e0e0e0'
}
},
axisLabel: {
color: '#666'
},
splitLine: {
lineStyle: {
color: '#e0e0e0',
type: 'solid'
}
}
},
xAxis: {
type: 'category',
axisTick: {
show: false
},
axisLabel: {
interval: 0,
rotate: 0,
color: '#666',
rich: {
a: {
height: 24,
align: 'center'
},
b: {
height: 30,
align: 'center'
}
}
},
name: '数量(个)',
data: [
'两河口',
'杨房沟',
'锦屏一级',
'锦屏二级',
'官地',
'二滩',
'桐子林'
]
},
series: [
{
name: '外来鱼类',
type: 'bar',
stack: 'stack',
data: [0, 0, 0, 0, 0, 1, 2],
label: {
show: true,
position: 'top',
color: '#FFF'
}
},
{
name: '本土受威胁鱼类',
type: 'bar',
stack: 'stack',
data: [1, 10, 10, 5, 4, 6, 11],
label: {
show: true,
position: 'top',
color: '#FFF'
}
},
{
name: '本土无危鱼类',
type: 'bar',
stack: 'stack',
data: [1, 10, 6, 5, 2, 13, 23],
label: {
show: true,
position: 'top',
color: '#FFF'
}
}
],
barWidth: 15,
color: ['#4B79AB', '#78C300', '#9556A4']
};
//
chartInstance.setOption(option);
};
//
const handleResize = () => {
if (chartInstance) {
chartInstance.resize();
}
};
// ==================== ====================
//
onMounted(() => {
nextTick(() => {
setTimeout(() => {
initChart();
window.addEventListener('resize', handleResize);
}, 50);
});
});
//
onUnmounted(() => {
//
window.removeEventListener('resize', handleResize);
//
if (chartInstance) {
chartInstance.dispose();
chartInstance = null;
}
});
</script>
<style lang="scss" scoped>
.chart-container {
width: 100%;
height: 231px;
min-height: 231px;
}
</style>

View File

@ -0,0 +1,286 @@
<!-- SidePanelItem.vue -->
<template>
<SidePanelItem title="鱼类介绍">
<div class="container" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
<!-- 跑马灯轨道容器 -->
<div class="carousel-track" :class="{ 'no-transition': isTransitioning }"
:style="{ transform: `translateX(-${currentIndex * 100}%)` }">
<!-- 遍历所有媒体项包含克隆项 -->
<div v-for="(item, index) in renderMediaData" :key="index" class="carousel-item">
<!-- 图片 -->
<img :src="item.url" alt="" />
<!-- 说明文字随媒体项移动 -->
<div class="text">{{ item.text }}</div>
</div>
</div>
<!-- 面板指示器固定在底部右侧 -->
<div class="pagination-dots-fixed">
<span
v-for="(dot, index) in originalMediaData"
:key="index"
class="dot"
:class="{ active: getCurrentRealIndex() === index }"
@click="goToSlide(index)"
></span>
</div>
</div>
<!-- 独立的文字说明区域随跑马灯切换而变化 -->
<div class="description-text">
{{ currentDescription }}
</div>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, computed } from 'vue';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
// 便
defineOptions({
name: 'zengZhiZhanJieShaoMod'
});
//
interface MediaItem {
type: 'image' | 'video';
url: string;
text: string;
description: string;
}
// 3
const originalMediaData = ref<MediaItem[]>([
{
type: 'image',
url: 'https://211.99.26.225:12125/?20230814205611342377136845462200&view=jpg&token=bearer c2e76c28-14db-4a0f-9ff2-10cc3f835920',
text: '松岗鱼类增殖站',
description: '松岗鱼类增殖放流站位于四川省阿坝藏族羌族自治州马尔康市松岗镇,主要服务于大渡河上游的双江口和金川两座水电站,同时还承担多种珍稀特有鱼类的救护和科研任务,实现工程建设与生态环境共同推进、相互促进。'
},
{
type: 'video',
url: 'https://211.99.26.225:12125/?20230805205848575430105387253710&view=jpg&token=bearer c2e76c28-14db-4a0f-9ff2-10cc3f835920', // URL
text: '猴子岩鱼类增殖站',
description: '猴子岩水电站鱼类增殖放流站位于猴子岩水电站坝址下游约7.0km(业主营地下游约1.5km)大渡河左岸桃花渣场顶部平台上紧邻枢纽桃花大桥下游侧占地面积47.3亩其中一期工程27.0亩预留二期工程用地20.3亩(二期工程目前为丹巴、巴底水电站预留工程)增殖放流站工作流程为:亲鱼收集购买、亲鱼驯养培育、人工催产和授精、人工孵化、苗种培育和放流。 猴子岩鱼类增殖放流站近期放流对象中齐口裂腹鱼、重口裂腹鱼、大渡软刺裸裂尻鱼增殖放流技术水平已趋于熟化,中期放流对象大渡软刺裸裂尻鱼人工繁殖技术逐渐趋于熟化'
},
{
type: 'image',
url: 'https://211.99.26.225:12125/?20230805205924378504010675106305&view=jpg&token=bearer c2e76c28-14db-4a0f-9ff2-10cc3f835920',
text: '黑马鱼类增殖站',
description: '大渡河黑马鱼类增殖放流站位于四川省甘洛县黑马乡黑马业主营地内距离甘洛县城45km,区域交通路况较好。主要承担瀑布沟、深溪沟、大岗山、枕头坝一级、沙坪二级等五座水电站鱼类增殖放流的重任。放流鱼类包含:齐口裂腹鱼、重口裂腹鱼、鲈鲤、长薄鳅、白甲鱼、中华倒刺、长吻脆、稀有鮊鲫、华鲮、侧沟爬岩鳅等10个种类共计约918.07万尾珍稀特有鱼苗。'
}
]);
//
// [, ..., ]
const renderMediaData = ref<MediaItem[]>([]);
// renderMediaData
const currentIndex = ref(1); // 1
//
let timer: any = null;
//
const isHovering = ref(false);
// transition
const isTransitioning = ref(false);
//
const initRenderData = () => {
const length = originalMediaData.value.length;
if (length === 0) return;
renderMediaData.value = [
originalMediaData.value[length - 1], //
...originalMediaData.value, //
originalMediaData.value[0] //
];
};
//
const startAutoPlay = () => {
if (timer) clearInterval(timer);
timer = setInterval(() => {
if (!isHovering.value && !isTransitioning.value) {
nextSlide();
}
}, 4000);
};
//
const nextSlide = () => {
currentIndex.value++;
//
setTimeout(() => {
checkSeamlessJump();
}, 500); // transition
};
//
const checkSeamlessJump = () => {
const realLength = originalMediaData.value.length;
// = realLength + 1
if (currentIndex.value >= realLength + 1) {
// 1.
isTransitioning.value = true;
// 2. 1
currentIndex.value = 1;
// 3. DOM
requestAnimationFrame(() => {
requestAnimationFrame(() => {
isTransitioning.value = false;
});
});
}
};
//
const handleMouseEnter = () => {
isHovering.value = true;
};
//
const handleMouseLeave = () => {
isHovering.value = false;
};
//
const currentDescription = computed(() => {
const realIndex = getCurrentRealIndex();
return originalMediaData.value[realIndex]?.description || '';
});
//
onMounted(() => {
initRenderData();
startAutoPlay();
});
//
onUnmounted(() => {
if (timer) clearInterval(timer);
});
//
const getCurrentRealIndex = () => {
const realLength = originalMediaData.value.length;
let realIndex = currentIndex.value - 1; //
//
if (realIndex < 0) realIndex = realLength - 1;
if (realIndex >= realLength) realIndex = 0;
return realIndex;
};
//
const goToSlide = (targetIndex: number) => {
if (isTransitioning.value) return;
//
currentIndex.value = targetIndex + 1;
};
</script>
<style lang="scss" scoped>
.container {
width: 100%;
height: 228px;
// border: 1px solid #7fd6ff;
// border-radius: 5px;
position: relative;
overflow: hidden; //
//
.carousel-track {
display: flex; //
width: 100%;
height: 100%;
transition: transform 0.5s ease-in-out; // 0.5
//
&.no-transition {
transition: none;
}
//
.carousel-item {
min-width: 100%; //
height: 100%;
position: relative;
flex-shrink: 0; //
img,
video {
width: 100%;
height: 100%;
object-fit: cover; //
}
.text {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 22px;
line-height: 22px;
background: rgba(0, 0, 0, 0.1);
color: #fff;
padding-left: 10px;
}
}
}
//
.pagination-dots-fixed {
position: absolute;
bottom: 10px;
right: 10px;
display: flex;
gap: 6px;
z-index: 10; //
.dot {
width: 5px;
height: 5px;
border-radius: 50%;
background-color: #D8D8D8;
cursor: pointer;
transition: background-color 0.3s ease;
&.active {
background-color: #005293;
}
&:hover {
opacity: 0.8;
}
}
}
}
//
.description-text {
// padding: 8px 12px;
font-size: 14px;
line-height: 1.5;
// min-height: 40px;
transition: all 0.3s ease;
margin-bottom: 20px;
//
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-word;
}
</style>

View File

@ -0,0 +1,76 @@
<!-- SidePanelItem.vue -->
<template>
<SidePanelItem title="视频" :select="select">
<div class="video-container">
<video
ref="videoRef"
class="video-player"
controls
autoplay
muted
playsinline
preload="auto"
>
<source src="" type="video/mp4">
您的浏览器不支持视频播放
</video>
</div>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, computed } from 'vue';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
// 便
defineOptions({
name: 'zengZhiZhanJieShaoMod'
});
//
const videoRef = ref<HTMLVideoElement>();
//
const select = ref({
show: true,
value: undefined,
options: [],
picker: undefined,
format: undefined
});
//
onMounted(() => {
});
//
onUnmounted(() => {
if (videoRef.value) {
videoRef.value.pause();
videoRef.value.src = '';
}
});
</script>
<style lang="scss" scoped>
.video-container{
height: 300px;
width: 100%;
.video-player {
width: 100%;
height: 100%;
object-fit: contain;
background-color: #000;
//
&::-webkit-media-controls-panel {
background-color: rgba(0, 0, 0, 0.7);
}
}
}
</style>

View File

@ -0,0 +1,286 @@
<!-- SidePanelItem.vue -->
<template>
<SidePanelItem title="鱼类调查装置介绍">
<div class="container" @mouseenter="handleMouseEnter" @mouseleave="handleMouseLeave">
<!-- 跑马灯轨道容器 -->
<div class="carousel-track" :class="{ 'no-transition': isTransitioning }"
:style="{ transform: `translateX(-${currentIndex * 100}%)` }">
<!-- 遍历所有媒体项包含克隆项 -->
<div v-for="(item, index) in renderMediaData" :key="index" class="carousel-item">
<!-- 图片 -->
<img :src="item.url" alt="" />
<!-- 说明文字随媒体项移动 -->
<div class="text">{{ item.text }}</div>
</div>
</div>
<!-- 面板指示器固定在底部右侧 -->
<div class="pagination-dots-fixed">
<span
v-for="(dot, index) in originalMediaData"
:key="index"
class="dot"
:class="{ active: getCurrentRealIndex() === index }"
@click="goToSlide(index)"
></span>
</div>
</div>
<!-- 独立的文字说明区域随跑马灯切换而变化 -->
<div class="description-text">
{{ currentDescription }}
</div>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, computed } from 'vue';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
// 便
defineOptions({
name: 'zengZhiZhanJieShaoMod'
});
//
interface MediaItem {
type: 'image' | 'video';
url: string;
text: string;
description: string;
}
// 3
const originalMediaData = ref<MediaItem[]>([
{
type: 'image',
url: 'https://211.99.26.225:12125/?20230814205611342377136845462200&view=jpg&token=bearer c2e76c28-14db-4a0f-9ff2-10cc3f835920',
text: '松岗鱼类增殖站',
description: '松岗鱼类增殖放流站位于四川省阿坝藏族羌族自治州马尔康市松岗镇,主要服务于大渡河上游的双江口和金川两座水电站,同时还承担多种珍稀特有鱼类的救护和科研任务,实现工程建设与生态环境共同推进、相互促进。'
},
{
type: 'video',
url: 'https://211.99.26.225:12125/?20230805205848575430105387253710&view=jpg&token=bearer c2e76c28-14db-4a0f-9ff2-10cc3f835920', // URL
text: '猴子岩鱼类增殖站',
description: '猴子岩水电站鱼类增殖放流站位于猴子岩水电站坝址下游约7.0km(业主营地下游约1.5km)大渡河左岸桃花渣场顶部平台上紧邻枢纽桃花大桥下游侧占地面积47.3亩其中一期工程27.0亩预留二期工程用地20.3亩(二期工程目前为丹巴、巴底水电站预留工程)增殖放流站工作流程为:亲鱼收集购买、亲鱼驯养培育、人工催产和授精、人工孵化、苗种培育和放流。 猴子岩鱼类增殖放流站近期放流对象中齐口裂腹鱼、重口裂腹鱼、大渡软刺裸裂尻鱼增殖放流技术水平已趋于熟化,中期放流对象大渡软刺裸裂尻鱼人工繁殖技术逐渐趋于熟化'
},
{
type: 'image',
url: 'https://211.99.26.225:12125/?20230805205924378504010675106305&view=jpg&token=bearer c2e76c28-14db-4a0f-9ff2-10cc3f835920',
text: '黑马鱼类增殖站',
description: '大渡河黑马鱼类增殖放流站位于四川省甘洛县黑马乡黑马业主营地内距离甘洛县城45km,区域交通路况较好。主要承担瀑布沟、深溪沟、大岗山、枕头坝一级、沙坪二级等五座水电站鱼类增殖放流的重任。放流鱼类包含:齐口裂腹鱼、重口裂腹鱼、鲈鲤、长薄鳅、白甲鱼、中华倒刺、长吻脆、稀有鮊鲫、华鲮、侧沟爬岩鳅等10个种类共计约918.07万尾珍稀特有鱼苗。'
}
]);
//
// [, ..., ]
const renderMediaData = ref<MediaItem[]>([]);
// renderMediaData
const currentIndex = ref(1); // 1
//
let timer: any = null;
//
const isHovering = ref(false);
// transition
const isTransitioning = ref(false);
//
const initRenderData = () => {
const length = originalMediaData.value.length;
if (length === 0) return;
renderMediaData.value = [
originalMediaData.value[length - 1], //
...originalMediaData.value, //
originalMediaData.value[0] //
];
};
//
const startAutoPlay = () => {
if (timer) clearInterval(timer);
timer = setInterval(() => {
if (!isHovering.value && !isTransitioning.value) {
nextSlide();
}
}, 4000);
};
//
const nextSlide = () => {
currentIndex.value++;
//
setTimeout(() => {
checkSeamlessJump();
}, 500); // transition
};
//
const checkSeamlessJump = () => {
const realLength = originalMediaData.value.length;
// = realLength + 1
if (currentIndex.value >= realLength + 1) {
// 1.
isTransitioning.value = true;
// 2. 1
currentIndex.value = 1;
// 3. DOM
requestAnimationFrame(() => {
requestAnimationFrame(() => {
isTransitioning.value = false;
});
});
}
};
//
const handleMouseEnter = () => {
isHovering.value = true;
};
//
const handleMouseLeave = () => {
isHovering.value = false;
};
//
const currentDescription = computed(() => {
const realIndex = getCurrentRealIndex();
return originalMediaData.value[realIndex]?.description || '';
});
//
onMounted(() => {
initRenderData();
startAutoPlay();
});
//
onUnmounted(() => {
if (timer) clearInterval(timer);
});
//
const getCurrentRealIndex = () => {
const realLength = originalMediaData.value.length;
let realIndex = currentIndex.value - 1; //
//
if (realIndex < 0) realIndex = realLength - 1;
if (realIndex >= realLength) realIndex = 0;
return realIndex;
};
//
const goToSlide = (targetIndex: number) => {
if (isTransitioning.value) return;
//
currentIndex.value = targetIndex + 1;
};
</script>
<style lang="scss" scoped>
.container {
width: 100%;
height: 228px;
// border: 1px solid #7fd6ff;
// border-radius: 5px;
position: relative;
overflow: hidden; //
//
.carousel-track {
display: flex; //
width: 100%;
height: 100%;
transition: transform 0.5s ease-in-out; // 0.5
//
&.no-transition {
transition: none;
}
//
.carousel-item {
min-width: 100%; //
height: 100%;
position: relative;
flex-shrink: 0; //
img,
video {
width: 100%;
height: 100%;
object-fit: cover; //
}
.text {
position: absolute;
bottom: 0;
left: 0;
width: 100%;
height: 22px;
line-height: 22px;
background: rgba(0, 0, 0, 0.1);
color: #fff;
padding-left: 10px;
}
}
}
//
.pagination-dots-fixed {
position: absolute;
bottom: 10px;
right: 10px;
display: flex;
gap: 6px;
z-index: 10; //
.dot {
width: 5px;
height: 5px;
border-radius: 50%;
background-color: #D8D8D8;
cursor: pointer;
transition: background-color 0.3s ease;
&.active {
background-color: #005293;
}
&:hover {
opacity: 0.8;
}
}
}
}
//
.description-text {
// padding: 8px 12px;
font-size: 14px;
line-height: 1.5;
// min-height: 40px;
transition: all 0.3s ease;
margin-bottom: 20px;
//
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
word-break: break-word;
}
</style>

View File

@ -12,7 +12,7 @@
<div class="facility-info"> <div class="facility-info">
<div class="facility-name">{{ facility.name }}</div> <div class="facility-name">{{ facility.name }}</div>
<div style="font-size: 16px;"> <span class="facility-count">{{ facility.count <div style="font-size: 16px;"> <span class="facility-count">{{ facility.count
}}</span><span></span></div> }}</span><span></span></div>
</div> </div>
</div> </div>
</div> </div>

View File

@ -0,0 +1,140 @@
<!-- SidePanelItem.vue -->
<template>
<SidePanelItem title="AI识别过鱼设施运行" :datetimePicker="datetimePicker">
<div class="facility-grid">
<div v-for="facility in facilities" :key="facility.name" class="facility-card">
<div style="width: 70px;height: 62px;display: flex;align-items: center;justify-content: center;">
<div class="facility-icon">
<i style="color: #fff;" :class="facility.icon" type="icon-shengtailiuliang2"></i>
</div>
</div>
<div class="facility-info">
<div class="facility-name">{{ facility.name }}</div>
<div style="font-size: 14px;"> <span class="facility-count">{{ facility.count }}</span>
<span></span>
</div>
</div>
</div>
</div>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
// 便
defineOptions({
name: 'zengzhizhanjiansheyunxing'
});
const datetimePicker = ref({
show: true,
value: `${new Date().getFullYear() - 1}`, //
format: 'YYYY-MM',
picker: 'month' as const,
options: []
});
//
const facilities = ref([
{
name: '赶鱼栅运行',
count: "32",
icon: 'icon iconfont icon-ganyushan'
},
{
name: '升鱼斗运行',
count: '66',
icon: 'icon iconfont icon-liuliangjiancezhan1'
},
{
name: 'AGV小车',
count: '0',
icon: 'icon iconfont icon-agvxiaoche'
},
{
name: '运鱼车运行',
count: '0',
icon: 'icon iconfont icon-yunyuche'
},
{
name: '运鱼船出港',
count: '32',
icon: 'icon iconfont icon-yunyuchuan'
},
{
name: '鱼道放流',
count: '0',
icon: 'icon iconfont icon-yudaofangliu'
}
]);
//
onMounted(() => {
//
});
//
onUnmounted(() => {
});
</script>
<style lang="scss" scoped>
.facility-grid {
width: 406px;
flex-flow: wrap;
display: flex;
justify-content: space-between;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
}
.facility-card {
width: 200px;
height: 70px;
display: flex;
align-items: center;
justify-content: space-between;
margin: 4px 0px;
background: #fff;
border: 1px solid #e8e8e8;
border-radius: 2px;
transition: all 0.3s;
cursor: pointer;
box-sizing: border-box;
}
.facility-icon {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
// margin-right: 8px;
background: rgb(47, 107, 152);
border-radius: 50%;
.anticon {
font-size: 24px;
color: #fff;
}
}
.facility-info {
flex: 1;
}
.facility-name {
font-size: 16px;
color: #333;
// margin-bottom: 4px;
// font-weight: 500;
}
.facility-count {
font-size: 18px;
color: #2f6b98;
// font-weight: 600;
}
</style>

View File

@ -0,0 +1,88 @@
<!-- SidePanelItem.vue -->
<template>
<div>
<SidePanelItem title="生态流量低于限值告警情况">
<div class="body_box">
<div class="box" v-for="(item, index) in data" :key="index">
<div>
<div :class="item.icon" :style="{background:item.background}"></div>
<div class="title_text">{{ item.name }}</div>
</div>
<div><span class="text_num">{{ item.num }}</span><span></span></div>
</div>
</div>
</SidePanelItem>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, watch } from "vue";
import SidePanelItem from "@/components/SidePanelItem/index.vue";
// 便
defineOptions({
name: "jidiInfoMod",
});
const data = ref([
{
name:'正常',
num:'447',
icon:'iconfont icon-shuidianzhan1 zhuangji',
background:'#78c300',
},
{
name:'告警',
num:'0',
icon:'iconfont icon-shuidianzhanGaojing shebeiZhengchang',
background:'#e55555',
},
{
name:'无数据',
num:'6',
icon:'iconfont icon-shuidianzhanWushujv shebeiLixian',
background:'#8d8d8d',
},
])
//
onMounted(() => { });
</script>
<style lang="scss">
.body_box {
width: 100%;
height: 132px;
display: flex;
align-items: center;
justify-content: space-between;
.box {
width: 126px;
height: 116px;
border: 1px solid rgba(108, 164, 247, 0.35);
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.iconfont {
width: 40px;
height: 40px;
background: #78c300;
border-radius: 50%;
text-align: center;
line-height: 40px;
font-size: 24px;
color: #fff;
}
.title_text{
width: 100%;
text-align: center;
}
.text_num{
width: 100%;
text-align: center;
font-size: 24px;
}
}
}
</style>

View File

@ -0,0 +1,95 @@
<!-- SidePanelItem.vue -->
<template>
<div>
<SidePanelItem title="水质监测数据告警情况" :select="select" >
<div class="body_box">
<div class="box" v-for="(item, index) in data" :key="index">
<div>
<div :class="item.icon" :style="{background:item.background}"></div>
<div class="title_text">{{ item.name }}</div>
</div>
<div><span class="text_num">{{ item.num }}</span><span></span></div>
</div>
</div>
</SidePanelItem>
</div>
</template>
<script lang="ts" setup>
import { ref, onMounted, watch } from "vue";
import SidePanelItem from "@/components/SidePanelItem/index.vue";
// 便
defineOptions({
name: "jidiInfoMod",
});
const select = ref({
show: true,
value: undefined,
options: [],
picker: undefined,
format: undefined
});
const data = ref([
{
name:'正常',
num:'56',
icon:'iconfont icon-shuidianzhan1 zhuangji',
background:'#78c300',
},
{
name:'告警',
num:'0',
icon:'iconfont icon-shuidianzhanGaojing shebeiZhengchang',
background:'#e55555',
},
{
name:'无数据',
num:'0',
icon:'iconfont icon-shuidianzhanWushujv shebeiLixian',
background:'#8d8d8d',
},
])
//
onMounted(() => { });
</script>
<style lang="scss">
.body_box {
width: 100%;
height: 132px;
display: flex;
align-items: center;
justify-content: space-between;
.box {
width: 126px;
height: 116px;
border: 1px solid rgba(108, 164, 247, 0.35);
display: flex;
justify-content: center;
flex-direction: column;
align-items: center;
.iconfont {
width: 40px;
height: 40px;
background: #78c300;
border-radius: 50%;
text-align: center;
line-height: 40px;
font-size: 24px;
color: #fff;
}
.title_text{
width: 100%;
text-align: center;
}
.text_num{
width: 100%;
text-align: center;
font-size: 24px;
}
}
}
</style>

View File

@ -0,0 +1,133 @@
<!-- SidePanelItem.vue -->
<template>
<SidePanelItem title="水生生态调查情况" :select="select" :datetimePicker="datetimePicker">
<div class="facility-grid">
<div v-for="facility in facilities" :key="facility.name" class="facility-card">
<div style="width: 60px;height: 62px;display: flex;align-items: center;justify-content: center;">
<div class="facility-icon">
<i style="color: #fff;" :class="facility.icon" type="icon-shengtailiuliang2"></i>
</div>
</div>
<div class="facility-info">
<div class="facility-name">{{ facility.name }}</div>
<div style="font-size: 16px;"> <span class="facility-count">{{ facility.count
}}</span><span></span></div>
</div>
</div>
</div>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
//
defineOptions({
name: 'shuishengshengtaijiance'
});
// ==================== ====================//
const select = ref({
show: true,
value: undefined,
options: [],
picker: undefined,
format: undefined
});
//
const datetimePicker = ref({
show: true,
value: `${new Date().getFullYear()}`,
format: 'YYYY',
picker: 'year' as const,
options: []
});
const facilities = ref([
{
name: '红外相机数量',
count: 31,
icon: 'icon iconfont icon-shipinjiankongshebei'
},
{
name: '重点陆生动物',
count: 24,
icon: 'icon iconfont icon-dongwujiuzhuzhan'
},
]);
// ==================== ====================
//
onMounted(() => {
});
//
onUnmounted(() => {
});
</script>
<style lang="scss" scoped>
.facility-grid {
width: 406px;
flex-flow: wrap;
display: flex;
justify-content: space-between;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
}
.facility-card {
width: 200px;
height: 64px;
display: flex;
align-items: center;
justify-content: space-between;
margin: 4px 0px;
background: #fff;
border: 1px solid #e8e8e8;
border-radius: 2px;
transition: all 0.3s;
cursor: pointer;
box-sizing: border-box;
}
.facility-icon {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
// margin-right: 8px;
background: #2f6b98;
border-radius: 50%;
.anticon {
font-size: 24px;
color: #fff;
}
}
.facility-info {
flex: 1;
}
.facility-name {
font-size: 16px;
color: #333;
// margin-bottom: 4px;
// font-weight: 500;
}
.facility-count {
font-size: 18px;
color: #2f6b98;
// font-weight: 600;
}
</style>

View File

@ -2,25 +2,23 @@
<template> <template>
<SidePanelItem title="主要栖息地基本信息" :select="select"> <SidePanelItem title="主要栖息地基本信息" :select="select">
<div class="table-container"> <div class="table-container">
<a-table <a-table :columns="columns" :data-source="tableData" :pagination="pagination" :scroll="{ y: 450 }"
:columns="columns" size="small">
:data-source="tableData"
:pagination="pagination"
:scroll="{ y: 450 }"
size="small"
>
<template #bodyCell="{ column, record }"> <template #bodyCell="{ column, record }">
<!-- 仅栖息地列需要自定义渲染 --> <!-- 仅栖息地列需要自定义渲染 -->
<template v-if="column.key === 'fhstnm'"> <template v-if="column.key === 'fhstnm'">
<a-tooltip :title="record.fhstnm"> <a-tooltip :title="record.fhstnm">
<span <span class="habitat-cell" @click="handleHabitatClick(record)">
class="habitat-cell" {{ formatValue(record.fhstnm) }}
@click="handleHabitatClick(record)"
>
{{ record.fhstnm }}
</span> </span>
</a-tooltip> </a-tooltip>
</template> </template>
<!-- 其他列统一处理空值 -->
<template v-else>
<a-tooltip :title="formatValue(record[column.dataIndex])">
<span>{{ formatValue(record[column.dataIndex]) }}</span>
</a-tooltip>
</template>
</template> </template>
</a-table> </a-table>
</div> </div>
@ -92,152 +90,174 @@ const pagination = {
} }
// //
const tableData = ref([ const tableData = ref(
{ [
key: '1', {
fhstnm: '长江上游珍稀鱼类栖息地A区', key: "1",
bhhl: '金沙江', qxdbhdx: null,
qxdbhdx: '中华鲟', fhstnm: "泽曲河鱼类栖息地",
qxdbhcd: 120.5, bhhl: "泽曲河",
qxdbhmj: 85.3 qxdbhcd: null,
}, qxdbhmj: null
{ },
key: '2', {
fhstnm: '岷江特有鱼类保护区', key: "2",
bhhl: '岷江', qxdbhdx: null,
qxdbhdx: '胭脂鱼', fhstnm: "黄河干流羊曲库尾河段鱼类栖息地",
qxdbhcd: 95.2, bhhl: "黄河干流",
qxdbhmj: 62.7 qxdbhcd: null,
}, qxdbhmj: null
{ },
key: '3', {
fhstnm: '雅砻江冷水鱼栖息地', key: "3",
bhhl: '雅砻江', qxdbhdx: "裂腹鱼、高原鳅类、鲇类",
qxdbhdx: '齐口裂腹鱼', fhstnm: "翠依河鱼类栖息地",
qxdbhcd: 110.8, bhhl: "翠依河",
qxdbhmj: 78.4 qxdbhcd: null,
}, qxdbhmj: null
{ },
key: '4', {
fhstnm: '大渡河高原鳅保护区', key: "4",
bhhl: '大渡河', qxdbhdx: "裂腹鱼、高原鳅类、鲇类",
qxdbhdx: '高原鳅', fhstnm: "金棉河鱼类栖息地",
qxdbhcd: 88.6, bhhl: "金棉河",
qxdbhmj: 55.9 qxdbhcd: null,
}, qxdbhmj: null
{ },
key: '5', {
fhstnm: '乌江珍稀鱼类核心栖息地', key: "5",
bhhl: '乌江', qxdbhdx: null,
qxdbhdx: '岩原鲤', fhstnm: "斜曲河口以上河段鱼类栖息地",
qxdbhcd: 135.4, bhhl: "斜曲",
qxdbhmj: 92.1 qxdbhcd: null,
}, qxdbhmj: null
{ },
key: '6', {
fhstnm: '嘉陵江鱼类自然保护区', key: "6",
bhhl: '嘉陵江', qxdbhdx: "白鲟、达氏鲟、胭脂鱼等珍稀特有鱼类",
qxdbhdx: '白甲鱼', fhstnm: "长江上游珍稀、特有鱼类国家级自然保护区",
qxdbhcd: 102.3, bhhl: "金沙江下游",
qxdbhmj: 71.5 qxdbhcd: 681,
}, qxdbhmj: null
{ },
key: '7', {
fhstnm: '沱江特有鱼类栖息地B段', key: "7",
bhhl: '沱江', qxdbhdx: null,
qxdbhdx: '圆口铜鱼', fhstnm: "六冲河种质资源保护区",
qxdbhcd: 76.9, bhhl: "六冲河、红岩河、后河、伍佐河",
qxdbhmj: 48.2 qxdbhcd: 146,
}, qxdbhmj: null
{ },
key: '8', {
fhstnm: '赤水河珍稀鱼类保护区', key: "8",
bhhl: '赤水河', qxdbhdx: "黄颡鱼、中华倒刺鲃、白甲鱼、鲤鱼、鲶鱼(鲇)、草鱼",
qxdbhdx: '赤水河独鱼', fhstnm: "白果树水电站坝址下游至河口段鱼类栖息地",
qxdbhcd: 118.7, bhhl: "乌江干流",
qxdbhmj: 82.6 qxdbhcd: 13,
}, qxdbhmj: null
{ },
key: '9', {
fhstnm: '涪江高原鱼类栖息地', key: "9",
bhhl: '涪江', qxdbhdx: null,
qxdbhdx: '松潘裸鲤', fhstnm: "红水河岩滩、大化、百龙滩、桥巩河段鱼类栖息地",
qxdbhcd: 92.4, bhhl: "红水河",
qxdbhmj: 64.8 qxdbhcd: null,
}, qxdbhmj: null
{ },
key: '10', {
fhstnm: '渠江特有鱼类核心保护区', key: "10",
bhhl: '渠江', qxdbhdx: "长身鱖、鯮、湖南吻鮈、湘华鲮、湘江蛇鮈",
qxdbhdx: '华鳊', fhstnm: "白洋河鱼类栖息地",
qxdbhcd: 105.6, bhhl: "白洋河",
qxdbhmj: 73.9 qxdbhcd: 121,
}, qxdbhmj: null
{ },
key: '11', {
fhstnm: '汉江上游珍稀鱼类栖息地', key: "11",
bhhl: '汉江', qxdbhdx: null,
qxdbhdx: '多鳞铲颌鱼', fhstnm: "锡潭水电站以下河段鱼类栖息地",
qxdbhcd: 128.3, bhhl: "麻溪",
qxdbhmj: 89.7 qxdbhcd: null,
}, qxdbhmj: null
{ },
key: '12', {
fhstnm: '丹江口库区鱼类保护区', key: "12",
bhhl: '丹江', qxdbhdx: null,
qxdbhdx: '青鱼', fhstnm: "西曲二级电站厂址至河口段鱼类栖息地",
qxdbhcd: 142.5, bhhl: "西曲",
qxdbhmj: 98.4 qxdbhcd: 23,
}, qxdbhmj: null
{ },
key: '13', {
fhstnm: '清江土著鱼类栖息地', key: "13",
bhhl: '清江', qxdbhdx: null,
qxdbhdx: '清江银鱼', fhstnm: "落漏河、达旦河段鱼类栖息地",
qxdbhcd: 85.7, bhhl: "支流落漏河、达旦河",
qxdbhmj: 59.3 qxdbhcd: null,
}, qxdbhmj: null
{ },
key: '14', {
fhstnm: '湘江珍稀鱼类核心栖息地C区', key: "14",
bhhl: '湘江', qxdbhdx: "长身鱖、鯮、湖南吻鮈、湘华鲮、湘江蛇鮈",
qxdbhdx: '湘鲫', fhstnm: "陬溪鱼类栖息地",
qxdbhcd: 112.9, bhhl: "陬溪",
qxdbhmj: 79.6 qxdbhcd: 38.9,
}, qxdbhmj: null
{ },
key: '15', {
fhstnm: '赣江特有鱼类保护区', key: "15",
bhhl: '赣江', qxdbhdx: null,
qxdbhdx: '赣江鮰', fhstnm: "资水金塘冲至马迹塘段鱼类栖息地",
qxdbhcd: 98.4, bhhl: "资水",
qxdbhmj: 68.2 qxdbhcd: null,
}, qxdbhmj: null
{ },
key: '16', {
fhstnm: '闽江珍稀鱼类栖息地D段', key: "16",
bhhl: '闽江', qxdbhdx: null,
qxdbhdx: '闽江小鳔鮈', fhstnm: "西科河鱼类栖息地",
qxdbhcd: 106.8, bhhl: "西科河",
qxdbhmj: 74.5 qxdbhcd: null,
}, qxdbhmj: null
{ },
key: '17', {
fhstnm: '珠江三角洲鱼类核心保护区', key: "17",
bhhl: '珠江', qxdbhdx: null,
qxdbhdx: '唐鱼', fhstnm: "尕柯河鱼类栖息地",
qxdbhcd: 132.6, bhhl: "尕柯河",
qxdbhmj: 91.8 qxdbhcd: null,
}, qxdbhmj: null
{ },
key: '18', {
fhstnm: '西江上游珍稀鱼类栖息地', key: "18",
bhhl: '西江', qxdbhdx: null,
qxdbhdx: '光倒刺鲃', fhstnm: "赛欠沟鱼类栖息地",
qxdbhcd: 115.3, bhhl: "赛欠沟",
qxdbhmj: 80.7 qxdbhcd: null,
} qxdbhmj: null
]) },
{
key: "19",
qxdbhdx: null,
fhstnm: "得科河鱼类栖息地",
bhhl: "得科河",
qxdbhcd: null,
qxdbhmj: null
},
{
key: "20",
qxdbhdx: null,
fhstnm: "黄河班多坝下及巴沟河段鱼类栖息地",
bhhl: "黄河干流、巴沟河",
qxdbhcd: 11,
qxdbhmj: null
}
])
//
const formatValue = (value: any): string => {
return value === null || value === undefined || value === '' ? '-' : String(value);
}
// //
const handleHabitatClick = (record: any) => { const handleHabitatClick = (record: any) => {
@ -270,7 +290,7 @@ onUnmounted(() => {
} }
// //
.ant-table-thead > tr > th { .ant-table-thead>tr>th {
font-weight: 500; font-weight: 500;
} }
} }

View File

@ -1,6 +1,6 @@
<!-- SidePanelItem.vue --> <!-- SidePanelItem.vue -->
<template> <template>
<SidePanelItem title="水文监测" :select="select"> <SidePanelItem title="水文监测" :select="select" :scopeDate="datetimePicker" >
<div class="chart-container"> <div class="chart-container">
<div ref="chartRef" class="echarts-chart"></div> <div ref="chartRef" class="echarts-chart"></div>
</div> </div>
@ -26,6 +26,20 @@ const select = ref({
picker: undefined, picker: undefined,
format: undefined format: undefined
}); });
//
const datetimePicker = ref({
show: true,
value: (() => {
const now = new Date();
const currentMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
const lastMonthStr = `${lastMonth.getFullYear()}-${String(lastMonth.getMonth() + 1).padStart(2, '0')}`;
return [lastMonthStr, currentMonth];
})(),
format: 'YY-MM',
picker: 'month' as const,
options: []
});
// ==================== ==================== // ==================== ====================
const chartRef = ref<HTMLElement | null>(null); const chartRef = ref<HTMLElement | null>(null);

View File

@ -1,6 +1,6 @@
<!-- SidePanelItem.vue --> <!-- SidePanelItem.vue -->
<template> <template>
<SidePanelItem title="水温监测" :select="select" :datetimePicker="datetimePicker"> <SidePanelItem title="水温监测" :select="select" :scopeDate="datetimePicker">
<div ref="chartRef" class="water-temp-chart"></div> <div ref="chartRef" class="water-temp-chart"></div>
</SidePanelItem> </SidePanelItem>
</template> </template>
@ -34,9 +34,15 @@ const select = ref({
// //
const datetimePicker = ref({ const datetimePicker = ref({
show: true, show: true,
value: undefined, value: (() => {
format: 'YYYY', const now = new Date();
picker: 'year' as const, const currentMonth = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, '0')}`;
const lastMonth = new Date(now.getFullYear(), now.getMonth() - 1, 1);
const lastMonthStr = `${lastMonth.getFullYear()}-${String(lastMonth.getMonth() + 1).padStart(2, '0')}`;
return [lastMonthStr, currentMonth];
})(),
format: 'YY-MM',
picker: 'month' as const,
options: [] options: []
}); });

View File

@ -0,0 +1,196 @@
<!-- SidePanelItem.vue -->
<template>
<SidePanelItem title="水生生态调查" :select="select" :datetimePicker="datetimePicker">
<div ref="chartRef" class="echarts-container"></div>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
//
defineOptions({
name: 'shuiShengShengTaiDiaoCha'
});
// ==================== ====================
const chartRef = ref<HTMLDivElement>();
let chartInstance: any = null;
//
const select = ref({
show: true,
value: undefined,
options: [],
picker: undefined,
format: undefined
});
//
const datetimePicker = ref({
show: true,
value: '2020',
format: 'YYYY',
picker: 'year' as const,
options: []
});
// ==================== ====================
const mockData = [
{ name: '鱼类', value: 320 },
{ name: '底栖动物', value: 280 },
{ name: '浮游植物', value: 250 },
{ name: '浮游动物', value: 220 },
{ name: '水生植物', value: 190 },
{ name: '两栖类', value: 150 },
{ name: '爬行类', value: 120 },
{ name: '鸟类', value: 100 },
{ name: '哺乳类', value: 80 },
{ name: '其他', value: 60 }
];
//
const totalValue = mockData.reduce((sum, item) => sum + item.value, 0);
// ==================== ====================
const initChart = () => {
if (!chartRef.value) return;
//
const rect = chartRef.value.getBoundingClientRect();
if (rect.width === 0 || rect.height === 0) {
console.warn('图表容器尺寸为0稍后重试...');
setTimeout(() => initChart(), 50);
return;
}
//
chartInstance = echarts.init(chartRef.value);
//
const option: EChartsOption = {
color: [
'#5470c6', '#91cc75', '#fac858', '#ee6666', '#73c0de',
'#3ba272', '#fc8452', '#9a60b4', '#ea7ccc', '#8dd3a7'
],
tooltip: {
trigger: 'item',
backgroundColor: 'rgba(0, 0, 0, 0.5)',
borderColor: 'transparent',
textStyle: {
color: '#ffffff'
},
formatter: '{b}: {c} ({d}%)'
},
legend: {
type: 'scroll',
orient: 'horizontal',
bottom: '5%',
data: mockData.map(item => item.name),
icon: 'rect',
itemWidth: 14,
itemHeight: 14,
textStyle: {
fontSize: 12,
height: 8
},
pageTextStyle: {
color: '#333'
},
pageIconColor: '#2F6B98',
pageIconInactiveColor: '#aaa'
},
title: [
{
text: `(类)`,
top: '42%',
textAlign: 'center',
left: '50%',
textStyle: {
color: '#333',
fontSize: 13,
fontWeight: 500
}
},
{
text: totalValue.toString(),
left: 'center',
top: '32%',
textStyle: {
color: '#2F6B98',
fontSize: 24
}
}
],
series: [
{
name: '生态类别',
type: 'pie',
radius: ['35%', '65%'],
center: ['50%', '40%'],
avoidLabelOverlap: false,
label: {
show: true,
position: 'outside',
formatter: '{b}: {c}'
},
labelLine: {
show: true,
length: 8,
length2: 10
},
emphasis: {
label: {
show: true,
fontSize: 14,
fontWeight: 'bold'
}
},
data: mockData
}
]
};
//
chartInstance.setOption(option);
};
// ==================== resize ====================
const handleResize = () => {
if (chartInstance) {
chartInstance.resize();
}
};
// ==================== ====================
//
onMounted(() => {
nextTick(() => {
setTimeout(() => {
initChart();
window.addEventListener('resize', handleResize);
}, 50);
});
});
//
onUnmounted(() => {
window.removeEventListener('resize', handleResize);
if (chartInstance) {
chartInstance.dispose();
chartInstance = null;
}
});
</script>
<style lang="scss" scoped>
.echarts-container {
width: 100%;
height: 270px;
min-height: 270px;
}
</style>

View File

@ -0,0 +1,133 @@
<!-- SidePanelItem.vue -->
<template>
<SidePanelItem title="水生生态调查情况" :select="select" :datetimePicker="datetimePicker">
<div class="facility-grid">
<div v-for="facility in facilities" :key="facility.name" class="facility-card">
<div style="width: 60px;height: 62px;display: flex;align-items: center;justify-content: center;">
<div class="facility-icon">
<i style="color: #fff;" :class="facility.icon" type="icon-shengtailiuliang2"></i>
</div>
</div>
<div class="facility-info">
<div class="facility-name">{{ facility.name }}</div>
<div style="font-size: 16px;"> <span class="facility-count">{{ facility.count
}}</span><span></span></div>
</div>
</div>
</div>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, nextTick } from 'vue';
import * as echarts from 'echarts';
import type { EChartsOption } from 'echarts';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
//
defineOptions({
name: 'shuishengshengtaijiance'
});
// ==================== ====================//
const select = ref({
show: true,
value: undefined,
options: [],
picker: undefined,
format: undefined
});
//
const datetimePicker = ref({
show: true,
value: '2023',
format: 'YYYY',
picker: 'year' as const,
options: []
});
const facilities = ref([
{
name: '水生态调查断面',
count: 145,
icon: 'icon iconfont icon-liuliangjiancezhan'
},
{
name: '调查鱼类统计',
count: 24,
icon: 'icon iconfont icon-yuleizengzhizhan'
},
]);
// ==================== ====================
//
onMounted(() => {
});
//
onUnmounted(() => {
});
</script>
<style lang="scss" scoped>
.facility-grid {
width: 406px;
flex-flow: wrap;
display: flex;
justify-content: space-between;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
}
.facility-card {
width: 200px;
height: 64px;
display: flex;
align-items: center;
justify-content: space-between;
margin: 4px 0px;
background: #fff;
border: 1px solid #e8e8e8;
border-radius: 2px;
transition: all 0.3s;
cursor: pointer;
box-sizing: border-box;
}
.facility-icon {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
// margin-right: 8px;
background: #2f6b98;
border-radius: 50%;
.anticon {
font-size: 24px;
color: #fff;
}
}
.facility-info {
flex: 1;
}
.facility-name {
font-size: 16px;
color: #333;
// margin-bottom: 4px;
// font-weight: 500;
}
.facility-count {
font-size: 18px;
color: #2f6b98;
// font-weight: 600;
}
</style>

View File

@ -0,0 +1,121 @@
<!-- SidePanelItem.vue -->
<template>
<SidePanelItem title="AI识别大坝环境" :datetimePicker="datetimePicker">
<div class="facility-grid">
<div v-for="facility in facilities" :key="facility.name" class="facility-card">
<div style="width: 70px;height: 62px;display: flex;align-items: center;justify-content: center;">
<div class="facility-icon">
<i style="color: #fff;" :class="facility.icon" type="icon-shengtailiuliang2"></i>
</div>
</div>
<div class="facility-info">
<div class="facility-name">{{ facility.name }}</div>
<div style="font-size: 14px;"> <span class="facility-count">{{ facility.count }}</span>
<span></span>
</div>
</div>
</div>
</div>
</SidePanelItem>
</template>
<script lang="ts" setup>
import { ref, onMounted, onUnmounted, watch, nextTick } from 'vue';
import SidePanelItem from '@/components/SidePanelItem/index.vue';
// 便
defineOptions({
name: 'zengzhizhanjiansheyunxing'
});
const datetimePicker = ref({
show: true,
value: `${new Date().getFullYear() - 1}`, //
format: 'YYYY-MM',
picker: 'month' as const,
options: []
});
//
const facilities = ref([
{
name: '漂浮物识别',
count: "34",
icon: 'icon iconfont icon-piaofuwu'
},
{
name: '叠梁门运行识别',
count: '0',
icon: 'icon iconfont icon-dieliangmen1'
},
]);
//
onMounted(() => {
//
});
//
onUnmounted(() => {
});
</script>
<style lang="scss" scoped>
.facility-grid {
width: 406px;
flex-flow: wrap;
display: flex;
justify-content: space-between;
font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Helvetica Neue, Arial, Noto Sans, sans-serif, Apple Color Emoji, Segoe UI Emoji, Segoe UI Symbol, Noto Color Emoji;
}
.facility-card {
width: 200px;
height: 70px;
display: flex;
align-items: center;
justify-content: space-between;
margin: 4px 0px;
background: #fff;
border: 1px solid #e8e8e8;
border-radius: 2px;
transition: all 0.3s;
cursor: pointer;
box-sizing: border-box;
}
.facility-icon {
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
// margin-right: 8px;
background: rgb(47, 107, 152);
border-radius: 50%;
.anticon {
font-size: 24px;
color: #fff;
}
}
.facility-info {
flex: 1;
}
.facility-name {
font-size: 16px;
color: #333;
// margin-bottom: 4px;
// font-weight: 500;
}
.facility-count {
font-size: 18px;
color: #2f6b98;
// font-weight: 600;
}
</style>

View File

@ -31,7 +31,7 @@ const select = ref({
const datetimePicker = ref({ const datetimePicker = ref({
show: true, show: true,
value: undefined, value: `${new Date().getFullYear() }`,
format: 'YYYY', // YYYY-MM-DD HH format: 'YYYY', // YYYY-MM-DD HH
picker: 'year' as const, // date | week | month | quarter | year picker: 'year' as const, // date | week | month | quarter | year
options: [] options: []

View File

@ -32,7 +32,7 @@ defineOptions({
}); });
const datetimePicker = ref({ const datetimePicker = ref({
show: true, show: true,
value: undefined, value: `${new Date().getFullYear() - 1}`, //
format: 'YYYY', format: 'YYYY',
picker: 'year' as const, picker: 'year' as const,
options: [] options: []

View File

@ -18,7 +18,7 @@ defineOptions({
const datetimePicker = ref({ const datetimePicker = ref({
show: true, show: true,
value: undefined, value: `${new Date().getFullYear() - 1}`, //
format: 'YYYY', format: 'YYYY',
picker: 'year' as const, picker: 'year' as const,
options: [] options: []

View File

@ -55,6 +55,8 @@ router.beforeEach(async (to, from, next) => {
if (userStore.Token) { if (userStore.Token) {
// 登录成功,跳转到首页 // 登录成功,跳转到首页
if (to.path === '/login') {
//login
if (to.path === '/login') { if (to.path === '/login') {
//login //login
next({ path: '/' }); next({ path: '/' });
@ -87,6 +89,7 @@ router.beforeEach(async (to, from, next) => {
accessRoutes = normalizeRoutes(accessRoutes); accessRoutes = normalizeRoutes(accessRoutes);
accessRoutes.forEach((route: any) => { accessRoutes.forEach((route: any) => {
console.log('Adding Route:', route.path);
router.addRoute(route); router.addRoute(route);
}); });

View File

@ -1,5 +1,23 @@
<script setup lang="ts">
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
import RightDrawer from "@/components/RightDrawer/index.vue";
import ZhuanZhiIntroduce from '@/modules/fishSurvey/ZhuanZhiIntroduce/index.vue'
import FishIntroduce from '@/modules/fishSurvey/FishIntroduce/index.vue'
import FishVideo from '@/modules/fishSurvey/FishVideo/index.vue'
</script>
<template> <template>
<div> <div class="moduleContent">
<h2>鱼类调查装置</h2> <div class="leftContent">
<JidiSelectorMod />
</div>
<div class="rightContent">
<RightDrawer>
<ZhuanZhiIntroduce />
<FishIntroduce />
<FishVideo />
</RightDrawer>
</div>
</div> </div>
</template> </template>
<style scoped lang="scss"></style>

View File

@ -1,5 +1,21 @@
<script setup lang="ts">
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
import RightDrawer from "@/components/RightDrawer/index.vue";
import LSSTJCQKTT from "@/modules/lushengshengtaijiance/index.vue"
import Ysdwjc from "@/modules/Ysdwjc/index.vue"
</script>
<template> <template>
<div> <div class="moduleContent">
<h2>陆生生态调查</h2> <div class="leftContent">
<JidiSelectorMod />
</div>
<div class="rightContent">
<RightDrawer>
<LSSTJCQKTT />
<Ysdwjc />
</RightDrawer>
</div>
</div> </div>
</template> </template>
<style scoped lang="scss"></style>

View File

@ -1,5 +1,25 @@
<script setup lang="ts">
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
import RightDrawer from "@/components/RightDrawer/index.vue";
import SSSTJCQKTT from "@/modules/shuishengshengtaijiance/index.vue"
import SSSTDCQK from "@/modules/shuiShengShengTaiDiaoCha/index.vue" //
// import SSSTJCQKTT from "@/modules/shuishengshengtaijiance"
import AlongFishMod from "@/modules/alongFishMod/index.vue" //沿
</script>
<template> <template>
<div> <div class="moduleContent">
<h2>水生生态调查</h2> <div class="leftContent">
<JidiSelectorMod />
</div>
<div class="rightContent">
<RightDrawer>
<SSSTJCQKTT />
<SSSTDCQK />
<AlongFishMod />
</RightDrawer>
</div>
</div> </div>
</template> </template>
<style scoped lang="scss"></style>

View File

@ -1,5 +1,21 @@
<script setup lang="ts">
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
import RightDrawer from "@/components/RightDrawer/index.vue";
import Aisbdbyx from '@/modules/yunXingGaoJIng/Aisbdbyx/index.vue'
import SPDZWAIJC from '@/modules/liuyu/ai/spdzwaijc/index.vue'
</script>
<template> <template>
<div> <div class="moduleContent">
<h2>智能分析</h2> <div class="leftContent">
<JidiSelectorMod />
</div>
<div class="rightContent">
<RightDrawer>
<Aisbdbyx />
<SPDZWAIJC />
</RightDrawer>
</div>
</div> </div>
</template> </template>
<style scoped lang="scss"></style>

View File

@ -1,5 +1,33 @@
<script setup lang="ts">
import JidiSelectorMod from "@/modules/jidiSelectorMod.vue";
import RightDrawer from "@/components/RightDrawer/index.vue";
import Shengtailiuliangxianzhigaojing from '@/modules/liuyu/yichangyujing/shengtailiuliangxianzhigaojing/shengtailiuliangxianshuju.vue'
import Shuizhijiancegaojing from '@/modules/liuyu/yichangyujing/shuizhijiancegaojing/shuizhijianceshuju.vue'
</script>
<template> <template>
<div> <div class="moduleContent">
<h2>监测告警</h2> <div class="leftContent">
<JidiSelectorMod />
</div>
<div class="rightContent">
<RightDrawer>
<Shengtailiuliangxianzhigaojing />
<Shuizhijiancegaojing />
<div class="text"><img src="@/assets/components/tishi1.png" alt=""><span> 基于水电站及监测站最新监测数据进行告警统计</span></div>
</RightDrawer>
</div>
</div> </div>
</template> </template>
<style scoped lang="scss">
.text {
display: flex;
align-items: center;
color: #969696;
font-size: 14px;
span{
display: inline-block;
margin-left: 3px;
}
}
</style>

View File

@ -34,7 +34,7 @@ export default ({ mode }: ConfigEnv): UserConfig => {
}, },
'/geoserver': { '/geoserver': {
// target: 'https://211.99.26.225:18085', // 地图-线上API地址 // target: 'https://211.99.26.225:18085', // 地图-线上API地址
target: 'http://172.16.31.112:18084', // 地图-本地API地址 // target: 'http://172.16.31.112:8093', // 地图-本地API地址
changeOrigin: true, changeOrigin: true,
secure: false, secure: false,
rewrite: path => path.replace(new RegExp('^/geoserver'), '/geoserver') rewrite: path => path.replace(new RegExp('^/geoserver'), '/geoserver')