he wei
37 分钟以前 7102b09561443f8c66bdcbecafac1706afc113fd
U 修改
3个文件已添加
11个文件已修改
2347 ■■■■■ 已修改文件
package-lock.json 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package.json 3 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/api/statistic.js 25 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/assets/401_images/401.gif 补丁 | 查看 | 原始文档 | blame | 历史
src/components/table-column-config.vue 71 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/hooks/useColumnConfig.js 60 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/router/modules/statistics.js 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/utils/request.js 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/alarm/earlyWarningAnalysis.vue 145 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/datas/addEdit.vue 1181 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/datas/device.vue 820 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/login/index.vue 19 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/views/realtime/tabs/system.vue 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
vite.config.js 9 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
package-lock.json
@@ -10,6 +10,7 @@
      "dependencies": {
        "@element-plus/icons-vue": "^2.3.1",
        "axios": "^1.7.2",
        "dayjs": "^1.11.13",
        "echarts": "^5.5.0",
        "echarts-gl": "^2.0.9",
        "echarts-liquidfill": "^3.1.0",
@@ -30,7 +31,7 @@
        "xlsx": "^0.18.5"
      },
      "devDependencies": {
        "@rollup/plugin-commonjs": "^28.0.3",
        "@rollup/plugin-commonjs": "^28.0.6",
        "@vitejs/plugin-vue": "^5.2.3",
        "less": "^4.2.2",
        "postcss-pxtorem": "^6.1.0",
@@ -983,9 +984,9 @@
      }
    },
    "node_modules/@rollup/plugin-commonjs": {
      "version": "28.0.3",
      "resolved": "https://registry.npmmirror.com/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.3.tgz",
      "integrity": "sha512-pyltgilam1QPdn+Zd9gaCfOLcnjMEJ9gV+bTw6/r73INdvzf1ah9zLIJBm+kW7R6IUFIQ1YO+VqZtYxZNWFPEQ==",
      "version": "28.0.6",
      "resolved": "https://registry.npmmirror.com/@rollup/plugin-commonjs/-/plugin-commonjs-28.0.6.tgz",
      "integrity": "sha512-XSQB1K7FUU5QP+3lOQmVCE3I0FcbbNvmNT4VJSj93iUjayaARrTQeoRdiYQoftAJBLrR9t2agwAd3ekaTgHNlw==",
      "dev": true,
      "license": "MIT",
      "dependencies": {
package.json
@@ -11,6 +11,7 @@
  "dependencies": {
    "@element-plus/icons-vue": "^2.3.1",
    "axios": "^1.7.2",
    "dayjs": "^1.11.13",
    "echarts": "^5.5.0",
    "echarts-gl": "^2.0.9",
    "echarts-liquidfill": "^3.1.0",
@@ -31,7 +32,7 @@
    "xlsx": "^0.18.5"
  },
  "devDependencies": {
    "@rollup/plugin-commonjs": "^28.0.3",
    "@rollup/plugin-commonjs": "^28.0.6",
    "@vitejs/plugin-vue": "^5.2.3",
    "less": "^4.2.2",
    "postcss-pxtorem": "^6.1.0",
src/api/statistic.js
@@ -80,13 +80,13 @@
/**
 * 蓄电池组对比分析界面(同一品牌同一时间)(1.2.15)
 */
export function getBattCompare15(data) {
  return request({
    url: "statistic/getBattCompare15Statistic",
    method: "POST",
    data
  });
}
// export function getBattCompare15(data) {
//   return request({
//     url: "statistic/getBattCompare15Statistic",
//     method: "POST",
//     data
//   });
// }
/**
 * 蓄电池组对比分析界面(不同品牌同一时间)(1.2.16)
@@ -190,4 +190,15 @@
    method: 'POST',
    data
  });
}
/**
 * 蓄电池组对比分析界面(同一时间同一品牌/同一时间不同一品牌/不同一时间同一品牌)(2.5.1/2/3)
 */
export function getBattCompare15Statistic(data) {
  return request({
    url: 'compare/getBattCompare15Statistic',
    method: 'POST',
    data
  });
}
src/assets/401_images/401.gif
src/components/table-column-config.vue
New file
@@ -0,0 +1,71 @@
<script setup name="colunmConfig">
import { ref, reactive, computed, watch, onMounted } from 'vue';
import useElement from "@/hooks/useElement.js";
    const { $loading, $message, $confirm } = useElement();
  import useColumnConfig from '@/hooks/useColumnConfig.js';
const props = defineProps({
  visible: {
    type: Boolean,
    default: false
  },
  columns: {
    type: Array,
    default: () => ([])
  },
  pageName: {
    type: String,
  }
});
const {
 getConfig,
    columnCfgVisible,
    isColumnFixed,
    fixedColumns,
  showConfigDialog,
    setConfig, } = useColumnConfig(props.pageName);
// 限制最多可固定的列数
const limit = 5;
const emit = defineEmits(['update:visible', 'change']);
const close = () => {
  emit('update:visible', false);
}
function save() {
  setConfig();
  close();
  emit('change');
}
onMounted(() => {
});
</script>
<template>
  <div class="colunm-config">
    <!-- 把所有的列都显示出来 勾选 -->
    <el-checkbox-group v-model="fixedColumns" :max="limit">
      <el-checkbox v-for="(item, idx) in columns" :key="idx" :checked="isColumnFixed(item.prop)" :value="item.prop">{{
        item.label
      }}</el-checkbox>
    </el-checkbox-group>
    <div class="footer">
      <el-button  @click="close">关闭</el-button>
      <el-button type="primary" @click="save">保存</el-button>
    </div>
  </div>
</template>
<style scoped lang="less">
</style>
src/hooks/useColumnConfig.js
New file
@@ -0,0 +1,60 @@
import {
  ref,
  reactive,
  onMounted,
  onUnmounted,
  onActivated,
  onDeactivated,
} from "vue";
export default function (pageName) {
  const configObj = ref({});
  const columnCfgVisible = ref(false);
  // 固定列状态
  const fixedColumns = ref([]);
  // 判断列是否固定
  function isColumnFixed (prop) {
    return fixedColumns.value.includes(prop)
  }
  function setConfig() {
    configObj.value[pageName] = fixedColumns.value;
    localStorage.setItem('columnConfig', JSON.stringify(configObj.value));
  }
  // 读取配置
  function getConfig() {
    // 查询配置
    let cfg = localStorage.getItem('columnConfig');
    console.log('cfg', cfg, '=============');
    if (cfg) {
      cfg = JSON.parse(cfg);
    } else {
      cfg = {}
    };
    configObj.value = cfg;
    console.log('cfg', cfg, cfg[pageName], '=============');
    fixedColumns.value = cfg[pageName] || [];
  }
  function showConfigDialog() {
    columnCfgVisible.value = true;
  }
  onMounted(() => {
    // 查询配置
    getConfig();
  });
  return {
    columnCfgVisible,
    showConfigDialog,
    getConfig,
    isColumnFixed,
    fixedColumns,
    setConfig,
  };
}
src/router/modules/statistics.js
@@ -57,7 +57,7 @@
      path: 'batt-compare0',
      component: () => import('@/views/statistics/battCompare0.vue'),
      name: 'battCompare0',
      meta: { title: '蓄电池组对比分析1', icon: 'component', noCache: false, hidden: true }
      meta: { title: '蓄电池组对比分析1', icon: 'component', noCache: false, }
    },
    {
      path: 'batt-compare1',
src/utils/request.js
@@ -2,6 +2,7 @@
// 生产环境和开发环境切换请求地址
let baseURL = 'http://localhost:8108/pis/';
// let baseURL = 'http://192.168.1.100:8108/pis/';
if (process.env.NODE_ENV === 'production') {
  baseURL = location.protocol + '//' + location.host + '/pis/';
}
src/views/alarm/earlyWarningAnalysis.vue
@@ -336,12 +336,12 @@
const chartRefs = ref({});
function setComponentRef (prop, el) {
function setComponentRef (idx, el) {
  if (el) {
    chartRefs.value[prop] = el;
    chartRefs.value[idx] = el;
  } else {
    // 组件卸载时移除引用
    delete chartRefs.value[prop];
    delete chartRefs.value[idx];
  }
};
@@ -476,12 +476,47 @@
  // xlabels.value = recordTimes;
}
function formatData2(data2, data3) {
  let { batt, pwr } = data2;
  let subs = [];
  if (batt && batt.length && data3.batt > 0) {
    for(let i = 1, len = data3.batt; i <= len; i++) {
      let prop = batt[0][`dataName${i}`];
      subs.push({prop, name: getPropName(prop), data: [], xLabels: [], valueProp: `dataValue${i}`, from: 'batt'});
    }
  }
  if (pwr && pwr.length && data3.pwr > 0) {
    for(let i = 1, len = data3.pwr; i <= len; i++) {
      let prop = pwr[0][`dataName${i}`];
      subs.push({prop, name: getPropName(prop), data: [], xLabels: [], valueProp: `dataValue${i}`, from: 'batt'});
    }
  }
  subProp.value = subs;
  let len = batt && batt.length ? batt.length : pwr && pwr.length ? pwr.length : 0;
  for (let i = 0; i < len; i++) {
    for (let j = 0, len = subs.length; j < len; j++) {
      let sub = subs[j];
      // 取属性对应的index
      let { prop, from, valueProp } = sub;
      sub.data.push(data2[from][i][valueProp]);
      sub.xLabels.push(data2[from][i].recordTime);
    }
  }
}
function updateChart() {
  console.log('xlabels.value, mainData.value', mainData.value, '=============');
  chart0.value.updateChart(mainData.value.labels, mainData.value.data, findClosestTime(mainData.value.labels, startTime.value));
  subProp.value.forEach((v, i) => {
    chartRefs.value[v.prop].updateChart(v.xLabels, v.data, findClosestTime(v.xLabels, startTime.value));
    chartRefs.value[i].updateChart(v.xLabels, v.data, findClosestTime(v.xLabels, startTime.value));
    nextTick(() => {
      chartRefs.value[i].getChart().resize();
    });
  });
}
@@ -643,6 +678,8 @@
  if (code && data) {
    $message.success("设置成功");
    timeLong.value = form1.time;
    // 重新查询数据
    getRtData();
    timeVisible.value = false;
  } else {
    $message.error("设置失败");
@@ -688,13 +725,6 @@
        prop: data[prop],
        type: data[type],
      });
      // arr.push({
      //   pid: data[type] + '',
      //   id: data[prop],
      //   label: getPropName(data[prop]),
      //   prop: data[prop],
      //   type: data[type],
      // });
    }
  });
@@ -710,36 +740,30 @@
  transferRef.value.removeToSource(false);
  transferRef.value.addToAims(false);
  toData.value = arr;
  // 左侧数据要去掉已经选中的数据
  fromData.value = fromData.value.map(v => {
    return {
      ...v,
      children: v.children.filter(vv => {
        if (!obj[v.id]) return true;
        return !obj[v.id].some(vvv => vvv.id == vv.id)
      })
    }
  }).filter(v => v.children.length);
}
function propSetOk() {
}
async function add (_fromData,_toData,{ checkedKeys, checkedNodes, harfKeys, harfNodes }) {
  console.log('fromData,toData,obj', _fromData,_toData, checkedKeys, checkedNodes, harfKeys, harfNodes , '=============');
async function propSetOk() {
  let params = {
    battgroupId: battId.value,
    powerId: currAlm.value.powerId,
    startTime: currAlm.value.almStartTime,
  }
  let arr = [];
  _toData.forEach((v) => {
    arr.push(...v.children);
  });
  let len = arr.length;
  if (len > 4) {
    $message.error('最多设置4个属性');
    console.log('toData', _toData, toData, '=============');
    toData.value = toData.value.map(v => ({
      ...v,
      children: v.children.filter(vv => !checkedKeys.includes(vv.id))
    }));
  let i = 0;
  if (!toData.value.length) {
    $message.error('请选择属性');
    return false;
  }
  let i = 0;
  _toData.forEach((item) => {
  toData.value.forEach((item) => {
    item.children.forEach((v) => {
      i++;
      params[`dataName${i}`] = v.id;
@@ -749,9 +773,60 @@
  });
  console.log('params', params, '=============');
  let loading = $loading();
  let res = await getHisRealWithChage(params);
  let { code, data, data2, data3, data4 } = res;
  loading.close();
  propInfo.value = data4;
  if (code && data) {
    formatData2(data2, data3);
    nextTick(() => {
      updateChart();
    });
    propVisible.value = false;
  } else {
    $message.error('查询出错');
  }
}
function add (_fromData,_toData,{ checkedKeys, checkedNodes, harfKeys, harfNodes }) {
  console.log('fromData,toData,obj', _fromData,_toData, checkedKeys, checkedNodes, harfKeys, harfNodes , '=============');
  let arr = [];
  _toData.forEach((v) => {
    arr.push(...v.children);
  });
  let len = arr.length;
  if (len > 4) {
    $message.error('最多设置4个属性');
    console.log('toData', _toData, toData, '=============');
    // 把这次选择的数据从右侧列表去掉
    toData.value = toData.value.map(v => ({
      ...v,
      children: v.children.filter(vv => !checkedKeys.includes(vv.id))
    })).filter(v => v.children.length);
    // 把这次操作的节点添加回左侧列表
    checkedNodes.forEach(v => {
      // 排除非叶子节点
      if (v.pid == 0) return;
      // 说明左侧列表还有这个节点的父节点
      if (_fromData.some(vv => vv.id == v.pid)) {
        _fromData.find(vv => vv.id == v.pid).children.push(v);
        // 左侧无此节点的父节点
      } else {
        _fromData.push({
          id: v.pid,
          pid: 0,
          label: v.fieldTypeName,
          children: [v],
        });
      }
    });
    fromData.value = _fromData;
    return false;
  }
}
function remove(fromData,toData,obj) {
@@ -1551,7 +1626,7 @@
            >
          </div>
          <div class="item">
            <el-button type="primary" size="small" @click="setProp"
            <el-button type="primary" size="small" :disabled="!currAlm.almId" @click="setProp"
              >关注属性</el-button
            >
          </div>
@@ -1563,7 +1638,7 @@
          <template v-for="(sub, idx) in subProp" :key="'sub_' + idx">
            <card :title="sub.name">
              <line-chart
                :ref="(el) => setComponentRef(sub.prop, el)"
                :ref="(el) => setComponentRef(idx, el)"
              ></line-chart>
            </card>
          </template>
@@ -1623,7 +1698,7 @@
      </tree-transfer>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="propVisible = false">取 消</el-button>
          <el-button @click="propVisible = false">关闭</el-button>
          <el-button type="primary" @click="propSetOk">确 定</el-button>
        </span>
      </template>
src/views/datas/addEdit.vue
@@ -1,518 +1,646 @@
<script setup>
  import { ref, reactive, watchEffect, computed, onMounted } from "vue";
import { ref, reactive, watchEffect, computed, onMounted } from "vue";
  import useStation from "@/hooks/useStationList.js";
  const { provice, city, country, stationName,
    proviceList, cityList, countryList, stationList,
    getProviceList, getCityList, getCountryList, getStationList, getPowerList,
  } = useStation();
import { ElMessageBox } from 'element-plus'
import useStation from "@/hooks/useStationList.js";
const { provice, city, country, stationName,
    proviceList, cityList, countryList, stationList,
    getProviceList, getCityList, getCountryList, getStationList, getPowerList,
} = useStation();
  import {
    getPowerBrand,
    getVoltageLevel,
    getDevType,
    getVoltage,
    getBatteryBrand,
    getPowerType,
    getProtocol,
    getMonVol,
    addDev,
    updateDev,
    addBatt,
    getMonCapByUid,
  } from "@/api/station";
import {
    getPowerBrand,
    getVoltageLevel,
    getDevType,
    getVoltage,
    getBatteryBrand,
    getPowerType,
    getProtocol,
    getMonVol,
    addDev,
    updateDev,
    addBatt,
    getMonCapByUid,
} from "@/api/station";
  import getBinaryDigits from '@/utils/getBinaryDigits.js';
import { checkSnId } from '@/api/user.js';
  import powerTypes from '@/utils/const/const_powerType.js';
  import moment from 'moment';
import getBinaryDigits from '@/utils/getBinaryDigits.js';
  import useElement from "@/hooks/useElement.js";
  const { $loading, $message, $confirm } = useElement();
  const props = defineProps({
    info: {
      type: Object,
    },
  });
import powerTypes from '@/utils/const/const_powerType.js';
import moment from 'moment';
  const addBinfFlag = ref(1);
  const props1 = { value: 'id', checkStrictly: true, multiple: true };
  const formRef = ref();
  const areaList = ref([]);
  const layout = {
    gutter: 16,
    span: 6
  };
import useElement from "@/hooks/useElement.js";
const { $loading, $message, $confirm } = useElement();
const props = defineProps({
    info: {
        type: Object,
    },
});
  const addDevFlag = ref(0);
const addBinfFlag = ref(1);
const props1 = { value: 'id', checkStrictly: true, multiple: true };
const formRef = ref();
const areaList = ref([]);
const layout = {
    gutter: 16,
    span: 6
};
const addDevFlag = ref(0);
const form1 = reactive({
    provice: provice.value,
    city: city.value,
    country: country.value,
    stationName: stationName.value,
    stationType: "",
    longitude: 0,
    latitude: 0,
    powerName: "",
    company: "",
    modelCfg: 0,
    powerModel: "",
    protocol: "",
    powerIp: "",
    devIp: "",
    devType: "",
    monvolstd: '',
    moncapstd: '',
    monresstd: '',
    nodeStation: '',
    moncount: '',
    product: "",
    battModel: "",
    acvolHighLimit: '',
    acvolLowLimit: '',
    dcoutvolLowLimit: '',
    floatCurrLevel: '',
    maxDisCurr: '',
    signType: '',
    commPort: '',
    loadCurr: '',
    videoUrl: '',
    powerType: 1,
    updateReason: '',
    powerInuseTime: moment().format('YYYY-MM-DD'),
    inuseTime: moment().format('YYYY-MM-DD'),
});
const otherIdList = ref([]);
const devData = reactive({
    devType: '',
    devIp: '',
});
const powerTypeList = computed(() => {
    return Object.keys(powerTypes).map(v => ({ label: powerTypes[v], value: v * 1 }));
});
const validatorIp = (rule, value, callback) => {
    const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$/;
    if (ipRegex.test(value)) {
        // 校验密码规则是否正确
        callback();
    } else {
        callback(new Error('请输入正确的IP地址'));
    }
}
const rules = {
    provice: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    city: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    country: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    stationName: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    stationType: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    acvolHighLimit: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    acvolLowLimit: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    dcoutvolLowLimit: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    floatCurrLevel: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    maxDisCurr: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    commPort: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    loadCurr: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    videoUrl: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    updateReason: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
    ],
    powerIp: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
        {
            validator: validatorIp,
            trigger: ["blur", "change"],
        },
    ],
    devIp: [
        {
            required: true,
            message: "不能为空",
            trigger: ["blur", "change"],
        },
        {
            validator: validatorIp,
            trigger: ["blur", "change"],
        },
    ],
    phoneNumber: [
        {
            validator: (rule, value, callback) => {
                let reg = /^1\d{10}$/;
                if (value === '' || reg.test(value)) {
                    // 校验密码规则是否正确
                    callback();
                } else {
                    callback(new Error('请输入正确的手机号'));
                }
            },
            trigger: ["change", "blur"]
        },
    ],
};
const uroleList = [
    {
        label: "普通用户",
        value: 1,
    },
    {
        label: "管理层",
        value: 2,
    },
    {
        label: "领导层",
        value: 3,
    },
    {
        label: "运维班组",
        value: 4,
    },
];
const isEdit = computed(() => !!props.info?.stationId);
const $emit = defineEmits(["cancel", "success"]);
function close() {
    $emit("cancel");
}
async function update() {
    let valid = await formRef.value.validate(() => { });
    // console.log('valid', valid, '=============');
    if (!valid) {
        $message.error("表单验证失败");
        return false;
    }
    // 修改之前需要先验证用户密码
    let re = await ElMessageBox.prompt('请输入用户密码', '安全验证', {
        confirmButtonText: '确定',
        cancelButtonText: '取消',
    inputType: 'password',
    inputPlaceholder: '请输入密码',
        // 关键:关闭前的钩子
        beforeClose: async (action, instance, done) => {
            // 处理取消操作(直接关闭)
            if (action == 'cancel') {
                done();
                return false;
            }
            // 处理确认操作
            const value = instance.inputValue.trim();
            // 验证逻辑
            if (!value) {
                // 空值验证失败
                $message.error("密码不能为空");
                // 阻止窗口关闭(不调用done())
                return false;
            }
            let res = await checkSnId(value);
      let { code, data } = res;
            if (code && data) {
                // 验证失败
                $message.success("密码正确");
                done();
            } else {
        // 验证失败
        $message.error("密码错误");
        // 阻止窗口关闭(不调用done())
        return false;
      }
            // 验证通过,关闭窗口
            done();
        }
    }).then((res) => res)
        .catch((err) => {
            console.log(err);
            return false;
        });
    if (!re) {
        return false;
    }
  
  const form1 = reactive({
    provice: provice.value,
    city: city.value,
    country: country.value,
    stationName: stationName.value,
    stationType: "",
    longitude: 0,
    latitude: 0,
    powerName: "",
    company: "",
    modelCfg: 0,
    powerModel: "",
    protocol: "",
    powerIp: "",
    devIp: "",
    devType: "",
    monvolstd: '',
    moncapstd: '',
    monresstd: '',
    nodeStation: '',
    moncount: '',
    product: "",
    battModel: "",
    powerType: 1,
    powerInuseTime: moment().format('YYYY-MM-DD'),
    inuseTime: moment().format('YYYY-MM-DD'),
  });
    let params = {};
  const otherIdList = ref([]);
  const devData = reactive({
    devType: '',
    devIp: '',
  });
    for (let key in form1) {
        params[key] = form1[key];
    }
    params.longitude = params.longitude || 0;
    params.latitude = params.latitude || 0;
    params.addBinfFlag = addBinfFlag.value;
    params.modelCfg = form1.modelCfg.reduce((pre, cur) => pre + cur, 0);
  const powerTypeList = computed(() => {
    return Object.keys(powerTypes).map(v => ({ label: powerTypes[v], value: v * 1 }));
  });
    // 编辑用户时, 区域中不在管理员管理内的区域要挑出来 最后更新时再追加进去
    console.log("params update", params, "=============");
  const validatorIp = (rule, value, callback) => {
    const ipRegex = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9]?[0-9])$/;
    let loading = $loading();
    updateDev(params)
        .then((res) => {
            let { code, data } = res;
            if (code && data) {
                $emit("success");
                $message.success("操作成功");
            } else {
                $message.error("操作失败");
            }
            loading.close();
        })
        .catch((err) => {
            console.log(err);
            loading.close();
        });
}
async function onSubmit() {
    let valid = await formRef.value.validate(() => { });
    // console.log('valid', valid, '=============');
    if (ipRegex.test(value)) {
      // 校验密码规则是否正确
      callback();
    } else {
      callback(new Error('请输入正确的IP地址'));
    }
  }
    if (!valid) {
        $message.error("表单验证失败");
        return false;
    }
  const rules = {
    provice: [
      {
        required: true,
        message: "不能为空",
        trigger: ["blur", "change"],
      },
    ],
    city: [
      {
        required: true,
        message: "不能为空",
        trigger: ["blur", "change"],
      },
    ],
    country: [
      {
        required: true,
        message: "不能为空",
        trigger: ["blur", "change"],
      },
    ],
    stationName: [
      {
        required: true,
        message: "不能为空",
        trigger: ["blur", "change"],
      },
    ],
    stationType: [
      {
        required: true,
        message: "不能为空",
        trigger: ["blur", "change"],
      },
    ],
    powerIp: [
      {
        required: true,
        message: "不能为空",
        trigger: ["blur", "change"],
      },
      {
        validator: validatorIp,
        trigger: ["blur", "change"],
      },
    ],
    devIp: [
      {
        required: true,
        message: "不能为空",
        trigger: ["blur", "change"],
      },
      {
        validator: validatorIp,
        trigger: ["blur", "change"],
      },
    ],
    phoneNumber: [
      {
        validator: (rule, value, callback) => {
          let reg = /^1\d{10}$/;
          if (value === '' || reg.test(value)) {
            // 校验密码规则是否正确
            callback();
          } else {
            callback(new Error('请输入正确的手机号'));
          }
        },
        trigger:["change", "blur"]
      },
    ],
  };
    let params = {};
  const uroleList = [
    {
      label: "普通用户",
      value: 1,
    },
    {
      label: "管理层",
      value: 2,
    },
    {
      label: "领导层",
      value: 3,
    },
    {
      label: "运维班组",
      value: 4,
    },
  ];
    for (let key in form1) {
        params[key] = form1[key];
    }
    params.longitude = params.longitude || 0;
    params.latitude = params.latitude || 0;
    params.addBinfFlag = addBinfFlag.value;
    params.modelCfg = form1.modelCfg.reduce((pre, cur) => pre + cur, 0);
    console.log("params", params, "=============");
  const isEdit = computed(() => !!props.info?.stationId);
  const $emit = defineEmits(["cancel", "success"]);
  function close() {
    $emit("cancel");
  }
    let loading = $loading();
    addDev(params)
        .then((res) => {
            let { code, data } = res;
            if (code && data) {
                $emit("success");
                $message.success("操作成功");
            } else {
                $message.error("操作失败");
            }
            loading.close();
        })
        .catch((err) => {
            console.log(err);
            loading.close();
        });
}
  async function update() {
    let valid = await formRef.value.validate(() => { });
    // console.log('valid', valid, '=============');
function devChange() {
    if (addDevFlag.value == 1) {
        form1.devType = "";
        form1.devIp = "";
    } else {
        form1.devType = devData.devType;
        form1.devIp = devData.devIp;
    }
}
    if (!valid) {
      $message.error("表单验证失败");
      return false;
    }
    let params = {};
async function addBattFn() {
    let valid = await formRef.value.validate(() => { });
    // console.log('valid', valid, '=============');
    for (let key in form1) {
      params[key] = form1[key];
    }
    params.longitude = params.longitude || 0;
    params.latitude = params.latitude || 0;
    params.addBinfFlag = addBinfFlag.value;
    params.modelCfg = form1.modelCfg.reduce((pre, cur) => pre + cur, 0);
    if (!valid) {
        $message.error("表单验证失败");
        return false;
    }
    // 编辑用户时, 区域中不在管理员管理内的区域要挑出来 最后更新时再追加进去
    console.log("params update", params, "=============");
    let params = {};
    let loading = $loading();
    updateDev(params)
      .then((res) => {
        let { code, data } = res;
        if (code && data) {
          $emit("success");
          $message.success("操作成功");
        } else {
          $message.error("操作失败");
        }
        loading.close();
      })
      .catch((err) => {
        console.log(err);
        loading.close();
      });
  }
    for (let key in form1) {
        params[key] = form1[key];
    }
    params.longitude = params.longitude || 0;
    params.latitude = params.latitude || 0;
    params.addBinfFlag = addBinfFlag.value;
    params.modelCfg = form1.modelCfg.reduce((pre, cur) => pre + cur, 0);
    console.log("params", params, "=============");
  async function onSubmit() {
    let valid = await formRef.value.validate(() => { });
    // console.log('valid', valid, '=============');
    if (addDevFlag.value == 1) {
        params.devId = undefined;
    }
    if (!valid) {
      $message.error("表单验证失败");
      return false;
    }
    let loading = $loading();
    addBatt(params)
        .then((res) => {
            let { code, data } = res;
            if (code && data) {
                $emit("success");
                $message.success("操作成功");
            } else {
                $message.error("操作失败");
            }
            loading.close();
        })
        .catch((err) => {
            console.log(err);
            loading.close();
        });
}
    let params = {};
watchEffect(() => {
    provice.value = form1.provice;
});
    for (let key in form1) {
      params[key] = form1[key];
    }
    params.longitude = params.longitude || 0;
    params.latitude = params.latitude || 0;
    params.addBinfFlag = addBinfFlag.value;
    params.modelCfg = form1.modelCfg.reduce((pre, cur) => pre + cur, 0);
    console.log("params", params, "=============");
watchEffect(() => {
    city.value = form1.city;
});
    let loading = $loading();
    addDev(params)
      .then((res) => {
        let { code, data } = res;
        if (code && data) {
          $emit("success");
          $message.success("操作成功");
        } else {
          $message.error("操作失败");
        }
        loading.close();
      })
      .catch((err) => {
        console.log(err);
        loading.close();
      });
  }
watchEffect(() => {
    country.value = form1.country;
});
  function devChange() {
    if (addDevFlag.value == 1) {
      form1.devType = "";
      form1.devIp = "";
    } else {
      form1.devType = devData.devType;
      form1.devIp = devData.devIp;
    }
  }
watchEffect(() => {
    stationName.value = form1.stationName;
});
  async function addBattFn() {
    let valid = await formRef.value.validate(() => { });
    // console.log('valid', valid, '=============');
watchEffect(() => {
    form1.provice = provice.value;
});
    if (!valid) {
      $message.error("表单验证失败");
      return false;
    }
watchEffect(() => {
    form1.city = city.value;
});
    let params = {};
watchEffect(() => {
    form1.country = country.value;
});
    for (let key in form1) {
      params[key] = form1[key];
    }
    params.longitude = params.longitude || 0;
    params.latitude = params.latitude || 0;
    params.addBinfFlag = addBinfFlag.value;
    params.modelCfg = form1.modelCfg.reduce((pre, cur) => pre + cur, 0);
    console.log("params", params, "=============");
watchEffect(() => {
    form1.stationName = stationName.value;
});
    if (addDevFlag.value == 1) {
      params.devId = undefined;
    }
const volLevels = ref([]);
const powerModelList = ref([]);
const companyList = ref([]);
const protocolList = ref([]);
const devTypeList = ref([]);
const monVolList = ref([]);
const productList = ref([]);
const battModelList = ref([]);
const monCapList = ref([]);
    let loading = $loading();
    addBatt(params)
      .then((res) => {
        let { code, data } = res;
        if (code && data) {
          $emit("success");
          $message.success("操作成功");
        } else {
          $message.error("操作失败");
        }
        loading.close();
      })
      .catch((err) => {
        console.log(err);
        loading.close();
      });
  }
// 获取标称容量
function getMonCapList() {
    getMonCapByUid().then((res) => {
        let { code, data, data2 } = res;
        let list = [];
        if (code && data) {
            list = data2;
        }
        monCapList.value = list;
    });
}
  watchEffect(() => {
    provice.value = form1.provice;
  });
// 获取电压等级
function getVolLevels() {
    console.log("获取电压等级");
    getVoltageLevel().then((res) => {
        let { code, data, data2 } = res;
        let list = [];
        if (code && data) {
            list = data2;
        }
        volLevels.value = list;
    });
}
  watchEffect(() => {
    city.value = form1.city;
  });
function getPowerModelList() {
    getPowerType().then((res) => {
        let { code, data, data2 } = res;
        let list = [];
        if (code && data) {
            list = data2;
        }
        powerModelList.value = list;
    });
}
  watchEffect(() => {
    country.value = form1.country;
  });
function getCompanyList() {
    getPowerBrand().then((res) => {
        let { code, data, data2 } = res;
        let list = [];
        if (code && data) {
            list = data2;
        }
        companyList.value = list;
    });
}
  watchEffect(() => {
    stationName.value = form1.stationName;
  });
function getProtocolList() {
    getProtocol().then((res) => {
        let { code, data, data2 } = res;
        let list = [];
        if (code && data) {
            list = data2;
        }
        protocolList.value = list;
    });
}
  watchEffect(() => {
    form1.provice = provice.value;
  });
function getDevTypeList() {
    getDevType().then((res) => {
        let { code, data, data2 } = res;
        let list = [];
        if (code && data) {
            list = data2;
        }
        devTypeList.value = list;
    });
}
  watchEffect(() => {
    form1.city = city.value;
  });
function getMonVolList() {
    getMonVol().then((res) => {
        let { code, data, data2 } = res;
        let list = [];
        if (code && data) {
            list = data2;
        }
        monVolList.value = list;
    });
}
  watchEffect(() => {
    form1.country = country.value;
  });
function getProductList() {
    getBatteryBrand().then((res) => {
        let { code, data, data2 } = res;
        let list = [];
        if (code && data) {
            list = data2;
        }
        productList.value = list;
    });
}
  watchEffect(() => {
    form1.stationName = stationName.value;
  });
onMounted(async () => {
    let info = props.info;
    getVolLevels();
    getPowerModelList();
    getCompanyList();
    getProtocolList();
    getDevTypeList();
    getMonVolList();
    getProductList();
    getMonCapList();
  const volLevels = ref([]);
  const powerModelList = ref([]);
  const companyList = ref([]);
  const protocolList = ref([]);
  const devTypeList = ref([]);
  const monVolList = ref([]);
  const productList = ref([]);
  const battModelList = ref([]);
  const monCapList = ref([]);
    if (info) {
        for (let key in info) {
            form1[key] = info[key];
        }
  // 获取标称容量
  function getMonCapList() {
    getMonCapByUid().then((res) => {
      let { code, data, data2 } = res;
      let list = [];
      if (code && data) {
        list = data2;
      }
      monCapList.value = list;
    });
  }
        form1.modelCfg = getBinaryDigits(info.modelCfg).map((v, i) => {
            return v == 1 ? 1 << i : 0;
        }).filter(v => !!v);
  // 获取电压等级
  function getVolLevels() {
    console.log("获取电压等级");
    getVoltageLevel().then((res) => {
      let { code, data, data2 } = res;
      let list = [];
      if (code && data) {
        list = data2;
      }
      volLevels.value = list;
    });
  }
        addBinfFlag.value = info.stationId ? !!info.battgroupId * 1 : 1;
        if (info.addBattFlag) {
            if (!info.devId) {
                addDevFlag.value = 1;
            }
  function getPowerModelList() {
    getPowerType().then((res) => {
      let { code, data, data2 } = res;
      let list = [];
      if (code && data) {
        list = data2;
      }
      powerModelList.value = list;
    });
  }
            devData.devType = info.devType;
            devData.devIp = info.devIp;
  function getCompanyList() {
    getPowerBrand().then((res) => {
      let { code, data, data2 } = res;
      let list = [];
      if (code && data) {
        list = data2;
      }
      companyList.value = list;
    });
  }
            form1.moncount = '';
            form1.monvolstd = '';
            form1.moncapstd = '';
            form1.monresstd = '';
            form1.product = '';
            form1.battModel = '';
  function getProtocolList() {
    getProtocol().then((res) => {
      let { code, data, data2 } = res;
      let list = [];
      if (code && data) {
        list = data2;
      }
      protocolList.value = list;
    });
  }
        }
  function getDevTypeList() {
    getDevType().then((res) => {
      let { code, data, data2 } = res;
      let list = [];
      if (code && data) {
        list = data2;
      }
      devTypeList.value = list;
    });
  }
  function getMonVolList() {
    getMonVol().then((res) => {
      let { code, data, data2 } = res;
      let list = [];
      if (code && data) {
        list = data2;
      }
      monVolList.value = list;
    });
  }
  function getProductList() {
    getBatteryBrand().then((res) => {
      let { code, data, data2 } = res;
      let list = [];
      if (code && data) {
        list = data2;
      }
      productList.value = list;
    });
  }
  onMounted(async () => {
    let info = props.info;
    getVolLevels();
    getPowerModelList();
    getCompanyList();
    getProtocolList();
    getDevTypeList();
    getMonVolList();
    getProductList();
    getMonCapList();
    if (info) {
      for(let key in info) {
        form1[key] = info[key];
      }
      form1.modelCfg = getBinaryDigits(info.modelCfg).map((v, i) => {
        return v == 1 ? 1 << i : 0;
      }).filter(v => !!v);
      addBinfFlag.value = info.stationId ? !!info.battgroupId * 1 : 1;
      if (info.addBattFlag) {
        if (!info.devId) {
          addDevFlag.value = 1;
        }
        devData.devType = info.devType;
        devData.devIp = info.devIp;
        form1.moncount = '';
        form1.monvolstd = '';
        form1.moncapstd = '';
        form1.monresstd = '';
        form1.product = '';
        form1.battModel = '';
      }
      await getProviceList();
      form1.provice = info.provice;
      await getCityList();
      form1.city = info.city;
      await getCountryList();
      form1.country = info.country;
      await getStationList();
      form1.stationName = info.stationName;
        await getProviceList();
        form1.provice = info.provice;
        await getCityList();
        form1.city = info.city;
        await getCountryList();
        form1.country = info.country;
        await getStationList();
        form1.stationName = info.stationName;
    }
  });
    }
});
</script>
<template>
  <div class="">
    <el-form ref="formRef" :model="form1" label-width="8em" :rules="rules">
    <el-form ref="formRef" :model="form1" label-width="10em" :rules="rules">
      <el-row :gutter="layout.gutter">
        <el-col :span="layout.span">
          <el-form-item label="省" prop="provice">
@@ -621,25 +749,25 @@
              placeholder="请选择"
              style="width: 180px"
            >
              <el-option
                label="非节点站"
                :value="0"
              />
              <el-option
                label="节点站"
                :value="1"
              />
              <el-option label="非节点站" :value="0" />
              <el-option label="节点站" :value="1" />
            </el-select>
          </el-form-item>
        </el-col>
        <el-col :span="layout.span">
          <el-form-item label="经度" prop="longitude">
            <el-input v-model="form1.longitude" :disabled="info.addBattFlag"></el-input>
            <el-input
              v-model="form1.longitude"
              :disabled="info.addBattFlag"
            ></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="layout.span">
          <el-form-item label="纬度" prop="latitude">
            <el-input v-model="form1.latitude" :disabled="info.addBattFlag"></el-input>
            <el-input
              v-model="form1.latitude"
              :disabled="info.addBattFlag"
            ></el-input>
          </el-form-item>
        </el-col>
      </el-row>
@@ -724,7 +852,10 @@
      <el-row :gutter="layout.gutter">
        <el-col :span="layout.span">
          <el-form-item label="电源IP" prop="powerIp">
            <el-input v-model="form1.powerIp" :disabled="info.addBattFlag"></el-input>
            <el-input
              v-model="form1.powerIp"
              :disabled="info.addBattFlag"
            ></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="layout.span * 2">
@@ -766,6 +897,32 @@
        </el-col>
      </el-row>
      <el-row :gutter="layout.gutter">
        <el-col :span="layout.span">
          <el-form-item label="交流上限阈值" prop="acvolHighLimit">
            <el-input
              v-model="form1.acvolHighLimit"
              :disabled="info.addBattFlag"
            ></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="layout.span">
          <el-form-item label="交流下限阈值" prop="acvolLowLimit">
            <el-input
              v-model="form1.acvolLowLimit"
              :disabled="info.addBattFlag"
            ></el-input>
          </el-form-item>
        </el-col>
        <el-col :span="layout.span">
          <el-form-item label="直流输出电压下限" prop="dcoutvolLowLimit">
            <el-input
              v-model="form1.dcvolLowLimit"
              :disabled="info.addBattFlag"
            ></el-input>
          </el-form-item>
        </el-col>
      </el-row>
      <el-row :gutter="layout.gutter">
        <el-col :span="layout.span" v-if="!info.addBattFlag">
          <el-form-item label="有无电池组">
            <el-select
@@ -776,14 +933,8 @@
              placeholder="请选择"
              style="width: 180px"
            >
              <el-option
                label="有电池组"
                :value="1"
              />
              <el-option
                label="无电池组"
                :value="0"
              />
              <el-option label="有电池组" :value="1" />
              <el-option label="无电池组" :value="0" />
            </el-select>
          </el-form-item>
        </el-col>
@@ -798,14 +949,8 @@
              @change="devChange"
              style="width: 180px"
            >
              <el-option
                label="创建新设备"
                :value="1"
              />
              <el-option
                label="当前设备"
                :value="0"
              />
              <el-option label="创建新设备" :value="1" />
              <el-option label="当前设备" :value="0" />
            </el-select>
          </el-form-item>
        </el-col>
@@ -831,7 +976,10 @@
          </el-col>
          <el-col :span="layout.span">
            <el-form-item label="设备IP" prop="devIp">
              <el-input v-model="form1.devIp" :disabled="info.addBattFlag && !addDevFlag"></el-input>
              <el-input
                v-model="form1.devIp"
                :disabled="info.addBattFlag && !addDevFlag"
              ></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="layout.span">
@@ -885,6 +1033,47 @@
            </el-form-item>
          </el-col>
          <el-col :span="layout.span">
            <el-form-item label="浮充电流阈值" prop="floatCurrLevel">
              <el-input v-model="form1.floatCurrLevel"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="layout.span">
            <el-form-item label="最大核容电流" prop="maxDisCurr">
              <el-input v-model="form1.maxDisCurr"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="layout.span">
            <el-form-item label="验签格式" prop="signType">
              <el-select
                v-model="form1.signType"
                filterable
                allow-create
                placeholder="请选择"
                style="width: 180px"
              >
                <el-option label="常规" :value="0" />
                <el-option label="正常1拖2" :value="1" />
              </el-select>
            </el-form-item>
          </el-col>
          <el-col :span="layout.span">
            <el-form-item label="通信端口号" prop="commPort">
              <el-input v-model="form1.commPort"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="layout.span">
            <el-form-item label="负载电流" prop="loadCurr">
              <el-input v-model="form1.loadCurr"></el-input>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="layout.gutter">
          <el-col :span="layout.span">
            <el-form-item label="视频监控序列号" prop="videoUrl">
              <el-input v-model="form1.videoUrl"></el-input>
            </el-form-item>
          </el-col>
          <el-col :span="layout.span">
            <el-form-item label="电池品牌" prop="product">
              <el-select
                v-model="form1.product"
@@ -902,8 +1091,6 @@
              </el-select>
            </el-form-item>
          </el-col>
        </el-row>
        <el-row :gutter="layout.gutter">
          <el-col :span="layout.span">
            <el-form-item label="电池型号" prop="battModel">
              <el-input v-model="form1.battModel"></el-input>
@@ -925,9 +1112,20 @@
          </el-col>
        </el-row>
      </template>
      <el-row :gutter="layout.gutter" v-if="isEdit && !info.addBattFlag">
        <el-col :span="layout.span * 3">
          <el-form-item label="修改说明" prop="updateReason">
            <el-input type="textarea" :rows="2" v-model="form1.updateReason" />
          </el-form-item>
        </el-col>
      </el-row>
      <div class="form-footer">
        <el-button v-if="info.addBattFlag" type="primary" @click="addBattFn">添加电池组</el-button>
        <el-button v-else-if="isEdit" type="primary" @click="update">修改</el-button>
        <el-button v-if="info.addBattFlag" type="primary" @click="addBattFn"
          >添加电池组</el-button
        >
        <el-button v-else-if="isEdit" type="primary" @click="update"
          >修改</el-button
        >
        <el-button v-else type="primary" @click="onSubmit">新增</el-button>
        <el-button @click="close">取消</el-button>
      </div>
@@ -939,6 +1137,7 @@
:deep(.select) {
  width: 100%;
}
.form-footer {
  padding: 10px;
  text-align: right;
src/views/datas/device.vue
@@ -1,337 +1,350 @@
<script setup name="device">
    import { ref, reactive, onMounted, computed, nextTick } from "vue";
    import { storeToRefs } from "pinia";
    import { Search, Plus } from "@element-plus/icons-vue";
    import ycCard from "@/components/ycCard/index.vue";
    import addEdit from "./addEdit.vue";
    import { ElMessage } from "element-plus";
    import useElement from "@/hooks/useElement.js";
  import { useUserStore } from '@/store/user';
import { ref, reactive, onMounted, computed, nextTick } from "vue";
import { storeToRefs } from "pinia";
import { Search, Plus } from "@element-plus/icons-vue";
import ycCard from "@/components/ycCard/index.vue";
import addEdit from "./addEdit.vue";
import { ElMessage } from "element-plus";
import useElement from "@/hooks/useElement.js";
import { useUserStore } from '@/store/user';
  import useStation from "@/hooks/useStationList.js";
  const { provice, city, country, stationName,
    proviceList, cityList, countryList, stationList,
  } = useStation();
import useStation from "@/hooks/useStationList.js";
const { provice, city, country, stationName,
    proviceList, cityList, countryList, stationList,
} = useStation();
  import powerTypes from '@/utils/const/const_powerType.js';
  import {
    delBatt,
    getPowerBrand,
    getVoltageLevel,
  } from "@/api/station";
  const userStore = useUserStore();
  const { uid, uname } = storeToRefs(userStore);
  import {
    getDevList,
  } from "@/api/station";
    const { $loading, $message, $confirm } = useElement();
    const headers = [
    {
            prop: "provice",
            label: "省",
            width: "80",
        },
    {
            prop: "city",
            label: "市",
            width: "80",
        },
    {
            prop: "country",
            label: "区县",
            width: "80",
        },
        {
            prop: "stationName",
            label: "机房名称",
            width: "160",
        },
    {
            prop: "stationType",
            label: "电压等级",
            width: "80",
        },
    {
      prop: "nodeStationStr",
      label: "是否节点站",
      width: "200",
    },
    {
            prop: "longitude",
            label: "经度",
            width: "80",
        },
    {
            prop: "latitude",
            label: "纬度",
            width: "80",
        },
    {
            prop: "powerName",
            label: "电源名称",
            width: "80",
        },
    {
            prop: "powerTypeStr",
            label: "电源类型",
            width: "80",
        },
    {
            prop: "company",
            label: "电源品牌",
            width: "80",
        },
        {
            prop: "powerModel",
            label: "电源型号",
            width: "80",
        },
    {
            prop: "protocol",
            label: "电源协议",
            width: "80",
        },
    {
            prop: "powerIp",
            label: "电源IP",
            width: "120",
        },
    {
            prop: "devName",
            label: "设备名称",
            width: "120",
        },
    {
            prop: "devType",
            label: "设备型号",
            width: "120",
        },
    {
            prop: "devIp",
            label: "设备IP",
            width: "120",
        },
    {
            prop: "battgroupName",
            label: "电池组名称",
            width: "120",
        },
    {
            prop: "moncount",
            label: "电池单体个数",
            width: "120",
        },
    {
            prop: "monvolstd",
            label: "电池标称电压",
            width: "120",
        },
    {
            prop: "moncapstd",
            label: "电池标称容量",
            width: "120",
        },
    {
            prop: "monresstd",
            label: "电池标称内阻",
            width: "120",
        },
    {
            prop: "product",
            label: "电池品牌",
            width: "120",
        },
    {
            prop: "battModel",
            label: "电池型号",
            width: "120",
        },
    ];
  const company = ref("");
  const companyList = ref([]);
  const volLevels = ref([]);
  const powerType = ref('');
  const stationType = ref('');
    const background = ref(true);
    const disabled = ref(false);
    const pageCurr = ref(1);
    const pageSize = ref(10);
    const total = ref(0);
    const addEditVisible = ref(false);
    const dialogTitle = ref("");
    const currentAreaId = ref();
    const currentAreaIds = ref([]);
    const datas = reactive({
        tableData: [],
        rowData: {},
    });
  const powerTypeList = computed(() => {
    return Object.keys(powerTypes).map(v => ({ label: powerTypes[v], value: v * 1 }));
  });
    // const tableData = reactive([]);
    // const rowData = reactive({});
    // const userStore = useUserStore();
    // const { uid, uname } = storeToRefs(userStore);
    function getList() {
        let loading = $loading();
    let params = {
      provice: provice.value || undefined,
      city: city.value || undefined,
      country: country.value || undefined,
      stationName: stationName.value || undefined,
      powerType: powerType.value || undefined,
      stationType: stationType.value || undefined,
      pageNum: pageCurr.value,
      pageSize: pageSize.value,
      // powerName: "",
    };
        getDevList(params)
            .then((res) => {
                let { code, data, data2 } = res;
                let list = [];
                let _total = 0;
                if (code && data) {
                    // console.log(data);
                    list = data2.list.map(v => ({
            ...v,
            powerTypeStr: powerTypes[v.powerType],
            nodeStationStr: v.nodeStation ? "是" : "否",
            // roleName: roles[v.role],
          }));
                    _total = data2.total;
                }
                loading.close();
                // tableData.length = 0;
                // tableData.push(...list);
                datas.tableData = list;
                total.value = _total;
            })
            .catch((err) => {
                console.log(err);
                loading.close();
            });
    }
  function getCompanyList() {
    getPowerBrand().then((res) => {
      let { code, data, data2 } = res;
      let list = [];
      if (code && data) {
        list = data2;
      }
      companyList.value = list;
    });
  }
  // 获取电压等级
  function getVolLevels() {
    console.log("获取电压等级");
    getVoltageLevel().then((res) => {
      let { code, data, data2 } = res;
      let list = [];
      if (code && data) {
        list = data2;
      }
      volLevels.value = list;
    });
  }
    // 展示数据数量
    function handleSizeChange(val) {
        pageSize.value = val;
        getList();
    }
    // 翻页
    function handleCurrentChange(val) {
        pageCurr.value = val;
        getList();
    }
    function add() {
        dialogTitle.value = "添加设备";
        datas.rowData = {};
        addEditVisible.value = true;
    }
    function edit(record) {
        dialogTitle.value = "编辑设备";
        addEditVisible.value = true;
        console.log(record, '=======edit======');
        // if (record.ainfList.idPath) {
        //     ids = record.ainfList.idPath.split("_").map((v) => v * 1);
        // }
        // ids.push(record.areaId);
        datas.rowData = { ...record };
    }
  function addBatt(record) {
    dialogTitle.value = "添加电池组";
        datas.rowData = { ...record, addBattFlag: true };
        addEditVisible.value = true;
  }
import useColumnConfig from '@/hooks/useColumnConfig.js';
import tableColumnConfig from '@/components/table-column-config.vue';
const pageName = 'datas_device';
const { getConfig,
    columnCfgVisible,
    isColumnFixed,
    fixedColumns,
  showConfigDialog,
    setConfig, } = useColumnConfig(pageName);
  
    function confirmRemove(record) {
        $confirm("删除", () => {
      let { stationId, powerId, battgroupId } = record;
            remove(stationId, powerId, battgroupId||undefined);
import powerTypes from '@/utils/const/const_powerType.js';
import {
    delBatt,
    getPowerBrand,
    getVoltageLevel,
} from "@/api/station";
const userStore = useUserStore();
const { uid, uname } = storeToRefs(userStore);
import {
    getDevList,
} from "@/api/station";
const { $loading, $message, $confirm } = useElement();
const headers = [
    {
        prop: "provice",
        label: "省",
        width: "80",
    },
    {
        prop: "city",
        label: "市",
        width: "80",
    },
    {
        prop: "country",
        label: "区县",
        width: "80",
    },
    {
        prop: "stationName",
        label: "机房名称",
        width: "160",
    },
    {
        prop: "stationType",
        label: "电压等级",
        width: "80",
    },
    {
        prop: "nodeStationStr",
        label: "是否节点站",
        width: "200",
    },
    {
        prop: "longitude",
        label: "经度",
        width: "80",
    },
    {
        prop: "latitude",
        label: "纬度",
        width: "80",
    },
    {
        prop: "powerName",
        label: "电源名称",
        width: "80",
    },
    {
        prop: "powerTypeStr",
        label: "电源类型",
        width: "80",
    },
    {
        prop: "company",
        label: "电源品牌",
        width: "80",
    },
    {
        prop: "powerModel",
        label: "电源型号",
        width: "80",
    },
    {
        prop: "protocol",
        label: "电源协议",
        width: "80",
    },
    {
        prop: "powerIp",
        label: "电源IP",
        width: "120",
    },
    {
        prop: "devName",
        label: "设备名称",
        width: "120",
    },
    {
        prop: "devType",
        label: "设备型号",
        width: "120",
    },
    {
        prop: "devIp",
        label: "设备IP",
        width: "120",
    },
    {
        prop: "battgroupName",
        label: "电池组名称",
        width: "120",
    },
    {
        prop: "moncount",
        label: "电池单体个数",
        width: "120",
    },
    {
        prop: "monvolstd",
        label: "电池标称电压",
        width: "120",
    },
    {
        prop: "moncapstd",
        label: "电池标称容量",
        width: "120",
    },
    {
        prop: "monresstd",
        label: "电池标称内阻",
        width: "120",
    },
    {
        prop: "product",
        label: "电池品牌",
        width: "120",
    },
    {
        prop: "battModel",
        label: "电池型号",
        width: "120",
    },
];
const company = ref("");
const companyList = ref([]);
const volLevels = ref([]);
const powerType = ref('');
const stationType = ref('');
const background = ref(true);
const disabled = ref(false);
const pageCurr = ref(1);
const pageSize = ref(10);
const total = ref(0);
const addEditVisible = ref(false);
const dialogTitle = ref("");
const currentAreaId = ref();
const currentAreaIds = ref([]);
const datas = reactive({
    tableData: [],
    rowData: {},
});
const powerTypeList = computed(() => {
    return Object.keys(powerTypes).map(v => ({ label: powerTypes[v], value: v * 1 }));
});
// const tableData = reactive([]);
// const rowData = reactive({});
// const userStore = useUserStore();
// const { uid, uname } = storeToRefs(userStore);
function getList() {
    let loading = $loading();
    let params = {
        provice: provice.value || undefined,
        city: city.value || undefined,
        country: country.value || undefined,
        stationName: stationName.value || undefined,
        powerType: powerType.value || undefined,
        stationType: stationType.value || undefined,
        pageNum: pageCurr.value,
        pageSize: pageSize.value,
        // powerName: "",
    };
    getDevList(params)
        .then((res) => {
            let { code, data, data2 } = res;
            let list = [];
            let _total = 0;
            if (code && data) {
                // console.log(data);
                list = data2.list.map(v => ({
                    ...v,
                    powerTypeStr: powerTypes[v.powerType],
                    nodeStationStr: v.nodeStation ? "是" : "否",
                    // roleName: roles[v.role],
                }));
                _total = data2.total;
            }
            loading.close();
            // tableData.length = 0;
            // tableData.push(...list);
            datas.tableData = list;
            total.value = _total;
        })
        .catch((err) => {
            console.log(err);
            loading.close();
        });
    }
    function remove(stationId, powerId, battgroupId) {
        let loading = $loading();
        delBatt(stationId, powerId, battgroupId)
            .then((res) => {
                let { code, data } = res;
                loading.close();
                if (code && data) {
                    $message.success("操作成功");
                    handleCurrentChange(1);
                } else {
                    $message.success("操作失败");
                }
            })
            .catch((err) => {
                loading.close();
                console.log(err);
            });
    }
    function onOk() {
        addEditVisible.value = false;
        handleCurrentChange(1);
    }
    function onCanel() {
        addEditVisible.value = false;
    }
}
  function filterChange() {
    nextTick(() => {
      pageCurr.value = 1;
      getList();
    });
  }
function getCompanyList() {
    getPowerBrand().then((res) => {
        let { code, data, data2 } = res;
        let list = [];
        if (code && data) {
            list = data2;
        }
        companyList.value = list;
    });
}
// 获取电压等级
function getVolLevels() {
    console.log("获取电压等级");
    getVoltageLevel().then((res) => {
        let { code, data, data2 } = res;
        let list = [];
        if (code && data) {
            list = data2;
        }
        volLevels.value = list;
    });
}
    onMounted(() => {
    getCompanyList();
    getVolLevels();
// 展示数据数量
function handleSizeChange(val) {
    pageSize.value = val;
    getList();
}
// 翻页
function handleCurrentChange(val) {
    pageCurr.value = val;
    getList();
}
function add() {
    dialogTitle.value = "添加设备";
    datas.rowData = {};
    addEditVisible.value = true;
}
function edit(record) {
    dialogTitle.value = "编辑设备";
    addEditVisible.value = true;
    console.log(record, '=======edit======');
    // if (record.ainfList.idPath) {
    //     ids = record.ainfList.idPath.split("_").map((v) => v * 1);
    // }
    // ids.push(record.areaId);
    datas.rowData = { ...record };
}
function addBatt(record) {
    dialogTitle.value = "添加电池组";
    datas.rowData = { ...record, addBattFlag: true };
    addEditVisible.value = true;
}
function confirmRemove(record) {
    $confirm("删除", () => {
        let { stationId, powerId, battgroupId } = record;
        remove(stationId, powerId, battgroupId || undefined);
    });
}
function remove(stationId, powerId, battgroupId) {
    let loading = $loading();
    delBatt(stationId, powerId, battgroupId)
        .then((res) => {
            let { code, data } = res;
            loading.close();
            if (code && data) {
                $message.success("操作成功");
                handleCurrentChange(1);
            } else {
                $message.success("操作失败");
            }
        })
        .catch((err) => {
            loading.close();
            console.log(err);
        });
}
function onOk() {
    addEditVisible.value = false;
    handleCurrentChange(1);
}
function onCanel() {
    addEditVisible.value = false;
}
function filterChange() {
    nextTick(() => {
        pageCurr.value = 1;
        getList();
    });
}
onMounted(() => {
  // console.log('fixedColumns', fixedColumns, '=============');
    getCompanyList();
    getVolLevels();
    getList();
});
</script>
<template>
  <div class="page-wrapper">
    <!-- <div class="page-header">
    </div> -->
      </div> -->
    <div class="page-content">
      <yc-card is-full>
        <div class="page-content-wrapper">
@@ -410,23 +423,23 @@
                </el-select>
              </div>
              <!-- <div class="table-cell text-right">品牌:</div>
              <div class="table-cell">
                <el-select
                  v-model="company"
                  size="small"
                  clearable
                  @change="filterChange"
                  placeholder="请选择品牌"
                >
                  <el-option
                    v-for="(item, idx) in companyList"
                    :key="'list4_' + idx"
                    :label="item"
                    :value="item"
                <div class="table-cell">
                  <el-select
                    v-model="company"
                    size="small"
                    clearable
                    @change="filterChange"
                    placeholder="请选择品牌"
                  >
                  </el-option>
                </el-select>
              </div> -->
                    <el-option
                      v-for="(item, idx) in companyList"
                      :key="'list4_' + idx"
                      :label="item"
                      :value="item"
                    >
                    </el-option>
                  </el-select>
                </div> -->
              <div class="table-cell text-right">电源类型:</div>
              <div class="table-cell">
                <el-select
@@ -468,20 +481,59 @@
          <div class="page-content-table">
            <div class="pos-rel">
              <div class="pos-abs">
                <el-table class="yc-table" stripe height="100%" size="small" :data="datas.tableData" style="width: 100%">
                  <el-table-column type="index" fixed="left" label="序号" width="60"></el-table-column>
                  <el-table-column v-for="header in headers" :key="header.prop" :prop="header.prop" :label="header.label"
                    :min-width="header.width" align="center">
                    <template #default="scope">{{ scope.row[header.prop] || '--' }}</template>
                <el-table
                  class="yc-table"
                  stripe
                  height="100%"
                  size="small"
                  :data="datas.tableData"
                  style="width: 100%"
                >
                  <el-table-column
                    type="index"
                    fixed="left"
                    label="序号"
                    width="60"
                  ></el-table-column>
                  <el-table-column
                    v-for="header in headers"
                    :key="header.prop"
                    :prop="header.prop"
                    :label="header.label"
                    :fixed="isColumnFixed(header.prop) ? 'left' : false"
                    :min-width="header.width"
                    align="center"
                  >
                    <template
                      #default="scope"
                      >{{ scope.row[header.prop] || '--' }}</template
                    >
                  </el-table-column>
                  <el-table-column label="操作" fixed="right" width="240" align="center">
                  <el-table-column
                    label="操作"
                    fixed="right"
                    width="240"
                    align="center"
                  >
                    <template #default="scope">
                      <el-button type="primary" size="small"
                        @click="edit(scope.row)">编辑</el-button>
                      <el-button type="danger" size="small"
                        @click="confirmRemove(scope.row)">删除</el-button>
                      <el-button type="primary" size="small"
                        @click="addBatt(scope.row)">添加电池组</el-button>
                      <el-button
                        type="primary"
                        size="small"
                        @click="edit(scope.row)"
                        >编辑</el-button
                      >
                      <el-button
                        type="danger"
                        size="small"
                        @click="confirmRemove(scope.row)"
                        >删除</el-button
                      >
                      <el-button
                        type="primary"
                        size="small"
                        @click="addBatt(scope.row)"
                        >添加电池组</el-button
                      >
                    </template>
                  </el-table-column>
                </el-table>
@@ -490,25 +542,77 @@
          </div>
          <div class="page-content-page">
            <div class="page-tool">
              <el-button type="primary" round size="small" @click="add" :icon="Plus">添加</el-button>
              <el-button type="primary" round size="small" @click="getList" :icon="Search">查询</el-button>
              <el-button
                type="primary"
                round
                size="small"
                @click="add"
                :icon="Plus"
                >添加</el-button
              >
              <el-button
                type="primary"
                round
                size="small"
                @click="getList"
                :icon="Search"
                >查询</el-button
              >
            </div>
            <div class="el-page-container">
              <el-pagination v-model:current-page="pageCurr" v-model:page-size="pageSize"
                :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]" size="small" :disabled="disabled"
                :background="background" layout="total, sizes, prev, pager, next, jumper" :total="total"
                @size-change="handleSizeChange" @current-change="handleCurrentChange" />
              <el-pagination
                v-model:current-page="pageCurr"
                v-model:page-size="pageSize"
                :page-sizes="[20, 40, 60, 80, 100, 200, 300, 400]"
                size="small"
                :disabled="disabled"
                :background="background"
                layout="total, sizes, prev, pager, next, jumper"
                :total="total"
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
              />
            </div>
            <div class="page-tool"></div>
            <div class="page-tool">
              <el-button type="primary" round size="small" @click="showConfigDialog"
                >配置固定列</el-button
              >
            </div>
          </div>
        </div>
      </yc-card>
    </div>
    <div class="page-footer"></div>
    <!-- 设置固定列 -->
    <el-dialog
      title="设置固定列"
      v-model="columnCfgVisible"
      top="0"
      draggable
      :close-on-click-modal="false"
      class="dialog-center"
      width="480px"
      center
    >
      <table-column-config v-model:visible="columnCfgVisible" :columns="headers" :pageName="pageName" @change="getConfig"></table-column-config>
    </el-dialog>
    <!-- 弹窗 -->
    <el-dialog :title="dialogTitle" v-model="addEditVisible" top="0" :close-on-click-modal="false" class="dialog-center"
      width="1000px" center>
      <add-edit v-if="addEditVisible" @success="onOk" :info="datas.rowData" @cancel="onCanel"></add-edit>
    <el-dialog
      :title="dialogTitle"
      v-model="addEditVisible"
      top="0"
      draggable
      :close-on-click-modal="false"
      class="dialog-center"
      width="1200px"
      center
    >
      <add-edit
        v-if="addEditVisible"
        @success="onOk"
        :info="datas.rowData"
        @cancel="onCanel"
      ></add-edit>
    </el-dialog>
  </div>
</template>
@@ -596,4 +700,4 @@
    }
  }
}
</style>
</style>
src/views/login/index.vue
@@ -3,7 +3,6 @@
    <div class="site-title">
      <div class="logo"><img :src="logUrl" alt=""></div>{{ platformName }}
    </div>
    <div class="img-hm"></div>
    <div class="login-wrap">
      <el-form
        ref="loginFormRef"
@@ -461,15 +460,15 @@
    }
  }
  .img-hm {
    position: absolute;
    width: clamp(500px, 50vw, 800px);
    height: clamp(300px, 80vh, 80vh);
    background: url(@/assets/images/img-hm.png) center center / contain no-repeat;
    left: 0;
    top: 20%;
    transform: translate(clamp(0px, calc(24vw - 50%), 50vw), 0);
  }
  // .img-hm {
  //   position: absolute;
  //   width: clamp(500px, 50vw, 800px);
  //   height: clamp(300px, 80vh, 80vh);
  //   background: url(@/assets/images/img-hm.png) center center / contain no-repeat;
  //   left: 0;
  //   top: 20%;
  //   transform: translate(clamp(0px, calc(24vw - 50%), 50vw), 0);
  // }
  .svg-container {
    padding: 6px 5px 6px 15px;
src/views/realtime/tabs/system.vue
@@ -1007,7 +1007,7 @@
    }
  }
  .svg-diagram {}
  // .svg-diagram {}
  .btn-setting {
    display: inline-block;
vite.config.js
@@ -14,6 +14,9 @@
  const env = loadEnv(mode, process.cwd(), '');
  return {
    plugins: [
      commonjs({
        include: ['node_modules/**'],
      }),
      vue(),
      Inspect(),
      VueSetupExtend(),
@@ -25,9 +28,6 @@
          return 'icon-' + filename.substring(0, filename.lastIndexOf('.'));
        }
      }),
      commonjs({
        include: ['node_modules/**'],
      }),
    ],
    base: './',
    define: {
@@ -35,7 +35,8 @@
    },
    resolve: {
      alias: {
        '@': fileURLToPath(new URL('./src', import.meta.url))
        '@': fileURLToPath(new URL('./src', import.meta.url)),
        'dayjs': 'dayjs/esm'
      },
      extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json', '.vue']
    },