YangJian0701 1 年之前
父節點
當前提交
3c5ac2f31d

+ 1 - 1
package.json

@@ -17,7 +17,7 @@
   "dependencies": {
     "@vueuse/core": "^9.13.0",
     "axios": "^1.3.2",
-    "highcharts": "^10.3.3",
+    "highcharts": "^10.3.2",
     "highcharts-vue": "^1.4.0",
     "md5": "^2.3.0",
     "pinia": "^2.0.32",

+ 151 - 0
src/components/highcharts-h.vue

@@ -0,0 +1,151 @@
+<template>
+    <div style="height: 100%;" id="Chartid">
+    <Chart ref="chart1" style="min-height: 600px" :options="chartOptions()" constructor-type="stockChart"></Chart>
+    </div>
+</template>
+
+<script>
+import { Chart } from 'highcharts-vue';
+import moment from 'moment';
+
+
+
+export default {
+    props:['higData'],
+    components: { Chart },
+    data() {
+        return {
+            seriesData:[],
+            selfshow:true,//true显示默认显示温度
+        }
+    },
+    watch:{
+        higData:{
+            handler(newVal){
+                this.TidyUpData(newVal)
+            },
+            deep:true
+        }
+    },
+    mounted(){
+        
+    },
+    methods: {
+        seIfchart(){//切换温湿度
+            console.log('切换',this.seriesData,this.selfshow)
+            this.selfshow = !this.selfshow
+           
+        },
+        
+
+
+
+        async TidyUpData(arr){
+            const loading = this.$loading({
+                lock: true,
+                text: '图表数据渲染中,请稍后...',
+                spinner: 'el-icon-loading',
+                background: 'rgba(0, 0, 0, 0.7)'
+            });
+            this.seriesData = []
+            for (let i = 0; i < arr.length; i++) {
+                let resIt = await this.setDataFun(arr[i])
+                this.seriesData.push(resIt)
+            }
+            loading.close()
+        },
+        
+        setDataFun(arr){
+            return new Promise(resolve=>{
+                const obj = {
+                    name:arr[0].T_sn,
+                    data:[]
+                }
+                arr.forEach(item => {
+                    obj.data.push([new Date(item.T_time).getTime(),item.T_rh,item.T_t,item.T_sn,item.T_id,item.ID])
+                });
+                
+                setTimeout(() => {
+                    resolve(obj)
+                }, 500);
+            }) 
+        },
+        chartOptions() {
+            let seIf = this
+            var obj = {
+                chart: {
+                    zoomType: 'x',//框选放大
+                    panning: true, //禁用放大
+                    // zooming: {
+                    //     singleTouch: true,
+                    //     resetButton: {},
+                    //     type: 'x',
+                    //     panning: true, //禁用放大
+                    // },
+                    events: {
+                        selection(event) {
+                            let maxTime1 = moment(Math.floor(event.xAxis[0].min)).format('YYYY-MM-DD HH:mm:ss');
+                            let maxTime2 = moment(Math.floor(event.xAxis[0].max)).format('YYYY-MM-DD HH:mm:ss')
+                            console.log('时间区间选择',maxTime1,maxTime2)
+                            let timearr = [maxTime1,maxTime2]
+                            seIf.$emit("setTime",timearr)
+                        },
+                    },
+                },
+                time: {
+                    useUTC: false
+                },
+                boost: {
+                    useGPUTranslations: true
+                },
+                // xAxis: {
+                //     labels: {
+                //         format: '{value:%Y-%m-%d %H:%M:%S}',
+                //     },
+                // },
+                yAxis: {
+                    title: {
+                        text: '湿度Rh'
+                    },
+                    opposite: false, //设置y轴提示在左边
+                },
+                plotOptions: {
+                    series:{
+                        turboThreshold:0 //性能阈值检查,默认值为1000,当数据量超过这个值就会报错;如果需要关掉性能阈值检查,可以将此参数设置为 0
+                    },
+                },
+                legend: {
+                    layout: 'vertical',
+                    align: 'right',
+                    verticalAlign: 'middle'
+                },
+                rangeSelector: {
+                    buttons: [], // 不显示左边的zoom
+                    selected: 1,
+                    inputEnabled: false // 不显示日期输入框
+                },
+                title: {
+                    text: '冷链湿度曲线图'
+                },
+                subtitle: {
+                    useHTML: true,
+                    // text:'1111'//副标题
+                },
+                dataGrouping: {
+                    enabled: true // 取消根据日期进行数据分组
+                },
+                tooltip: {
+                    valueSuffix: 'Rh',
+                    xDateFormat: '%Y-%m-%d %H:%M:%S',
+                    // chart: {
+                    //     type: 'spline' //图表类型,column,line,spline,area等
+                    // }
+                },
+                series:this.seriesData
+            }
+            // window.onresize = resize;
+            return obj
+        },
+    }
+}
+</script>

+ 126 - 0
src/components/highcharts-t.vue

@@ -0,0 +1,126 @@
+<template>
+    <div style="height: 100%;">
+        <Chart ref="chart1" style="min-height: 600px;" :options="chartOptions()" constructor-type="stockChart"></Chart>
+        <div style="text-align: center;margin-top: 20px;">{{ computedData }}</div>
+    </div>
+</template>
+
+<script setup>
+import { Chart } from 'highcharts-vue';
+import { computed } from "vue";
+import { useMessage } from "naive-ui";
+const message = useMessage()
+const popData = defineProps({
+    dataList:{
+        type:Array,
+        default: () => [],
+    }
+})
+const computedData = computed(()=>{
+    // console.log('计算属性',popData.dataList)
+    if(popData.dataList.length!=0){
+        return computedDataFun()
+    }else{
+        return ''
+    }
+})
+const computedDataFun = ()=>{
+    let arr = popData.dataList
+    let mapData = []
+    for (const key of arr) {
+        for (let i = 0; i < key.data.length; i++) {
+            mapData.push(key.data[i][1])
+        }
+    }
+    if(mapData.length==0){
+        message.error('哎呀,没有可展示的数据哦')
+        return
+    }
+    //求和
+    let num = mapData.reduce((n,m) => n + m);//求和
+    //最大值
+    let maxData = Math.max(...mapData)
+    //最小值
+    let minData = Math.min(...mapData)
+    //平均值
+    let pingjun = num/mapData.length
+    
+    return `最大值${maxData},最小值${minData},平均值${pingjun}`
+}
+const chartOptions = () => {
+    var obj = {
+        chart: {
+            zoomType: 'x',//框选放大
+            panning: true, //禁用放大
+            // zooming: {
+            //     singleTouch: true,
+            //     resetButton: {},
+            //     type: 'x',
+            //     panning: true, //禁用放大
+            // },
+            events: {
+                selection(event) {
+                    console.log('时间区间选择', event.xAxis)
+                },
+            },
+        },
+        time: {
+            useUTC: false
+        },
+        boost: {
+            useGPUTranslations: false
+        },
+        xAxis: {
+            // labels: {
+            //     format: '{value:%Y-%m-%d %H:%M:%S}',
+            // },
+            type: 'datetime',
+        },
+        yAxis: {
+            title: {
+                // text: '温度℃'
+            },
+            opposite: false, //设置y轴提示在左边
+        },
+        plotOptions: {
+            series: {
+                turboThreshold: 0 //性能阈值检查,默认值为1000,当数据量超过这个值就会报错;如果需要关掉性能阈值检查,可以将此参数设置为 0
+            },
+        },
+        legend: {
+            layout: 'vertical',
+            align: 'right',
+            verticalAlign: 'middle'
+        },
+        rangeSelector: {
+            buttons: [], // 不显示左边的zoom
+            selected: 1,
+            inputEnabled: false // 不显示日期输入框
+        },
+        title: {
+            // text: '冷链温度曲线图'
+        },
+        subtitle: {
+            useHTML: true,
+            // text:'1111'//副标题
+        },
+        dataGrouping: {
+            enabled: true // 取消根据日期进行数据分组
+        },
+        tooltip: {
+            valueSuffix: ' ℃',
+            xDateFormat: '%Y-%m-%d %H:%M:%S',
+            // pointFormat: '<span style="color:{series.color}">{series.name}: <b>{point.y:,.0f}%</b><br/>',
+            shared: true
+            // chart: {
+            //     type: 'spline' //图表类型,column,line,spline,area等
+            // }
+        },
+        series: popData.dataList
+    }
+    return obj
+}
+
+
+
+</script>

+ 15 - 0
src/plugin/timeFun.js

@@ -12,4 +12,19 @@ export function TimeData(time) {
 		return '0000-00-00  00-00-00'
 	}
     
+}
+export function TimeDate(time) {//不要带秒
+    if (time) {
+		var date = new Date(time); //时间戳为10位需*1000,时间戳为13位的话不需乘1000
+		let y = date.getFullYear();
+		let MM = (date.getMonth() + 1).toString().padStart(2, '0');
+		let d = date.getDate().toString().padStart(2, '0');
+		let h = date.getHours().toString().padStart(2, '0');
+		let m = date.getMinutes().toString().padStart(2, '0');
+		let s = date.getSeconds().toString().padStart(2, '0');
+		return y + '-' + MM + '-' + d + ' ' + h + ':' + m;
+	} else {
+		return '0000-00-00  00-00'
+	}
+    
 }

+ 6 - 3
src/views/data/edit/DeleteTaskClass.vue

@@ -1,15 +1,18 @@
 <template>
   <n-popconfirm @positive-click="handleDelete">
     <template #trigger>
-      <n-button type="error" size="small">删除</n-button>
+      <n-icon size="20" style="cursor: pointer;">
+        <Trash />
+      </n-icon>
+      <!-- <n-button type="error" size="small">删除</n-button> -->
     </template>
-    一切都将一去杳然,任何人都无法将其捕获。
+    删除操作,是否继续
   </n-popconfirm>
 </template>
 
 <script setup>
 import { deleteTaskDataClass } from "@/api";
-
+import { Trash} from "@vicons/ionicons5";
 const message = useMessage();
 
 const props = defineProps({

+ 1 - 1
src/views/data/edit/ExportVue.vue

@@ -15,7 +15,7 @@
         <n-select
           v-model:value="formValue.T_sn_list"
           label-field="T_id"
-          value-field="T_id"
+          value-field="T_sn"
           :options="options"
           multiple
           :max-tag-count="2"

+ 18 - 3
src/views/data/edit/ImportVue.vue

@@ -20,7 +20,7 @@
       <n-button @click="showModal=false">
         取消
       </n-button>
-      <n-button type="primary" @click="submitCallback" :disabled="dataList.length==0" style="margin-left: 20px;">
+      <n-button type="primary" @click="submitCallback" :disabled="disableds" style="margin-left: 20px;">
         确认
       </n-button>
     </div>
@@ -39,7 +39,7 @@ const props = defineProps({
     default: {},
   },
 });
-
+const disableds = ref(false)
 const message = useMessage();
 const sum = ref(0)
 // 是否展示 Modal
@@ -88,7 +88,9 @@ const formValue = reactive({
 
 // 显示导入
 const showImportModal = () => {
+  sum.value = 0
   showModal.value = true;
+  disableds.value = false
 };
 watch(showModal,(newVal)=>{
   console.log('监听',newVal)
@@ -99,13 +101,26 @@ watch(showModal,(newVal)=>{
 })
 //
 const submitCallback = async () => {
-  for (let i = 0; i <  dataList.value.length; i++) {
+  sum.value = 0
+  if(dataList.value.length==0){
+    message.error('没有可导入数据哦,检查文件是否为空数据')
+    return
+  }else{
+    disableds.value = true
+    for (let i = 0; i <  dataList.value.length; i++) {
       let resIt  = await addTask(dataList.value[i]);
       sum.value +=1
       if(resIt.data.Code!=200){
         break
       }
+      if(sum.value==dataList.value.length){
+        message.success('数据导入完成')
+        disableds.value = false
+      }
+  }
   }
+  
+  
 };
 
 //

+ 603 - 0
src/views/data/edit/index copy.vue

@@ -0,0 +1,603 @@
+<template>
+  <div class="h-full flex flex-col gap-y-3">
+    <n-page-header @back="$router.back">
+      <template #title> 数据编辑 </template>
+    </n-page-header>
+    <div class="flex-1 grid grid-cols-4 gap-x-3">
+      <n-card>
+        <n-tabs display-directive="show">
+          <n-tab-pane name="1" tab="设备">
+            <n-list>
+              <template #header>
+                <div style="display: flex;justify-content: space-between;align-items: center;">
+                  <n-checkbox v-model:checked="checked" @update:checked="handleSelectAll">
+                  全选
+                </n-checkbox>
+                <n-button type="primary" @click="renderFun()">渲染</n-button>
+                </div>
+              </template>
+              <n-scrollbar :style="{ maxHeight: `${height - 310}px` }" trigger="none">
+                <n-checkbox-group v-model:value="checkValues" @update:value="handleCheckValues">
+                  <template v-for="item of classList" :key="item.T_id">
+                    <n-list-item class="mr-5">
+                      <template #prefix>
+                        <n-checkbox :value="item" />
+                      </template>
+                      <template #suffix>
+                        <n-space :wrap="false">
+                          <EditClass :task="task" :taskClass="item" :getClassList="getClassList" />
+                          <DeleteClass :task="task" :taskClass="item" :getClassList="getClassList" />
+                        </n-space>
+                      </template>
+                      <n-thing>
+                        <template #header> {{ item.T_id }} </template>
+                        <template #description> {{ item.T_sn }} </template>
+                      </n-thing>
+                    </n-list-item>
+                  </template>
+                </n-checkbox-group>
+              </n-scrollbar>
+              <template #footer>
+                <n-gradient-text type="info">
+                  传感器总数:{{ classList.length }}
+                </n-gradient-text>
+              </template>
+            </n-list>
+          </n-tab-pane>
+          <n-tab-pane name="2" tab="表单">
+            <FormList :task="task" :class-list="classList" :time="time" :temporal-interval="temporalInterval" />
+          </n-tab-pane>
+        </n-tabs>
+      </n-card>
+      <n-card class="h-full col-span-3">
+        <div class="h-full flex flex-col gap-y-3">
+          <n-space justify="space-between">
+            <n-input-group>
+              <n-date-picker format="yyyy-MM-dd HH:mm" :time-picker-props="{ format: 'HH:mm' }" @update:formatted-value="(value) => {
+                  queryData.Time_start = value[0];
+                  queryData.Time_end = value[1];
+                }
+                " type="datetimerange" clearable />
+              <n-button type="primary" @click="getDataList">搜索</n-button>
+            </n-input-group>
+            <n-space>
+              <ExportVue :task="task" :class-list="classList" />
+              <ImportVue :task="task" />
+              <ImportPlatform :task="task" />
+              <AddVue :class-list="classList" :task="task" />
+              <SetVue @submit="handleSet" />
+              <n-button type="primary" @click="goDataEd">数据编辑</n-button>
+            </n-space>
+          </n-space>
+          <n-tabs type="segment" animated v-model:value="tabChart" @update:value="handleTabChange">
+            <n-tab-pane name="温度" tab="温度">
+              <!-- <Chart :style="{ minHeight: `${height - 300}px` }" ref="chart1" constructor-type="stockChart"
+                :options="chartOptions1"></Chart> -->
+                <highchartsT></highchartsT> 
+            </n-tab-pane>
+            <n-tab-pane name="湿度" tab="湿度">
+              <Chart :style="{ minHeight: `${height - 300}px` }" ref="chart2" constructor-type="stockChart"
+                :options="chartOptions2"></Chart>
+            </n-tab-pane>
+          </n-tabs>
+        </div>
+      </n-card>
+    </div>
+  </div>
+  <n-modal v-model:show="modal.showModal" :title="modal.title" :show-icon="false" preset="dialog">
+    <template v-if="modal.title === '温度'">
+      <n-form-item show-require-mark>
+        <n-input v-model:value="formValue.T_t" />
+      </n-form-item>
+    </template>
+    <template v-else>
+      <n-form-item show-require-mark>
+        <n-input v-model:value="formValue.T_rh" />
+      </n-form-item>
+    </template>
+    <n-space justify="end">
+      <n-popconfirm @positive-click="deleteTask">
+        <template #trigger>
+          <n-button type="error">删除该点</n-button>
+        </template>
+        是否确认删除?
+      </n-popconfirm>
+      <n-button type="primary" @click="editTask">确定</n-button>
+      
+    </n-space>
+  </n-modal>
+</template>
+
+<script setup>
+import { Chart } from 'highcharts-vue';
+import highchartsT from '@/components/highcharts-t.vue'
+import {
+  deleteTaskData,
+  editTaskData,
+  getTaskDataClassList,
+  getTaskDataList,
+} from '@/api';
+import AddVue from './AddVue.vue';
+import ImportVue from './ImportVue.vue';
+import ImportPlatform from './ImportPlatform.vue';
+import SetVue from './SetVue.vue';
+import ExportVue from './ExportVue.vue';
+import FormList from './FormList.vue';
+// import ForData from './formData.vue';
+
+import { useWindowSize } from '@vueuse/core';
+import { useNow, useDateFormat } from '@vueuse/core';
+import EditClass from './EditTaskClass.vue';
+import DeleteClass from './DeleteTaskClass.vue';
+import { dateFormat } from 'highcharts';
+import { TimeData } from '@/plugin/timeFun';
+
+
+const formatted = useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss');
+
+const notification = useNotification();
+
+const { height } = useWindowSize();
+
+const message = useMessage();
+
+const task = window.sessionStorage.getItem('task')
+  ? JSON.parse(window.sessionStorage.getItem('task'))
+  : {};
+
+const chart1 = ref(null);
+const chart2 = ref(null);
+
+// Modal 数据源
+const modal = reactive({
+  showModal: false,
+  title: '',
+});
+
+
+const renderFun = async ()=>{
+  for (let i = 0; i < checkValues.value.length; i++) {
+    queryData.T_id = checkValues.value[i].T_id;
+    queryData.T_sn = checkValues.value[i].T_sn;
+    console.log('循环',queryData)
+    await getDataList();
+  }
+}
+
+// 查询数据
+const queryData = reactive({
+  T_task_id: task.T_task_id,
+  T_sn: '',
+  T_id: '',
+  // Time_start: '2023-02-06 21:00',
+  // Time_end: '2023-02-06 21:10',
+  Time_start: '',
+  Time_end: '',
+  page: 1,
+  page_z: 9999,
+});
+const goDataEd = ()=>{
+  
+  // window.open(`http://coldverifylocal.coldbaozhida.com/data_edit/?taskId=${queryData.T_task_id}`, '_blank')
+  window.open(`http://coldverifylocal.coldbaozhida.com/data_edit/?taskId=${queryData.T_task_id}`, '_blank')
+
+}
+// 表单数据
+const formValue = reactive({
+  T_t: null,
+  T_rh: null,
+});
+
+// 数据源对象
+// const state = reactive({});
+
+// 设备列表
+const classList = ref([]);
+
+// 列表
+const dataList = ref([]);
+
+//
+const dataInfo = ref({});
+
+// 选项组受控模式下的值
+const checkValues = ref(null);
+
+// tab
+const tabChart = ref('温度');
+
+const handleTabChange = (value) => {
+  console.log(value);
+  checkValues.value = [];
+  checked.value = false;
+};
+
+//
+const handleSet = (data) => {
+  if (tabChart.value === '温度') {
+    chart1.value.chart.yAxis[0].addPlotLine({
+      color: 'red',
+      width: 2,
+      value: data.tTop,
+      label: {
+        text: `上限(${data.tTop})`,
+      },
+    });
+    chart1.value.chart.yAxis[0].addPlotLine({
+      color: 'red',
+      width: 2,
+      value: data.tBottom,
+      label: {
+        text: `下限(${data.tBottom})`,
+      },
+    });
+  } else {
+    chart2.value.chart.yAxis[0].addPlotLine({
+      color: 'red',
+      width: 2,
+      value: data.hTop,
+      label: {
+        text: `上限(${data.hTop})`,
+      },
+    });
+    chart2.value.chart.yAxis[0].addPlotLine({
+      color: 'red',
+      width: 2,
+      value: data.hBottom,
+      label: {
+        text: `下限(${data.hBottom})`,
+      },
+    });
+  }
+};
+
+const checked = ref(false);
+
+// 全选
+const handleSelectAll = async (value) => {
+  if (value) {
+    checkValues.value = classList.value.map((item) => item.T_id);
+    const arr = classList.value.filter(
+      (item) => !selectedValue.value.includes(item.T_id)
+    );
+    for (let item of arr) {
+      queryData.T_id = item.T_id;
+      queryData.T_sn = item.T_sn;
+      await getDataList();
+      if (tabChart.value === '温度') {
+        const data1 = dataList.value
+          .map((item) => [new Date(item.T_time).getTime(), item.T_t])
+          .sort((a, b) => a[0] - b[0]);
+        chart1.value.chart.addSeries({
+          id: item.T_id,
+          name: item.T_id,
+          data: data1,
+          lineWidth: 1,
+          cursor: 'pointer',
+          events: {
+            click(e) {
+              
+              modal.title = '温度';
+              modal.showModal = true;
+              time.value = dateFormat('%Y-%m-%d %H:%M:%S', e.point.x);
+              formValue.T_t = e.point.y;
+              queryData.T_id = e.point.series.name;
+              getDataList();
+              dataInfo.value = dataList.value[e.point.index];
+            },
+          },
+        });
+      } else {
+        const data2 = dataList.value
+          .map((item) => [new Date(item.T_time).getTime(), item.T_rh])
+          .sort((a, b) => a[0] - b[0]);
+        chart2.value.chart.addSeries({
+          id: item.T_id,
+          name: item.T_id,
+          data: data2,
+          lineWidth: 1,
+          cursor: 'pointer',
+          events: {
+            click(e) {
+              console.log('////',e)
+              modal.title = '湿度';
+              modal.showModal = true;
+              time.value = dateFormat('%Y-%m-%d %H:%M:%S', e.point.x);
+              formValue.T_rh = e.point.y;
+              queryData.T_id = e.point.series.name;
+              getDataList();
+              dataInfo.value = dataList.value[e.point.index];
+            },
+          },
+        });
+      }
+    }
+  } else {
+    if (tabChart.value === '温度') {
+      classList.value.forEach((item) => {
+        chart1.value.chart.get(item.T_id).remove();
+      });
+    } else {
+      classList.value.forEach((item) => {
+        chart2.value.chart.get(item.T_id).remove();
+      });
+    }
+    checkValues.value = [];
+  }
+};
+
+const time = ref('');
+const selectedValue = ref([]);
+// 选项组的值改变时的回调
+const handleCheckValues = async (values, meta) => {
+  console.log('单选',values, meta)
+  return
+  selectedValue.value = values;
+  const classInfo = classList.value.find((item) => item.T_id === meta.value);
+  queryData.T_id = classInfo.T_id;
+  queryData.T_sn = classInfo.T_sn;
+  await getDataList();
+  const data1 = dataList.value
+    .map((item) => [new Date(item.T_time).getTime(), item.T_t])
+    .sort((a, b) => a[0] - b[0]);
+  const data2 = dataList.value
+    .map((item) => [new Date(item.T_time).getTime(), item.T_rh])
+    .sort((a, b) => a[0] - b[0]);
+  if (meta.actionType === 'check') {
+    if (tabChart.value === '温度') {
+      chart1.value.chart.addSeries({
+        id: meta.value,
+        name: meta.value,
+        data: data1,
+        cursor: 'pointer',
+        events: {
+          click(e) {
+            console.log('/=======================///',e,TimeData(e.point.x))
+            
+            modal.title = '温度';
+            modal.showModal = true;
+            time.value = TimeData(e.point.x);
+            formValue.T_t = e.point.y;
+            queryData.T_id = e.point.series.name;
+            getDataList();
+            dataInfo.value = dataList.value[e.point.index];
+          },
+        },
+      });
+    } else {
+      chart2.value.chart.addSeries({
+        id: meta.value,
+        name: meta.value,
+        data: data2,
+        events: {
+          click(e) {
+            console.log('点击11119',e)
+            modal.title = '湿度';
+            modal.showModal = true;
+            time.value = dateFormat('%Y-%m-%d %H:%M:%S', e.point.x);
+            formValue.T_rh = e.point.y;
+            queryData.T_id = e.point.series.name;
+            getDataList();
+            dataInfo.value = dataList.value[e.point.index];
+          },
+        },
+      });
+    }
+  } else {
+    if (tabChart.value === '温度') {
+      chart1.value.chart.get(meta.value).remove();
+    } else {
+      chart2.value.chart.get(meta.value).remove();
+    }
+  }
+};
+
+const temporalInterval = ref('');
+
+// 图表配置
+const chartOptions1 = {
+  xAxis: {
+    labels: {
+      format: '{value:%Y-%m-%d %H:%M:%S}',
+    },
+  },
+  time: {
+    useUTC: false
+  },
+  boost: {
+    useGPUTranslations: true
+  },
+
+  tooltip: {
+    xDateFormat: '%Y-%m-%d %H:%M:%S',
+    // headerFormat: '<small class="headerFormat">{.key}:{point.stackTotal}</small><table>',
+    // valueDecimals: 0  //会导致提示框内容显示错误
+    
+  },
+  yAxis: {
+    labels: {
+      format: '{text}℃',
+    },
+    plotLines: [],
+  },
+
+  legend: {
+    enabled: true,
+  },
+
+  accessibility: {
+    enabled: false,
+  },
+
+  boost: {
+    useGPUTranslations: true,
+    seriesThreshold: 5,
+  },
+
+  scrollbar: {
+    enabled: false,
+  },
+
+  // tooltip: {
+  //   formatter() {
+  //     return `${this.y} ${dateFormat('%Y-%m-%d %H:%M:%S', this.x)}`;
+  //   },
+  // },
+
+  chart: {
+    zooming: {
+      singleTouch: true,
+      resetButton: {},
+      type: 'xy',
+    },
+    events: {
+      selection(event) {
+        // console.log(
+        //   dateFormat('%Y-%m-%d %H:%M', event.xAxis[0].min),
+        //   dateFormat('%Y-%m-%d %H:%M', event.xAxis[0].max)
+        // );
+        if (event.xAxis) {
+          console.log('时间区间选择', event.xAxis)
+          temporalInterval.value = [
+            dateFormat('%Y-%m-%d %H:%M', event.xAxis[0].min),
+            dateFormat('%Y-%m-%d %H:%M', event.xAxis[0].max),
+          ];
+        }
+      },
+    },
+  },
+
+  series: [],
+};
+const chartOptions2 = {
+  xAxis: {
+    labels: {
+      format: '{value:%Y-%m-%d %H:%M:%S}',
+    },
+  },
+
+  yAxis: {
+    labels: {
+      format: '{text}%',
+    },
+  },
+
+  legend: {
+    enabled: true,
+  },
+
+  accessibility: {
+    enabled: false,
+  },
+
+  boost: {
+    useGPUTranslations: true,
+    seriesThreshold: 5,
+  },
+
+  scrollbar: {
+    enabled: false,
+  },
+
+  chart: {
+    zoomType: 'xy',
+  },
+
+  series: [],
+};
+
+
+
+// 删除
+const deleteTask = async () => {
+  const { data: res } = await deleteTaskData({
+    T_task_id: queryData.T_task_id,
+    Id: dataInfo.value.ID,
+  });
+  if (res.Code === 200) {
+    modal.showModal = false;
+    message.success(res.Msg);
+  }
+};
+
+// 编辑
+const editTask = async () => {
+  console.log('提交',dataInfo,time.value)
+  
+  const { data: res } = await editTaskData({
+    T_task_id: queryData.T_task_id,
+    Id: dataInfo.value.ID,
+    T_t: formValue.T_t ? formValue.T_t : dataInfo.value.T_t,
+    T_rh: formValue.T_rh ? formValue.T_rh : dataInfo.value.T_rh,
+    T_time: time.value,
+  });
+  if (res.Code === 200) {
+    modal.showModal = false;
+    message.success(res.Msg);
+  }
+};
+
+// 获取设备列表
+const getClassList = async () => {
+  const { data: res } = await getTaskDataClassList({
+    T_task_id: queryData.T_task_id,
+  });
+  classList.value = res.Data || [];
+};
+
+// 获取任务数据列表
+const getDataList = async () => {
+  const { data: res } = await getTaskDataList(queryData);
+  if (queryData.page_z <= res.Data.Page_size) {
+    const arr = classList.value.filter((item) =>
+      checkValues.value.includes(item.T_sn)
+    );
+    arr.forEach((item) => {
+      item.T_sn = queryData.T_sn;
+      item.T_id = queryData.T_id;
+      getDataList();
+    });
+  }
+  dataList.value = res.Data.List || [];
+};
+
+getClassList();
+
+onMounted(() => {
+  if (task.T_collection_state === 0) {
+    notification.info({
+      closable: false,
+      title: '未完成',
+      meta: `当前时间:${formatted.value}`,
+      duration: 2500,
+      keepAliveOnHover: true,
+    });
+  } else if (task.T_collection_state === 1) {
+    notification.info({
+      closable: false,
+      title: '已完成',
+      meta: `当前时间:${formatted.value}`,
+      duration: 2500,
+      keepAliveOnHover: true,
+    });
+  } else if (task.T_collection_state === 2) {
+    notification.info({
+      closable: false,
+      title: '处理中',
+      meta: `当前时间:${formatted.value}`,
+      duration: 2500,
+      keepAliveOnHover: true,
+    });
+  } else if (task.T_collection_state === 3) {
+    notification.info({
+      closable: false,
+      title: '已采集-无数据',
+      meta: `当前时间:${formatted.value}`,
+      duration: 2500,
+      keepAliveOnHover: true,
+    });
+  }
+});
+</script>
+
+<style lang="scss" scoped></style>

+ 203 - 221
src/views/data/edit/index.vue

@@ -3,31 +3,35 @@
     <n-page-header @back="$router.back">
       <template #title> 数据编辑 </template>
     </n-page-header>
-    <div class="flex-1 grid grid-cols-4 gap-x-3">
-      <n-card>
+    <div class="flex-1 grid grid-cols-4 gap-x-3" style="display: flex;">
+      <n-card style="width: 250px;flex-shrink: 0;">
         <n-tabs display-directive="show">
           <n-tab-pane name="1" tab="设备">
             <n-list>
               <template #header>
-                <n-checkbox v-model:checked="checked" @update:checked="handleSelectAll">
-                  全选
-                </n-checkbox>
+                <div style="display: flex;justify-content: space-between;align-items: center;">
+                  <n-checkbox v-model:checked="checked" @update:checked="handleSelectAll">
+                    全选
+                  </n-checkbox>
+                  <n-button type="primary" @click="renderFun()">渲染</n-button>
+                </div>
               </template>
               <n-scrollbar :style="{ maxHeight: `${height - 310}px` }" trigger="none">
                 <n-checkbox-group v-model:value="checkValues" @update:value="handleCheckValues">
                   <template v-for="item of classList" :key="item.T_id">
                     <n-list-item class="mr-5">
                       <template #prefix>
-                        <n-checkbox :value="item.T_id" />
+                        <n-checkbox :value="item" />
                       </template>
                       <template #suffix>
                         <n-space :wrap="false">
-                          <EditClass :task="task" :taskClass="item" :getClassList="getClassList" />
                           <DeleteClass :task="task" :taskClass="item" :getClassList="getClassList" />
                         </n-space>
                       </template>
                       <n-thing>
-                        <template #header> {{ item.T_id }} </template>
+                        <template #header>
+                          <div @dblclick="dblclickFun(item)">{{ item.T_id }} </div>
+                        </template>
                         <template #description> {{ item.T_sn }} </template>
                       </n-thing>
                     </n-list-item>
@@ -46,16 +50,16 @@
           </n-tab-pane>
         </n-tabs>
       </n-card>
-      <n-card class="h-full col-span-3">
+      <n-card style="flex: 1;">
         <div class="h-full flex flex-col gap-y-3">
           <n-space justify="space-between">
             <n-input-group>
               <n-date-picker format="yyyy-MM-dd HH:mm" :time-picker-props="{ format: 'HH:mm' }" @update:formatted-value="(value) => {
-                  queryData.Time_start = value[0];
-                  queryData.Time_end = value[1];
-                }
-                " type="datetimerange" clearable />
-              <n-button type="primary" @click="getDataList">搜索</n-button>
+                queryData.Time_start = value[0];
+                queryData.Time_end = value[1];
+              }
+                " type="datetimerange" />
+              <n-button type="primary" @click="renderFun">搜索</n-button>
             </n-input-group>
             <n-space>
               <ExportVue :task="task" :class-list="classList" />
@@ -68,8 +72,9 @@
           </n-space>
           <n-tabs type="segment" animated v-model:value="tabChart" @update:value="handleTabChange">
             <n-tab-pane name="温度" tab="温度">
-              <Chart :style="{ minHeight: `${height - 300}px` }" ref="chart1" constructor-type="stockChart"
-                :options="chartOptions1"></Chart>
+              <!-- <Chart :style="{ minHeight: `${height - 300}px` }" ref="chart1" constructor-type="stockChart"
+                :options="chartOptions1"></Chart> -->
+              <highchartsT :dataList="dataList"></highchartsT>
             </n-tab-pane>
             <n-tab-pane name="湿度" tab="湿度">
               <Chart :style="{ minHeight: `${height - 300}px` }" ref="chart2" constructor-type="stockChart"
@@ -99,18 +104,33 @@
         是否确认删除?
       </n-popconfirm>
       <n-button type="primary" @click="editTask">确定</n-button>
-      
+
     </n-space>
   </n-modal>
+  <!-- 编辑 -->
+  <n-modal v-model:show="showModal" preset="dialog" positive-text="确认" negative-text="取消" :show-icon="false"
+    @positive-click="handleEdit">
+    <n-form :model="formDatas" label-width="auto" show-require-mark>
+      <n-form-item label="ID" path="T_id">
+        <n-input v-model:value="formDatas.T_id" />
+      </n-form-item>
+      <n-form-item label="SN" path="T_sn">
+        <n-input v-model:value="formDatas.T_sn" disabled="false" />
+      </n-form-item>
+    </n-form>
+  </n-modal>
 </template>
 
 <script setup>
+
 import { Chart } from 'highcharts-vue';
+import highchartsT from '@/components/highcharts-t.vue'
 import {
   deleteTaskData,
   editTaskData,
   getTaskDataClassList,
   getTaskDataList,
+  editTaskDataClass
 } from '@/api';
 import AddVue from './AddVue.vue';
 import ImportVue from './ImportVue.vue';
@@ -122,11 +142,10 @@ import FormList from './FormList.vue';
 
 import { useWindowSize } from '@vueuse/core';
 import { useNow, useDateFormat } from '@vueuse/core';
-import EditClass from './EditTaskClass.vue';
 import DeleteClass from './DeleteTaskClass.vue';
 import { dateFormat } from 'highcharts';
-import { TimeData } from '@/plugin/timeFun';
-
+import { TimeDate } from '@/plugin/timeFun';
+import { useMessage } from "naive-ui";
 
 const formatted = useDateFormat(useNow(), 'YYYY-MM-DD HH:mm:ss');
 
@@ -149,29 +168,178 @@ const modal = reactive({
   title: '',
 });
 
+/**
+ * --------最新写法开始-----------------------------------------------------------------------------------
+ */
+ const formDatas = reactive({
+  T_sn: '',
+  T_id: '',
+});
+const showModal = ref(false);
+const dblclickFun = (e) => {
+  console.log('双击',e)
+  formDatas.T_sn = e.T_sn
+  formDatas.T_id = e.T_id
+  showModal.value = true;
+}
+const handleEdit = async () => {
+  try {
+    const { data: res } = await editTaskDataClass({
+      T_task_id: queryData.T_task_id,
+      T_sn: formDatas.T_sn,
+      T_id: formDatas.T_id,
+    });
+    if (res.Code === 200) {
+      message.success(res.Msg);
+      getClassList()
+    }
+  } catch (e) {
+    console.log(e);
+  }
+};
+
+
+// 表单数据
+const formValue = reactive({
+  T_t: null,
+  T_rh: null,
+});
 // 查询数据
 const queryData = reactive({
   T_task_id: task.T_task_id,
   T_sn: '',
   T_id: '',
-  // Time_start: '2023-02-06 21:00',
-  // Time_end: '2023-02-06 21:10',
-  Time_start: '',
-  Time_end: '',
+  Time_start: '2023-04-18 07:14:00',
+  Time_end: '2023-04-18 07:25:00',
+  // Time_start: '',
+  // Time_end: '',
   page: 1,
   page_z: 9999,
 });
-const goDataEd = ()=>{
-  
+// 获取导航栏设备列表
+const getClassList = async () => {
+  const { data: res } = await getTaskDataClassList({
+    T_task_id: queryData.T_task_id,
+  });
+  classList.value = res.Data || [];
+};
+getClassList();
+
+
+//渲染按钮
+const renderFun = async () => {
+  if(checkValues.value==null){
+    message.error("哎呀,请选择设备在查询哟");
+    return
+  }
+  dataList.value = []
+  let arr = []
+  for (let i = 0; i < checkValues.value.length; i++) {
+    queryData.T_id = checkValues.value[i].T_id;
+    queryData.T_sn = checkValues.value[i].T_sn;
+    const resIt = await getDataList();
+    console.log('/*/*/',resIt)
+    arr.push(convertDataFun(resIt.data.Data.List))
+  }
+  dataList.value = arr
+}
+
+const tabValue = ref('温度')
+
+const time = ref('');
+const dataInfo = ref({});
+// 删除
+const deleteTask = async () => {
+  const { data: res } = await deleteTaskData({
+    T_task_id: queryData.T_task_id,
+    Id: dataInfo.value[5],
+  });
+  if (res.Code === 200) {
+    modal.showModal = false;
+    message.success(`${res.Msg},点击渲染或搜索更新数据`);
+  }
+};
+
+// 编辑
+const editTask = async () => {
+  console.log(tabValue.value, dataInfo.value)
+  const { data: res } = await editTaskData({
+    T_task_id: queryData.T_task_id,
+    Id: dataInfo.value[5],
+    T_t: tabValue.value == '温度' ? formValue.T_t : dataInfo.value[2],
+    T_rh: tabValue.value == '湿度' ? formValue.T_rh : dataInfo.value[2],
+    T_time: TimeDate(dataInfo.value[0]),
+  });
+  if (res.Code === 200) {
+    modal.showModal = false;
+    message.success(`${res.Msg},点击渲染或搜索更新数据`);
+  }
+};
+
+//转换图表所需数据
+const convertDataFun = (array) => {
+  let objData = {
+    name: '',
+    data: [],
+    events: {
+      click(e) {
+        formValue.T_t = e.point.y
+        modal.showModal = true
+        queryData.T_id = e.point.series.name;
+        modal.title = '温度';
+        let serName = e.point.series.name
+        const b = dataList.value.find(item => item.name == serName)
+        dataInfo.value = b.data[e.point.index];
+      }
+    }
+  }
+  if (array != null) {
+    let arr = array.reverse()
+    objData.name = arr[0].T_sn
+    arr.forEach(item => {
+      objData.data.push([new Date(item.T_time).getTime(), item.T_t, item.T_rh, item.T_sn, item.T_id, item.ID])
+    });
+  } else {
+    objData.data = []
+  }
+  return objData
+
+}
+// 获取任务数据列表
+const getDataList = () => {
+  return new Promise((resolve) => {
+    const resIt = getTaskDataList(queryData);
+    // console.log('返回',resIt)
+    setTimeout(() => {
+      resolve(resIt)
+    }, 500)
+  })
+};
+
+
+const checked = ref(false);
+
+// 全选
+const handleSelectAll = async () => {
+  checked.value ? checkValues.value = classList.value : checkValues.value = []
+};
+//单选
+const handleCheckValues = () => {
+  checkValues.value.length != classList.value.length ? checked.value = false : checked.value = true
+}
+
+/**
+ * --------最新写法结束-----------------------------------------------------------------------------------
+ */
+
+
+const goDataEd = () => {
+
   // window.open(`http://coldverifylocal.coldbaozhida.com/data_edit/?taskId=${queryData.T_task_id}`, '_blank')
   window.open(`http://coldverifylocal.coldbaozhida.com/data_edit/?taskId=${queryData.T_task_id}`, '_blank')
 
 }
-// 表单数据
-const formValue = reactive({
-  T_t: null,
-  T_rh: null,
-});
+
 
 // 数据源对象
 // const state = reactive({});
@@ -183,7 +351,7 @@ const classList = ref([]);
 const dataList = ref([]);
 
 //
-const dataInfo = ref({});
+
 
 // 选项组受控模式下的值
 const checkValues = ref(null);
@@ -192,7 +360,7 @@ const checkValues = ref(null);
 const tabChart = ref('温度');
 
 const handleTabChange = (value) => {
-  console.log(value);
+  tabValue.value = value
   checkValues.value = [];
   checked.value = false;
 };
@@ -236,145 +404,10 @@ const handleSet = (data) => {
   }
 };
 
-const checked = ref(false);
 
-// 全选
-const handleSelectAll = async (value) => {
-  if (value) {
-    checkValues.value = classList.value.map((item) => item.T_id);
-    const arr = classList.value.filter(
-      (item) => !selectedValue.value.includes(item.T_id)
-    );
-    for (let item of arr) {
-      queryData.T_id = item.T_id;
-      queryData.T_sn = item.T_sn;
-      await getDataList();
-      if (tabChart.value === '温度') {
-        const data1 = dataList.value
-          .map((item) => [new Date(item.T_time).getTime(), item.T_t])
-          .sort((a, b) => a[0] - b[0]);
-        chart1.value.chart.addSeries({
-          id: item.T_id,
-          name: item.T_id,
-          data: data1,
-          lineWidth: 1,
-          cursor: 'pointer',
-          events: {
-            click(e) {
-              
-              modal.title = '温度';
-              modal.showModal = true;
-              time.value = dateFormat('%Y-%m-%d %H:%M:%S', e.point.x);
-              formValue.T_t = e.point.y;
-              queryData.T_id = e.point.series.name;
-              getDataList();
-              dataInfo.value = dataList.value[e.point.index];
-            },
-          },
-        });
-      } else {
-        const data2 = dataList.value
-          .map((item) => [new Date(item.T_time).getTime(), item.T_rh])
-          .sort((a, b) => a[0] - b[0]);
-        chart2.value.chart.addSeries({
-          id: item.T_id,
-          name: item.T_id,
-          data: data2,
-          lineWidth: 1,
-          cursor: 'pointer',
-          events: {
-            click(e) {
-              console.log('////',e)
-              modal.title = '湿度';
-              modal.showModal = true;
-              time.value = dateFormat('%Y-%m-%d %H:%M:%S', e.point.x);
-              formValue.T_rh = e.point.y;
-              queryData.T_id = e.point.series.name;
-              getDataList();
-              dataInfo.value = dataList.value[e.point.index];
-            },
-          },
-        });
-      }
-    }
-  } else {
-    if (tabChart.value === '温度') {
-      classList.value.forEach((item) => {
-        chart1.value.chart.get(item.T_id).remove();
-      });
-    } else {
-      classList.value.forEach((item) => {
-        chart2.value.chart.get(item.T_id).remove();
-      });
-    }
-    checkValues.value = [];
-  }
-};
 
-const time = ref('');
 const selectedValue = ref([]);
-// 选项组的值改变时的回调
-const handleCheckValues = async (values, meta) => {
-  console.log('单选',values, meta)
-  selectedValue.value = values;
-  const classInfo = classList.value.find((item) => item.T_id === meta.value);
-  queryData.T_id = classInfo.T_id;
-  queryData.T_sn = classInfo.T_sn;
-  await getDataList();
-  const data1 = dataList.value
-    .map((item) => [new Date(item.T_time).getTime(), item.T_t])
-    .sort((a, b) => a[0] - b[0]);
-  const data2 = dataList.value
-    .map((item) => [new Date(item.T_time).getTime(), item.T_rh])
-    .sort((a, b) => a[0] - b[0]);
-  if (meta.actionType === 'check') {
-    if (tabChart.value === '温度') {
-      chart1.value.chart.addSeries({
-        id: meta.value,
-        name: meta.value,
-        data: data1,
-        cursor: 'pointer',
-        events: {
-          click(e) {
-            console.log('/=======================///',e,TimeData(e.point.x))
-            
-            modal.title = '温度';
-            modal.showModal = true;
-            time.value = TimeData(e.point.x);
-            formValue.T_t = e.point.y;
-            queryData.T_id = e.point.series.name;
-            getDataList();
-            dataInfo.value = dataList.value[e.point.index];
-          },
-        },
-      });
-    } else {
-      chart2.value.chart.addSeries({
-        id: meta.value,
-        name: meta.value,
-        data: data2,
-        events: {
-          click(e) {
-            console.log('点击11119',e)
-            modal.title = '湿度';
-            modal.showModal = true;
-            time.value = dateFormat('%Y-%m-%d %H:%M:%S', e.point.x);
-            formValue.T_rh = e.point.y;
-            queryData.T_id = e.point.series.name;
-            getDataList();
-            dataInfo.value = dataList.value[e.point.index];
-          },
-        },
-      });
-    }
-  } else {
-    if (tabChart.value === '温度') {
-      chart1.value.chart.get(meta.value).remove();
-    } else {
-      chart2.value.chart.get(meta.value).remove();
-    }
-  }
-};
+
 
 const temporalInterval = ref('');
 
@@ -396,7 +429,7 @@ const chartOptions1 = {
     xDateFormat: '%Y-%m-%d %H:%M:%S',
     // headerFormat: '<small class="headerFormat">{.key}:{point.stackTotal}</small><table>',
     // valueDecimals: 0  //会导致提示框内容显示错误
-    
+
   },
   yAxis: {
     labels: {
@@ -492,60 +525,9 @@ const chartOptions2 = {
 
 
 
-// 删除
-const deleteTask = async () => {
-  const { data: res } = await deleteTaskData({
-    T_task_id: queryData.T_task_id,
-    Id: dataInfo.value.ID,
-  });
-  if (res.Code === 200) {
-    modal.showModal = false;
-    message.success(res.Msg);
-  }
-};
 
-// 编辑
-const editTask = async () => {
-  console.log('提交',dataInfo,time.value)
-  
-  const { data: res } = await editTaskData({
-    T_task_id: queryData.T_task_id,
-    Id: dataInfo.value.ID,
-    T_t: formValue.T_t ? formValue.T_t : dataInfo.value.T_t,
-    T_rh: formValue.T_rh ? formValue.T_rh : dataInfo.value.T_rh,
-    T_time: time.value,
-  });
-  if (res.Code === 200) {
-    modal.showModal = false;
-    message.success(res.Msg);
-  }
-};
-
-// 获取设备列表
-const getClassList = async () => {
-  const { data: res } = await getTaskDataClassList({
-    T_task_id: queryData.T_task_id,
-  });
-  classList.value = res.Data || [];
-};
 
-// 获取任务数据列表
-const getDataList = async () => {
-  const { data: res } = await getTaskDataList(queryData);
-  if (queryData.page_z <= res.Data.Page_size) {
-    const arr = classList.value.filter((item) =>
-      checkValues.value.includes(item.T_sn)
-    );
-    arr.forEach((item) => {
-      item.T_sn = queryData.T_sn;
-      item.T_id = queryData.T_id;
-      getDataList();
-    });
-  }
-  dataList.value = res.Data.List || [];
-};
 
-getClassList();
 
 onMounted(() => {
   if (task.T_collection_state === 0) {