Browse Source

[Wip 0000] 首页配置列表二次开发,对接首页各个模块

houzekong 8 months ago
parent
commit
83efa9ce4e

+ 13 - 0
src/views/vent/deviceManager/configurationTable/configuration.data.ts

@@ -21,6 +21,10 @@ export const columns: BasicColumn[] = [
     dataIndex: 'moduleData.main',
   },
   {
+    title: '模块页头配置',
+    dataIndex: 'moduleData.header',
+  },
+  {
     title: '模块图表配置',
     dataIndex: 'moduleData.chart',
   },
@@ -107,6 +111,15 @@ export const formSchema: FormSchema[] = [
     },
   },
   {
+    label: '模块页头配置',
+    field: 'moduleData.header',
+    component: 'JAddInput',
+    componentProps: {
+      min: 0,
+      placeholders: ['请输入点位', '请输入名称'],
+    },
+  },
+  {
     label: '模块图表配置',
     field: 'moduleData.chart',
     component: 'JAddInput',

+ 24 - 15
src/views/vent/deviceManager/configurationTable/index.vue

@@ -1,17 +1,7 @@
 <!-- eslint-disable vue/multi-word-component-names -->
 <template>
   <div class="device-manager-box">
-    <NormalTable
-      :columns="columns"
-      :searchFormSchema="searchFormSchema"
-      :formSchema="formSchema"
-      :list="list"
-      :deleteById="deleteById"
-      :saveOrUpdate="saveOrUpdate"
-      title="配置列表"
-      :showTab="true"
-      :deviceType="deviceType"
-    >
+    <BasicTable @register="register">
       <template #filterCell="{ column, record }">
         <template v-if="column.key === 'moduleData.main'">
           <div v-for="(val, key) in record.moduleData.main" :key="key">
@@ -19,6 +9,12 @@
             <span>名称:{{ val }};</span>
           </div>
         </template>
+        <template v-if="column.key === 'moduleData.header'">
+          <div v-for="(val, key) in record.moduleData.header" :key="key">
+            <span>点位:{{ key }};</span>
+            <span>名称:{{ val }};</span>
+          </div>
+        </template>
         <template v-if="column.key === 'moduleData.chart'">
           <div v-for="(val, key) in record.moduleData.chart" :key="key">
             <span>点位:{{ key }};</span>
@@ -38,20 +34,33 @@
           {{ get(ModuleChartTypeMap, record.showStyle?.charttype) }}
         </template>
       </template>
-    </NormalTable>
+    </BasicTable>
   </div>
 </template>
 
 <script lang="ts" name="system-user" setup>
   // 相关文档请参阅 vent/home/configurable/README.md
-  import { ref } from 'vue';
-  import NormalTable from '../comment/NormalTable.vue';
+  // import NormalTable from '../comment/NormalTable.vue';
   import { list, deleteById, saveOrUpdate } from './configuration.api';
   import { ModuleVersionMap, ModuleChartTypeMap, ModulePositionMap, ModuleSizeMap } from './options';
   import { searchFormSchema, columns, formSchema } from './configuration.data';
   import { get } from '../../home/billboard/utils';
+  import BasicTable from '/@/components/Table/src/BasicTable.vue';
+  import { useListPage } from '/@/hooks/system/useListPage';
+
+  const { tableContext } = useListPage({
+    tableProps: {
+      api: list,
+      columns: columns, //表格列
+      useSearchForm: true,
+      formConfig: {
+        schemas: searchFormSchema,
+      },
+    },
+  });
 
-  const deviceType = ref('');
+  //BasicTable绑定注册,methods包含的方法参考下方Methods的api
+  const [register, methods] = tableContext;
 </script>
 
 <style scoped></style>

+ 1 - 0
src/views/vent/deviceManager/configurationTable/types.ts

@@ -6,6 +6,7 @@ export interface Config {
   showStyle: ShowStyle;
 }
 export interface ModuleData {
+  header?: Record<string, string>;
   main?: Record<string, string>;
   chart?: Record<string, string>;
 }

+ 21 - 28
src/views/vent/home/configurable/components/AirVolumeMonitor.vue

@@ -9,7 +9,7 @@
       </div>
     </div>
   </CostumeHeader> -->
-    <PictorialBar :option="chartOption" :series-prop-type="seriesPropType" x-axis-prop-type="x" :chart-data="chartData" height="100%" />
+    <PictorialBar :option="chartOption" series-prop-type="y" x-axis-prop-type="x" :chart-data="chartData" height="100%" />
     <!-- <div class="flex justify-around mt-10px">
     <MiniBoard v-for="item in configs" :key="item.prop" :label="item.label" :value="selectedDevice[item.prop]" />
   </div> -->
@@ -19,51 +19,44 @@
   import { computed, onMounted, ref } from 'vue';
   import PictorialBar from '/@/components/chart/PictorialBar.vue';
   import { EChartsOption, graphic } from 'echarts';
-  import { useInitConfig } from '../hooks/useInit';
+  import { useInitScene } from '../hooks/useInit';
   import _ from 'lodash-es';
+  import { get } from '../../billboard/utils';
   import ModuleBasic from './moduleBasic.vue';
   // import mapComponent from './components/3Dmap/index.vue';
 
   // 设备类别,是个枚举 TODO: 将手动换为自动获取类别
-  const devicekind = 'fanlocal';
+  const devicekind = 'sys_wind';
 
   const config = ref({
     moduleName: '矿井风量实时监测',
+    moduleData: {
+      chart: {
+        x: 'stationname',
+        y: 'readData.m3',
+      },
+    },
     showStyle: {
       size: 'width:1000px;height:280px;',
       position: 'left:460px;top:640px;',
       version: 'enhanced',
     },
   });
-  const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
+  // const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
+  const { scene, fetchScene } = useInitScene(devicekind);
 
-  onMounted(() => {
-    fetchConfig();
+  const chartData = computed(() => {
+    return scene.value.map((ele) => {
+      return {
+        x: get(ele, get(config.value, 'moduleData.chart.x', 'x')),
+        y: get(ele, get(config.value, 'moduleData.chart.y', 'y')),
+      };
+    });
   });
 
-  // 适用于 PictorialBar 的 prop,即从配置中选取第一项作取值依赖
-  const seriesPropType = computed(() => {
-    if (remoteConfig.value.moduleData?.chart) {
-      return Object.keys(remoteConfig.value.moduleData?.chart)[0];
-    } else {
-      return 'y';
-    }
-  });
-
-  const chartData = ref<any[]>([
-    { valueA: 1, y: 1, x: 2 },
-    { valueA: 1, y: 1, x: 3 },
-    { valueA: 1, y: 1, x: 4 },
-    { valueA: 1, y: 1, x: 5 },
-    { valueA: 2, y: 2, x: 6 },
-    { valueA: 3, y: 1, x: 7 },
-    { valueA: 1, y: 1, x: 8 },
-  ]);
-
-  function fetchChartData() {}
-
   onMounted(() => {
-    fetchChartData();
+    // fetchConfig();
+    fetchScene();
   });
 
   // 图表的配置项

+ 35 - 33
src/views/vent/home/configurable/components/DeviceWarning.vue

@@ -8,9 +8,9 @@
       </template>
       <div class="w-200px flex flex-items-center">
         <RightCircleOutlined class="w-30px" />
-        <div class="flex-grow-1">
-          网络断开
-          <span> {{ warns.length }}条 </span>
+        <div v-for="(label, prop) in config.moduleData.header" :key="prop" class="flex-grow-1">
+          {{ label }}
+          <span> {{ get(scene, prop) }}条 </span>
         </div>
       </div>
     </CostumeHeader>
@@ -26,17 +26,20 @@
   </ModuleBasic>
 </template>
 <script lang="ts" setup>
-  import { onMounted, ref } from 'vue';
+  import { computed, onMounted, ref } from 'vue';
   // import { list as cfgList } from '@/views/vent/deviceManager/configurationTable/configuration.api';
   // import { list } from '@/views/vent/deviceManager/deviceTable/device.api';
   import ModuleBasic from './moduleBasic.vue';
   import CostumeHeader from './CostumeHeader.vue';
   import { RightCircleOutlined } from '@ant-design/icons-vue';
+  import { useInitScene } from '../hooks/useInit';
+  import { get } from '../../billboard/utils';
+  import _ from 'lodash-es';
   // import MiniBoard from './MiniBoard.vue';
   // import mapComponent from './components/3Dmap/index.vue';
 
   // 设备类别,是个枚举 TODO: 将手动换为自动获取类别
-  // const devicekind = 'fanlocal';
+  const devicekind = 'warn';
 
   // const configs = ref<{ prop: string; label: string }[]>([]);
   // function fetchConfig() {
@@ -53,7 +56,19 @@
   //   });
   // }
   const config = ref({
-    moduleName: '采煤工作面智能管控',
+    moduleName: '设备告警',
+    moduleData: {
+      header: {
+        'netstatus.val': '网络断开',
+      },
+      main: {
+        'red.val': '严重',
+        'orange.val': '非常严重',
+        'yellow.val': '较严重',
+        'blue.val': '一般严重',
+        'alarm.val': '报警',
+      },
+    },
     showStyle: {
       size: 'width:450px;height:280px;',
       position: 'right:0px;top:640px;',
@@ -61,36 +76,23 @@
     },
   });
   // const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
+  const { scene, fetchScene } = useInitScene(devicekind);
 
-  const warns = ref([
-    {
-      label: 'test',
-      count: 0,
-      color: 'red',
-    },
-    {
-      label: 'test',
-      count: 0,
-      color: 'orange',
-    },
-    {
-      label: 'test',
-      count: 0,
-      color: 'yellow',
-    },
-    {
-      label: 'test',
-      count: 0,
-      color: 'green',
-    },
-    {
-      label: 'test',
-      count: 0,
-      color: 'blue',
-    },
-  ]);
+  const warns = computed(() => {
+    const colors = ['red', 'orange', 'yellow', 'green', 'blue'];
+    let i = -1;
+    return _.map(config.value.moduleData.main || [], (label, prop) => {
+      i += 1;
+      return {
+        label,
+        count: get(scene, prop),
+        color: colors[i],
+      };
+    });
+  });
 
   onMounted(() => {
+    fetchScene();
     // fetchConfig();
   });
 </script>

+ 30 - 31
src/views/vent/home/configurable/components/VentilateAnalysis.vue

@@ -12,7 +12,7 @@
     <Pie :option="chartOption" :chart-data="chartData" height="140px" />
     <div class="flex justify-around mt-10px">
       <MiniBoard
-        v-for="(label, prop) in remoteConfig.moduleData?.main"
+        v-for="(label, prop) in config.moduleData?.main"
         :key="`vhccva-${prop}`"
         :label="label"
         :value="get(selectedDevice, prop)"
@@ -24,10 +24,10 @@
 </template>
 <script lang="ts" setup>
   import CostumeHeader from './CostumeHeader.vue';
-  import { onMounted, ref } from 'vue';
+  import { computed, onMounted, ref } from 'vue';
   import Pie from '/@/components/chart/Pie.vue';
   import { EChartsOption } from 'echarts';
-  import { useInitConfig, useInitDevices } from '../hooks/useInit';
+  import { useInitDevices } from '../hooks/useInit';
   import { get } from '../../billboard/utils';
   import _ from 'lodash-es';
   import MiniBoard from './MiniBoard.vue';
@@ -35,51 +35,50 @@
   // import mapComponent from './components/3Dmap/index.vue';
 
   // 设备类别,是个枚举 TODO: 将手动换为自动获取类别
-  const devicekind = 'fanlocal';
+  const devicekind = 'sys_majorpath';
 
   const config = ref({
-    moduleName: '通风系统监测与分析',
+    moduleName: '关键通风路线', // 通风系统监测与分析
+    moduleData: {
+      main: {
+        // m3_total: '总风量',
+        // drag_total: '总阻力',
+        // dengjikong: '等积孔',
+        'majorpath.drag_1': '阻力1',
+        'majorpath.drag_2': '阻力2',
+        'majorpath.drag_3': '阻力3',
+      },
+      chart: {
+        'majorpath.drag_1': '阻力1',
+        'majorpath.drag_2': '阻力2',
+        'majorpath.drag_3': '阻力3',
+      },
+    },
     showStyle: {
       size: 'width:450px;height:280px;',
       position: 'right:0px;top:60px;',
       version: 'enhanced',
     },
   });
-  const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
+  // const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
   const { options, selectedDevice, selectedDeviceID, fetchDevices } = useInitDevices(devicekind);
 
   onMounted(() => {
-    fetchConfig();
+    // fetchConfig();
     fetchDevices();
   });
 
-  const chartData = ref<any[]>([
-    {
-      value: 70,
-      name: 'A',
-    },
-    {
-      value: 30,
-      name: 'B',
-    },
-  ]);
-
-  function fetchChartData() {
-    return;
-    Promise.resolve({ a: 3, b: 7 }).then((res) => {
-      chartData.value = _.map(remoteConfig.value.moduleData?.chart || [], (label, prop) => {
-        return {
-          value: _.get(res, prop),
-          name: label,
-        };
-      });
+  const chartData = computed(() => {
+    return _.map(config.value.moduleData?.chart || [], (label, prop) => {
+      return {
+        value: parseInt(get(selectedDevice.value, prop, 0)),
+        name: label,
+      };
     });
-  }
-
-  onMounted(() => {
-    fetchChartData();
   });
 
+  onMounted(() => {});
+
   // 图表配置项
   const chartOption: EChartsOption = {
     series: [

+ 12 - 14
src/views/vent/home/configurable/components/VentilateControl.vue

@@ -1,14 +1,12 @@
 <!-- eslint-disable vue/multi-word-component-names -->
 <template>
   <ModuleBasic :title="config.moduleName" :version="config.showStyle?.version" :size="config.showStyle?.size" :position="config.showStyle?.position">
-    <CostumeHeader v-model:value="selectedDeviceID" :options="options">
-      <div class="w-200px flex flex-items-center">
-        <RightCircleOutlined class="w-30px" />
-        <div class="flex-grow-1">
-          {{ selectedDevice.strinstallpos }}
-        </div>
-      </div>
-    </CostumeHeader>
+    <!-- <CostumeHeader v-model:value="selectedDeviceID" :options="options">
+      <template #select>
+        <div></div>
+      </template>
+      <div> </div>
+    </CostumeHeader> -->
     <!-- <div class="flex justify-around mt-10px">
     <MiniBoard v-for="item in configs" :key="item.prop" :label="item.label" :value="selectedDevice[item.prop]" />
   </div> -->
@@ -16,16 +14,16 @@
 </template>
 <script lang="ts" setup>
   import { onMounted, ref } from 'vue';
-  import CostumeHeader from './CostumeHeader.vue';
-  import { RightCircleOutlined } from '@ant-design/icons-vue';
+  // import CostumeHeader from './CostumeHeader.vue';
+  // import { RightCircleOutlined } from '@ant-design/icons-vue';
   import ModuleBasic from './moduleBasic.vue';
   // import MiniBoard from './MiniBoard.vue';
-  import { useInitDevices } from '../hooks/useInit';
+  // import { useInitDevices } from '../hooks/useInit';
   // import { get } from '../../billboard/utils';
   // import mapComponent from './components/3Dmap/index.vue';
 
   // 设备类别,是个枚举 TODO: 将手动换为自动获取类别
-  const devicekind = 'fanlocal';
+  // const devicekind = 'fanlocal';
 
   const config = ref({
     moduleName: '通风设施远程控制',
@@ -36,11 +34,11 @@
     },
   });
   // const { configs, fetchConfig } = useInitConfig(devicekind);
-  const { options, selectedDevice, selectedDeviceID, fetchDevices } = useInitDevices(devicekind);
+  // const { options, selectedDevice, selectedDeviceID, fetchDevices } = useInitDevices(devicekind);
 
   onMounted(() => {
     // fetchConfig();
-    fetchDevices();
+    // fetchDevices();
   });
 </script>
 <style scoped></style>

+ 26 - 30
src/views/vent/home/configurable/components/WorkSurface.vue

@@ -12,14 +12,14 @@
     <LineMulti
       :option="chartOption"
       :prop-type-arr="propTypeArr"
-      x-axis-prop-type="x"
+      x-axis-prop-type="time"
       :chart-data="chartData"
       height="140px"
       class="worksurface-chart"
     />
     <div class="flex justify-around">
       <MiniBoard
-        v-for="(label, prop) in remoteConfig.moduleData?.main"
+        v-for="(label, prop) in config.moduleData?.main"
         :key="`vhccws-${prop}`"
         :label="label"
         :value="get(selectedDevice, prop)"
@@ -34,7 +34,7 @@
   import CostumeHeader from './CostumeHeader.vue';
   import { computed, onMounted, ref } from 'vue';
   import { EChartsOption } from 'echarts';
-  import { useInitConfig, useInitDevices } from '../hooks/useInit';
+  import { useInitDevices } from '../hooks/useInit';
   import { get } from '../../billboard/utils';
   import _ from 'lodash-es';
   import MiniBoard from './MiniBoard.vue';
@@ -42,53 +42,49 @@
   // import mapComponent from './components/3Dmap/index.vue';
 
   // 设备类别,是个枚举 TODO: 将手动换为自动获取类别
-  const devicekind = 'fanlocal';
+  const devicekind = 'sys_surface_caimei';
 
   const config = ref({
     moduleName: '采煤工作面智能管控',
+    moduleData: {
+      main: {
+        jin: '进风',
+        hui: '回风',
+        xufengliang: '需风量',
+      },
+      // 这里的配置比较特殊,需要配置为数据中 history 对象下的取值路径。无法针对 x 轴进行配置
+      // 例如数据为 { history: [ jin: 10 ] },那么需要配置为 jin
+      chart: {
+        hui: '回风量',
+        jin: '进风量',
+      },
+    },
     showStyle: {
       size: 'width:450px;height:280px;',
       position: 'right:0px;top:350px;',
       version: 'enhanced',
     },
   });
-  const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
+  // const { config: remoteConfig, fetchConfig } = useInitConfig(devicekind);
   const { options, selectedDevice, selectedDeviceID, fetchDevices } = useInitDevices(devicekind);
 
   onMounted(() => {
-    fetchConfig();
+    // fetchConfig();
     fetchDevices();
   });
 
-  const chartData = ref<any[]>([
-    { valueA: 1, valueB: 3, x: 2 },
-    { valueA: 2, valueB: 1, x: 3 },
-    { valueA: 1, valueB: 1, x: 4 },
-    { valueA: 3, valueB: 2, x: 5 },
-    { valueA: 2, valueB: 1, x: 6 },
-    { valueA: 1, valueB: 2, x: 7 },
-  ]);
+  const chartData = computed(() => {
+    return selectedDevice.value.history || [];
+  });
 
   const propTypeArr = computed(() => {
-    if (remoteConfig.value.moduleData?.chart) {
-      const map = new Map();
-      _.forEach(remoteConfig.value.moduleData?.chart || [], (label, prop) => {
+    const map = new Map();
+    if (config.value.moduleData?.chart) {
+      _.forEach(config.value.moduleData?.chart || [], (label, prop) => {
         map.set(prop, label);
       });
-
-      return map;
-    } else {
-      return new Map([
-        ['valueA', '值A'],
-        ['valueB', '值B'],
-      ]);
     }
-  });
-
-  function fetchChartData() {}
-
-  onMounted(() => {
-    fetchChartData();
+    return map;
   });
 
   // 图表相关

+ 17 - 1
src/views/vent/home/configurable/configurable.api.ts

@@ -4,10 +4,26 @@ enum Api {
   list = '/ventanaly-device/safety/ventanalyDevice/homedata2',
   getHomeData = '/ventanaly-device/safety/ventanalyDevice/homedata',
 }
+
+// 搞这个缓存是由于:目前代码上的设计是多个模块发出多次请求,每个模块自己负责消费前者的响应。
+// 这会导致相同的请求被同时发送多次。
+const cache = new Map<string, Promise<any>>();
+
 /**
  * 列表接口
  * @param params
  */
 export const list = (params) => defHttp.post({ url: Api.list, params });
 
-export const getHomeData = (params) => defHttp.post({ url: Api.getHomeData, params });
+export const getHomeData = (params) => {
+  const key = `${Api.getHomeData}?${JSON.stringify(params)}`;
+  if (!cache.has(key)) {
+    cache.set(
+      key,
+      defHttp.post({ url: Api.getHomeData, params }).finally(() => {
+        cache.delete(key);
+      })
+    );
+  }
+  return cache.get(key) as Promise<any>;
+};

+ 41 - 8
src/views/vent/home/configurable/hooks/useInit.ts

@@ -1,7 +1,8 @@
 import { computed, ref } from 'vue';
 import { list as cfgList } from '@/views/vent/deviceManager/configurationTable/configuration.api';
-import { list } from '@/views/vent/deviceManager/deviceTable/device.api';
+// import { list } from '@/views/vent/deviceManager/deviceTable/device.api';
 import { Config } from '@/views/vent/deviceManager/configurationTable/types';
+import { getHomeData } from '../configurable.api';
 // import mapComponent from './components/3Dmap/index.vue';
 
 export function useInitConfig(deviceType: string) {
@@ -28,25 +29,38 @@ export function useInitDevices(devicekind: string) {
   const selectedDevice = computed(() => {
     return (
       devices.value.find((e) => {
-        return e.id === selectedDeviceID.value;
+        return e.deviceID === selectedDeviceID.value;
       }) || {}
     );
   });
 
   // 获取设备数据,赋值并以选项格式返回给 Header 消费
   function fetchDevices() {
-    return list({
-      devicekind,
-    }).then(({ records }) => {
+    return getHomeData({}).then((result) => {
+      if (!result[devicekind]) return;
+      // 如果数据只有一条,转为数据
+      const records: { strinstallpos?: string; deviceID: string; devicePos?: string }[] = result[devicekind];
       devices.value = records;
-      selectedDeviceID.value = records[0]?.id;
+      selectedDeviceID.value = records[0]?.deviceID;
       options.value = records.map((e) => {
         return {
-          label: e.strinstallpos,
-          value: e.id,
+          label: e.strinstallpos || e.devicePos || '/',
+          value: e.deviceID,
         };
       });
     });
+    // return list({
+    //   // devicekind,
+    // }).then(({ records }) => {
+    //   devices.value = records;
+    //   selectedDeviceID.value = records[0]?.id;
+    //   options.value = records.map((e) => {
+    //     return {
+    //       label: e.strinstallpos,
+    //       value: e.id,
+    //     };
+    //   });
+    // });
   }
 
   return {
@@ -56,3 +70,22 @@ export function useInitDevices(devicekind: string) {
     options,
   };
 }
+
+export function useInitScene(scenekind: string) {
+  const scene = ref<Record<string, any>[]>([]);
+
+  // 获取设备数据,赋值并以选项格式返回给 Header 消费
+  function fetchScene() {
+    return getHomeData({}).then((result) => {
+      if (!result[scenekind]) return;
+      // 如果数据只有一条,转为数据
+      const records: { strinstallpos: string; deviceID: string }[] = result[scenekind];
+      scene.value = records;
+    });
+  }
+
+  return {
+    fetchScene,
+    scene,
+  };
+}