web
4 天以前 8f50c8203c8df64dd0a566b228bae7f69156e109
fix:添加季度选择器
已修改9个文件
已添加2个文件
562 ■■■■ 文件已修改
.env.development 2 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/screen/home/index.js 12 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/components/Quarter/index.vue 210 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/screen/flow/ecology/index.vue 4 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/screen/flow/graphic/index.vue 59 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/screen/flow/home/index.vue 77 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/screen/temperature/graphic/index.vue 127 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/screen/temperature/home/index.vue 46 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.js 15 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
.env.development
@@ -8,7 +8,5 @@
# 图片地址
VITE_APP_IMG_BASEURL='http://192.168.0.200:8036/upload'
# 金川接口
  # VITE_APP_PUBLIC_REQUEST_API = 'http://113.250.189.120:8036'
#后端本地
  VITE_APP_PUBLIC_REQUEST_API = 'http://192.168.0.200:8036'
package-lock.json
@@ -20,6 +20,7 @@
        "html2canvas": "^1.4.1",
        "js-cookie": "3.0.5",
        "jsencrypt": "3.3.2",
        "moment": "^2.30.1",
        "nprogress": "0.2.0",
        "pinia": "2.1.7",
        "pinia-plugin-persist": "^1.0.0",
@@ -3421,6 +3422,14 @@
        "ufo": "^1.5.3"
      }
    },
    "node_modules/moment": {
      "version": "2.30.1",
      "resolved": "https://registry.npmjs.org/moment/-/moment-2.30.1.tgz",
      "integrity": "sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how==",
      "engines": {
        "node": "*"
      }
    },
    "node_modules/ms": {
      "version": "2.1.2",
      "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
package.json
@@ -27,6 +27,7 @@
    "html2canvas": "^1.4.1",
    "js-cookie": "3.0.5",
    "jsencrypt": "3.3.2",
    "moment": "^2.30.1",
    "nprogress": "0.2.0",
    "pinia": "2.1.7",
    "pinia-plugin-persist": "^1.0.0",
src/api/screen/home/index.js
对比新文件
@@ -0,0 +1,12 @@
import { publicRequest } from '@/utils/request'
/**
 * 获取生态流量首页监测点
 */
export const getHomePonit = () => {
    return publicRequest({
        url: '/waterFlow/getPointDate',
        method: 'get',
    })
}
src/components/Quarter/index.vue
对比新文件
@@ -0,0 +1,210 @@
<script setup>
import {onMounted, ref, watch} from 'vue'
const props = defineProps({
    valueArr: {
        default: () => {
            return ['01-03', '04-06', '07-09', '10-12'];
        },
        type: Array,
    },
    getValue: {
        default: () => { },
        type: Function,
    },
    // 传入显示的时间
    defaultValue: {
        default: "",
        type: String,
    },
    limitTime: {
        type: String,
        default: ''
    },
    clearable: {
        type: Boolean,
        default: false
    },
    placeholder: {
        type: String,
        default: ''
    }
})
const emit = defineEmits(['change'])
const showSeason = ref(false)
const showValue = ref('')
const year =  ref(new Date().getFullYear())
const season = ref()
watch(() => props.defaultValue, (value) => {
    initDefaultValue(value)
})
const prev = () => {
    year.value = year.value * 1 - 1;
}
const next = () => {
    // 如果有时间限制的话会进行判断
    if (props.limitTime == "") {
        year.value =  year.value * 1 + 1;
    } else if (props.limitTime != "" &&  year.value < props.limitTime) {
        year.value =  year.value * 1 + 1;
    }
}
const whitchQuarter = (month) => {
    let quarter = "";
    month = Number(month);
    switch (month) {
        case 1:
        case 2:
        case 3:
            quarter = "1";
            break;
        case 4:
        case 5:
        case 6:
            quarter = "2";
            break;
        case 7:
        case 8:
        case 9:
            quarter = "3";
            break;
        case 10:
        case 11:
        case 12:
            quarter = "4";
            break;
        default:
            console.error("The entered time is incorrect");
    }
    return quarter;
}
// 季度时间判定
const InitialTime = (val) => {
    let num = "";
    val = Number(val);
    switch (val) {
        case 1:
            num = "01";
            break;
        case 2:
            num = "04";
            break;
        case 3:
            num = "07";
            break;
        case 4:
            num = "10";
            break;
        default:
            console.error("时间格式有误!");
    }
    return num;
}
const selectSeason = (i) => {
    season.value = i + 1;
    let arr = props.valueArr[i].split("-");
    props.getValue(year.value + arr[0] + "-" + year.value + arr[1]);
    showSeason.value = false;
    showValue.value = `${year.value}年${season.value}季度`;
    var formatValue = `${year.value}-${InitialTime(season.value)}`;
    emit("change", formatValue);
}
const initDefaultValue = (value) => {
    let arr = value.split("-");
    year.value = arr[0].slice(0, 4);
    var myseason = arr[1];
    showValue.value = `${year.value}年${whitchQuarter(myseason)}季度`;
}
onMounted(() => {
    if (props.defaultValue) {
        console.log(props.defaultValue)
        initDefaultValue(props.defaultValue);
    }
})
</script>
<template>
    <div class="quarter">
        <mark style="position:fixed;top:0;bottom:0;left:0;right:0;background:rgba(0,0,0,0);z-index:999;" v-show="showSeason"
              @click.stop="showSeason = false"></mark>
        <el-popover
            :visible="showSeason"
            placement="bottom"
            trigger="click"
            class="popover"
            :width="300"
        >
            <template #reference>
                <el-input :placeholder="props.placeholder" v-model="showValue" style="width:100%;" class="elWidth" :clearable="props.clearable" @click="showSeason = true" >
                    <template #prefix>
                        <el-icon class="el-input__icon"><Calendar /></el-icon>
                    </template>
                </el-input>
            </template>
            <template #default>
                <div class="box-card">
                    <div class="yearBox">
                        <el-button type="info" icon="DArrowLeft" @click="prev" link></el-button>
                        <span role="button" class="el-date-picker__header-label">{{ year }}年</span>
                        <el-button type="info" @click="next" :class="{ notallow: year === props.limitTime }"
                                   icon="DArrowRight" link></el-button>
                    </div>
                    <div class="text">
                        <div @click="selectSeason(0)" class="item">第一季度</div>
                        <div @click="selectSeason(1)" class="item">第二季度</div>
                    </div>
                    <div class="text">
                        <div @click="selectSeason(2)" class="item">第三季度</div>
                        <div @click="selectSeason(3)" class="item">第四季度</div>
                    </div>
                </div>
            </template>
        </el-popover>
    </div>
</template>
<style scoped lang="scss">
.quarter{
    width: 100%;
    .elWidth{
        width: 100%;
    }
}
:deep(.el-popover .el-popper){
    width: 300px !important;
}
.notallow {
    cursor: not-allowed;
}
.box-card {
    width: 100%;
    .yearBox{
        text-align:center;
        padding:0;
        display: flex;
        justify-content: space-between;
        align-items: center;
    }
    .text{
        margin-top: 1rem;
        display: flex;
        .item{
            width: 50%;
            text-align: center;
            &:hover{
                color: #409eff !important;
                cursor: pointer;
            }
        }
    }
}
</style>
src/views/screen/flow/ecology/index.vue
@@ -35,7 +35,7 @@
            trigger: 'axis',
        },
        grid: {
            left: 60,
            left: 100,
            right: 20,
        },
        xAxis: {
@@ -96,7 +96,7 @@
            trigger: 'axis',
        },
        grid: {
            left: 60,
            left: 100,
            right: 20,
        },
        xAxis: {
src/views/screen/flow/graphic/index.vue
@@ -1,16 +1,13 @@
<script setup>
import {ref} from "vue";
import {onMounted, ref} from "vue";
import {getUserType} from '@/utils/auth.js'
import html2canvas from "html2canvas";
import {getFlowPointList} from '@/api/screen/index'
const menuList = ref([])
const userType = ref(getUserType())
const monitorRef = ref()
const searchVal = ref('')
const selectType = ref(1);
const typeOption = ref([
    { label: '水电站流量监测点', value: 1 },
    { label: '新扎口流量监测点', value: 2 },
])
const video = ref()
// 全屏操作
@@ -33,6 +30,19 @@
const handleSearch = async () => {
}
// 获取监控点
const getMoitorList = () => {
    getFlowPointList().then(res => {
        menuList.value = res.data
    })
}
onMounted(() => {
    getMoitorList()
})
</script>
<template>
@@ -40,37 +50,26 @@
        <div class="graphic-menu">
            <div class="menu-t">监控点列表</div>
            <el-menu class="el-menu">
                <el-sub-menu index="1">
                    <template #title>
                        <span>可移动监测点</span>
                <template v-for="(item, index) in menuList" :key="index+1">
                    <template v-if="item?.childrenList?.length === 0">
                        <el-menu-item :index="item.id">{{ item.pointName }}</el-menu-item>
                    </template>
                    <el-menu-item index="1-1">水电站流量监测点</el-menu-item>
                </el-sub-menu>
                <el-sub-menu index="2">
                    <template #title>
                        <span>固定位监测点</span>
                    <template v-else>
                        <el-sub-menu :index="item.id">
                            <template #title>
                                <span>{{ item.pointName }}</span>
                            </template>
                            <el-menu-item v-for="(child, cidx) in item.childrenList" :key="cidx" :index="child.id">
                                {{ child.pointName }}
                            </el-menu-item>
                        </el-sub-menu>
                    </template>
                    <el-menu-item index="2-1">新扎口流量监测点</el-menu-item>
                </el-sub-menu>
                </template>
            </el-menu>
        </div>
        <div class="graphic-monitor">
            <div class="monitor-tool">
                <div class="tool-l">
                    <div class="name">监测点类型</div>
                    <el-select
                        v-model="selectType"
                        class="tool-select"
                        placeholder="Select"
                        style="width: 15rem"
                    >
                        <el-option
                            v-for="item in typeOption"
                            :key="item.value"
                            :label="item.label"
                            :value="item.value"
                        />
                    </el-select>
                    <el-input v-model="searchVal" style="width: 20rem" placeholder="请输入监测点名称" />
                    <el-button @click="handleSearch"><el-icon><Search /></el-icon>搜索</el-button>
                    <el-button style="margin-left: 0" v-if="userType === '1'"><el-icon><Plus /></el-icon>新增</el-button>
src/views/screen/flow/home/index.vue
@@ -6,31 +6,31 @@
                <div class="point-address" @click="handleShow(index)"></div>
                <div class="point-message" v-show="item.showMsg">
                    <div class="msg-box">
                        <div class="video-box">
                        <div class="video-box" :style="{backgroundImage: `url(${item.imageRul})`}">
                            <el-icon><VideoPlay /></el-icon>
                        </div>
                        <div class="info-box">
                            <div class="info-t">{{ item.name }}</div>
                            <div class="info-sw">水位:<span>{{ item.shuiwei }}</span>m</div>
                            <div class="info-ls">流速:<span>{{item.liushu}}</span>m/s</div>
                            <div class="info-ssls">瞬时流速:<span>{{ item.ssls }}</span>m/s</div>
                            <div class="info-t">{{ item.pointName }}</div>
                            <div class="info-sw">水位:<span>{{ item.waterLevel }}</span>m</div>
                            <div class="info-ls">流速:<span>{{item.newFlow}}</span>m/s</div>
                            <div class="info-ssls">瞬时流速:<span>{{ item.flowVelocity }}</span>m/s</div>
                            <div class="info-ljll">
                                累计流量:
                                <el-select
                                    v-model="selectll"
                                    v-model="selectll[index]"
                                    class="m-2"
                                    placeholder="Select"
                                    size="small"
                                    style="width: 240px"
                                >
                                    <el-option
                                        v-for="(item, idx) in item.liuliangOptions"
                                        v-for="(item, idx) in liuliangOptions"
                                        :key="idx"
                                        :label="item.label"
                                        :value="idx"
                                        :value="item.value"
                                    />
                                </el-select>
                                <span>{{ item.liuliangOptions[selectll].value }}</span>m/s
                                <span>{{ item[selectll[index]] }}</span>m/s
                            </div>
                        </div>
                    </div>
@@ -42,34 +42,46 @@
<script setup>
import {ref} from "vue";
import {ref, onMounted} from "vue";
import {getHomePonit} from '@/api/screen/home/index.js'
const selectll = ref(0)
// 标点配置
const config = [
    { left: '18%', top: '67%', showMsg: false },
    { left: '60%', top: '12.5%', showMsg: false },
]
const liuliangOptions = [
    { label: '总计流量', value: 'totalFlow' },
    { label: '日累计流量', value: 'dayFlow' },
    { label: '周累计流量', value: 'weekFlow' },
    { label: '月累计流量', value: 'monthFlow' },
    { label: '年累计流量', value: 'yearFlow' },
]
const pointList = reactive([
    { name: '新扎沟口流量监测点', liushu: 22, ssls: '38', shuiwei: 1000, device: 1, left: '18%', top: '67%', showMsg: false,
        liuliangOptions: [
            { label: '总计流量', value: 500 },
            { label: '日累计流量', value: 1000 },
            { label: '周累计流量', value: 10000 },
            { label: '月累计流量', value: 300000 },
            { label: '年累计流量', value: 3600000 },
        ]
    },
    { name: '电站尾水出口水温监测点', liushu: 22, ssls: '38', shuiwei: 1000, device: 2, left: '60%', top: '12.5%', showMsg: false,
        liuliangOptions: [
            { label: '总计流量', value: 500 },
            { label: '日累计流量', value: 1000 },
            { label: '周累计流量', value: 10000 },
            { label: '月累计流量', value: 300000 },
            { label: '年累计流量', value: 3600000 },
        ]
    },
])
const selectll = ref(['totalFlow', 'totalFlow'])
const pointList = ref([])
const getPoint = () => {
    getHomePonit().then(res => {
        let data = res.data
        if(data.length > 2) data = data.splice(0, 1)
        pointList.value = data.map((item, index) => {
            return {
                ...item,
                ...config[index]
            }
        })
    })
}
const handleShow = (index) => {
    pointList[index].showMsg = !pointList[index].showMsg;
    pointList.value[index].showMsg = !pointList.value[index].showMsg;
}
onMounted(() => {
    getPoint()
})
</script>
@@ -124,7 +136,6 @@
                    line-height: 138px;
                    text-align: center;
                    font-size: 38px;
                    background: #cccb40;
                }
                .info-box{
                    height: 100%;
src/views/screen/temperature/graphic/index.vue
@@ -2,16 +2,15 @@
import {ref, reactive, onMounted} from "vue";
import * as echarts from 'echarts/core';
import html2canvas from "html2canvas";
import {getTemperaturePointList} from '@/api/screen/index.js'
import Quarter from "@/components/Quarter";
import moment from "moment";
const startTime = ref()
const endTime = ref()
const menuList = ref([])
const timeType = ref('date')
const timeRange = ref()
const searchVal = ref()
const selectType = ref(1);
const typeOption = ref([
    { label: '水电站流量监测点', value: 1 },
    { label: '新扎口流量监测点', value: 2 },
])
const graphicRef = ref(null)
const chartsRef = ref([])  //动态生成图表ref
let charts = []
@@ -99,6 +98,10 @@
    }
}
const changeType = (type) => {
    timeType.value = type;
    timeRange.value = ''
}
// 初始化图表
const initCharts = () => {
@@ -118,7 +121,7 @@
// 一键导出
const handleExport = () => {
    chartsRef.value?.forEach(item => {
    chartsRef.value?.forEach((item, index) => {
        html2canvas(item, {
            scale: 2, // 提高渲染质量
            useCORS: true, // 如果需要跨域资源
@@ -127,13 +130,27 @@
        }).then(canvas => {
            const link = document.createElement("a");
            link.href = canvas.toDataURL("image/png");
            link.download = '截图.png';
            link.download = `图表分析${index}.png`;
            link.click()
        })
    })
}
// 获取水温监控点菜单
const getTempMonitor = () => {
    getTemperaturePointList().then(res => {
        menuList.value = res.data
    })
}
// 获取时间
const getTime = (value) => {
    const time = moment(value).format('YYYY-MM-DD')
    console.log(time)
}
onMounted(() => {
    getTempMonitor()
    initCharts()
})
@@ -144,51 +161,75 @@
        <div class="graphic-menu">
            <div class="menu-t">监测点列表</div>
            <el-menu class="el-menu">
                <el-sub-menu index="1">
                    <template #title>
                        <span>可移动监测点</span>
                <template v-for="(item, index) in menuList" :key="index+1">
                    <template v-if="item?.childrenList?.length === 0">
                        <el-menu-item :index="item.id">{{ item.pointName }}</el-menu-item>
                    </template>
                    <el-menu-item index="1-1">水电站流量监测点</el-menu-item>
                </el-sub-menu>
                <el-sub-menu index="2">
                    <template #title>
                        <span>固定位监测点</span>
                    <template v-else>
                        <el-sub-menu :index="item.id">
                            <template #title>
                                <span>{{ item.pointName }}</span>
                            </template>
                            <el-menu-item v-for="(child, cidx) in item.childrenList" :key="cidx" :index="child.id">
                                {{ child.pointName }}
                            </el-menu-item>
                        </el-sub-menu>
                    </template>
                    <el-menu-item index="2-1">新扎口流量监测点</el-menu-item>
                </el-sub-menu>
                </template>
            </el-menu>
        </div>
        <div class="graphic-info">
            <div class="graphic-tool">
                <div class="tool-l">
                    <div class="name">开始时间</div>
                    <div class="name">类型</div>
                    <el-button-group class="ml-4">
                        <el-button :type="timeType === 'date' ? 'primary' : ''" @click="changeType('date')">日</el-button>
                        <el-button :type="timeType === 'week' ? 'primary' : ''" @click="changeType('week')">周</el-button>
                        <el-button :type="timeType === 'month' ? 'primary' : ''" @click="changeType('month')">月</el-button>
                        <el-button :type="timeType === 'quarter' ? 'primary' : ''" @click="changeType('quarter')">季</el-button>
                        <el-button :type="timeType === 'year' ? 'primary' : ''" @click="changeType('year')">年</el-button>
                    </el-button-group>
                    <el-date-picker
                        v-model="startTime"
                        type="datetime"
                        style="width: 12rem"
                        placeholder="请选择开始时间"
                        v-if="timeType === 'date'"
                        v-model="timeRange"
                        type="date"
                        placeholder="选择时间"
                        style="width: 15rem"
                        @change="getTime"
                    />
                    <div class="name">结束时间</div>
                    <el-date-picker
                        v-model="endTime"
                        type="datetime"
                        style="width: 12rem"
                        placeholder="请选择结束时间"
                        v-if="timeType === 'week'"
                        v-model="timeRange"
                        type="week"
                        format="YYYY年 ww[周]"
                        placeholder="选择时间"
                        style="width: 15rem"
                        @change="getTime"
                    />
                    <div class="name">监测点区域</div>
                    <el-select
                        v-model="selectType"
                        class="tool-select"
                        placeholder="Select"
                        style="width: 10rem"
                    >
                        <el-option
                            v-for="item in typeOption"
                            :key="item.value"
                            :label="item.label"
                            :value="item.value"
                        />
                    </el-select>
                    <el-date-picker
                        v-if="timeType === 'month'"
                        v-model="timeRange"
                        type="month"
                        placeholder="选择时间"
                        style="width: 15rem"
                        @change="getTime"
                    />
                    <Quarter
                        v-if="timeType === 'quarter'"
                        placeholder="选择时间"
                        :default-value="timeRange"
                        clearable
                        style="width: 15rem"
                        @change="getTime"
                    />
                    <el-date-picker
                        v-if="timeType === 'year'"
                        v-model="timeRange"
                        type="year"
                        placeholder="选择时间"
                        style="width: 15rem"
                        @change="getTime"
                    />
                    <el-input v-model="searchVal" style="width: 15rem" placeholder="请输入监测点名称" />
                    <el-button><el-icon><Search /></el-icon>搜索</el-button>
                    <el-button type="success" @click="handleExport">一键导出</el-button>
src/views/screen/temperature/home/index.vue
@@ -2,25 +2,25 @@
    <div class="home">
        <div class="home-bg"></div>
        <div class="home-c">
            <div class="point" v-for="(item, index) in pointList" :key="index" :style="{left: item.left, top: item.top}">
            <div class="point" v-for="(item, index) in monitorList" :key="index" :style="{left: item.left, top: item.top}">
                <div class="point-address" @click="handleShow(index)"></div>
                <div class="point-message" v-show="item.showMsg">
                   <div class="msg-box">
                       <div class="msg-t">{{ item.name }}</div>
                       <div class="msg-t">{{ item.pointName }}</div>
                       <div class="num">
                           <div class="item">
                               <div class="item-t">水温:</div>
                               <div class="item-num"><span>{{item.temputer}}</span>°C</div>
                               <div class="item-num"><span>{{item.waterTemperature}}</span>°C</div>
                           </div>
                           <div class="item">
                               <div class="item-t">水位:</div>
                               <div class="item-num"><span>{{ item.shuiwei }}</span>m</div>
                               <div class="item-num"><span>{{ item.waterLevel }}</span>m</div>
                           </div>
                       </div>
                       <div class="shebei">
                           监测设备:
                           <span v-if="item.device === 1" style="color: #1ab394">监测设备运行正常(点击跳转)</span>
                           <span v-else style="color: #ff0a0a">设备异常</span>
                           <span v-if="item.isOnline === 1">设备运作正常</span>
                           <span v-else style="color: red">设备运作异常</span>
                       </div>
                   </div>
                </div>
@@ -31,16 +31,38 @@
<script setup>
import pointApi from '@/api/facility/point.js'
import {ref, onMounted} from "vue";
const pointList = reactive([
    { name: '电站尾水出口水温监测点', temputer: 22, shuiwei: 1000, device: 1, left: '15%', top: '53%', showMsg: false },
    { name: '电站尾水出口水温监测点', temputer: 22, shuiwei: 1000, device: 2, left: '12%', top: '68%', showMsg: false },
])
const monitorList = ref([])
const handleShow = (index) => {
    pointList[index].showMsg = !pointList[index].showMsg;
// 标点配置
const config = [
    { left: '15%', top: '53%', showMsg: false },
    { left: '12%', top: '68%', showMsg: false },
]
// 获取监控点列表
const getMonitorList = () => {
    pointApi().search({type: 1, page: 1, limit: 3}).then(res => {
        let data = res.data.list.filter(el => el.parentId !== 0)
        if(data.length > 2) data = data.splice(0, 1)
        monitorList.value = data.map((item, index) => {
            return {
                ...item,
                ...config[index]
            }
        })
    })
}
const handleShow = (index) => {
    monitorList.value[index].showMsg = !monitorList.value[index].showMsg;
}
onMounted(() => {
    getMonitorList()
})
</script>
vite.config.js
@@ -28,14 +28,13 @@
      port: 5036,
      host: true,
      open: true,
      proxy: {
        // https://cn.vitejs.dev/config/#server-proxy
        '/dev-api': {
          target: 'http://localhost:8080',
          changeOrigin: true,
          rewrite: (p) => p.replace(/^\/dev-api/, '')
        }
      }
      // proxy: {
      //   '/api': {
      //     target: 'http://192.168.0.200:8036',
      //     changeOrigin: true,
      //     rewrite: (p) => p.replace(/^\/api/, '')
      //   }
      // }
    },
    //fix:error:stdin>:7356:1: warning: "@charset" must be the first rule in the file
    css: {