XuZinan hace 2 años
padre
commit
6869f83760

+ 4 - 0
config/router.config.js

@@ -68,6 +68,10 @@ export default [
             path: '/home/flow-list',
             component: './PurchaseAdmin/PurchaseList/Flow/List',
           },
+          {
+            path: '/home/mobiletest/chart',
+            component: './Mobile/DataMeter/Chart',
+          }
         ],
       },
       {

+ 274 - 0
src/components/ChartUtils/utils.js

@@ -0,0 +1,274 @@
+import moment from 'moment';
+
+import {
+  getDeviceRealData,
+  getDeviceRealDataByTime,
+  queryFormCurrentData,
+  queryFormHistoryData,
+} from '@/services/ProjectAdmin';
+
+/**
+ * 获取图表的options
+ * @param {object} values 表单数据
+ * @param {array} datas 数据项
+ * @param {array} formula 数据公式
+ * @returns
+ */
+export async function getPlcOptions(values, datas, formula) {
+  let arrtData = values.data || [];
+  let params = getSingleData(datas);
+  let multiParams = getFormula(formula);
+  if (!values.timeType) {
+    let res = await getData(params, values);
+    for (let i = 0; i < multiParams.length; i++) {
+      let device = multiParams[i].paramsDevice;
+      let indexArr = multiParams[i].indexArr;
+      let tempExpression = [...multiParams[i].expression];
+      let formulaRes = await getData(device, values);
+      formulaRes.data.map(res => {
+        let temp = device.find(child => child.deviceName === res.alias);
+        console.log(temp);
+        if (temp) {
+          var indexObj = indexArr.find(item => item.deviceName === temp.deviceName);
+          if (indexObj) {
+            tempExpression[indexObj.index] = res.val;
+          }
+        }
+      });
+      let tempValue = computePrefixExpression([...tempExpression]);
+      multiParams[i].formatExpression = tempExpression;
+      multiParams[i].value = tempValue;
+    }
+    let resData = res.data.map((item, index) => {
+      let attrDataItem = arrtData[index + formula.length] || {};
+      return {
+        ...attrDataItem,
+        name: item.alias,
+        value: item.val * 1,
+      };
+    });
+    let formulaData = multiParams.map((item, index) => {
+      let attrDataItem = arrtData[index] || {};
+      return {
+        ...attrDataItem,
+        name: item.FormulaName,
+        value: item.value * 1,
+      };
+    });
+
+    return {
+      ...values,
+      data: [...resData, ...formulaData],
+    };
+  } else {
+    let singleData = [];
+    for (let i = 0; i < params.length; i++) {
+      const item = params[i];
+      let res = await getData(item, values);
+      let attrDataItem = arrtData[i + multiParams.length] || {};
+      singleData.push({
+        ...attrDataItem,
+        name: item.deviceName,
+        data: (res.data || []).map(item => {
+          return {
+            val: item.val,
+            htime: moment(item.htime_at).format('YYYY-MM-DD HH:mm:ss'),
+          };
+        }),
+      });
+    }
+
+    let firstHTimeArr = [];
+    let formulaData = [];
+    for (let i = 0; i < multiParams.length; i++) {
+      const element = multiParams[i];
+      let indexArr = element.indexArr;
+      let tempExpression = [...element.expression];
+      let device = element.paramsDevice;
+      let child = {};
+      child.tempExpression = tempExpression;
+      child.name = element.FormulaName;
+      child.data = [];
+      child.indexArr = indexArr;
+      for (let j = 0; j < device.length; j++) {
+        const tempDevice = device[j];
+        let res = await getData(tempDevice, values);
+        child.data.push({
+          data: res.data,
+          device: tempDevice,
+        });
+      }
+      formulaData.push(child);
+    }
+
+    let data = [];
+
+    formulaData.map((item, index) => {
+      let attrDataItem = arrtData[index] || {};
+      data.push({ ...attrDataItem, ...getFunctionValue(item) });
+    });
+
+    values.data = [...singleData, ...data];
+    return values;
+  }
+}
+// 根据数据项获取请求参数
+function getSingleData(datas) {
+  let params = [];
+  datas.forEach(({ device_id, device_items, seq }) => {
+    if (device_id && device_items) {
+      params.push({
+        deviceName: seq,
+        deviceId: device_id,
+        deviceItems: device_items,
+      });
+    }
+  });
+  return params;
+}
+// 根据公式获得请求参数
+function getFormula(formula) {
+  let params = [];
+  formula.forEach(item => {
+    let tempItem = item;
+    let tempDeviceArr = [];
+    let indexArr = [];
+    item.Device.map(device => {
+      if (device.Id && device.ItemAlias && device.ItemName) {
+        tempDeviceArr.push({
+          deviceName: device.ItemAlias,
+          deviceId: String(device.PlcDeviceId),
+          deviceItems: device.ItemName,
+        });
+
+        indexArr.push({ index: device.index, deviceName: device.ItemAlias });
+      }
+    });
+    tempItem.paramsDevice = tempDeviceArr;
+    tempItem.indexArr = indexArr;
+    params.push(tempItem);
+  });
+  return params;
+}
+
+var DATA_CACHE = {};
+// 请求plc数据
+async function getData(params, values) {
+  const { timeType, date, size, interval, aggregator } = values;
+  let key, etime, stime;
+  if (!timeType) {
+    key = `${params.map(item => item.deviceItems).join(',')}-${timeType}`;
+  } else if (timeType != -1) {
+    key = `${params.deviceItems}-${timeType}-${size}-${interval}-${aggregator}`;
+  } else {
+    let clear = { hour: 0, minute: 0, second: 0, millisecond: 0 };
+    etime = moment(date[1]).set(clear) * 1;
+    stime = moment(date[0]).set(clear) * 1;
+    key = `${params.deviceItems}-${stime}-${etime}-${size}-${interval}-${aggregator}`;
+  }
+  if (!DATA_CACHE[key]) {
+    if (!timeType) {
+      DATA_CACHE[key] = await getDeviceRealData({
+        ...params,
+      });
+    } else {
+      if (timeType != -1) {
+        let currentDate = moment();
+        etime = currentDate * 1;
+        stime = currentDate.add(-1 * timeType, 'hour') * 1;
+      }
+      DATA_CACHE[key] = await getDeviceRealDataByTime({
+        deviceid: params.deviceId * 1,
+        dataitemid: params.deviceItems,
+        stime,
+        etime,
+        size,
+        interval,
+        aggregator,
+      });
+    }
+  }
+  return DATA_CACHE[key];
+}
+
+// 获取表单的options
+export async function getFormOptions(values, datas, projectId) {
+  let arrtData = values.data || [];
+  const params = getFormParams(datas, projectId);
+  if (!values.timeType) {
+    // 请求最新数据
+    let data = await getFormCurrentData(params, values);
+    let resData = data.map((item, index) => {
+      let attrDataItem = arrtData[index] || {};
+      return {
+        ...attrDataItem,
+        name: item.title,
+        value: item.value * 1,
+      };
+    });
+    return {
+      ...values,
+      data: resData,
+    };
+  } else {
+    // 请求历史数据
+    let data = await getFormHistoryData(params, values);
+    values.data = data.map((item, i) => {
+      let attrDataItem = arrtData[i] || {};
+      return {
+        ...attrDataItem,
+        ...item,
+      };
+    });
+
+    return values;
+  }
+}
+
+// 根据表单的数据项获取请求参数
+function getFormParams(datas, projectId) {
+  let params = {};
+  datas.forEach(item => {
+    if (!params[item.data_name]) params[item.data_name] = [];
+    params[item.data_name].push(item.data_title);
+  });
+  return Object.keys(params).map(data_name => ({
+    formName: data_name,
+    titles: params[data_name],
+    projectId,
+  }));
+}
+
+// 请求表单最新数据
+async function getFormCurrentData(params, values) {
+  const { timeType, date } = values;
+  let data = [];
+  for (let i = 0; i < params.length; i++) {
+    const resData = await queryFormCurrentData(params[i]);
+    data = [...data, ...resData];
+  }
+  return data;
+}
+
+// 请求表单历史数据
+async function getFormHistoryData(params, values) {
+  const { timeType, date } = values;
+  let sTime, eTime;
+  let data = [];
+  // -1为自选日期  从date内获取时间
+  if (timeType == -1) {
+    let clear = { hour: 0, minute: 0, second: 0, millisecond: 0 };
+    eTime = moment(date[1]).set(clear) * 1;
+    sTime = moment(date[0]).set(clear) * 1;
+  } else {
+    let currentDate = moment();
+    eTime = currentDate * 1;
+    sTime = currentDate.add(-1 * timeType, 'hour') * 1;
+  }
+
+  for (let i = 0; i < params.length; i++) {
+    const resData = await queryFormHistoryData({ ...params[i], eTime, sTime });
+    data = [...data, ...resData];
+  }
+  return data;
+}

+ 944 - 0
src/components/DataMeter/config.js

@@ -0,0 +1,944 @@
+export const CHILD_MAP = {
+  ProjectInfo: [
+    {
+      title: '项目编号',
+      key: 'Code',
+      show: true,
+    },
+    {
+      title: '项目工期',
+      key: 'Duration',
+      show: true,
+    },
+    {
+      title: '建设单位',
+      key: 'ConstructionUnit',
+      show: true,
+    },
+    {
+      title: '承建单位',
+      key: 'UndertakenUnit',
+      show: true,
+    },
+    {
+      title: '所在地',
+      key: 'Position',
+      show: true,
+    },
+
+    {
+      title: '项目规模',
+      key: 'Scale',
+      show: true,
+    },
+    {
+      title: '主体工艺',
+      key: 'MainProcess',
+      show: true,
+    },
+    {
+      title: '服务范围',
+      key: 'ServiceScope',
+      show: true,
+    },
+    {
+      title: '签约时间',
+      key: 'ContractTime',
+      show: true,
+    },
+    {
+      title: '运营服务时间',
+      key: 'ServiceTime',
+      show: true,
+    },
+    {
+      title: '合作模式',
+      key: 'CooperateMode',
+      show: true,
+    },
+    {
+      title: '出水执行标准',
+      key: 'WaterStandard',
+      show: true,
+    },
+    {
+      title: '核心管理人员',
+      key: 'Admin',
+      show: true,
+    },
+    {
+      title: '项目成员',
+      key: 'User',
+      show: true,
+    },
+  ],
+  AlarmCenter: [
+    { title: '全部', key: 4, show: true },
+    {
+      title: '待办事项',
+      key: 3,
+      show: true,
+    },
+    {
+      title: '异常报警',
+      key: 1,
+      show: true,
+    },
+    {
+      title: '逾期预警',
+      key: 2,
+      show: true,
+    },
+  ],
+  MessageCenter: [
+    {
+      title: '消息推送',
+      key: 1,
+      show: true,
+    },
+    {
+      title: '新闻动态',
+      key: 2,
+      show: true,
+    },
+    {
+      title: '大事记',
+      key: 3,
+      show: true,
+    },
+    {
+      title: '所获奖项',
+      key: 4,
+      show: true,
+    },
+  ],
+  PlanManagement: [
+    // {
+    //   title: '设计',
+    //   key: 1,
+    //   show: true,
+    // },
+    // {
+    //   title: '采购',
+    //   key: 2,
+    //   show: true,
+    // },
+    {
+      title: '到货',
+      key: 1,
+      show: true,
+    },
+    {
+      title: '施工',
+      key: 2,
+      show: true,
+    },
+    {
+      title: '单机调试',
+      key: 3,
+      show: true,
+    },
+    {
+      title: '系统调试',
+      key: 4,
+      show: true,
+    },
+    {
+      title: '试运行',
+      key: 5,
+      show: true,
+    },
+    // {
+    //   title: '维修',
+    //   key: 6,
+    //   show: true,
+    // },
+    {
+      title: '项目动态',
+      key: 7,
+      show: true,
+    },
+    // {
+    //   title: '巡检',
+    //   key: 7,
+    //   show: true,
+    // },
+    // {
+    //   title: '其它',
+    //   key: 8,
+    //   show: true,
+    // },
+  ],
+  Other: [
+    {
+      title: '安全操作规范',
+      key: 1,
+      show: true,
+    },
+    {
+      title: '项目日志',
+      key: 2,
+      show: true,
+    },
+  ],
+  Monitor: [],
+  DebugData: [],
+  DataCenter: [
+    {
+      title: '水质管理',
+      key: 1,
+      show: true,
+    },
+    {
+      title: '水质指标',
+      key: 2,
+      show: true,
+    },
+    {
+      title: '客户满意度',
+      key: 3,
+      show: true,
+    },
+    {
+      title: '设备完好率',
+      key: 4,
+      show: true,
+    },
+    {
+      title: 'KPI',
+      key: 5,
+      show: true,
+      children: [
+        {
+          title: '累计EBITDA',
+          key: 11,
+          show: true,
+        },
+        {
+          title: '累计经营性净现金流',
+          key: 12,
+          show: true,
+        },
+      ],
+    },
+    {
+      title: '水量计费',
+      key: 6,
+      show: true,
+    },
+    {
+      title: '预算成本',
+      key: 7,
+      show: true,
+      children: [
+        {
+          title: '累计成本支出',
+          key: 13,
+          show: true,
+        },
+        {
+          title: '累计月度吨水成本',
+          key: 14,
+          show: true,
+        },
+      ],
+    },
+    {
+      title: '季度绩效',
+      key: 8,
+      show: true,
+    },
+    {
+      title: '化学实验室数据',
+      key: 9,
+      show: true,
+    },
+    {
+      title: '安全生产天',
+      key: 10,
+      show: true,
+    },
+    // {
+    //   title: '调试数据',
+    //   key: 11,
+    //   show: true,
+    // },
+  ],
+};
+
+export const DEFAULT_LAYOUT = [
+  {
+    i: '41',
+    key: 'AlarmCenter',
+    w: 8,
+    h: 5,
+    x: 28,
+    y: 14,
+    child: [
+      { title: '全部', key: 4, show: true },
+      { title: '待办事项', key: 3, show: true },
+      { title: '异常报警', key: 1, show: true },
+      { title: '逾期预警', key: 2, show: true },
+    ],
+    moved: false,
+    static: false,
+    active: 2,
+  },
+  {
+    i: '40',
+    key: 'DataCenter',
+    active: 11,
+    w: 6,
+    h: 5,
+    x: 42,
+    y: 14,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: '累计EBITDA', key: 11, show: true },
+      { title: '累计经营性净现金流', key: 12, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '累计成本支出', key: 13, show: true },
+      { title: '累计月度吨水成本', key: 14, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '39',
+    key: 'DataCenter',
+    active: '4',
+    w: 6,
+    h: 5,
+    x: 42,
+    y: 9,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: '累计EBITDA', key: 11, show: true },
+      { title: '累计经营性净现金流', key: 12, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '累计成本支出', key: 13, show: true },
+      { title: '累计月度吨水成本', key: 14, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '38',
+    key: 'DataCenter',
+    active: '2',
+    w: 6,
+    h: 5,
+    x: 42,
+    y: 4,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: '累计EBITDA', key: 11, show: true },
+      { title: '累计经营性净现金流', key: 12, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '累计成本支出', key: 13, show: true },
+      { title: '累计月度吨水成本', key: 14, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '37',
+    key: 'DataCenter',
+    active: 10,
+    w: 6,
+    h: 4,
+    x: 42,
+    y: 0,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: '累计EBITDA', key: 11, show: true },
+      { title: '累计经营性净现金流', key: 12, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '累计成本支出', key: 13, show: true },
+      { title: '累计月度吨水成本', key: 14, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '36',
+    key: 'DataCenter',
+    active: '1',
+    w: 6,
+    h: 5,
+    x: 36,
+    y: 4,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: '累计EBITDA', key: 11, show: true },
+      { title: '累计经营性净现金流', key: 12, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '累计成本支出', key: 13, show: true },
+      { title: '累计月度吨水成本', key: 14, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '35',
+    key: 'DataCenter',
+    active: 13,
+    w: 7,
+    h: 5,
+    x: 7,
+    y: 14,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: '累计EBITDA', key: 11, show: true },
+      { title: '累计经营性净现金流', key: 12, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '累计成本支出', key: 13, show: true },
+      { title: '累计月度吨水成本', key: 14, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '34',
+    key: 'DataCenter',
+    active: '8',
+    w: 7,
+    h: 5,
+    x: 0,
+    y: 14,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: '累计EBITDA', key: 11, show: true },
+      { title: '累计经营性净现金流', key: 12, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '累计成本支出', key: 13, show: true },
+      { title: '累计月度吨水成本', key: 14, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '33',
+    key: 'DataCenter',
+    active: 11,
+    w: 7,
+    h: 4,
+    x: 7,
+    y: 10,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: '累计EBITDA', key: 11, show: true },
+      { title: '累计经营性净现金流', key: 12, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '累计成本支出', key: 13, show: true },
+      { title: '累计月度吨水成本', key: 14, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '32',
+    key: 'DataCenter',
+    active: '2',
+    w: 7,
+    h: 5,
+    x: 7,
+    y: 5,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: '累计EBITDA', key: 11, show: true },
+      { title: '累计经营性净现金流', key: 12, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '累计成本支出', key: 13, show: true },
+      { title: '累计月度吨水成本', key: 14, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '31',
+    key: 'DataCenter',
+    active: '1',
+    w: 7,
+    h: 5,
+    x: 0,
+    y: 0,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: '累计EBITDA', key: 11, show: true },
+      { title: '累计经营性净现金流', key: 12, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '累计成本支出', key: 13, show: true },
+      { title: '累计月度吨水成本', key: 14, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '30',
+    key: 'DataCenter',
+    w: 7,
+    h: 5,
+    x: 7,
+    y: 0,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: '累计EBITDA', key: 11, show: true },
+      { title: '累计经营性净现金流', key: 12, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '累计成本支出', key: 13, show: true },
+      { title: '累计月度吨水成本', key: 14, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+    active: 12,
+  },
+  {
+    i: '29',
+    key: 'DataCenter',
+    w: 6,
+    h: 5,
+    x: 36,
+    y: 14,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: 'KPI', key: 5, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '预算成本', key: 7, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '20',
+    key: 'DataCenter',
+    w: 6,
+    h: 5,
+    x: 36,
+    y: 9,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: 'KPI', key: 5, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '预算成本', key: 7, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+    active: 3,
+  },
+  {
+    i: '14',
+    key: 'DataCenter',
+    w: 7,
+    h: 5,
+    x: 0,
+    y: 5,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: 'KPI', key: 5, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '预算成本', key: 7, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+    active: 3,
+  },
+  {
+    i: '12',
+    key: 'PlanManagement',
+    w: 6,
+    h: 4,
+    x: 36,
+    y: 0,
+    child: [
+      { title: '设计', key: 1, show: true },
+      { title: '采购', key: 2, show: true },
+      { title: '施工', key: 3, show: true },
+      { title: '调试', key: 4, show: true },
+      { title: '保养', key: 5, show: true },
+      { title: '维修', key: 6, show: true },
+      { title: '项目动态', key: 7, show: true },
+    ],
+    moved: false,
+    static: false,
+    active: 1,
+  },
+  {
+    i: '10',
+    key: 'PlanManagement',
+    w: 7,
+    h: 4,
+    x: 0,
+    y: 10,
+    child: [
+      { title: '设计', key: 1, show: true },
+      { title: '采购', key: 2, show: true },
+      { title: '施工', key: 3, show: true },
+      { title: '调试', key: 4, show: true },
+      { title: '保养', key: 5, show: true },
+      { title: '维修', key: 6, show: true },
+      { title: '项目动态', key: 7, show: true },
+    ],
+    moved: false,
+    static: false,
+    active: 2,
+  },
+  {
+    i: '8',
+    key: 'ProjectInfo',
+    w: 14,
+    h: 5,
+    x: 14,
+    y: 14,
+    active: 1,
+    child: [
+      { title: '项目编号', key: 'Code', show: true },
+      { title: '项目工期', key: 'Duration', show: true },
+      { title: '建设单位', key: 'ConstructionUnit', show: true },
+      { title: '承建单位', key: 'UndertakenUnit', show: true },
+      { title: '所在地', key: 'Position', show: true },
+      { title: '项目规模', key: 'Scale', show: true },
+      { title: '主体工艺', key: 'MainProcess', show: true },
+      { title: '服务范围', key: 'ServiceScope', show: true },
+      { title: '签约时间', key: 'ContractTime', show: true },
+      { title: '运营服务时间', key: 'ServiceTime', show: true },
+      { title: '合作模式', key: 'CooperateMode', show: true },
+      { title: '出水执行标准', key: 'WaterStandard', show: true },
+      { title: '核心管理人员', key: 'Admin', show: true },
+      { title: '项目成员', key: 'User', show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  { i: '7', key: 'Map', w: 22, h: 14, x: 14, y: 0, moved: false, static: false },
+];
+export const DEFAULT_MAP_LAYOUT = [
+  {
+    i: '20',
+    key: 'DataCenter',
+    w: 14,
+    h: 7,
+    x: 0,
+    y: 0,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: 'KPI', key: 5, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '预算成本', key: 7, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '19',
+    key: 'DataCenter',
+    w: 7,
+    h: 7,
+    x: 7,
+    y: 13,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: 'KPI', key: 5, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '预算成本', key: 7, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+    active: 9,
+  },
+  {
+    i: '18',
+    key: 'DataCenter',
+    w: 7,
+    h: 6,
+    x: 0,
+    y: 13,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: 'KPI', key: 5, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '预算成本', key: 7, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+    active: 3,
+  },
+  {
+    i: '17',
+    key: 'DataCenter',
+    w: 7,
+    h: 6,
+    x: 7,
+    y: 7,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: 'KPI', key: 5, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '预算成本', key: 7, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+    active: 7,
+  },
+  {
+    i: '15',
+    key: 'DataCenter',
+    w: 13,
+    h: 6,
+    x: 35,
+    y: 6,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: 'KPI', key: 5, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '预算成本', key: 7, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+    active: 6,
+  },
+  {
+    i: '12',
+    key: 'DataCenter',
+    w: 7,
+    h: 6,
+    x: 0,
+    y: 7,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: 'KPI', key: 5, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '预算成本', key: 7, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+    active: 5,
+  },
+  {
+    i: '11',
+    key: 'DataCenter',
+    w: 13,
+    h: 7,
+    x: 35,
+    y: 12,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: 'KPI', key: 5, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '预算成本', key: 7, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+    active: 4,
+  },
+  { i: '7', key: 'Map', w: 21, h: 12, x: 14, y: 0, moved: false, static: false },
+  {
+    i: '5',
+    key: 'AlarmCenter',
+    w: 10,
+    h: 6,
+    x: 25,
+    y: 12,
+    active: 3,
+    child: [
+      { title: '待办事项', key: 3, show: true },
+      { title: '异常报警', key: 1, show: true },
+      { title: '项目预警', key: 2, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '3',
+    key: 'DataCenter',
+    w: 13,
+    h: 6,
+    x: 35,
+    y: 0,
+    active: 10,
+    child: [
+      { title: '水质管理', key: 1, show: true },
+      { title: '水质指标', key: 2, show: true },
+      { title: '客户满意度', key: 3, show: true },
+      { title: '设备完好率', key: 4, show: true },
+      { title: 'KPI', key: 5, show: true },
+      { title: '水量计费', key: 6, show: true },
+      { title: '预算成本', key: 7, show: true },
+      { title: '季度绩效', key: 8, show: true },
+      { title: '化学实验室数据', key: 9, show: true },
+      { title: '安全生产天', key: 10, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+  {
+    i: '2',
+    key: 'MessageCenter',
+    w: 11,
+    h: 6,
+    x: 14,
+    y: 12,
+    active: 1,
+    child: [
+      { title: '消息推送', key: 1, show: true },
+      { title: '新闻动态', key: 2, show: true },
+      { title: '大事记', key: 3, show: true },
+      { title: '所获奖项', key: 4, show: true },
+    ],
+    moved: false,
+    static: false,
+  },
+];
+
+export const U3D_PATH_STATE = {
+  ProjectInfo: 1,
+  AlarmCenter: {
+    3: 53,
+    1: 39,
+    2: 54,
+  },
+  MessageCenter: {
+    1: 54,
+  },
+  FileManagement: [27, 44],
+  Monitor: 100,
+  PlanManagement: {
+    1: 48,
+    2: 49,
+    3: 50,
+    4: 50,
+    5: 51,
+  },
+  Other: {
+    2: 35
+  },
+};
+
+export const COL_COLS = 48;
+export const ROW_COLS = 24;

+ 624 - 0
src/models/dataMeterNew.js

@@ -0,0 +1,624 @@
+import {
+  getProject,
+  getFaultAnalysis,
+  getIssueList,
+  getProjectActive,
+  getNotificationList,
+  getMediaList,
+  getMonitorList,
+  getUserGuide,
+  getDailyList,
+  getProjectProgress,
+  deleteFile,
+  getProjectTotalProgress,
+  getLayoutOptions,
+  saveLayoutOptions,
+  getProjectAlarm,
+  getBreakdownRecord,
+  getProjectList,
+  getAutoPatrol,
+  getBreakdownList,
+  getPatrolRecord,
+} from '@/services/DataMeter';
+import { queryProjectFileList } from '@/services/FileAdmin';
+import { getprojectPlanProgress, getProjectRealProgress } from '@/services/projectPlanProgress';
+import { getRepairRecord } from '@/services/EquipmentMaintenance';
+import { queryConfigList, queryTemplateList } from '@/services/CharUtils';
+import { queryPatrolRecord } from '@/services/patrol';
+import { message } from 'antd';
+import { DEFAULT_LAYOUT, DEFAULT_MAP_LAYOUT } from '@/components/DataMeter/config';
+import { getDefaultConfList } from '@/services/ProjectAdmin';
+const PLAN_TYPE = {
+  15: 1,
+  3: 3,
+  12: 4,
+};
+
+export default {
+  namespace: 'dataMeterNew',
+  state: {
+    projectDetail: {},
+    faultAnalysis: [],
+    issueList: [],
+    projectActive: [],
+    news: [],
+    memorabilia: [],
+    awards: [],
+    notificationList: [],
+    projectAlarmList: [],
+    repairList: [],
+    breakdownList: [],
+    mediaImgList: [],
+    mediaVideo: null,
+    monitorList: [],
+    userGuideList: [],
+    dailyList: [],
+    projectProgress: null,
+    projectTotalProgress: {
+      AllProgress: 0,
+    },
+    layout: {
+      0: {
+        config_json: [],
+      },
+      1: {
+        config_json: [],
+      },
+      2: {
+        config_json: [],
+      },
+    },
+    chartConfigList: false,
+    realProgress: {},
+    progress: {},
+    // currentChart: {}
+    projectList: [],
+    autoReport: {},
+    patrolRecordDetail: {},
+    patrolList: [],
+    fileList: [],
+    defaultConf: {},
+    layoutAdmin: {
+      0: {
+        config_json: [],
+      },
+      1: {
+        config_json: [],
+      },
+      2: {
+        config_json: [],
+      },
+    },
+  },
+
+  effects: {
+    *getAutoPatrol({ payload, callback }, { call, put }) {
+      const response = yield call(getAutoPatrol, payload);
+      if (response) {
+        // 查询数据报表详情
+        const { data } = yield call(queryPatrolRecord, { recordId: response.data[0].Id });
+        if (data) {
+          const creatorName = data.CreatorUser && data.CreatorUser.CName;
+          var status = {};
+          let Items = [];
+          const getItems = (item, patrolType) => {
+            let key;
+            if (patrolType == 1) {
+              key = item.PatrolName;
+            } else {
+              key = item.DeviceCode + '-' + item.DeviceName;
+            }
+            item.patrolType = patrolType;
+            item.ThresholdEnum = item.TemplateItem.ThresholdEnum;
+            item.Type = item.TemplateItem.Type;
+            if (!status[key]) status[key] = { normal: 0, error: 0 };
+            if (item.Status == 1) {
+              status[key].error++;
+            } else {
+              status[key].normal++;
+            }
+            return item;
+          };
+          data.ItemsExtend.forEach(item => {
+            console.log(Items);
+            if (item.PatrolCardRecordItemAssocThreshold) {
+              var arr = item.PatrolCardRecordItemAssocThreshold.map(i => getItems(i, 1));
+              Items = Items.concat(arr);
+            } else {
+              Items.push(getItems(item, 0));
+            }
+          });
+          data.Items = Items;
+
+          data.Points.forEach(item => {
+            let key;
+            if (item.PatrolType == 1) {
+              key = item.DeviceName;
+            } else {
+              key = item.DeviceCode + '-' + item.DeviceName;
+            }
+            item.creatorName = creatorName;
+            item.level = `${item.ExceptionLevel || '-'}/${item.DeviceLevel || '-'}`;
+            item.status = status[key] || { normal: 0, error: 0 };
+          });
+          console.log(data);
+          callback && callback(data);
+          yield put({
+            type: 'save',
+            payload: { autoReport: data },
+          });
+        }
+      }
+    },
+    *getProject({ payload }, { call, put }) {
+      const response = yield call(getProject, payload);
+      if (response) {
+        yield put({
+          type: 'save',
+          payload: { projectDetail: response.data },
+        });
+      }
+    },
+    *getFaultAnalysis({ payload }, { call, put }) {
+      const response = yield call(getFaultAnalysis, payload);
+      if (response) {
+        var list = [];
+        response.data.forEach(item => {
+          item.Details.forEach(err => {
+            list.push({
+              ...item,
+              ...err,
+            });
+          });
+        });
+        yield put({
+          type: 'save',
+          payload: { faultAnalysis: list },
+        });
+      }
+    },
+    *getIssueList({ payload }, { call, put }) {
+      const response = yield call(getIssueList, payload);
+      if (response) {
+        yield put({
+          type: 'save',
+          payload: { issueList: response.data.list },
+        });
+      }
+    },
+    *getRepairRecord({ payload }, { call, put }) {
+      const response = yield call(getRepairRecord, payload);
+      if (response) {
+        yield put({
+          type: 'save',
+          payload: { repairList: response.data.list },
+        });
+      }
+    },
+    *getBreakdownRecord({ payload }, { call, put }) {
+      const response = yield call(getBreakdownList, payload);
+      if (response) {
+        yield put({
+          type: 'save',
+          payload: { breakdownList: response.data.list },
+        });
+      }
+    },
+    *getPatrolRecord({ payload }, { call, put }) {
+      const response = yield call(getPatrolRecord, payload);
+      if (response) {
+        yield put({
+          type: 'save',
+          payload: { patrolList: response.data.list },
+        });
+      }
+    },
+    *getProjectAlarm({ payload }, { call, put }) {
+      const response = yield call(getProjectAlarm, payload);
+      if (response) {
+        yield put({
+          type: 'save',
+          payload: { projectAlarmList: response.data.list },
+        });
+      }
+    },
+    *getProjectActive({ payload }, { call, put }) {
+      const response = yield call(getProjectActive, payload);
+      if (response) {
+        let stateName;
+
+        // 0-项目动态 1-新闻动态 2-大事记 3-所获奖项
+        switch (payload.type) {
+          case 0:
+            stateName = 'projectActive';
+            break;
+          case 1:
+            stateName = 'news';
+            break;
+          case 2:
+            stateName = 'memorabilia';
+            break;
+          case 3:
+            stateName = 'awards';
+            break;
+        }
+        if (!stateName) return;
+        yield put({
+          type: 'save',
+          payload: { [stateName]: response.data.list },
+        });
+      }
+    },
+    *getNotificationList({ payload }, { call, put }) {
+      const response = yield call(getNotificationList, payload);
+      if (response) {
+        yield put({
+          type: 'save',
+          payload: { notificationList: response.data.list },
+        });
+      }
+    },
+    *getMediaList({ payload }, { call, put }) {
+      const response = yield call(getMediaList, payload);
+      if (response) {
+        var mediaVideo = null,
+          mediaImgList = [];
+        response.data.forEach(item => {
+          if (/\.mp4$/.test(item.Name)) {
+            if (!mediaVideo) {
+              mediaVideo = item;
+            }
+          } else {
+            mediaImgList.push(item);
+          }
+        });
+        yield put({
+          type: 'save',
+          payload: {
+            mediaVideo,
+            mediaImgList,
+          },
+        });
+      }
+    },
+    *getMonitorList({ payload }, { call, put }) {
+      const response = yield call(getMonitorList, payload);
+      if (response) {
+        var obj = JSON.parse(response.data.config_json) || {};
+        yield put({
+          type: 'save',
+          // payload: { monitorList: response.data.list },
+          payload: { monitorList: Object.keys(obj).map(key => obj[key]) || [] },
+        });
+      }
+    },
+    *getUserGuide({ payload }, { call, put }) {
+      const response = yield call(getUserGuide, payload);
+      if (response) {
+        var list = [];
+        response.data.list.forEach(item => {
+          item.UserGuideFiles.forEach(file => {
+            list.push({
+              ...item,
+              ...file,
+            });
+          });
+        });
+        yield put({
+          type: 'save',
+          payload: { userGuideList: list },
+        });
+      }
+    },
+    *getDailyList({ payload }, { call, put }) {
+      const response = yield call(getDailyList, payload);
+      if (response) {
+        yield put({
+          type: 'save',
+          payload: { dailyList: response.data.list },
+        });
+      }
+    },
+
+    *getProjectPlanProgress({ payload, callback }, { call, put }) {
+      const response = yield call(getprojectPlanProgress, payload);
+      if (response) {
+        var progress = response.data;
+        Object.keys(progress).forEach(k => {
+          if (
+            progress[k] == '0001-01-01T00:00:00Z' ||
+            progress[k] == '0001-01-01 00:00:00' ||
+            progress[k] == '0001-01-01 00:00:00 +0000 UTC'
+          ) {
+            progress[k] = '';
+          }
+        });
+        yield put({
+          type: 'save',
+          payload: { progress },
+        });
+      }
+    },
+    *getProjectRealProgress({ payload }, { call, put, select }) {
+      const calcProgress = data => {
+        let count = 0,
+          total = 0;
+        data.forEach(item => {
+          total += item.TotalCount;
+          count += item.RealCount;
+        });
+        return ((count / total) * 100).toFixed(2);
+      };
+      let { realProgress } = yield select(s => s.dataMeterNew);
+      console.log(realProgress);
+      var keys = Object.keys(PLAN_TYPE);
+      for (let i = 0; i < keys.length; i++) {
+        let k = keys[i];
+        var response = yield call(getProjectRealProgress, {
+          ...payload,
+          type: PLAN_TYPE[k],
+        });
+        if (response) {
+          let tempRealProgress = response.data.Task.map(item => ({
+            ...item,
+            RealCount: item.FinishList.length || 0,
+            TotalCount: item.DeviceCodes ? item.DeviceCodes.length : 0,
+            children: null,
+          }));
+          console.log(tempRealProgress);
+          realProgress[k] = calcProgress(tempRealProgress);
+        }
+      }
+      yield put({
+        type: 'save',
+        payload: { realProgress: { ...realProgress } },
+      });
+    },
+    *getProjectProgress({ payload }, { call, put }) {
+      const response = yield call(getProjectProgress, payload);
+      if (response) {
+        yield put({
+          type: 'save',
+          payload: { projectProgress: response.data },
+        });
+      }
+    },
+    *deleteFile({ payload }, { call, put }) {
+      const response = yield call(deleteFile, payload);
+      if (response) {
+        yield put({
+          type: 'getMediaList',
+          payload: payload,
+        });
+      }
+    },
+    *getProjectTotalProgress({ payload }, { call, put }) {
+      const response = yield call(getProjectTotalProgress, payload);
+      if (response) {
+        yield put({
+          type: 'save',
+          payload: { projectTotalProgress: response.data },
+        });
+      }
+    },
+    *getLayoutOptions({ payload }, { call, put, select }) {
+      // if (payload.is_default == 1) {
+      //   // 默认配置的projectId为0
+      //   payload.projectId = 0;
+      // }
+      const response = yield call(getLayoutOptions, payload);
+      if (response) {
+        var layout = yield select(state => state.dataMeterNew.layout);
+        if (payload.is_default == 1) {
+          layout = yield select(state => state.dataMeterNew.layoutAdmin);
+        }
+        var defaultLayout = payload.sub_module === 0 ? DEFAULT_MAP_LAYOUT : DEFAULT_LAYOUT;
+        var data = response.data;
+        try {
+          data.config_json = JSON.parse(data.config_json);
+          // response.data.config_json = defaultLayout;
+        } catch (error) {
+          // 解析失败则使用默认布局
+          data.config_json = defaultLayout;
+          console.log(error);
+        }
+        layout[payload.sub_module] = data;
+        if (payload.is_default == 0)
+          yield put({
+            type: 'save',
+            payload: { layout: { ...layout } },
+          });
+        else
+          yield put({
+            type: 'save',
+            payload: { layoutAdmin: { ...layout } },
+          });
+      }
+    },
+    *saveLayoutOptions({ payload }, { call, put, select }) {
+      // if (payload.is_default == 1) {
+      //   // 默认配置的projectId为0
+      //   payload.projectId = 0;
+      // }
+      if (payload.config_json == '[]') {
+        message.error('保存的配置不能为空');
+        return;
+      }
+      var response = yield call(saveLayoutOptions, payload);
+      if (response) {
+        var layout = yield select(state => state.dataMeterNew.layout);
+        if (payload.is_default == 1) {
+          layout = yield select(state => state.dataMeterNew.layoutAdmin);
+        }
+        console.log(payload.config_json);
+        layout[payload.sub_module].config_json = JSON.parse(payload.config_json);
+        if (payload.is_default == 0)
+          yield put({
+            type: 'save',
+            payload: { layout: { ...layout } },
+          });
+        else
+          yield put({
+            type: 'save',
+            payload: { layoutAdmin: { ...layout } },
+          });
+      }
+    },
+    *resizeLayout({ payload }, { call, select, put }) {
+      // 默认配置的projectId为0
+      const response = yield call(getLayoutOptions, {
+        ...payload,
+        // projectId: 0,
+      });
+      if (response) {
+        var layout = yield select(state => state.dataMeterNew.layout);
+        var defaultLayout = payload.sub_module === 0 ? DEFAULT_MAP_LAYOUT : DEFAULT_LAYOUT;
+        var config_json = response.data.config_json
+          ? JSON.parse(response.data.config_json)
+          : defaultLayout;
+        // response.data.config_json = defaultLayout;
+
+        // 将默认配置保存到本地
+        layout[payload.sub_module].config_json = config_json;
+        yield put({
+          type: 'save',
+          payload: { layout: { ...layout } },
+        });
+        yield call(saveLayoutOptions, {
+          ...payload,
+          config_json: JSON.stringify(config_json),
+          is_default: 0,
+        });
+      }
+    },
+    *resizeDefaultLayout({ payload }, { call, select, put }) {
+      var layout = yield select(state => state.dataMeterNew.layout);
+      var config_json = payload.sub_module === 0 ? DEFAULT_MAP_LAYOUT : DEFAULT_LAYOUT;
+
+      // 将默认配置保存到本地
+      layout[payload.sub_module].config_json = config_json;
+      yield put({
+        type: 'save',
+        payload: { layout: { ...layout } },
+      });
+      yield call(saveLayoutOptions, {
+        ...payload,
+        config_json: JSON.stringify(config_json),
+        is_default: 0,
+      });
+    },
+    *queryConfigList({ payload, callback }, { call, put }) {
+      const {
+        data: { list: tplList },
+      } = yield call(queryTemplateList, { pageSize: 999 });
+      const {
+        data: { list: configList },
+      } = yield call(queryConfigList, {
+        ...payload,
+        isNew: 1,
+        pageSize: 9999,
+      });
+      let list = [];
+      configList.map(item => {
+        let template = tplList.find(tpl => tpl.ID == item.type);
+        item.options = JSON.parse(item.options);
+        item.template = template;
+        list.push(item);
+      });
+      callback && callback(list);
+      yield put({
+        type: 'save',
+        payload: {
+          chartConfigList: list,
+        },
+      });
+    },
+    *queryConfig({ payload, callback }, { call, put }) {
+      const response = yield call(queryConfigList, payload);
+      if (response) {
+        var currentChart = response.data.list[0];
+        currentChart.options = JSON.parse(currentChart.options);
+        let { options, configs, type } = currentChart;
+
+        // 将接口返回的实时数据更新到图表中
+        if (type != 'pfd') {
+          if (!options.series) {
+            callback && callback(currentChart);
+          }
+          let series = options.series[0];
+          if (type == 'pie') {
+            configs.forEach((item, index) => {
+              series.data[index].value = item.value;
+            });
+          } else if (series.type == 'bar') {
+            configs.forEach((item, index) => {
+              series.data[index] = item.value;
+            });
+          }
+        }
+        callback && callback(currentChart);
+        // yield put({
+        //   type: 'save',
+        //   payload: {
+        //     currentChart,
+        //   },
+        // });
+      }
+    },
+    *getProjectList({ payload, callback }, { call, put }) {
+      const response = yield call(getProjectList, payload);
+      if (response) {
+        let nowDate = new Date();
+        (response.data.list || []).map(item => {
+          let type;
+          if (!item.EndDate) {
+            type = 2;
+          } else {
+            type = nowDate >= new Date(item.EndDate) ? 2 : 1;
+          }
+          item.type = type;
+        });
+        yield put({
+          type: 'save',
+          payload: { projectList: response.data.list },
+        });
+        console.log(response.data.list);
+        callback && callback(response.data.list);
+      }
+    },
+    *queryProjectFileList({ payload }, { call, put, select }) {
+      try {
+        const response = yield call(queryProjectFileList, {
+          ...payload,
+          deviceCode: -1,
+        });
+        if (response) {
+          yield put({
+            type: 'save',
+            payload: { fileList: response.data },
+          });
+        }
+      } catch (e) {
+        console.error(e);
+      }
+    },
+    *getDefaultConfList({ payload }, { call, put }) {
+      const response = yield call(getDefaultConfList, payload);
+      if (response) {
+        yield put({
+          type: 'save',
+          payload: { defaultConf: response.data },
+        });
+      }
+    },
+  },
+
+  reducers: {
+    save(state, action) {
+      return {
+        ...state,
+        ...action.payload,
+      };
+    },
+  },
+};

+ 125 - 0
src/pages/Mobile/DataMeter/Chart.js

@@ -0,0 +1,125 @@
+import React, { useState, useEffect, useRef } from 'react';
+import echarts from 'echarts';
+import { connect } from 'dva';
+import moment from 'moment';
+import { getPlcOptions, getFormOptions } from '@/components/ChartUtils/utils';
+const dataCache = {};
+
+function DataCenter(props) {
+  const [chart, setChart] = useState();
+  const [timer, setTimer] = useState();
+  const [chartOptions, setChartOptions] = useState(false);
+  const chartEle = useRef();
+  const iframeRef = useRef();
+  const signalRef = useRef();
+  const [loading, setLoading] = useState(false);
+  const { chartConfigList, dispatch } = props;
+  // const { projectId } = props.location; //?
+  const projectId = 46;
+
+  const handleClickTabs = id => {
+    let item = chartConfigList.find(c => c.id == id);
+    getOptionsForConfig(item);
+  };
+
+  useEffect(() => {
+    if (projectId) {
+      // 获取自定义图表列表
+      dispatch({
+        type: 'dataMeterNew/queryConfigList',
+        payload: {
+          projectId,
+        },
+        // callback: list => console.log(list),
+      });
+    }
+  }, [projectId]);
+
+  useEffect(() => {
+    let chart = echarts.init(chartEle.current);
+    setChart(chart);
+    const controller = new AbortController();
+    signalRef.current = controller;
+    return () => {
+      clearTimeout(timer);
+      signalRef.current.abort();
+    };
+  }, []);
+
+  useEffect(() => {
+    const chartWindow = iframeRef.current?.contentWindow;
+    if (!chartWindow) return;
+    if (chartWindow.render) {
+      renderChart();
+    } else {
+      chartWindow.onload = () => {
+        renderChart();
+      };
+    }
+  }, [chartOptions]);
+
+  const getOptionsForConfig = item => {
+    console.log(item);
+    setChartOptions(item);
+    let t = setTimeout(() => {
+      getOptionsForConfig({ ...item });
+    }, 1000 * 60);
+    setTimer(t);
+  };
+
+  const renderChart = async () => {
+    let datas = chartOptions.configs;
+    let values = chartOptions.options;
+    let formula = JSON.parse(chartOptions.formula || '[]');
+    setLoading(true);
+    try {
+      if (chartOptions.source === 0) {
+        // plc渲染数据
+        let options = await getPlcOptions(values, datas, formula);
+        iframeRef.current.contentWindow.render(options);
+      } else {
+        // 图表渲染数据
+        let options = await getFormOptions(values, datas, projectId);
+        iframeRef.current.contentWindow.render(options);
+      }
+    } catch (error) {
+      console.log(error);
+    }
+    setLoading(false);
+  };
+
+  return (
+    <>
+      <ul>
+        {/* <ul className={style.tabsList}> */}
+        {(chartConfigList || [])
+          // .filter(item => item.show)
+          .map(item => (
+            <li
+              // key={item.key}
+              key = {item.id}
+              // className={`${active == item.key ? style.active : ''}`}
+              onClick={() => handleClickTabs(item.id)}
+            >
+              {/* {item.title} */}
+              {item.name}
+            </li>
+          ))}
+      </ul>
+      <div style={{ paddingTop: '0.1rem', overflow: 'hidden' }}>
+        {chartOptions && chartOptions.template && (
+          <iframe
+            ref={iframeRef}
+            style={{ width: '100%', height: '98%', border: 'none' }}
+            srcDoc={chartOptions.template.Content}
+          ></iframe>
+        )}
+        <div style={{ display: chartOptions, height: '100%' }} ref={chartEle}></div>
+      </div>
+    </>
+  );
+}
+export default connect(({ dataMeterNew, user }) => ({
+  chartConfigList: dataMeterNew.chartConfigList,
+  user: user.currentUser,
+}))(DataCenter);

+ 13 - 0
src/services/DataMeter.js

@@ -204,3 +204,16 @@ export async function getProjectList(params) {
   return request(`/api/v2/project?${stringify(params)}`)
 }
 
+//获取巡检结果
+export async function getAutoPatrol(params) {
+  return request(`/patrol/auto/data/${params.projectId}`)
+}
+
+export async function getBreakdownList(params) {
+  return request(`/breakdown-record/list/${params.projectId}?${stringify(params)}`);
+}
+
+export async function getPatrolRecord(params) {
+  return request(`/patrol/data/${params.projectId}?${stringify(params)}`);
+}
+

+ 103 - 2
src/services/ProjectAdmin.js

@@ -1,4 +1,5 @@
 import request from '@/utils/request';
+import moment from 'moment';
 import { stringify } from 'qs';
 
 export async function queryProjectV1(params) {
@@ -256,7 +257,7 @@ export async function getDeviceRealData(params) {
 export async function getDeviceRealDataByTime(params) {
   params.size = 999999;
   return request(`/jinke-cloud/db/device/history-data?${stringify(params)}`, {
-  // return request(`/jinke-cloud/device/history-data?${stringify(params)}`, {
+    // return request(`/jinke-cloud/device/history-data?${stringify(params)}`, {
     method: 'GET',
     // body: params,
   });
@@ -272,5 +273,105 @@ export async function queryScreenShort(data) {
 }
 
 export async function deleteScreenShort(data) {
-  return request(`/api/v1/project-file/${data.id}`,{method: 'DELETE'});
+  return request(`/api/v1/project-file/${data.id}`, { method: 'DELETE' });
+}
+
+const CACHE = {};
+// 查询图表对应的表单数据-最新数据
+export async function queryFormCurrentData({ projectId, formName, titles }) {
+  if (!CACHE[formName]) {
+    const resCell = await queryFormCell({ projectId, formName });
+    CACHE[formName] = resCell.data || [];
+  }
+  let cells = titles.map(t => {
+    let cell = CACHE[formName].find(item => item.title == t);
+    return cell;
+  });
+  const { data } = await request(`/runtime_form/chart/current/${projectId}/${formName}`);
+
+  return cells.map(item => ({
+    key: item.cell_key,
+    value: data[item.cell_key],
+    title: item.title,
+  }));
+}
+
+export async function queryFormCell({ projectId, formName }) {
+  const res = await request(`/api/v1/runtime_form/cell/to/chart/${projectId}/${formName}`);
+  return res;
+}
+
+// 查询图表对应的表单数据-历史数据
+export async function queryFormHistoryData({ projectId, formName, titles, sTime, eTime }) {
+  // 查询表单配置
+  if (!CACHE[formName]) {
+    const resCell = await queryFormCell({ projectId, formName });
+    CACHE[formName] = resCell.data || [];
+  }
+  // 获取key、time与title的对应关系
+  let titleKey = titles.map(t => {
+    let data = CACHE[formName].filter(item => item.title == t);
+    if (data[0].time) {
+      return {
+        title: t,
+        keys: data.map(item => {
+          return {
+            time: item.time,
+            key: item.cell_key,
+          };
+        }),
+      };
+    } else {
+      return {
+        title: t,
+        keys: data.map(item => item.cell_key),
+      };
+    }
+  });
+  // 查询数据
+  const { data } = await request(
+    `/runtime_form/chart/list/${projectId}/${formName}?sTime=${sTime}&eTime=${eTime}`
+  );
+
+  return titleKey.map(item => {
+    const { title, keys } = item;
+    let chartData = [];
+    // 从数据中获取key和value
+    keys.forEach(keyItem => {
+      // 判断是否含有time
+      if (keyItem instanceof Object) {
+        const { key, time } = keyItem;
+        data.forEach(dItem => {
+          let value = dItem[key];
+          // 含有time则替换时间  c_time结构2022-03-10T16:05:37+08:00
+          let t = dItem.c_time.split('T')[0] + ' ' + dItem[time];
+          chartData.push({
+            htime: new Date(t),
+            val: value || 0,
+          });
+        });
+      } else {
+        data.forEach(dItem => {
+          let value = dItem[keyItem];
+          // 没有time则使用c_time
+          let time = dItem.c_time;
+          chartData.push({
+            htime: new Date(time),
+            val: value || 0,
+          });
+        });
+      }
+    });
+
+    chartData
+      .sort((a, b) => a.htime - b.htime)
+      .forEach(item => {
+        item.htime = moment(item.htime).format('YYYY-MM-DD HH:mm:ss');
+      });
+
+    return {
+      name: title,
+      data: chartData,
+    };
+  });
 }