zhangzengfei
2020-07-30 b4902c47c0ffd80276ffd9cb0ea6bf6908b0420c
添加数据推送, 日志管理
6个文件已添加
5个文件已修改
1934 ■■■■ 已修改文件
src/pages/datapush/index/App.vue 113 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/datapush/index/LeftList.vue 225 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/datapush/index/RightEvent.vue 862 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/datapush/index/main.ts 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/desktop/index/App.vue 8 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/desktop/index/components/Tools.vue 109 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/desktop/index/mock/userData.json 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/settings/components/BasicSetting.vue 230 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/syslog/index/App.vue 190 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/syslog/index/main.ts 11 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/vindicate/index/App.vue 159 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
src/pages/datapush/index/App.vue
New file
@@ -0,0 +1,113 @@
<template>
  <div class="flex-box bg-w p10">
    <div class="ev-left-list">
      <leftList
        ref="baseSync"
        listWidth="350px"
        title="同步库"
        type="1"
        :isSelected="isSelected"
        :activeId="selectedId"
        @getEvents="getEventList"
        @del-list="delList"
        @add="changeToAdd"
        @enabled="eventSwitch"
      ></leftList>
    </div>
    <div v-show="isShowRight">
      <rightEvent
        ref="right"
        :eventObject="eventObject"
        @onCancle="onCancle"
        @updateList="updateList"
      ></rightEvent>
    </div>
  </div>
</template>
<script>
import leftList from "./LeftList";
import rightEvent from "./RightEvent";
import { getById } from "@/api/event";
export default {
  name: "eventPush",
  components: {
    leftList,
    rightEvent
  },
  props: {},
  data() {
    return {
      // 是否展示右侧
      isShowRight: false,
      // 是否选中
      isSelected: false,
      // 当前选中的事件
      eventObject: {},
      selectedId: ""
    };
  },
  methods: {
    eventSwitch(e) {
      if (this.eventObject.id) {
        if (e.id === this.eventObject.id) {
          this.eventObject.enable = e.enable
        }
      }
      // console.log(e)
    },
    /**
     * 添加事件推送
     */
    changeToAdd() {
      this.$refs.right.reAdd();
      this.isShowRight = true;
    },
    // 获取事件列表
    async getEventList(data) {
      // console.log(data, "当前选中的");
      let json = {
        id: data.id
      };
      let res = await getById(json);
      if (res && res.success) {
        this.eventObject = res.data;
        this.isShowRight = true;
      }
    },
    // 保存成功后的回调
    updateList(id) {
      this.$refs.baseSync.findAll();
      this.getEventList({ id: id });
      this.selectedId = id;
    },
    delList() {
      this.$refs.baseSync.findAll();
      this.isShowRight = false;
    },
    onCancle() {
      this.isShowRight = false;
    }
  }
};
</script>
<style src="../../../assets/css/common.scss" lang="scss"></style>
<style src="../../../assets/css/overried.scss" lang="scss"></style>
<style lang="scss">
.ev-left-list {
  border-right: 1px solid #e0e0e0;
}
.ant-divider,
.ant-divider-vertical {
  margin: 0 8px;
  display: inline-block;
  height: 100%;
  width: 1px;
  vertical-align: middle;
  position: relative;
  top: -0.06em;
}
</style>
src/pages/datapush/index/LeftList.vue
New file
@@ -0,0 +1,225 @@
<template>
  <div class="out-div">
    <div class="flex-center left-list">
      <el-input placeholder="请输入内容" v-model="eventName" size="mini" style="width: 280px">
        <i slot="suffix" class="el-input__icon el-icon-search"></i>
      </el-input>
      <div class="icon-btn" @click="add" style="margin-left:10px">
        <i class="el-icon-circle-plus-outline"></i>
        <span>&nbsp;新增</span>
      </div>
    </div>
    <div class="max-height" style="overflow-y:auto;overflow-x:hidden">
      <el-row
        class="cursor-pointer"
        v-for="(item, index) in eventList"
        :key="item.id"
        @click.native="clickCategory(index, item)"
        :class="{activeRow:categoryIndex==index}"
      >
        <div class="event-name">
          <b>{{item.name}}</b>
          <p style="margin-top:8px; color:#9e9e9e">{{item.time_start}} ~ {{item.time_end}}</p>
        </div>
        <div class="event-btn">
          <el-switch
            v-model="item.enable"
            @change="enabled(item)"
            :inactive-value="false"
            :active-value="true"
            style="margin-top:-5px"
          ></el-switch>
          <span
            class="iconfont iconshanchu iconStyle1"
            style="color:#E74C3C"
            @click.stop="deleteBase(item)"
          ></span>
        </div>
      </el-row>
    </div>
  </div>
</template>
<script>
import { findAll, changeStatus, deleteByid } from "@/api/event";
export default {
  name: "leftList",
  props: {
    listWidth: {
      default: "350px",
      type: String
    },
    title: {
      default: "",
      type: String
    },
    isSelected: {
      default: false,
      type: Boolean
    },
    type: {
      default: "",
      type: String
    },
    activeId: {
      default: "",
      type: String
    }
  },
  data() {
    return {
      activeNames: ["1"],
      categoryIndex: -1,
      eventList: [],
      // 当前点击的事件对象
      clickBase: {},
      // 事件名称
      eventName: ""
    };
  },
  mounted() {
    this.findAll();
  },
  methods: {
    async enabled(item) {
      let json = {
        id: item.id,
        enable: item.enable
      };
      let res = await changeStatus(json);
      if (res && res.success) {
        // console.log(res, "更新状态");
        this.$emit("enabled", item)
      }
      // this.$emit("getEvents", item);
    },
    async searchSyncTables() {
      // let res = await selectSyncTables()
      // this.data = res.data.datalist
    },
    async searchLocalTables() {
      // let res = await selectLocalTables()
      // this.data = res.data.datalist
    },
    add() {
      this.$emit("add");
      this.categoryIndex = -1;
    },
    clickCategory(index, item) {
      // 这里我们传入一个当前值
      this.categoryIndex = index;
      // 调用切换右侧面板的函数并且切换父组件中isSelected的值让另一个组件清除被选中状态
      this.clickBase = item;
      this.$emit("getEvents", item);
    },
    edit(item) {
      this.$emit("changeShow", item, this.type);
    },
    async deleteBase(data) {
      // console.log(data, "要删除的事件推送");
      this.$confirm("确定要删除该条推送任务吗?", {
        center: true,
        cancelButtonClass: "comfirm-class-cancle",
        confirmButtonClass: "comfirm-class-sure"
      }).then(() => {
        let json = {
          type: "formData",
          id: data.id
        };
        deleteByid(json).then(res => {
          if (res && res.success) {
            this.$emit("del-list");
            this.$notify({
              type: "success",
              message: "删除成功"
            })
          }
        });
      })
    },
    // 查询事件列表
    async findAll() {
      let json = {
        name: this.eventName
      };
      let res = await findAll(json);
      if (res && res.success) {
        // console.log(res, "查询所有事件列表");
        if (this.activeId !== "") {
          res.data.forEach((element, index) => {
            if (element.id === this.activeId) {
              this.categoryIndex = index;
            }
          });
        }
        this.eventList = res.data;
      }
    }
  }
};
</script>
<style lang="scss" scoped>
.flex-center {
  justify-content: left;
}
.iconStyle1 {
  font-size: 18px;
  margin-left: 15px;
  cursor: pointer;
}
.activeRow {
  background: #f8f8f8;
}
.cursor-pointer {
  cursor: pointer;
  height: 75px;
}
.max-height {
  position: absolute;
  left: 0px;
  width: 355px;
  height: 100%;
  margin-top: 20px;
  border-top: 1px solid #e0e0e0;
  border-bottom: 1px solid #e0e0e0;
}
.out-div {
  width: 350px;
  height: 58.9em;
  text-align: left;
  padding-top: 20px;
  .left-list {
    position: absolute;
    left: 15px;
    top: 10px;
  }
}
.event-name {
  padding: 17px;
  font-size: 14px;
}
.event-btn {
  position: absolute;
  left: 79%;
  top: 18%;
}
.icon-btn {
  i {
    font-size: 18px;
    position: relative;
    top: 2px;
  }
  span {
    font-size: 14px;
  }
  display: inline;
  color: #3d68e1;
  line-height: 38px;
  margin-left: 10px;
  cursor: pointer;
}
</style>
src/pages/datapush/index/RightEvent.vue
New file
@@ -0,0 +1,862 @@
<template>
  <div class="s-event-push-right">
    <div class="s-right-config">
      <el-form>
        <el-form-item label="名称">
          <el-input v-model="eventData.name" placeholder="请输入名称" size="small" style="width:400px"></el-input>
        </el-form-item>
        <el-form-item label="时间">
          <el-date-picker
            v-model="eventData.time"
            format="yyyy-MM-dd HH:mm:ss"
            value-format="yyyy-MM-dd HH:mm:ss"
            type="datetimerange"
            range-separator="至"
            start-placeholder="开始日期"
            end-placeholder="结束日期"
            size="small"
          ></el-date-picker>
        </el-form-item>
        <span style="line-height: 38px;">推送服务器</span>
        <div class="icon-btn" v-if="ips.length < 1" @click="addUrl('ip')">
          <i class="el-icon-circle-plus-outline"></i>
          <span>&nbsp;添加ip</span>
        </div>
        <div class="icon-btn" v-if="domains.length < 1" @click="addUrl('domain')">
          <i class="el-icon-circle-plus-outline"></i>
          <span>&nbsp;添加域名</span>
        </div>
        <div v-for="(item,index) in urls" :key="item.hash" class="flex-box server-url">
          <div>
            <el-checkbox v-model="item.enable"></el-checkbox>
            <span class="ml20">{{item.type =='ip' ? 'IP&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;' : '域名 '}}</span>
            <!-- <el-input v-model="item.url" style="width:400px;margin-left:34px;" size="small"></el-input> -->
            <ip-input
              v-if="item.type == 'ip'"
              :id="item.url"
              :ip="item.ip"
              :item="item"
              :on-item-change="onIpBlur"
              style="width: 255px"
            ></ip-input>
            <el-input
              v-else
              v-model="item.domain"
              style="width:256px;margin-left:0px;"
              size="small"
            ></el-input>
            <span class="ml10">端口</span>
            <el-input v-model="item.port" style="width:100px;margin-left:5px;" size="small"></el-input>
          </div>
          <div class="server-add">
            <i
              class="el-icon-remove-outline"
              @click="delUrl(index)"
              style="color:red;margin-right:10px"
            />
            <i class="el-icon-circle-plus-outline" @click="addUrl(item.type)"></i>
          </div>
        </div>
        <el-form-item label="联动方式" style="margin-top: 20px;width:100">
          <el-select v-model="eventData.lineWay" placeholder="请选择" size="small">
            <el-option
              v-for="item in eventData.lineOptions"
              :key="item.value"
              :label="item.label"
              :value="item.value"
            ></el-option>
          </el-select>
        </el-form-item>
        <el-form-item label="标签">
          <el-radio v-model="eventData.radioValue" label="1">满足全部</el-radio>
          <el-radio v-model="eventData.radioValue" label="2">满足任意一个</el-radio>
        </el-form-item>
      </el-form>
    </div>
    <div class="s-right-mid"></div>
    <div class="s-right-rule">
      <div class="rule-title">
        <b style="margin-right:20px">任务配置</b>
        <div class="icon-btn" v-if="dataList.length === 0" @click="createSet">
          <i class="el-icon-circle-plus-outline"></i>
          <span>&nbsp;新增</span>
        </div>
        <div class="icon-btn" v-if="dataList.length > 0" @click="cleanSet">
          <i class="el-icon-remove-outline"></i>
          <span>&nbsp;清空</span>
        </div>
      </div>
      <div v-for="(temp,index) in dataList" :key="index" style="margin-top:10px">
        <el-row :gutter="20">
          <el-col :span="4">
            <el-select
              v-model="temp.polygon_id"
              placeholder="请选择"
              @change="selectChange($event,'options1',temp)"
              size="small"
            >
              <el-option
                v-for="item in temp.options1"
                :key="item.id"
                :label="item.name"
                :value="item.value"
              ></el-option>
            </el-select>
          </el-col>
          <el-col :span="4">
            <el-select
              v-model="temp.sdk_id"
              placeholder="请选择"
              @change="selectChange($event,'options2',temp)"
              size="small"
            >
              <el-option
                v-for="item in temp.options2"
                :key="item.id"
                :label="item.name"
                :value="item.value"
              ></el-option>
            </el-select>
          </el-col>
          <el-col :span="4">
            <el-select
              v-model="temp.sdk_arg_alias"
              placeholder="请选择"
              @change="selectChange($event,'options3',temp)"
              size="small"
            >
              <el-option
                v-for="item in temp.options3"
                :key="item.id"
                :label="item.name"
                :value="item.value"
              ></el-option>
            </el-select>
          </el-col>
          <el-col :span="4">
            <el-select
              v-model="temp.operator"
              placeholder="请选择"
              @change="selectChange($event,'options4',temp)"
              size="small"
            >
              <el-option
                v-for="item in temp.options4"
                :key="item.id"
                :label="item.name"
                :value="item.value"
              ></el-option>
            </el-select>
          </el-col>
          <el-col :span="4">
            <div v-if="temp.operator === 'custom'">
              <el-input v-model="temp.operator_type" placeholder="请输入内容" size="small"></el-input>
            </div>
            <div v-if="temp.operator !== 'custom'">
              <el-select
                v-model="temp.operator_type"
                placeholder="请选择"
                @change="selectChange($event,'options5',temp)"
                size="small"
              >
                <el-option
                  v-for="item in temp.options5"
                  :key="item.id"
                  :label="item.name"
                  :disabled="item.disabled"
                  :value="item.value"
                ></el-option>
              </el-select>
            </div>
          </el-col>
          <el-col :span="4">
            <div class="rule-edit-btn">
              <i
                v-show="dataList.length > 1"
                class="el-icon-remove-outline"
                @click="delRule(index)"
                style="color:red;margin-right:10px"
              />
              <i
                v-show="index === dataList.length -1"
                class="el-icon-circle-plus-outline"
                @click="addRule()"
                style="color:#3D68E1"
              ></i>
            </div>
          </el-col>
        </el-row>
        <el-row></el-row>
      </div>
      <div class="rule-title2">
        <b>规则</b>
        <div class="div-border">{{eventData.eventTxt}}</div>
      </div>
      <div class="save-btn">
        <el-button type="info" size="small" @click="onCancle">取消</el-button>
        <el-button type="primary" @click="eventPushsSave" size="small">保存</el-button>
      </div>
    </div>
  </div>
</template>
<script>
import ipInput from "@/components/subComponents/IPInput";
import { eventPushsSave, findByEventTopic } from "@/api/event";
import { findDictionaryByType, findDictionaryByID } from "@/api/dictionary";
export default {
  name: "rightEvent",
  components: { ipInput },
  filters: {
    ipSplit(url) {
      return url.split(":")[0]
    },
    portSplit(url) {
      return url.split(":")[1]
    }
  },
  props: {
    eventObject: {
      type: Object,
      default: () => {
        return {};
      }
    }
  },
  computed: {
    urls() {
      return this.eventData.urls
    },
    ips() {
      return this.eventData.urls.filter(item => {
        return item.type === 'ip';
      })
    },
    domains() {
      return this.eventData.urls.filter(item => {
        return item.type === 'domain';
      })
    }
  },
  watch: {
    eventObject: {
      handler(newVal, oldVal) {
        this.eventData.enable = this.eventObject.enable;
        if (newVal !== oldVal) {
          // console.log(newVal, "当前选中的事件watch");
          if (this.eventData.id !== newVal.id) {
            this.dataList = [];
            // console.log(this.eventObject.enable)
            this.eventData.id = newVal.id;
            this.eventData.name = newVal.name;
            this.eventData.time = [
              this.eventObject.time_start,
              this.eventObject.time_end
            ];
            this.eventData.serverIp = newVal.ip_ports;
            this.eventData.urls = newVal.urls;
            this.eventData.lineWay = newVal.link_type;
            this.eventData.eventTxt = newVal.rule_text;
            this.eventData.radioValue = newVal.is_satisfy_all ? "1" : "2";
            // urls反解析
            let ipSum = 0, domainSum = 0;
            if (!this.eventData.urls) {
              this.$set(this.eventData, "urls", [])
            }
            for (let i = 0; i < this.eventData.urls.length; i++) {
              let item = this.eventData.urls[i]
              item.hash = Math.random().toString(36).substr(2);
              // 解析成ip或域名
              let addr = item.url.split(":")[0]
              if (this.isValidIP(addr)) {
                item.ip = addr
                this.$set(item, "domain", "")
                this.$set(item, "type", "ip")
                ipSum++
              } else {
                this.$set(item, "domain", addr)
                this.$set(item, "type", "domain")
                item.ip = ""
                domainSum++
              }
              // item.port =
              this.$set(item, "port", item.url.split(":")[1])
            }
            this.eventData.urls.sort(function (a, b) {
              var val1 = b.type;
              var val2 = a.type;
              if (val1 < val2) {
                return -1;
              } else if (val1 > val2) {
                return 1;
              } else {
                return 0;
              }
            })
            if (newVal.rules) {
              newVal.rules.map((i, index) => {
                this.dataList.push(JSON.parse(JSON.stringify(this.baseDateL)));
                this.dataList[index].id = i.id;
                this.dataList[index].event_push_id = i.event_push_id;
                this.dataList[index].polygon_id = i.topic_type;
                this.selectChange(i.topic_type, "options1", this.dataList[index]);
                this.dataList[index].sdk_id = i.topic_arg;
                this.selectChange(i.topic_arg, "options2", this.dataList[index]);
                this.dataList[index].operator_type = i.rule_value;
                this.dataList[index].sdk_arg_alias = i.operator;
                this.dataList[index].operator = i.operator_type;
              });
            }
          }
        }
      },
      deep: true
    }
  },
  data() {
    return {
      eventData: {
        enable: false,
        id: "",
        name: "",
        time: [
          this.$moment().format("YYYY-MM-DD 00:00:00"),
          this.$moment().format("YYYY-MM-DD HH:mm:ss")
        ],
        serverIp: [
          {
            enable: true,
            server_ip: "",
            port: 0
          }
        ],
        urls: [
          {
            enable: true,
            url: "http://"
          }
        ],
        lineWay: "",
        lineOptions: [
          {
            value: "001",
            label: "IP广播"
          }
        ],
        radioValue: "1",
        eventTxt: ""
      },
      dataList: [],
      baseDateL: {
        event_push_id: "",
        id: "",
        options1: [
          {
            id: "all",
            name: "全部区域"
          },
          {
            id: "002",
            name: "矩形1"
          }
        ],
        polygon_id: "",
        options2: [
          {
            value: "001",
            label: "全部算法"
          },
          {
            value: "002",
            label: "算法1"
          },
          {
            value: "003",
            label: "算法2"
          }
        ],
        sdk_id: "",
        options3: [
          {
            value: "001",
            label: "人数"
          },
          {
            value: "002",
            label: "敏感度"
          },
          {
            value: "003",
            label: "持续时间"
          }
        ],
        sdk_arg_alias: "",
        unit: "",
        options4: [
          {
            value: "001",
            label: ">"
          },
          {
            value: "002",
            label: "<"
          },
          {
            value: "003",
            label: "=="
          }
        ],
        operator: "",
        options5: [
          {
            value: "001",
            label: "值"
          },
          {
            value: "002",
            label: "备选项"
          }
        ],
        operator_type: "",
        options6: [
          {
            value: "001",
            label: "值"
          },
          {
            value: "002",
            label: "备选项"
          }
        ],
        select_time_rule: "",
        sdk_arg_value: "",
        options7: [
          {
            value: "001",
            label: "任务1"
          },
          {
            value: "002",
            label: "任务2"
          }
        ],
        select_task: ""
      }
    };
  },
  methods: {
    addServer() {
      // console.log("addServer");
      let obj = {
        enable: true,
        server_ip: "",
        port: ""
      };
      this.eventData.serverIp.push(obj);
    },
    addUrl(type) {
      let obj = {
        checked: true,
        hash: Math.random().toString(36).substr(2),
        url: "",
        ip: "",
        port: "",
        type: type,
        domain: ""
      };
      this.eventData.urls.push(obj);
      this.eventData.urls.sort(function (a, b) {
        var val1 = b.type;
        var val2 = a.type;
        if (val1 < val2) {
          return -1;
        } else if (val1 > val2) {
          return 1;
        } else {
          return 0;
        }
      })
    },
    delUrl(index) {
      this.$set(this.eventData.urls, index, this.baseDateL)
      this.eventData.urls.splice(index, 1)
    },
    // 保存
    async eventPushsSave() {
      // 判断保存的ip是否符合格式要求
      if (this.eventData.urls.length < 1) {
        this.$notify({
          type: "warning",
          message: "请配置至少一台推送服务器"
        });
        return;
      }
      let isValid = true;
      for (let i = 0; i < this.eventData.urls.length; i++) {
        let item = this.eventData.urls[i]
        if (item.type == 'ip') {
          if (this.isValidIP(item.ip) && this.isValidPort(item.port)) {
            item.url = item.ip + ":" + item.port
          } else {
            isValid = false
          }
        } else {
          if (item.domain.length > 0 && this.isValidPort(item.port)) {
            item.url = item.domain + ":" + item.port
          } else {
            isValid = false
          }
        }
      }
      if (!isValid) {
        this.$notify({
          type: "warning",
          message: "请输入正确格式的服务器地址 和 端口"
        });
        return;
      }
      // 拼接字符串
      let ruleDesc = []
      this.dataList.map(i => {
        let str = "";
        if (i.polygon_id) {
          str += this.getNameByValue(i.options1, i.polygon_id);
        }
        if (i.sdk_id && i.sdk_id !== 'empty') {
          str += this.getNameByValue(i.options2, i.sdk_id);
        }
        if (i.sdk_arg_alias === '==') {
          str += '=';
        } else {
          // str += i.sdk_arg_alias;
          str += this.getNameByValue(i.options3, i.sdk_arg_alias);
        }
        if (i.operator_type) {
          if (i.operator === "custom") {
            str += i.operator_type;
          } else {
            str += this.getNameByValue(i.options5, i.operator_type);
          }
        }
        if (str.length > 0) {
          ruleDesc.push(str)
        }
      });
      // 处理规则列表数据结构
      let list = this.dataList.map(i => {
        let obj = {};
        obj.operator = i.sdk_arg_alias;
        obj.rule_value = i.operator_type;
        obj.operator_type = i.operator;
        obj.topic_type = i.polygon_id;
        obj.topic_arg = i.sdk_id;
        return obj;
      });
      // console.log(this.eventData)
      let json = {
        enable: this.eventData.enable,
        id: this.eventData.id,
        ip_ports: this.eventData.serverIp,
        name: this.eventData.name,
        rule_text: ruleDesc.join(","),
        rules: list,
        time_start: this.eventData.time[0],
        time_end: this.eventData.time[1],
        urls: this.eventData.urls,
        is_satisfy_all: this.eventData.radioValue === "1",
        link_type: this.eventData.lineWay
      };
      let res = await eventPushsSave(json);
      if (res && res.success) {
        this.eventData.eventTxt = ruleDesc.join(",");
        this.$emit("updateList", res.data.id);
        this.$notify({
          type: "success",
          message: "保存成功"
        });
      }
    },
    // 查找字典
    async findByType() {
      let res = await findDictionaryByType();
      if (res && res.success) {
        // console.log(res, "查询配置区域数据源");
        this.baseDateL.options1 = res.data.EVENTRULETOPIC;
        this.baseDateL.options3 = res.data.RULECOMPUTE;
        this.baseDateL.options4 = res.data.EVENTTYPECOMPUTE;
      }
    },
    // 验证ip的js方法
    isValidIP(str) {
      // let reg = /^(http:\/\/|https:\/\/)(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\:([0-9]|[1-9]\d{1,3}|[1-5]\d{4}|6[0-5]{2}[0-3][0-5])(\/)([a-zA-Z0-9_/]+)$/
      /* eslint-disable */
      let reg = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
      return reg.test(str);
    },
    isValidPort(str) {
      return parseInt(str) > 0 && parseInt(str) < 65536
    },
    // 新建配置
    createSet() {
      this.dataList.push(JSON.parse(JSON.stringify(this.baseDateL)));
    },
    cleanSet() {
      this.dataList.splice(0, this.dataList.length);
    },
    // 添加子规则
    addRule() {
      this.dataList.push(JSON.parse(JSON.stringify(this.baseDateL)));
    },
    // 删除子规则
    delRule(index) {
      this.dataList.splice(index, 1);
    },
    // 规则中下拉框的选择回调
    async selectChange(value, type, data) {
      if (type === "options1") {
        this.$set(data, "sdk_id", "");
        if (value === "dbtable" || value === "task" || value === "alarmLevel") {
          let list = [
            {
              name: "空",
              value: "empty",
              id: "000"
            }
          ];
          this.$set(data, "options2", list);
          this.$set(data, "sdk_id", "empty");
          let json = {
            topic: data.polygon_id,
            type: ""
          };
          let res = await findByEventTopic(json);
          if (res && res.success) {
            console.log(res, "根据一二级选项获取");
            this.$set(data, "options5", res.data);
          }
        } else {
          let id = this.getIdByValue(data.options1, value);
          if (id !== undefined) {
            this.findByParentId(id).then(i => {
              // console.log(i, '根据父id查询子参数')
              if (i && i.length !== 0) {
                this.$set(data, "options2", i);
              }
            });
          }
        }
      }
      if (type === "options2") {
        if (data.polygon_id && data.sdk_id) {
          let json = {
            topic: data.polygon_id,
            type: data.sdk_id
          };
          let res = await findByEventTopic(json);
          if (res && res.success) {
            // console.log(res, "根据一二级选项获取");
            this.$set(data, "options5", res.data);
          }
        }
      }
      if (type === "options3") {
        return false;
      }
      if (type === "options4") {
        return false;
      }
      if (type === "options5") {
        return false;
      }
    },
    // 根据value返回对应的id
    getIdByValue(arr, id) {
      let s = arr.find(item => {
        return item.value === id;
      });
      // console.log(s, 'label')
      return s.id;
    },
    // 根据value返回对应的name
    getNameByValue(arr, value) {
      let s = arr.find(item => {
        return item.value === value;
      });
      return s.name;
    },
    // 根据字典的id查询对应的字典
    async findByParentId(id) {
      let res = await findDictionaryByID({ parentId: id });
      if (res && res.success) {
        // console.log(res, "根据字典的id查询对应的字典");
        let list = JSON.parse(JSON.stringify(res.data));
        return list;
      }
    },
    // 清空重新新增
    reAdd() {
      this.eventData = {
        id: "",
        name: "",
        time: [
          this.$moment().format("YYYY-MM-DD 00:00:00"),
          this.$moment().format("YYYY-MM-DD HH:mm:ss")
        ],
        serverIp: [
          {
            enable: true,
            server_ip: "",
            port: 0
          }
        ],
        urls: [
        ],
        lineWay: "",
        lineOptions: [
          {
            value: "001",
            label: "IP广播"
          }
        ],
        radioValue: "1",
        eventTxt: ""
      };
      this.dataList = [];
    },
    onIpBlur(ip, item) {
      item.ip = ip
    },
    onCancle(){
      this.$emit('onCancle')
    }
  },
  mounted() {
    this.findByType().then(() => {
      if (Object.keys(this.eventObject).length !== 0) {
        // console.log(this.eventObject, "当前选中的事件mounted");
        this.eventData.enable = this.eventObject.enable;
        this.eventData.id = this.eventObject.id;
        this.eventData.name = this.eventObject.name;
        this.eventData.time = [
          this.eventObject.time_start,
          this.eventObject.time_end
        ];
        this.eventData.serverIp = this.eventObject.ip_ports;
        this.eventData.urls = this.eventObject.urls;
        this.eventData.lineWay = this.eventObject.link_type;
        this.eventData.eventTxt = this.eventObject.rule_text;
        this.eventData.radioValue = this.eventObject.is_satisfy_all ? "1" : "2";
        if (this.eventObject.rules) {
          this.eventObject.rules.map((i, index) => {
            this.dataList.push(JSON.parse(JSON.stringify(this.baseDateL)));
            this.dataList[index].id = i.id;
            this.dataList[index].event_push_id = i.event_push_id;
            this.dataList[index].polygon_id = i.topic_type;
            this.selectChange(i.topic_type, "options1", this.dataList[index]);
            this.dataList[index].sdk_id = i.topic_arg;
            this.selectChange(i.topic_arg, "options2", this.dataList[index]);
            this.dataList[index].sdk_arg_alias = i.operator;
            this.dataList[index].operator = i.operator_type;
            this.dataList[index].operator_type = i.rule_value;
          });
        }
      }
    });
  }
};
</script>
<style lang="scss">
.s-event-push-right {
  text-align: left;
  font-size: 14px;
  i {
    cursor: pointer;
  }
  .s-right-config {
    padding: 10px 40px;
  }
  .el-form-item__label {
    text-align: left;
  }
  .s-right-mid {
    height: 10px;
    background-color: #e9ebf2;
    width: 100%;
    position: absolute;
  }
  .s-right-rule {
    padding: 20px 40px;
    margin-top: 17px;
    .rule-title {
      border-bottom: 1px solid #e0e0e0;
    }
    .rule-title2 {
      margin-top: 20px;
    }
    .div-border {
      width: 995px;
      padding: 10px;
      margin-top: 15px;
      min-height: 80px;
      background: #fafafa;
      border: 1px solid #f2f2f2;
    }
    .rule-edit-btn {
      font-size: 18px;
      line-height: 38px;
    }
    .save-btn {
      // float: right;
      margin-top: 20px;
      margin-left: 895px;
    }
  }
  .el-button--text {
    text-decoration: unset;
  }
  .icon-btn {
    i {
      font-size: 18px;
      position: relative;
      top: 2px;
    }
    span {
      font-size: 14px;
    }
    display: inline;
    color: #3d68e1;
    line-height: 38px;
    margin-left: 10px;
    cursor: pointer;
  }
  .server-url {
    padding-top: 25px;
  }
  .server-add {
    font-size: 18px;
    margin-left: 8px;
    color: #3d68e1;
    line-height: 39px;
  }
}
</style>
src/pages/datapush/index/main.ts
New file
@@ -0,0 +1,25 @@
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import "@/assets/css/element-variables.scss";
import "../../../assets/icons/alibaba/iconfont.css";
import "../../../assets/icons/basic/iconfont.css";
import "../../../assets/icons/iconfont.css";
import "../../../assets/icons/symbol.js";
import App from './App.vue'
import moment from "moment";
Vue.prototype.$moment = moment;
Vue.use(ElementUI)
Vue.filter('moment', function (value, formatString) {
  formatString = formatString || 'YYYY-MM-DD HH:mm:ss';
  return moment(value).format(formatString);
});
new Vue({
  el: '#app',
  render: h => h(App)
})
src/pages/desktop/index/App.vue
@@ -11,8 +11,6 @@
<script>
import Desktop from './components/Desktop';
import Dock from './components/Dock';
import Preference from './components/Preference';
import NotificationCenter from './components/NotificationCenter';
import NoticeTip from './components/NoticeTip';
import Tools from './components/Tools';
@@ -22,7 +20,7 @@
export default {
  name: 'app',
  components: {
    Desktop, Dock, Preference, NotificationCenter, NoticeTip, Tools, ToolsEntry
    Desktop, NotificationCenter, NoticeTip, Tools, ToolsEntry
  },
  mounted() {
    document.getElementById('app').style.backgroundImage = process.env.VUE_APP_MAIN_URL;
@@ -118,8 +116,8 @@
  background-attachment: fixed;
}
.clearFix:after{
  content: '';
.clearFix:after {
  content: "";
  display: block;
  height: 0;
  clear: both;
src/pages/desktop/index/components/Tools.vue
@@ -1,67 +1,56 @@
<template>
  <div class="tools">
      <div class="tools-left">
        <div
          :class="['tools-icon','tools-show-desktop', {clicked:this.$store.state.desktop.preferenceVisiable}]"
          @click="togglePreference()"
        >
          <img class="system" :src="`${publicPath}images/header-icon/system.png`" />
          <!-- <span class="fa fa-apple"></span> -->
        </div>
        <div class="tools-icon" >
          <!-- <span class="fa fa-safari"></span> -->
          <img class="smart-ai" :src="`${publicPath}images/header-icon/SmartAI.png`" alt />
        </div>
    <div class="tools-left">
      <div
        :class="['tools-icon','tools-show-desktop', {clicked:this.$store.state.desktop.preferenceVisiable}]"
        @click="togglePreference()"
      >
        <img class="system" :src="`${publicPath}images/header-icon/system.png`" />
        <!-- <span class="fa fa-apple"></span> -->
      </div>
      <div class="tools-middle">
        <div
          v-for="dock in this.$store.state.desktop.minDocks"
          :key="dock.id"
          class="dock-item-wrap"
        >
          <a @click="dockClick(dock)">
            <img class="dock-item" :src="dock.src" :alt="dock.alt" />
          </a>
        </div>
      <div class="tools-icon">
        <!-- <span class="fa fa-safari"></span> -->
        <img class="smart-ai" :src="`${publicPath}images/header-icon/SmartAI.png`" alt />
      </div>
      <div class="tools-right">
        <div class="tools-icon">
          <!-- <span class="fa fa-battery-full"></span> -->
          <img :src="`${publicPath}images/header-icon/search.png`" alt />
        </div>
        <div class="tools-icon">
          <!-- <span class="fa fa-battery-full"></span> -->
          <img :src="`${publicPath}images/header-icon/help.png`" alt />
        </div>
        <div class="tools-icon" @click="notificationCenterClick()">
          <!-- <span class="fa fa-battery-full"></span> -->
          <img :src="`${publicPath}images/header-icon/notice.png`" alt />
        </div>
        <div class="tools-icon">
          <!-- <span class="fa fa-battery-full"></span> -->
          <img :src="`${publicPath}images/header-icon/user.png`" alt />
        </div>
        <!-- <timer></timer> -->
        <!-- <div class="tools-icon tools-notification-center" @click="notificationCenterClick()">
    </div>
    <div class="tools-middle">
      <div v-for="dock in this.$store.state.desktop.minDocks" :key="dock.id" class="dock-item-wrap">
        <a @click="dockClick(dock)">
          <img class="dock-item" :src="dock.src" :alt="dock.alt" />
        </a>
      </div>
    </div>
    <div class="tools-right">
      <div class="tools-icon">
        <!-- <span class="fa fa-battery-full"></span> -->
        <img :src="`${publicPath}images/header-icon/search.png`" alt />
      </div>
      <div class="tools-icon">
        <!-- <span class="fa fa-battery-full"></span> -->
        <img :src="`${publicPath}images/header-icon/help.png`" alt />
      </div>
      <div class="tools-icon" @click="notificationCenterClick()">
        <!-- <span class="fa fa-battery-full"></span> -->
        <img :src="`${publicPath}images/header-icon/notice.png`" alt />
      </div>
      <div class="tools-icon">
        <!-- <span class="fa fa-battery-full"></span> -->
        <img :src="`${publicPath}images/header-icon/user.png`" alt />
      </div>
      <!-- <timer></timer> -->
      <!-- <div class="tools-icon tools-notification-center" @click="notificationCenterClick()">
          <span
            :class="['fa', {'fa-list-ul':notificationCenterNoMessage()}, {'fa-comment-o on-new-msg':!notificationCenterNoMessage()},{'fa-commenting-o':notificationCenterMessageFlicker()}]"
          ></span>
        </div> -->
      </div>
      </div>-->
    </div>
  </div>
</template>
<script>
import Timer from "./Timer";
export default {
  name: "Tools",
  components: {
    Timer
  },
  data() {
    return {
      publicPath: process.env.BASE_URL,
@@ -75,23 +64,23 @@
      window.toolIntervalArr.forEach(item => clearInterval(item));
    }
    window.toolIntervalArr = [
      setInterval(function() {
      setInterval(function () {
        _that.notificationCenterMessageCount += 1;
      }, 600)
    ];
  },
  methods: {
    notificationCenterClick: function() {
    notificationCenterClick: function () {
      this.notificationCenterVisible = !this.notificationCenterVisible;
      this.$store.commit(
        "desktop/changeNotificationCenterVisible",
        this.notificationCenterVisible
      );
    },
    notificationCenterNoMessage: function() {
    notificationCenterNoMessage: function () {
      return this.$store.state.desktop.messageNotices.length === 0;
    },
    notificationCenterMessageFlicker: function() {
    notificationCenterMessageFlicker: function () {
      return (
        this.notificationCenterMessageCount % 2 === 0 &&
        !this.notificationCenterNoMessage()
@@ -102,7 +91,7 @@
      //this.$store.commit("desktop/togglePreference");
      //显示桌面,最小化已打开的应用
      debugger;
      this.$store.state.desktop.frames.forEach(frame=>{
      this.$store.state.desktop.frames.forEach(frame => {
        this.$store.commit('desktop/addMinDock', {
          id: frame.id,
          src: frame.icon,
@@ -152,14 +141,14 @@
  float: left;
  margin-left: 14px;
}
.tools .tools-middle{
.tools .tools-middle {
  float: left;
  position: relative;
}
.tools .tools-middle::before{
.tools .tools-middle::before {
  width: 1px;
  height: 20px;
  content: '';
  content: "";
  position: absolute;
  top: 10px;
  left: 0;
@@ -174,10 +163,10 @@
  border-bottom: 2px solid transparent;
}
.tools .tools-middle .dock-item-wrap:hover,
.tools .tools-middle .dock-item-wrap.clicked{
.tools .tools-middle .dock-item-wrap.clicked {
  color: white;
  background-color: #98aabe;
  border-color: #40C3FF;
  border-color: #40c3ff;
  cursor: pointer;
}
.dock-item-wrap a {
src/pages/desktop/index/mock/userData.json
@@ -120,7 +120,7 @@
        "src": "../../images/app-mid/log-manage.png",
        "alt": "日志管理",
        "type": "2",
        "url": "/view/logManage",
        "url": "/view/syslog",
        "name": "日志管理"
      },
      {
src/pages/settings/components/BasicSetting.vue
@@ -18,7 +18,6 @@
          class="menu-css"
          @open="menuOpen"
          @close="menuClose"
        >
          <!-- 本机信息 -->
          <el-submenu index="0">
@@ -160,7 +159,7 @@
            </el-menu-item-group>
          </el-submenu>
          <!-- 对外服务IP 改名为外部网络(新tab)-->
          <!-- 文件音视频 -->
          <!-- <el-submenu index="4">
            <template slot="title">
@@ -362,157 +361,30 @@
        </div>
        <div class="flex-box">
          <label>域名</label>
          <el-input size="small"  v-model="ipServer.localhost"></el-input>
          <el-input size="small" v-model="ipServer.localhost"></el-input>
        </div>
        <div class="flex-box">
          <label>本地文件端口</label>
          <el-input size="small"  v-model="ipServer.localFilePort"></el-input>
          <el-input size="small" v-model="ipServer.localFilePort"></el-input>
        </div>
        <div class="mt15 save-btn" style="width:460px; margin-bottom:20px; float:left;">
          <el-button type="primary" @click="submitResource" size="small">保存</el-button>
        </div>
        <div>
              <el-table
                :data="ipServer.fileTable"
                border
                fit
                style="width: 100%">
                <el-table-column
                  type="index"
                  label="序号"
                  align="center"
                  width="50">
                </el-table-column>
                <el-table-column
                  prop="date"
                  label="名称"
                  align="center"
                  >
                </el-table-column>
                <el-table-column
                  prop="name"
                  label="ID"
                  align="center"
                  >
                </el-table-column>
                <el-table-column
                  prop="name"
                  label="IP"
                  align="center"
                  >
                </el-table-column>
                <el-table-column
                  prop="name"
                  label="在线状态"
                  align="center"
                  >
                </el-table-column>
              </el-table>
            </div>
          <el-table :data="ipServer.fileTable" border fit style="width: 100%">
            <el-table-column type="index" label="序号" align="center" width="50"></el-table-column>
            <el-table-column prop="date" label="名称" align="center"></el-table-column>
            <el-table-column prop="name" label="ID" align="center"></el-table-column>
            <el-table-column prop="name" label="IP" align="center"></el-table-column>
            <el-table-column prop="name" label="在线状态" align="center"></el-table-column>
          </el-table>
        </div>
      </el-tab-pane>
      <el-tab-pane label="权限管理" name="user" >
      <el-tab-pane label="权限管理" name="user">
        <authority-management v-if="activeName === 'user'"></authority-management>
      </el-tab-pane>
      <el-tab-pane label="广播设置" name="radio" >
      <el-tab-pane label="广播设置" name="radio">
        <radio-set v-if="activeName === 'radio'"></radio-set>
      </el-tab-pane>
      <!-- GB28181设置 -->
      <el-tab-pane label="GB28181设置" name="fifth">
        <el-form
          :model="gb28181"
          :rules="rules"
          label-width="140px"
          class="alarmSetting"
          ref="gb28181"
        >
          <!-- <el-form-item label="国际服务器IP" prop="ServerIp">
            <ip-input :ip="gb28181.ServerIp" @on-blur="gb28181.ServerIp = arguments[0]"></ip-input>
          </el-form-item>-->
          <div style="text-align: left;margin-bottom: 22px;">
            <el-radio-group v-model="gb28181.idType">
              <el-radio :label="0">输入已有ID</el-radio>
              <el-radio :label="1">生成新的ID</el-radio>
            </el-radio-group>
          </div>
          <el-form-item label="所在地">
            <el-select
              v-model="locationCity.province"
              @change="changeProvince"
              size="small"
              placeholder="请选择省份"
            >
              <el-option
                v-for="item in locationCity.provinceOptions"
                :key="item.id"
                :label="item.name"
                size="small"
                :value="item.id"
              ></el-option>
            </el-select>
            <el-select
              class="ml10 mr10"
              v-model="locationCity.city"
              :disabled="!locationCity.province"
              @change="changeCity"
              size="small"
              placeholder="请选择城市"
            >
              <el-option
                v-for="item in locationCity.cityOptions"
                :key="item.id"
                :label="item.name"
                :value="item.id"
              ></el-option>
            </el-select>
            <el-select
              v-model="locationCity.county"
              :disabled="!locationCity.city"
              size="small"
              placeholder="请选择区县"
            >
              <el-option
                v-for="item in locationCity.countyOptions"
                :key="item.id"
                :label="item.name"
                :value="item.id"
              ></el-option>
            </el-select>
            <el-button
              type="text"
              style="position: absolute"
              v-show="gb28181.idType === 1"
              @click="newGBID"
            >生成ID</el-button>
          </el-form-item>
          <!-- <el-form-item label="国际服务器端口" prop="GbServerPort">
            <el-input v-model.number="gb28181.ServerPort" placeholder="请输入" size="small"></el-input>
          </el-form-item>-->
          <el-form-item label="国标ID">
            <el-input v-model="gb28181.PublicId" placeholder="请输入" size="small"></el-input>
          </el-form-item>
          <el-form-item label="国标端口" prop="ServerPort">
            <el-input v-model.number="gb28181.GbServerPort" placeholder="请输入" size="small"></el-input>
          </el-form-item>
          <el-form-item label="开启鉴权">
            <el-switch v-model="gb28181.IsAuth"></el-switch>
          </el-form-item>
          <el-form-item label="鉴权密码" v-show="gb28181.IsAuth">
            <el-input v-model="gb28181.Password" placeholder="请输入" size="small"></el-input>
          </el-form-item>
          <el-col :span="12">
            <el-form-item>
              <el-button type="primary" @click="submitGB28281" size="small">保存</el-button>
            </el-form-item>
          </el-col>
        </el-form>
      </el-tab-pane>
    </el-tabs>
  </div>
@@ -522,17 +394,13 @@
import {
  getDevInfo,
  getAlarmConfig,
  getGB28181Config,
  saveDevInfo,
  saveAlarmConfig,
  saveGB28181Config,
  getClockInfo,
  saveClockInfo,
  testNTPserver,
  getResourceConfig,
  saveResourceConfig,
  getGb28181AreaList,
  newGb28181ID
} from "@/api/system";
import { isPort, isIPv4 } from "@/scripts/validate";
@@ -588,7 +456,6 @@
      timestamp: 0,
      sysinfo: {},
      alarmConf: {},
      gb28181: {},
      originNetConfig: {
        ip: "",
        gw: "",
@@ -702,7 +569,6 @@
      this.initSysinfo();
      // this.initAlarmConf();
      this.initResourceConfig();
      this.initGB28181Conf();
      this.initClockConf();
    });
  },
@@ -773,19 +639,6 @@
          this.ipServer.ip = rsp.data.serviceIp
          this.ipServer.localhost = rsp.data.domain
          this.ipServer.localFilePort = rsp.data.filePort
        }
      })
    },
    initGB28181Conf() {
      getGB28181Config().then(rsp => {
        if (rsp && rsp.success) {
          this.gb28181 = rsp.data;
          this.gb28181.idType = 0;
        }
      });
      getGb28181AreaList().then(rsp => {
        if (rsp && rsp.success) {
          this.locationCity.provinceOptions = rsp.data;
        }
      })
    },
@@ -969,23 +822,6 @@
        }
      })
    },
    submitGB28281() {
      this.$refs["gb28181"].validate(valid => {
        if (valid) {
          saveGB28181Config(this.gb28181).then(rsp => {
            if (rsp && rsp.success) {
              this.$notify({
                type: "success",
                message: "GB28181设置保存成功"
              });
            }
          });
        } else {
          console.log("error submit!!");
          return false;
        }
      });
    },
    onIpBlur(e, ip) {
      console.log(e, ip);
    },
@@ -1040,33 +876,6 @@
      let re = /^(?=^.{3,255}$)(http(s)?:\/\/)?(www\.)?[a-zA-Z0-9][-a-zA-Z0-9]{0,62}(\.[a-zA-Z0-9][-a-zA-Z0-9]{0,62})+(:\d+)*(\/\w+\.\w+)*$/
      return re.test(str)
    },
    changeProvince() {
      let pid = this.locationCity.province;
      getGb28181AreaList({ parentId: pid }).then(rsp => {
        if (rsp && rsp.success) {
          this.locationCity.cityOptions = rsp.data;
          this.locationCity.city = this.locationCity.cityOptions[0].id;
          this.changeCity();
        }
      })
    },
    changeCity() {
      let pid = this.locationCity.city;
      getGb28181AreaList({ parentId: pid }).then(rsp => {
        if (rsp && rsp.success) {
          this.locationCity.countyOptions = rsp.data;
          this.locationCity.county = this.locationCity.countyOptions[0].id;
        }
      })
    },
    newGBID() {
      let cCode = this.locationCity.county + "";
      newGb28181ID({ code: cCode }).then(rsp => {
        if (rsp && rsp.success) {
          this.gb28181.PublicId = rsp.data;
        }
      })
    }
  }
};
</script>
@@ -1076,7 +885,7 @@
  height: 100%;
  .el-form {
    width: 1000px;
    // margin-left: -80px;
    .el-form-item {
      text-align: left;
@@ -1136,7 +945,6 @@
    font-weight: 600;
    background-color: #e4e6ed;
  }
  #cut_min_duration {
    .el-slider__bar {
@@ -1218,13 +1026,13 @@
}
</style>
<style lang="scss" scoped>
.flex-box{
.flex-box {
  display: flex;
  height: 50px;
  label{
  label {
    width: 120px;
  }
  .el-input{
  }
  .el-input {
    width: 300px;
  }
}
@@ -1236,7 +1044,7 @@
  margin: 0;
  padding-left: 0;
  background-color: #ffffff;
  .tree-font {
    font-family: PingFangSC-Medium;
    font-size: 14px;
src/pages/syslog/index/App.vue
New file
@@ -0,0 +1,190 @@
<template>
  <div class="s-log-management">
    <div class="top">
      <b>日志类型:</b>
      <el-select v-model="logValue" placeholder="请选择" size="small">
        <el-option
          v-for="item in logOptions"
          :key="item.value"
          :label="item.label"
          :value="item.value"
        ></el-option>
      </el-select>
      <b>时间:</b>
      <el-date-picker
        v-model="timeValue"
        type="datetimerange"
        size="small"
        range-separator="至"
        start-placeholder="开始日期"
        end-placeholder="结束日期"
      ></el-date-picker>
      <el-input
        v-model="searchValue"
        placeholder="请输入内容"
        clearable
        style="width: 150px;margin: 0px 10px;"
        size="small"
      ></el-input>
      <el-button type="primary" size="small">搜索</el-button>
      <el-button type="danger" size="small" @click="delSelected">批量删除</el-button>
      <el-button type="text" size="small" style="font-size: 13px;font-weight: 600;">导出</el-button>
    </div>
    <div class="foot-table s-table">
      <el-table
        ref="multipleTable"
        highlight-current-row
        :data="tableData"
        style="width: 100%"
        :header-cell-style="{background:'#f8f8f8',color:'#222222'}"
        @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" width="55"></el-table-column>
        <el-table-column :align="'center'" sortable prop="index" label="序号"></el-table-column>
        <el-table-column :align="'center'" sortable prop="logtype" label="日志类型"></el-table-column>
        <el-table-column :align="'center'" sortable prop="username" label="用户名"></el-table-column>
        <el-table-column :align="'center'" sortable prop="ipaddress" label="IP地址"></el-table-column>
        <el-table-column :align="'center'" sortable prop="operation" label="操作功能"></el-table-column>
        <el-table-column :align="'center'" sortable prop="operatetime" label="操作时间"></el-table-column>
        <el-table-column :align="'center'" sortable prop="operateinfo" label="操作信息"></el-table-column>
        <el-table-column label="操作" :align="'center'">
          <template slot-scope="scope">
            <el-button
              type="text"
              style="color: red;font-size:16px"
              @click="handleDelete(scope.$index, scope.row)"
              icon="el-icon-delete"
            ></el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
  </div>
</template>
<script>
export default {
  data() {
    return {
      tableData: [
        {
          index: "1",
          logtype: "异常",
          username: "admin",
          ipaddress: "192.168.10.110",
          operation: "添加摄像机",
          operatetime: "2019-5-31 16:38:21",
          operateinfo: "添加操作"
        },
        {
          index: "2",
          logtype: "信息",
          username: "admin",
          ipaddress: "192.168.10.108",
          operation: "删除摄像机",
          operatetime: "2019-5-31 16:38:21",
          operateinfo: "添加操作"
        },
        {
          index: "3",
          logtype: "操作",
          username: "admin",
          ipaddress: "192.168.10.110",
          operation: "添加摄像机",
          operatetime: "2019-5-31 16:38:21",
          operateinfo: "添加操作"
        },
        {
          index: "4",
          logtype: "异常",
          username: "admin",
          ipaddress: "192.168.10.110",
          operation: "添加摄像机",
          operatetime: "2019-5-31 16:38:21",
          operateinfo: "添加操作"
        },
        {
          index: "5",
          logtype: "异常",
          username: "admin",
          ipaddress: "192.168.10.110",
          operation: "删除摄像机",
          operatetime: "2019-5-31 16:38:21",
          operateinfo: "添加操作"
        },
        {
          index: "6",
          logtype: "异常",
          username: "admin",
          ipaddress: "192.168.10.110",
          operation: "添加摄像机",
          operatetime: "2019-5-31 16:38:21",
          operateinfo: "添加操作"
        }
      ],
      multipleSelection: [],
      logOptions: [
        {
          value: "全部类型",
          label: "全部类型"
        },
        {
          value: "其他类型",
          label: "其他类型"
        }
      ],
      logValue: "全部类型",
      timeValue: [
        new Date(2000, 10, 10, 10, 10),
        new Date(2000, 10, 11, 10, 10)
      ],
      searchValue: ""
    };
  },
  methods: {
    handleDelete(index, row) {
      console.log(index, row);
    },
    handleSelectionChange(val) {
      this.multipleSelection = val;
    },
    delSelected() {
      console.log(this.multipleSelection);
    }
  }
};
</script>
<style lang="scss">
.s-log-management {
  height: 100%;
  width: 100%;
  .top {
    width: 100%;
    margin-top: 10px;
    margin-bottom: 20px;
    overflow-y: auto;
    min-width: 1156px;
    height: 40px;
    text-align: left;
    b {
      padding: 0px 10px;
    }
  }
  .export {
    display: inline-block;
    padding-right: 10px;
    box-sizing: border-box;
    margin-top: 20px;
    b:hover {
      color: #2249b4;
    }
  }
  .clear-searching {
    cursor: pointer;
    text-decoration: underline;
    width: 40px;
    font-size: 13px;
    color: #3d68e1;
  }
}
</style>
src/pages/syslog/index/main.ts
New file
@@ -0,0 +1,11 @@
import Vue from 'vue'
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'
import App from './App.vue'
Vue.use(ElementUI)
new Vue({
  el: '#app',
  render: h => h(App)
})
src/pages/vindicate/index/App.vue
@@ -1,12 +1,12 @@
<template>
    <el-tabs
      id="systemMaintenance"
      v-model="activeName"
      v-loading="loading"
      :element-loading-text="loadingText"
    >
      <el-tab-pane label="设备维护" name="first" >
        <div class="s-system-maintenance">
  <el-tabs
    id="systemMaintenance"
    v-model="activeName"
    v-loading="loading"
    :element-loading-text="loadingText"
  >
    <el-tab-pane label="设备维护" name="first">
      <div class="s-system-maintenance">
        <div class="box-card">
          <div class="ui-top-view">
            <div class="ui-top-title">重启</div>
@@ -14,14 +14,10 @@
          <el-divider></el-divider>
          <div class="box-card-content">
                <el-button type="primary" size="small" style="width:80px" @click="reboot">重启</el-button>
                <b class="card-text">重启节点</b>
            <el-button type="primary" size="small" style="width:80px" @click="reboot">重启</el-button>
            <b class="card-text">重启节点</b>
            <el-row style="margin-top:20px">
              <el-col>
                <vue-cron :expression="rebootCron" @update="setRebootCron" />
@@ -124,43 +120,42 @@
          </el-row>
        </div>
      </div>
      </el-tab-pane>
      <el-tab-pane label="数据库维护" name="second" >
        <div class="box">
          <p class="title">
            <label>数据清理</label>
          </p>
          <div class="range">
            <div class="left">
              <p>选择数据范围:</p>
            </div>
            <div class="middle">
              <el-date-picker
                v-model="dataRange"
                type="daterange"
                range-separator="至"
                start-placeholder="开始日期"
                end-placeholder="结束日期"
                style="height:38px"
                :picker-options="pickerOptions"
              ></el-date-picker>
            </div>
            <div class="right">
              <el-button @click="deleteData" style="height:38px;background:#ff0000;color:white">删除数据</el-button>
            </div>
          </div>
          <div class="tip">
            <i class="iconfont icontishi-zhuyi"></i>
            <p class="zhuyi">请注意,按以上日期范围删除的数据不可恢复,立即生效,请谨慎操作</p>
          </div>
        </div>
      </el-tab-pane>
    </el-tabs>
    </el-tab-pane>
    <el-tab-pane label="数据库维护" name="second">
      <div class="box">
        <p class="title">
          <label>数据清理</label>
        </p>
        <div class="range">
          <div class="left">
            <p>选择数据范围:</p>
          </div>
          <div class="middle">
            <el-date-picker
              v-model="dataRange"
              type="daterange"
              range-separator="至"
              start-placeholder="开始日期"
              end-placeholder="结束日期"
              style="height:38px"
              :picker-options="pickerOptions"
            ></el-date-picker>
          </div>
          <div class="right">
            <el-button @click="deleteData" style="height:38px;background:#ff0000;color:white">删除数据</el-button>
          </div>
        </div>
        <div class="tip">
          <i class="iconfont icontishi-zhuyi"></i>
          <p class="zhuyi">请注意,按以上日期范围删除的数据不可恢复,立即生效,请谨慎操作</p>
        </div>
      </div>
    </el-tab-pane>
  </el-tabs>
</template>
<script>
import { rebootServer, getDevInfo, getRebootTask, setRebootTask, fileUpload, doUpgrade,deleteDate } from "@/api/system"
import { rebootServer, getDevInfo, getRebootTask, setRebootTask, fileUpload, doUpgrade, deleteDate } from "@/api/system"
import VueCron from "@/components/subComponents/VueCron"
import FileUploader from "@/components/subComponents/FileUpload/index"
@@ -220,7 +215,7 @@
    }
  },
  methods: {
    isShow (authority) {
    isShow(authority) {
      if (this.isAdmin) {
        return true
      } else if (
@@ -285,8 +280,8 @@
      var timeRange = this.format(this.dataRange);
      var showStartTime = timeRange[0]
      var showEndTime = timeRange[1]
      console.log("时间:",showStartTime,showEndTime)
      this.$confirm("提示:"+showStartTime+" 至 "+showEndTime+" 产生的全部数据将被删除,此操作立即生效,不可恢复,是否删除?", {
      console.log("时间:", showStartTime, showEndTime)
      this.$confirm("提示:" + showStartTime + " 至 " + showEndTime + " 产生的全部数据将被删除,此操作立即生效,不可恢复,是否删除?", {
        center: true,
        cancelButtonClass: "comfirm-class-cancle",
        confirmButtonClass: "comfirm-class-sure"
@@ -417,13 +412,13 @@
    }
  }
}
.box{
.box {
  width: 50%;
  min-width: 700px;
  height: 270px;
  border: 1px solid #eee;
  .title {
    font-size:20px;
    font-size: 20px;
    font-weight: bold;
    text-align: left;
    padding: 20px;
@@ -475,35 +470,33 @@
    }
  }
}
#systemMaintenance{
#systemMaintenance {
  .el-tabs__header {
      border: 0px solid #dcdfe6;
      .el-tabs__item {
        padding: 5px 50px;
        height: 50px;
        font-family: PingFangSC-Regular;
        font-size: 14px;
        color: #222222;
        text-align: center;
        border: 0px solid transparent;
      }
      .el-tabs__item:nth-child(2) {
        padding-left: 50px;
      }
      .el-tabs__item:last-child {
        padding-right: 50px;
      }
      .el-tabs__item.is-active {
        color: #ff7733;
        font-weight: bold;
        // border-right-color: #fff;
        // border-left-color: #fff;
      }
      .el-tabs__item:not(.is-disabled):hover {
        color: #ff7733;
      }
    border: 0px solid #dcdfe6;
    .el-tabs__item {
      padding: 5px 50px;
      height: 50px;
      font-family: PingFangSC-Regular;
      font-size: 14px;
      color: #222222;
      text-align: center;
      border: 0px solid transparent;
    }
    .el-tabs__item:nth-child(2) {
      padding-left: 50px;
    }
    .el-tabs__item:last-child {
      padding-right: 50px;
    }
    .el-tabs__item.is-active {
      color: #ff7733;
      font-weight: bold;
      // border-right-color: #fff;
      // border-left-color: #fff;
    }
    .el-tabs__item:not(.is-disabled):hover {
      color: #ff7733;
    }
  }
  .el-tabs__active-bar {
    background-color: #ff7733;