Browse Source

完成历史数据页面

Yue 2 years ago
parent
commit
7e15eb79f8

+ 2 - 1
components.d.ts

@@ -15,7 +15,7 @@ declare module '@vue/runtime-core' {
     BaseChart: typeof import('./src/components/charts/BaseChart.vue')['default']
     CodeHighlighter: typeof import('./src/components/highlighters/CodeHighlighter.vue')['default']
     CodeHighlighter2: typeof import('./src/components/highlighters/CodeHighlighter2.vue')['default']
-    copy: typeof import('./src/components/Forms/VbForm copy.vue')['default']
+    copy: typeof import('./src/components/Table/table-partials/table-content/table-body/TableTreeRow copy.vue')['default']
     DateRangeSelect: typeof import('./src/components/select/DateRangeSelect.vue')['default']
     DynamicTreeSelect: typeof import('./src/components/select/DynamicTreeSelect.vue')['default']
     DySearchSelect: typeof import('./src/components/select/DySearchSelect.vue')['default']
@@ -60,6 +60,7 @@ declare module '@vue/runtime-core' {
     TablePagination: typeof import('./src/components/Table/table-partials/table-content/table-footer/TablePagination.vue')['default']
     TableRightFixed: typeof import('./src/components/Table/table-partials/table-content/table-fixed/TableRightFixed.vue')['default']
     TableTreeRow: typeof import('./src/components/Table/table-partials/table-content/table-body/TableTreeRow.vue')['default']
+    TableTreeRowChild: typeof import('./src/components/Table/table-partials/table-content/table-body/TableTreeRowChild.vue')['default']
     VbDataTable: typeof import('./src/components/Table/VbDataTable.vue')['default']
     VbForm: typeof import('./src/components/Forms/VbForm.vue')['default']
     VbFormItem: typeof import('./src/components/Forms/VbFormItem.vue')['default']

+ 2 - 2
src/App.vue

@@ -59,8 +59,8 @@ export default defineComponent({
 //@import "line-awesome/dist/line-awesome/css/line-awesome.css";
 //@import "dropzone/dist/dropzone.css";
 //@import "@vueform/multiselect/themes/default.css";
-//@import "prism-themes/themes/prism-shades-of-purple.css";
-//@import "element-plus/dist/index.css";
+@import "prism-themes/themes/prism-shades-of-purple.css";
+@import "element-plus/dist/index.css";
 
 // Main demo style scss
 @import "assets/fonticon/fonticon.css";

+ 1 - 0
src/assets/sass/_table.scss

@@ -52,6 +52,7 @@
       table-layout: fixed;
     }
     thead{
+      vertical-align: middle;
       tr {
         th {
           height: 52px;

+ 1 - 0
src/components/Table/VbDataTable.vue

@@ -127,6 +127,7 @@ const totalItems = computed(() => {
 const pageChange = (page: number) => {
   emits("update:currentPage", page)
   emits("page-change", page)
+  currentPage.value = page
   remote()
 }
 const onSort = (sort: Sort) => {

+ 4 - 0
src/components/Table/table-partials/table-content/TableContent.vue

@@ -183,7 +183,11 @@ defineExpose({
         :class="loading ? `overlay overlay-block ${tableClass}` : `${tableClass}`"
         :style="tableStyle"
       >
+        <template v-if="$slots.tableHeader">
+          <slot name="tableHeader" />
+        </template>
         <TableHeadRow
+          v-else
           @onSort="onSort"
           @on-select-all="onSelectAll"
           :checkbox-all-value="check"

+ 6 - 7
src/components/Table/table-partials/table-content/table-body/TableTreeRow.vue

@@ -1,7 +1,7 @@
 <script setup lang="ts">
 import { ref, withDefaults, onMounted, computed } from "vue"
 import type { Header } from "@/components/Table/table-partials/models"
-
+import TableTreeRowChild from "./TableTreeRowChild.vue"
 const props = withDefaults(
   defineProps<{
     header: Array<Header>
@@ -61,7 +61,6 @@ const tdStyle = (column: Header) => {
   return style
 }
 const tdClass = (column: Header) => {
-  console.log("prop.iconField", props.iconField)
   let classStr = ""
   if (column.tdClass) {
     classStr += column.tdClass
@@ -82,7 +81,7 @@ const onChange = (event: Event) => {
 }
 
 function init() {
-  //console.log("TREE_ROW")
+  //console.log("TREE_ROW", props.row)
 }
 
 onMounted(() => {
@@ -141,7 +140,7 @@ onMounted(() => {
     </template>
   </tr>
   <template v-if="hasChildren">
-    <TableTreeRow
+    <TableTreeRowChild
       v-for="(child, i) in row[props.childrenField]"
       :key="i"
       :row="child"
@@ -158,9 +157,9 @@ onMounted(() => {
       :parent-field="parentField"
       :children-field="childrenField"
     >
-      <template v-for="(_, name) in $slots" #[name]="">
-        <slot :name="name" :row="child">{{ child }}</slot>
+      <template v-for="(_, name) in $slots" #[name]="{ row: item }">
+        <slot :name="name" :row="item"></slot>
       </template>
-    </TableTreeRow>
+    </TableTreeRowChild>
   </template>
 </template>

+ 169 - 0
src/components/Table/table-partials/table-content/table-body/TableTreeRowChild.vue

@@ -0,0 +1,169 @@
+<script setup lang="ts">
+import { ref, withDefaults, onMounted, computed } from "vue"
+import type { Header } from "@/components/Table/table-partials/models"
+import TableTreeRow from "./TableTreeRow.vue"
+
+const props = withDefaults(
+  defineProps<{
+    header: Array<Header>
+    row: any
+    depth?: number
+    expandDepth?: number
+    currentlySelectedItems?: Array<any>
+    hasCheckbox?: boolean //是否有选择框
+    checkMultiple?: boolean //是否多选
+    checkboxField?: string //选择框字段
+    tdTrClass?: string
+    rowSpanSuffix?: string //rowsapn 的字段后缀 后台应该组成 `${字段}${后缀}`
+    intervalLeft?: number
+    iconField?: string
+    keyField?: string
+    parentField?: string
+    childrenField?: string
+  }>(),
+  {
+    checkboxField: "id",
+    keyField: "id",
+    parentField: "parent_id",
+    childrenField: "children",
+    iconField: "name",
+    depth: 0,
+    expandDepth: 0,
+    intervalLeft: 10,
+  }
+)
+const emits = defineEmits<{
+  (e: "on-change", isChecked: boolean, v: any, row: any): void
+  (e: "update:currentlySelectedItems", v: any): void
+}>()
+const selectedItems = ref<Array<any>>([])
+const isExpand = computed(() => {
+  return props.expandDepth > props.depth
+})
+const hasChildren = computed(() => {
+  return props.row[props.childrenField] && props.row[props.childrenField].length
+})
+
+const trClass = computed(() => {
+  let _trClass = ` ${props.tdTrClass} `
+  if (hasChildren.value) {
+    _trClass += `hasChildren ${isExpand.value ? "tr-expand" : "tr-collapse"} `
+  }
+  _trClass += props.depth > props.expandDepth ? "hide" : "show"
+  return _trClass
+})
+
+const tdStyle = (column: Header) => {
+  const style: any = {}
+  if (column.align) {
+    style.textAlign = column.align
+  }
+
+  return style
+}
+const tdClass = (column: Header) => {
+  let classStr = ""
+  if (column.tdClass) {
+    classStr += column.tdClass
+  }
+  if (column.field == props.iconField) {
+    classStr += " tree-icon"
+  }
+  return classStr
+}
+const onChange = (event: Event) => {
+  const target = event.target as HTMLInputElement
+  selectedItems.value = props.checkMultiple ? selectedItems.value : target.checked ? [target.value] : []
+  // const row = props.data.find((v: any) => {
+  //   return v[props.checkboxField] == target.value
+  // })
+  emits("on-change", target.checked, selectedItems.value, props.row)
+  emits("update:currentlySelectedItems", selectedItems.value)
+}
+
+function init() {
+  console.log("TREE_ROW", props.row)
+}
+function ss(r: any, c: any) {
+  console.log("========>", r, c)
+  return
+}
+onMounted(() => {
+  init()
+})
+</script>
+<template>
+  <tr :class="trClass" :id="`tr_${row[keyField]}`" :data-parent="`tr_${row[parentField]}`">
+    <td v-if="hasCheckbox">
+      <div class="form-check form-check-sm form-check-custom form-check-solid">
+        <input
+          class="form-check-input"
+          type="checkbox"
+          :value="row[checkboxField]"
+          v-model="selectedItems"
+          @change="onChange"
+        />
+      </div>
+    </td>
+    <template v-for="(column, i) in header" :key="i">
+      <td
+        v-if="row[column.field + props.rowSpanSuffix]"
+        :style="tdStyle(column)"
+        :class="tdClass(column)"
+        :rowspan="`${row[column.field + props.rowSpanSuffix] ? row[column.field + props.rowSpanSuffix] : ''}`"
+      >
+        <span
+          v-if="column.field == iconField"
+          class="icon"
+          :style="`margin-left: ${intervalLeft * depth}px!important`"
+        ></span>
+        <template v-if="$slots[column.field]">
+          <slot :name="`${column.field}`" :row="row">
+            {{ row }}
+          </slot>
+        </template>
+        <template v-else>
+          {{ row[column.field] }}
+        </template>
+      </td>
+      <td v-else-if="row[column.field + props.rowSpanSuffix] != 0" :style="tdStyle(column)" :class="tdClass(column)">
+        <span
+          v-if="column.field == iconField"
+          class="icon"
+          :style="`margin-left: ${intervalLeft * depth}px!important`"
+        ></span>
+        <template v-if="$slots[column.field]">
+          <slot :name="`${column.field}`" :row="row">
+            {{ row }}
+          </slot>
+        </template>
+        <template v-else>
+          {{ row[column.field] }}
+        </template>
+      </td>
+    </template>
+  </tr>
+  <template v-if="hasChildren">
+    <TableTreeRow
+      v-for="(child, i) in row[props.childrenField]"
+      :key="i"
+      :row="child"
+      :header="header"
+      :depth="depth + 1"
+      :expand-depth="expandDepth"
+      :currently-selected-items="currentlySelectedItems"
+      :has-checkbox="hasCheckbox"
+      :checkbox-field="checkboxField"
+      :td-tr-class="tdTrClass"
+      :row-span-suffix="rowSpanSuffix"
+      :icon-field="iconField"
+      :key-field="keyField"
+      :parent-field="parentField"
+      :children-field="childrenField"
+    >
+      <template v-for="(_, name) in $slots" #[name]="{ row: item }">
+        <slot :name="name" :row="item"></slot>
+      </template>
+    </TableTreeRow>
+  </template>
+</template>

+ 4 - 0
src/components/Table/table-partials/table-content/table-fixed/TableFixed.vue

@@ -130,7 +130,11 @@ onBeforeUnmount(() => {
 <template>
   <div class="fixed-columns no-shadow" ref="tableBox">
     <table class="table align-middle fs-6 gy-5 no-footer" :class="tableClass">
+      <template v-if="$slots.tableHeader">
+        <slot name="tableHeader" />
+      </template>
       <TableHeadRow
+        v-else
         @on-sort="onSort"
         @on-select-all="onSelectAll"
         :checkbox-all-value="check"

+ 4 - 0
src/components/Table/table-partials/table-content/table-fixed/TableRightFixed.vue

@@ -86,7 +86,11 @@ onBeforeUnmount(() => {
 <template>
   <div ref="tableBox" class="fixed-columns-right">
     <table class="table align-middle fs-6 gy-5 no-footer" :class="tableClass">
+      <template v-if="$slots.tableHeader">
+        <slot name="tableHeader" />
+      </template>
       <TableHeadRow
+        v-else
         @onSort="onSort"
         :has-checkbox="false"
         :sort-field="sortField"

+ 1 - 1
src/components/select/DySelectTree.vue

@@ -11,7 +11,7 @@ interface TreeOption {
 }
 const props = withDefaults(
   defineProps<{
-    value: string | null | undefined
+    value: string | number | Array<string | number> | null | undefined
     id?: string //id变化后重新加载树
     name?: string
     url?: string

+ 35 - 16
src/core/services/RequestService.ts

@@ -5,7 +5,7 @@ import VueAxios from "vue-axios"
 import JwtService from "@/core/services/JwtService"
 import configs from "@/core/config/Index"
 import { dialog, toast } from "@/core/utils/message"
-import router from "@/router"
+import router from "@/router/Index"
 
 export interface errorObj {
   message: string
@@ -158,21 +158,22 @@ class RequestService {
         }
         return Promise.reject(data) 
       },
-      ({ config, response }) => {
-        console.error(`ERROR ==>${config.url} ==>`, response)
-        if (config.loading) {
-          //toast.close()
-        }
-        if (config.errorAlert) {
-          if (response?.data) {
-            DEFAULR_ERROR.showError(response.data?.msg)
-          } else {
-            DEFAULR_ERROR.handleErrorStatusCode(response.status)
-          }
-        } else if (response.status === 401) {
-          router.push({ name: configs.SIGN_ROUTE_NAME })
-        }
-        return Promise.reject(response.data) //失败
+      (error: any) => {
+        console.log("ERROR",error )
+        // console.error(`ERROR ==>${config.url} ==>`, response)
+        // if (config.loading) {
+        //   //toast.close()
+        // }
+        // if (config.errorAlert) {
+        //   if (response?.data) {
+        //     DEFAULR_ERROR.showError(response.data?.msg)
+        //   } else {
+        //     DEFAULR_ERROR.handleErrorStatusCode(response.status)
+        //   }
+        // } else if (response.status === 401) {
+        //   router.push({ name: configs.SIGN_ROUTE_NAME })
+        // }
+        return Promise.reject(error) //失败
       }
     )
   }
@@ -246,6 +247,24 @@ class RequestService {
     option.method = "delete"
     return this.request(option)
   }
+
+  public static postParams(url: string, option: AxiosRequestConfig) {
+    if (typeof url == "string") {
+      option = option || {}
+      option.url = url.toString()
+    } else {
+      option = (url as AxiosRequestConfig) || {}
+    }
+    //查询数据默认不弹成功提示
+    if (option.url && option.url.toLocaleLowerCase().indexOf("/get") > 0) {
+      option.successAlert = option.successAlert ?? false
+    }
+    const params = option.params || option.data || ""
+     delete  option.params
+     delete  option.data
+    option.method = "post"
+    return  RequestService.vueInstance.axios.post(url,params,option)
+  }
 }
 
 export default RequestService

+ 5 - 5
src/views/goLineData/_ViewCompany.vue

@@ -1,10 +1,10 @@
 <script setup lang="ts">
-import { toRefs, withDefaults, onMounted } from "vue"
+import { ref, withDefaults, onMounted } from "vue"
 import ViewCompanyGeneral from "./_ViewCompany_General.vue"
 import ViewCompanyAlarm from "./_ViewCompany_Alarm.vue"
 import ViewCompanyInfo from "./_ViewCompany_Info.vue"
 const props = withDefaults(defineProps<{ id: string; active: number }>(), { id: "", active: 0 })
-const { active } = toRefs(props)
+const active = ref(props.active)
 function init() {
   //
 }
@@ -16,13 +16,13 @@ onMounted(() => {
 <template>
   <el-tabs v-model="active">
     <el-tab-pane label="商户概览" :name="0">
-      <ViewCompanyGeneral :id="id"></ViewCompanyGeneral>
+      <ViewCompanyGeneral v-if="active == 0" :id="id"></ViewCompanyGeneral>
     </el-tab-pane>
     <el-tab-pane label="报警信息" :name="1">
-      <ViewCompanyAlarm :id="id"></ViewCompanyAlarm>
+      <ViewCompanyAlarm v-if="active == 1" :id="id"></ViewCompanyAlarm>
     </el-tab-pane>
     <el-tab-pane label="商户档案" :name="2">
-      <ViewCompanyInfo :id="id"></ViewCompanyInfo>
+      <ViewCompanyInfo v-if="active == 2" :id="id"></ViewCompanyInfo>
     </el-tab-pane>
   </el-tabs>
 </template>

+ 87 - 5
src/views/goLineData/_ViewCompany_Alarm.vue

@@ -1,17 +1,99 @@
 <script setup lang="ts">
-import { ref, withDefaults, onMounted } from "vue"
-
-const props = withDefaults(defineProps<{ value: string }>(), { value: "" })
-const emits = defineEmits<{ (e: "update:value", v: string): void }>()
+import moment from "moment"
+import { ref, withDefaults, onMounted, watch } from "vue"
+import { useRoute } from "vue-router"
+const route = useRoute()
+const props = withDefaults(defineProps<{ id: string }>(), { id: "" })
+const cols = ref([
+  {
+    name: "设备名称",
+    field: "device_name",
+  },
+  {
+    name: "告警类型",
+    field: "warn_type_name",
+  },
+  {
+    name: "告警数据",
+    field: "warn_value",
+  },
+  {
+    name: "发生时间",
+    field: "warn_starttime",
+  },
+  {
+    name: "恢复时间",
+    field: "warn_endtime",
+  },
+  {
+    name: "持续时间",
+    field: "stay_time",
+  },
+])
+const date = ref<[Date, Date]>([new Date(), new Date()])
+const warnType = ref<string | undefined>()
+const queryParams = ref({
+  id: props.id,
+  begin: moment(date.value[0]).format("YYYYMMDD"),
+  end: moment(date.value[1]).format("YYYYMMDD"),
+  //warn_type: warnType.value && warnType.value != "undefined" ? warnType.value : "",
+})
 
 function init() {
   //
+  warnType.value = route.query.type as string
 }
+function query() {
+  const params: any = {
+    id: props.id,
+    begin: moment(date.value[0]).format("YYYYMMDD"),
+    end: moment(date.value[1]).format("YYYYMMDD"),
+  }
+  if (warnType.value) {
+    params.warn_type = warnType.value
+  }
+
+  queryParams.value = params
+}
+watch(() => props.id, init)
 
 onMounted(() => {
   init()
 })
 </script>
 <template>
-  <div>44</div>
+  <VbDataTable
+    :header="cols"
+    url="sys/onlineData/warnTable"
+    :query-params="queryParams"
+    method="post"
+    :has-checkbox="false"
+  >
+    <template v-slot:table-tool="">
+      <el-form class="align-items-center" :inline="true">
+        <el-form-item class="mb-0 me-5 align-items-center" label="日期:">
+          <el-date-picker
+            v-model="date"
+            type="daterange"
+            range-separator="~"
+            start-placeholder="开始时间"
+            end-placeholder="结束时间"
+            size="default"
+          />
+        </el-form-item>
+        <el-form-item class="mb-0 me-5 align-items-center" label="告警类型:">
+          <DySelect
+            v-model:value="warnType"
+            url="sys/dict/getList?code=000100001&key=temp"
+            method="get"
+            :formatRemoteData="(v:any)=>{return v?.list}"
+          ></DySelect>
+        </el-form-item>
+
+        <el-form-item class="mb-0 me-0 align-items-center">
+          <el-button class="ms-3 mt-0 btn btn-sm btn-primary" @click="query">查询</el-button>
+        </el-form-item>
+      </el-form>
+    </template>
+  </VbDataTable>
 </template>

+ 1 - 6
src/views/goLineData/_ViewCompany_General.vue

@@ -62,12 +62,7 @@ function init() {
   queryChart(2)
   queryChart(3)
 }
-watch(
-  () => props.id,
-  () => {
-    init()
-  }
-)
+watch(() => props.id, init)
 onMounted(() => {
   init()
 })

+ 73 - 58
src/views/goLineData/_ViewCompany_Info.vue

@@ -1,9 +1,11 @@
 <script setup lang="ts">
-import { ref, withDefaults, onMounted } from "vue"
+import { ref, withDefaults, onMounted, watch } from "vue"
 import Rs from "@/core/services/RequestService"
-//import axios from "axios"
+import { getAssetPath } from "@/core/helpers/assets"
 
 const props = withDefaults(defineProps<{ id: string }>(), { id: "" })
+const id = ref(props.id)
+const emptyTableText = "未查询到数据"
 const companyInfo = ref({
   name: "",
   type_name: "",
@@ -25,7 +27,7 @@ const companyInfo = ref({
 const contactInfo = ref<Array<{ name: string; position: string; tel: string; phone: string }>>([])
 const monitorPointInfo = ref<Array<{ name: string; status: string; attr: string }>>([])
 function getCompanyInfo() {
-  Rs.post("sys/onlineData/record/" + props.id).then((res) => {
+  Rs.post("sys/onlineData/record", { data: id.value, successAlert: false }).then((res) => {
     const company = res.data.company
     if (company) {
       companyInfo.value.name = company.name
@@ -69,6 +71,7 @@ function getCompanyInfo() {
 function init() {
   getCompanyInfo()
 }
+watch(() => props.id, init)
 
 onMounted(() => {
   init()
@@ -78,59 +81,61 @@ onMounted(() => {
   <div class="px-10 py-5">
     <h2 class="my-5">商户信息</h2>
     <table class="table table-bordered table-flush table-layout-fixed">
-      <tr>
-        <th class="bg-light-primary">商户名称</th>
-        <td>{{ companyInfo.name }}</td>
-        <th class="bg-light-primary align-right">类型</th>
-        <td>{{ companyInfo.type_name }}</td>
-      </tr>
-      <tr>
-        <th class="bg-light-primary">商户性质</th>
-        <td>{{ companyInfo.property_name }}</td>
-        <th class="bg-light-primary">规模</th>
-        <td>{{ companyInfo.catering_scale_name }}</td>
-      </tr>
-      <tr>
-        <th class="bg-light-primary">营业状态</th>
-        <td>{{ companyInfo.catering_state }}</td>
-        <th class="bg-light-primary">菜系</th>
-        <td>{{ companyInfo.catering_style_name }}</td>
-      </tr>
-      <tr>
-        <th class="bg-light-primary">法人代码</th>
-        <td>{{ companyInfo.xinyong_code }}</td>
-        <th class="bg-light-primary">区域</th>
-        <td>{{ companyInfo.org_name }}</td>
-      </tr>
-      <tr>
-        <th class="bg-light-primary">法人代表</th>
-        <td>{{ companyInfo.corporation_name }}</td>
-        <th class="bg-light-primary">经度</th>
-        <td>{{ companyInfo.longitude }}</td>
-      </tr>
-      <tr>
-        <th class="bg-light-primary">商户地址</th>
-        <td>{{ companyInfo.address }}</td>
-        <th class="bg-light-primary">纬度</th>
-        <td>{{ companyInfo.latitude }}</td>
-      </tr>
-      <tr>
-        <th class="bg-light-primary">灶头数</th>
-        <td>{{ companyInfo.stove_num }}</td>
-        <th class="bg-light-primary">人数</th>
-        <td>{{ companyInfo.people }}</td>
-      </tr>
-      <tr>
-        <th class="bg-light-primary">排口数</th>
-        <td>{{ companyInfo.outlet_num }}</td>
-        <th class="bg-light-primary">面积</th>
-        <td>{{ companyInfo.acreage }}</td>
-      </tr>
+      <tbody>
+        <tr>
+          <th class="bg-light-primary">商户名称</th>
+          <td>{{ companyInfo.name }}</td>
+          <th class="bg-light-primary align-right">类型</th>
+          <td>{{ companyInfo.type_name }}</td>
+        </tr>
+        <tr>
+          <th class="bg-light-primary">商户性质</th>
+          <td>{{ companyInfo.property_name }}</td>
+          <th class="bg-light-primary">规模</th>
+          <td>{{ companyInfo.catering_scale_name }}</td>
+        </tr>
+        <tr>
+          <th class="bg-light-primary">营业状态</th>
+          <td>{{ companyInfo.catering_state }}</td>
+          <th class="bg-light-primary">菜系</th>
+          <td>{{ companyInfo.catering_style_name }}</td>
+        </tr>
+        <tr>
+          <th class="bg-light-primary">法人代码</th>
+          <td>{{ companyInfo.xinyong_code }}</td>
+          <th class="bg-light-primary">区域</th>
+          <td>{{ companyInfo.org_name }}</td>
+        </tr>
+        <tr>
+          <th class="bg-light-primary">法人代表</th>
+          <td>{{ companyInfo.corporation_name }}</td>
+          <th class="bg-light-primary">经度</th>
+          <td>{{ companyInfo.longitude }}</td>
+        </tr>
+        <tr>
+          <th class="bg-light-primary">商户地址</th>
+          <td>{{ companyInfo.address }}</td>
+          <th class="bg-light-primary">纬度</th>
+          <td>{{ companyInfo.latitude }}</td>
+        </tr>
+        <tr>
+          <th class="bg-light-primary">灶头数</th>
+          <td>{{ companyInfo.stove_num }}</td>
+          <th class="bg-light-primary">人数</th>
+          <td>{{ companyInfo.people }}</td>
+        </tr>
+        <tr>
+          <th class="bg-light-primary">排口数</th>
+          <td>{{ companyInfo.outlet_num }}</td>
+          <th class="bg-light-primary">面积</th>
+          <td>{{ companyInfo.acreage }}</td>
+        </tr>
+      </tbody>
     </table>
     <h2 class="my-5">联系信息</h2>
     <table class="table table-bordered table-flush table-layout-fixed">
       <thead>
-        <tr>
+        <tr class="text-center">
           <th class="bg-light-primary">联系人</th>
           <th class="bg-light-primary">职务属性</th>
           <th class="bg-light-primary">手机号</th>
@@ -138,7 +143,7 @@ onMounted(() => {
         </tr>
       </thead>
       <tbody v-if="contactInfo.length">
-        <tr v-for="(v, i) in contactInfo" :key="i">
+        <tr v-for="(v, i) in contactInfo" :key="i" class="text-center">
           <td>{{ v.name }}</td>
           <td>{{ v.position }}</td>
           <td>{{ v.phone }}</td>
@@ -146,22 +151,27 @@ onMounted(() => {
         </tr>
       </tbody>
       <tbody v-else>
-        <tr>
-          <td>暂无数据</td>
+        <tr class="text-center">
+          <td colspan="4">
+            <div class="h-100px w-100 d-flex justify-content-center flex-column align-items-center">
+              <img class="mb-2" :src="getAssetPath('media/table/empty.svg')" />
+              <span class="text-gray-500">{{ emptyTableText }}</span>
+            </div>
+          </td>
         </tr>
       </tbody>
     </table>
     <h2 class="my-5">监测点信息</h2>
     <table class="table table-bordered table-flush table-layout-fixed">
       <thead>
-        <tr>
+        <tr class="text-center">
           <th class="bg-light-primary">点位名称</th>
           <th class="bg-light-primary">处理风量 m3/h</th>
           <th class="bg-light-primary">当前状态</th>
         </tr>
       </thead>
       <tbody v-if="monitorPointInfo.length">
-        <tr v-for="(v, i) in monitorPointInfo" :key="i">
+        <tr v-for="(v, i) in monitorPointInfo" :key="i" class="text-center">
           <td>{{ v.name }}</td>
           <td>{{ v.attr }}</td>
           <td>{{ v.status }}</td>
@@ -169,7 +179,12 @@ onMounted(() => {
       </tbody>
       <tbody v-else>
         <tr>
-          <td>暂无数据</td>
+          <td colspan="3">
+            <div class="h-100px w-100 d-flex justify-content-center flex-column align-items-center">
+              <img class="mb-2" :src="getAssetPath('media/table/empty.svg')" />
+              <span class="text-gray-500">{{ emptyTableText }}</span>
+            </div>
+          </td>
         </tr>
       </tbody>
     </table>

+ 12 - 3
src/views/goLineData/_ViewDevice.vue

@@ -1,8 +1,10 @@
 <script setup lang="ts">
 import { ref, withDefaults, onMounted } from "vue"
+import ViewDeviceGeneral from "./_ViewDevice_General.vue"
+import ViewDeviceData from "./_ViewDevice_Data.vue"
 
-const props = withDefaults(defineProps<{ value: string }>(), { value: "" })
-const emits = defineEmits<{ (e: "update:value", v: string): void }>()
+const props = withDefaults(defineProps<{ id: string; active: number }>(), { id: "", active: 0 })
+const active = ref(props.active)
 
 function init() {
   //
@@ -13,5 +15,12 @@ onMounted(() => {
 })
 </script>
 <template>
-  <div>DEVICE</div>
+  <el-tabs v-model="active">
+    <el-tab-pane label="设备数据" :name="0">
+      <ViewDeviceData v-if="active == 0" :id="id"></ViewDeviceData>
+    </el-tab-pane>
+    <el-tab-pane label="设备概览" :name="1">
+      <ViewDeviceGeneral v-if="active == 1" :id="id"></ViewDeviceGeneral>
+    </el-tab-pane>
+  </el-tabs>
 </template>

+ 143 - 0
src/views/goLineData/_ViewDevice_Data.vue

@@ -0,0 +1,143 @@
+<script setup lang="ts">
+import { ref, withDefaults, onMounted, watch } from "vue"
+import moment from "moment"
+import Rs from "@/core/services/RequestService"
+
+const props = withDefaults(defineProps<{ id: string }>(), { id: "" })
+const date = ref<[Date, Date]>([new Date(), new Date()])
+const chartData = ref<Array<any>>([{}, {}, {}])
+const lineOptions = {
+  grid: { top: 30 },
+  titleText: " ",
+}
+
+function queryChart(type: number) {
+  let url = ""
+  let data: any = {}
+  switch (type) {
+    case 0:
+      url = "sys/onlineData/terminal/line"
+      data = {
+        id: props.id,
+        begin: moment(date.value[0]).format("YYYYMMDD"),
+        end: moment(date.value[1]).format("YYYYMMDD"),
+      }
+      break
+    case 1:
+      url = "sys/onlineData/terminal/powerline"
+      data = {
+        id: props.id,
+        begin: moment(date.value[0]).format("YYYYMMDD"),
+        end: moment(date.value[1]).format("YYYYMMDD"),
+      }
+      break
+    case 2:
+      url = "sys/onlineData/terminal/workLine"
+      data = {
+        id: props.id,
+        begin: moment(date.value[0]).format("YYYYMMDD"),
+        end: moment(date.value[1]).format("YYYYMMDD"),
+      }
+      break
+  }
+  Rs.post(url, { data: data, successAlert: false }).then((res) => {
+    chartData.value[type] = res.data
+  })
+}
+
+const cols = ref([
+  {
+    name: "数据项",
+    field: "name",
+  },
+  {
+    name: "最大值",
+    field: "value",
+  },
+  {
+    name: "最大值发生时间",
+    field: "time",
+  },
+])
+const queryParams = ref({
+  id: props.id,
+  begin: moment(date.value[0]).format("YYYYMMDD"),
+  end: moment(date.value[1]).format("YYYYMMDD"),
+})
+function query() {
+  queryChart(0)
+  queryChart(1)
+}
+
+onMounted(() => {
+  query()
+})
+watch(() => props.id, query)
+</script>
+<template>
+  <el-row :gutter="20" class="mb-5">
+    <el-col :span="24">
+      <el-form class="align-items-center" :inline="true">
+        <el-form-item class="mb-0 me-5 align-items-center" label="日期:">
+          <el-date-picker
+            v-model="date"
+            type="daterange"
+            range-separator="~"
+            start-placeholder="开始时间"
+            end-placeholder="结束时间"
+            size="default"
+          />
+        </el-form-item>
+
+        <el-form-item class="mb-0 me-0 align-items-center">
+          <el-button class="ms-3 mt-0 btn btn-sm btn-primary" @click="query">查询</el-button>
+        </el-form-item>
+      </el-form>
+    </el-col>
+  </el-row>
+  <el-row :gutter="20" class="mb-5">
+    <el-col :span="24">
+      <div class="card card-bordered border-primary">
+        <div class="card-header bg-light-primary min-h-50px">
+          <div class="card-title"><h2 class="text-primary">浓度数据曲线</h2></div>
+        </div>
+        <div class="card-body p-3">
+          <BaseChart :data="chartData[0]" type="line" :options="lineOptions" h="230px"></BaseChart>
+        </div>
+      </div>
+    </el-col>
+  </el-row>
+  <el-row :gutter="20" class="mb-5">
+    <el-col :span="24">
+      <div class="card card-bordered border-primary">
+        <div class="card-header bg-light-primary min-h-50px">
+          <div class="card-title"><h2 class="text-primary">用电数据曲线</h2></div>
+        </div>
+        <div class="card-body p-3">
+          <BaseChart :data="chartData[1]" type="line" :options="lineOptions" h="230px"></BaseChart>
+        </div>
+      </div>
+    </el-col>
+  </el-row>
+  <!-- TODO chart -->
+  <el-row :gutter="20" class="mb-5" v-if="false">
+    <el-col :span="24">
+      <div class="card card-bordered border-primary">
+        <div class="card-header bg-light-primary min-h-50px">
+          <div class="card-title"><h2 class="text-primary">设备停上电情况</h2></div>
+        </div>
+        <div class="card-body p-3">
+          <BaseChart :data="chartData[2]" type="line" :options="lineOptions" h="230px"></BaseChart>
+        </div>
+      </div>
+    </el-col>
+  </el-row>
+  <VbDataTable
+    :header="cols"
+    url="sys/onlineData/getMonitorList"
+    :query-params="queryParams"
+    method="post"
+    :has-checkbox="false"
+    :no-page="true"
+  ></VbDataTable>
+</template>

+ 129 - 0
src/views/goLineData/_ViewDevice_General.vue

@@ -0,0 +1,129 @@
+<script setup lang="ts">
+import { ref, withDefaults, onMounted, watch } from "vue"
+import { getAssetPath } from "@/core/helpers/assets"
+import Rs from "@/core/services/RequestService"
+
+const props = withDefaults(defineProps<{ id: string }>(), { id: "" })
+const emptyTableText = "未查询到数据"
+const deviceInfo = ref<any>({})
+const cleanInfo = ref<Array<any>>([])
+function getDeviceInfo() {
+  Rs.post("sys/onlineData/getMonitorData", { data: { id: props.id } }).then((res) => {
+    if (res.data) {
+      deviceInfo.value.name = res.data.name
+      deviceInfo.value.air_volume = res.data.air_volume
+      deviceInfo.value.monitor_status = res.data.monitor_status
+      deviceInfo.value.fan_status = res.data.fan_status
+      deviceInfo.value.purifier_status = res.data.purifier_status
+      deviceInfo.value.efficiency = res.data.efficiency
+    }
+  })
+}
+const cols = ref([
+  // {
+  //   name: "序号",
+  //   field: "index",
+  // },
+  {
+    name: "净化器名称",
+    field: "monitor_name",
+  },
+  {
+    name: "天数",
+    field: "day_condition",
+  },
+  {
+    name: "开机小时",
+    field: "hour_condition",
+  },
+  {
+    name: "最后清洗时间",
+    field: "last_clean_time",
+  },
+  {
+    name: "经过天数",
+    field: "run_day",
+  },
+  {
+    name: "开机小时数",
+    field: "run_hour",
+  },
+  {
+    name: "剩余天数",
+    field: "surplus_day",
+  },
+  {
+    name: "剩余小时数",
+    field: "surplus_hour",
+  },
+])
+const queryParams = ref({
+  id: props.id,
+})
+function init() {
+  getDeviceInfo()
+  queryParams.value = {
+    id: props.id,
+  }
+}
+watch(() => props.id, init)
+
+onMounted(() => {
+  init()
+})
+</script>
+<template>
+  <div class="px-10 py-5">
+    <h2 class="my-5">设备信息</h2>
+    <table class="table table-bordered table-flush table-layout-fixed">
+      <tbody>
+        <tr>
+          <th class="bg-light-primary">净化设施</th>
+          <td>{{ deviceInfo.name }}</td>
+          <th class="bg-light-primary align-right">处理风量</th>
+          <td>{{ deviceInfo.air_volume }}</td>
+          <th class="bg-light-primary align-right">净化能效</th>
+          <td>{{ deviceInfo.efficiency }}</td>
+        </tr>
+        <tr>
+          <th class="bg-light-primary">监控仪状态</th>
+          <td>{{ deviceInfo.monitor_status }}</td>
+          <th class="bg-light-primary align-right">风机状态</th>
+          <td>{{ deviceInfo.fan_status }}</td>
+          <th class="bg-light-primary align-right">净化器状态</th>
+          <td>{{ deviceInfo.purifier_status }}</td>
+        </tr>
+      </tbody>
+    </table>
+    <h2 class="my-5">设备信息</h2>
+    <VbDataTable
+      url="sys/onlineData/selectCleanPage"
+      :header="cols"
+      :query-params="queryParams"
+      method="post"
+      :has-checkbox="false"
+      :pagination="false"
+    >
+      <template #tableHeader>
+        <thead>
+          <tr class="text-center">
+            <!-- <th class="bg-light-primary" rowspan="2" style="vertical-align: middle">序号</th> -->
+            <th class="bg-light-primary" rowspan="2" style="vertical-align: middle">净化器名称</th>
+            <th class="bg-light-primary" colspan="2">清洗周期</th>
+            <th class="bg-light-primary" rowspan="2" style="vertical-align: middle">最后清洗时间</th>
+            <th class="bg-light-primary" colspan="2">上次清洗至今</th>
+            <th class="bg-light-primary" colspan="2">距下次清洗</th>
+          </tr>
+          <tr class="text-center">
+            <th class="bg-light-primary">天数</th>
+            <th class="bg-light-primary">开机小时</th>
+            <th class="bg-light-primary">经过天数</th>
+            <th class="bg-light-primary">开机小时数</th>
+            <th class="bg-light-primary">剩余天数</th>
+            <th class="bg-light-primary">剩余小时数</th>
+          </tr>
+        </thead>
+      </template>
+    </VbDataTable>
+  </div>
+</template>

+ 7 - 1
src/views/overAnalysis/overParam copy.vue

@@ -39,7 +39,7 @@ const saveUrl = computed(() => {
     ? "sys/organizational/delById"
     : ""
 })
-
+const org_Id = ref("22")
 //只放增改传到后台的共用参数,其余需要modal显示的参数另外定义
 const emptyData = {
   org_id: "",
@@ -63,6 +63,9 @@ const items: Array<VbFormItem> = [
     required: false,
     component: OrgSelectTree,
     span: 12,
+    props: {
+      id: org_Id,
+    },
   },
   {
     field: "code",
@@ -161,11 +164,14 @@ function pcdChange(v: Array<string>) {
   formData.value.district = v[2]
 }
 function add() {
+  org_Id.value = "2111"
   opreationType.value = "A"
   formData.value = Object.assign({ province_city_district: ["", "", ""] }, emptyData)
   modal.value.show()
 }
 function edit(row: any) {
+  org_Id.value = "3111"
+
   opreationType.value = "U"
   formData.value = Object.assign({}, row)
   modal.value.show()