Преглед на файлове

Merge branch 'master' of http://39.106.8.246:3003/web/ibms

chuwu преди 6 години
родител
ревизия
803521f117

+ 2 - 0
index.html

@@ -4,6 +4,8 @@
     <meta charset="utf-8" />
     <meta name="viewport" content="width=device-width,initial-scale=1.0" />
     <title>sagacloud-admin</title>
+    <link rel="stylesheet" href="//at.alicdn.com/t/font_646072_j1rtd99vj8.css">
+    <link href='//at.alicdn.com/t/font_1112731_cpdyeyhpqk.css'>
   </head>
   <body>
     <div id="app"></div>

+ 1 - 0
package.json

@@ -53,6 +53,7 @@
     "sass-loader": "^7.1.0",
     "semver": "^5.3.0",
     "shelljs": "^0.7.6",
+    "swiper": "^4.0.0",
     "uglifyjs-webpack-plugin": "^1.1.1",
     "url-loader": "^0.5.8",
     "vue-loader": "^13.3.0",

Файловите разлики са ограничени, защото са твърде много
+ 1378 - 0
src/assets/js/chosen.jquery.min.js


+ 327 - 0
src/assets/js/handsontable-chosen-editor.js

@@ -0,0 +1,327 @@
+/// chosen plugin
+import Handsontable from "handsontable-pro"
+import 'handsontable-pro/dist/handsontable.full.css'
+import zhCN from 'handsontable-pro/languages/zh-CN';
+(function(Handsontable) {
+    "use strict";
+
+    var ChosenEditor = Handsontable.editors.TextEditor.prototype.extend();
+
+    ChosenEditor.prototype.prepare = function(row, col, prop, td, originalValue, cellProperties) {
+
+        Handsontable.editors.TextEditor.prototype.prepare.apply(this, arguments);
+
+        this.options = {};
+
+        if (this.cellProperties.chosenOptions) {
+            this.options = $.extend(this.options, cellProperties.chosenOptions);
+        }
+
+        cellProperties.chosenOptions = $.extend({}, cellProperties.chosenOptions);
+    };
+
+    ChosenEditor.prototype.createElements = function() {
+        this.$body = $(document.body);
+
+        this.TEXTAREA = document.createElement('select');
+        //this.TEXTAREA.setAttribute('type', 'text');
+        this.$textarea = $(this.TEXTAREA);
+
+        Handsontable.dom.addClass(this.TEXTAREA, 'handsontableInput');
+
+        this.textareaStyle = this.TEXTAREA.style;
+        this.textareaStyle.width = 0;
+        this.textareaStyle.height = 0;
+
+        this.TEXTAREA_PARENT = document.createElement('DIV');
+        Handsontable.dom.addClass(this.TEXTAREA_PARENT, 'handsontableInputHolder');
+
+        this.textareaParentStyle = this.TEXTAREA_PARENT.style;
+        this.textareaParentStyle.top = 0;
+        this.textareaParentStyle.left = 0;
+        this.textareaParentStyle.display = 'none';
+        this.textareaParentStyle.width = "200px";
+
+        this.TEXTAREA_PARENT.appendChild(this.TEXTAREA);
+
+        this.instance.rootElement.appendChild(this.TEXTAREA_PARENT);
+
+        var that = this;
+        this.instance._registerTimeout(setTimeout(function() {
+            that.refreshDimensions();
+        }, 0));
+    };
+
+    var onChosenChanged = function() {
+        var options = this.cellProperties.chosenOptions;
+
+        if (!options.multiple) {
+            this.close();
+            this.finishEditing();
+        }
+    };
+    var onChosenClosed = function() {
+        var options = this.cellProperties.chosenOptions;
+
+        if (!options.multiple) {
+            this.close();
+            this.finishEditing();
+        } else {}
+    };
+    var onBeforeKeyDown = function(event) {
+        var instance = this;
+        var that = instance.getActiveEditor();
+
+        var keyCodes = Handsontable.helper.KEY_CODES;
+        var ctrlDown = (event.ctrlKey || event.metaKey) && !event.altKey; //catch CTRL but not right ALT (which in some systems triggers ALT+CTRL)
+
+        //Process only events that have been fired in the editor
+        if (event.target.tagName !== "INPUT") {
+            return;
+        }
+        if (event.keyCode === 17 || event.keyCode === 224 || event.keyCode === 91 || event.keyCode === 93) {
+            //when CTRL or its equivalent is pressed and cell is edited, don't prepare selectable text in textarea
+            event.stopImmediatePropagation();
+            return;
+        }
+
+        var target = event.target;
+
+        switch (event.keyCode) {
+            case keyCodes.ARROW_RIGHT:
+                if (Handsontable.dom.getCaretPosition(target) !== target.value.length) {
+                    event.stopImmediatePropagation();
+                } else {
+                    that.$textarea.trigger("chosen:close");
+                }
+                break;
+
+            case keyCodes.ARROW_LEFT:
+                if (Handsontable.dom.getCaretPosition(target) !== 0) {
+                    event.stopImmediatePropagation();
+                } else {
+                    that.$textarea.trigger("chosen:close");
+                }
+                break;
+
+            case keyCodes.ENTER:
+                if (that.cellProperties.chosenOptions.multiple) {
+                    event.stopImmediatePropagation();
+                    event.preventDefault();
+                    event.stopPropagation();
+                }
+
+                break;
+
+            case keyCodes.A:
+            case keyCodes.X:
+            case keyCodes.C:
+            case keyCodes.V:
+                if (ctrlDown) {
+                    event.stopImmediatePropagation(); //CTRL+A, CTRL+C, CTRL+V, CTRL+X should only work locally when cell is edited (not in table context)
+                }
+                break;
+
+            case keyCodes.BACKSPACE:
+                var txt = $(that.TEXTAREA_PARENT).find("input").val();
+                $(that.TEXTAREA_PARENT).find("input").val(txt.substr(0, txt.length - 1)).trigger("keyup.chosen");
+
+                event.stopImmediatePropagation();
+                break;
+            case keyCodes.DELETE:
+            case keyCodes.HOME:
+            case keyCodes.END:
+                event.stopImmediatePropagation(); //backspace, delete, home, end should only work locally when cell is edited (not in table context)
+                break;
+        }
+
+    };
+
+    ChosenEditor.prototype.open = function(keyboardEvent) {
+        this.refreshDimensions();
+        this.textareaParentStyle.display = 'block';
+        this.instance.addHook('beforeKeyDown', onBeforeKeyDown);
+
+        this.$textarea.css({
+            height: $(this.TD).height() + 4,
+            'min-width': $(this.TD).outerWidth() - 4
+        });
+
+        //display the list
+        this.$textarea.hide();
+
+        //make sure that list positions matches cell position
+        //this.$textarea.offset($(this.TD).offset());
+
+        var options = $.extend({}, this.options, {
+            width: "100%",
+            search_contains: true
+        });
+
+        if (options.multiple) {
+            this.$textarea.attr("multiple", true);
+        } else {
+            this.$textarea.attr("multiple", false);
+        }
+
+        this.$textarea.empty();
+        this.$textarea.append("<option value=''></option>");
+        var el = null;
+        var originalValue = (this.originalValue + "").split(",");
+        if (options.data && options.data.length) {
+            for (var i = 0; i < options.data.length; i++) {
+                // el = $("<option />");
+                // el.attr("value", options.data[i].Code);
+                // el.html(options.data[i].Name);
+
+                // if (originalValue.indexOf(options.data[i].Code + "") > -1) {
+                //     el.attr("selected", true);
+                // }
+
+                // this.$textarea.append(el);
+                if (options.data[i].content && options.data[i].content.length) {
+                    for (var k = 0; k < options.data[i].content.length; k++) {
+                        if (options.data[i].content[k] && options.data[i].content[k].length) {
+                            for (var j = 0; j < options.data[i].content[k].length; j++) {
+                                el = $("<option />");
+                                el.attr("value", options.data[i].content[k].content[j].Code);
+                                el.html(options.data[i].content[k].content[j].Name);
+
+                                if (originalValue.indexOf(options.data[i].content[k].content[j].Code + "") > -1) {
+                                    el.attr("selected", true);
+                                }
+                                this.$textarea.append(el);
+                            }
+                        } else {
+                            el = $("<option />");
+                            el.attr("value", options.data[i].content[k].Code);
+                            el.html(options.data[i].content[k].Name);
+
+                            if (originalValue.indexOf(options.data[i].content[k].Code + "") > -1) {
+                                el.attr("selected", true);
+                            }
+                            this.$textarea.append(el);
+                        }
+                    }
+                } else {
+                    el = $("<option />");
+                    el.attr("value", options.data[i].Code);
+                    el.html(options.data[i].Name);
+
+                    if (originalValue.indexOf(options.data[i].Code + "") > -1) {
+                        el.attr("selected", true);
+                    }
+                    this.$textarea.append(el);
+                }
+            }
+        }
+
+        if ($(this.TEXTAREA_PARENT).find(".chosen-container").length) {
+            this.$textarea.chosen("destroy");
+        }
+
+        this.$textarea.chosen(options);
+
+        var self = this;
+        setTimeout(function() {
+
+            self.$textarea.on('change', onChosenChanged.bind(self));
+            self.$textarea.on('chosen:hiding_dropdown', onChosenClosed.bind(self));
+
+            self.$textarea.trigger("chosen:open");
+
+            $(self.TEXTAREA_PARENT).find("input").on("keydown", function(e) {
+                if (e.keyCode === Handsontable.helper.KEY_CODES.ENTER /*|| e.keyCode === Handsontable.helper.KEY_CODES.BACKSPACE*/ ) {
+                    if ($(this).val()) {
+                        e.preventDefault();
+                        e.stopPropagation();
+                    } else {
+                        e.preventDefault();
+                        e.stopPropagation();
+
+                        self.close();
+                        self.finishEditing();
+                    }
+
+                }
+
+                if (e.keyCode === Handsontable.helper.KEY_CODES.BACKSPACE) {
+                    var txt = $(self.TEXTAREA_PARENT).find("input").val();
+
+                    $(self.TEXTAREA_PARENT).find("input").val(txt.substr(0, txt.length - 1)).trigger("keyup.chosen");
+
+                    e.preventDefault();
+                    e.stopPropagation();
+                }
+
+                if (e.keyCode === Handsontable.helper.KEY_CODES.ARROW_DOWN || e.keyCode === Handsontable.helper.KEY_CODES.ARROW_UP) {
+                    e.preventDefault();
+                    e.stopPropagation();
+                }
+
+            });
+
+            setTimeout(function() {
+                self.$textarea.trigger("chosen:activate").focus();
+
+                if (keyboardEvent && keyboardEvent.keyCode && keyboardEvent.keyCode != 113) {
+                    var key = keyboardEvent.keyCode;
+                    var keyText = (String.fromCharCode((96 <= key && key <= 105) ? key - 48 : key)).toLowerCase();
+
+                    $(self.TEXTAREA_PARENT).find("input").val(keyText).trigger("keyup.chosen");
+                    self.$textarea.trigger("chosen:activate");
+                }
+            }, 1);
+        }, 1);
+
+    };
+
+    ChosenEditor.prototype.init = function() {
+        Handsontable.editors.TextEditor.prototype.init.apply(this, arguments);
+    };
+
+    ChosenEditor.prototype.close = function() {
+        this.instance.listen();
+        this.instance.removeHook('beforeKeyDown', onBeforeKeyDown);
+        this.$textarea.off();
+        this.$textarea.hide();
+        Handsontable.editors.TextEditor.prototype.close.apply(this, arguments);
+    };
+
+    ChosenEditor.prototype.getValue = function() {
+        if (!this.$textarea.val()) {
+            return "";
+        }
+        if (typeof this.$textarea.val() === "object") {
+            return this.$textarea.val().join(",");
+        }
+        return this.$textarea.val();
+    };
+
+
+    ChosenEditor.prototype.focus = function() {
+        this.instance.listen();
+
+        // DO NOT CALL THE BASE TEXTEDITOR FOCUS METHOD HERE, IT CAN MAKE THIS EDITOR BEHAVE POORLY AND HAS NO PURPOSE WITHIN THE CONTEXT OF THIS EDITOR
+        //Handsontable.editors.TextEditor.prototype.focus.apply(this, arguments);
+    };
+
+    ChosenEditor.prototype.beginEditing = function(initialValue) {
+        var onBeginEditing = this.instance.getSettings().onBeginEditing;
+        if (onBeginEditing && onBeginEditing() === false) {
+            return;
+        }
+
+        Handsontable.editors.TextEditor.prototype.beginEditing.apply(this, arguments);
+
+    };
+
+    ChosenEditor.prototype.finishEditing = function(isCancelled, ctrlDown) {
+        this.instance.listen();
+        return Handsontable.editors.TextEditor.prototype.finishEditing.apply(this, arguments);
+    };
+
+    Handsontable.editors.ChosenEditor = ChosenEditor;
+    Handsontable.editors.registerEditor('chosen', ChosenEditor);
+
+})(Handsontable);

+ 121 - 0
src/components/data_admin/buildData/dataFill.vue

@@ -0,0 +1,121 @@
+<template>
+  <div class="saga-fill">
+    <div class="saga-label saga-item">{{renderData.label}}:</div>
+    <div class="saga-input saga-item" style="padding: 0 10px;">
+      <div v-if="renderData.type == 'Str'">
+        <el-input size="small" v-model="value" @keyup.native="change" placeholder="请输入内容">
+          <template slot="append" v-if="renderData.Unit">{{renderData.Unit}}</template>
+        </el-input>
+      </div>
+      <div v-if="renderData.type == 'Num'">
+        <el-input
+          size="small"
+          type="number"
+          @keyup.native="change"
+          v-model="value"
+          placeholder="请输入内容"
+        ></el-input>
+      </div>
+      <div v-if="renderData.type == 'Enum' || renderData.type == 'Bool'">
+        <el-select
+          v-model="value"
+          placeholder="请选择"
+          size="small"
+          @change="change"
+          filterable
+          style="width:100%;padding-left:15px;"
+        >
+          <el-option
+            v-for="item in renderData.dataSource"
+            :key="item.Code"
+            :label="item.Name"
+            :value="item.Code"
+          ></el-option>
+        </el-select>
+      </div>
+    </div>
+    <div class="saga-button saga-item" v-if="!isCreated">
+      <div v-if="!!renderData.oldValue && renderData.oldValue != value">
+        <el-button
+          @click="oldToNew"
+          style="width:100%;"
+          size="small"
+          type="info"
+        >《 更新值为: “{{renderData.oldValue}}”</el-button>
+      </div>
+      <div v-else>{{renderData.oldValue == value ? "资产中的值与厂商库中的值相同" : "无可用的新值"}}</div>
+    </div>
+  </div>
+</template>
+<script>
+export default {
+  props: {
+    renderData: {
+      type: [Object],
+      default: function () {
+        return {}
+      },
+    },
+    isCreated: {
+      type: Boolean,
+      default: false
+    }
+  },
+  data() {
+    return {
+      value: ""
+    }
+  },
+  created() {
+    this.value = this.renderData.value
+  },
+  mounted() { },
+  methods: {
+    change() {
+      this.renderData.value = this.value
+    },
+    oldToNew() {
+      this.renderData.value = this.renderData.oldValue
+      this.value = this.renderData.oldValue
+    }
+  },
+  watch: {
+    renderData: {
+      deep: true,
+      handler: function () {
+        this.value = this.renderData.value
+      }
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.saga-fill {
+  display: flex;
+  margin: 10px 0;
+  .saga-item {
+    line-height: 30px;
+  }
+  .saga-label {
+    flex-grow: 5;
+    width: 80px;
+    text-align: right;
+  }
+  .saga-input {
+    flex-grow: 5;
+  }
+  .saga-button {
+    flex-grow: 6;
+    width: 150px;
+  }
+}
+input[type="number"]::-webkit-outer-spin-button,
+input[type="number"]::-webkit-inner-spin-button {
+  -webkit-appearance: none !important;
+  margin: 0;
+}
+
+input[type="number"] {
+  -moz-appearance: textfield;
+}
+</style>

+ 9 - 0
src/components/data_admin/buildData/findId.js

@@ -0,0 +1,9 @@
+import { physics } from '@/api/scan/config'
+import http from '@/api/scan/httpUtil'
+
+function getVenderRecommend(param, success) {
+    let url = `${physics}/venders/basic/recommend`
+    http.postJson(url, param, success)
+}
+
+export default getVenderRecommend

+ 642 - 0
src/components/data_admin/buildData/recommend.vue

@@ -0,0 +1,642 @@
+<template>
+    <div class="saga-recommend">
+        <div v-if="hasData">
+            <h4>当前资产:{{fm.FmName}}</h4>
+            <div class="saga-change-name" v-if="!isChangeFor">
+                <h3 class="saga-gray saga-explain">您可能需要快捷改值操作</h3>
+                <!-- 智能推荐按钮 -->
+                <div v-if="isChangeId">
+                    <template v-if="changeList.length" v-for="item in changeList">
+                <saga-button @click="getList(item)">修正 "{{getName(key)}}" 为 {{item.value}}</saga-button>
+</template>
+<template v-if="!changeList.length">
+    <p>
+        {{changeMsg}}</p>
+</template>
+        </div>
+        <!-- 修正按钮 -->
+        <div v-else>
+          <saga-button @click="changeToNull">修正 "{{getName(key)}}" 为 {{noIdChangeVal}}</saga-button>
+        </div>
+      </div>
+      <div class="saga-change-name" v-if="!isSameForCreate">
+        <h3 class="saga-gray saga-explain">您可能需要快捷维护厂商库</h3>
+<template>
+    <saga-button v-if="!isChangeVender" @click="create">
+        增加 {{obj.name}} “ {{val ? val : fm.Infos[key]}} ”</saga-button>
+    <saga-button v-if="isChangeVender" @click="changeVender">更新厂商库中此{{obj.name}}对应值</saga-button>
+</template>
+        <!--<template v-else>
+    <p>
+        {{ !!message ? message : "请确定该信息点内有值"}}</p>
+</template>-->
+      </div>
+      <div class="saga-change-name" v-if="elseBtnsShow">
+        <h3 class="saga-gray saga-explain">您可能需要其他快捷操作</h3>
+        <!-- <saga-button @click="checkVenders">先维护 xxx 信息点</saga-button> -->
+        <saga-button @click="checkVenders" v-if="showBtn">批量维护 {{!!obj ? obj.name : ""}} 相关信息点</saga-button>
+        <saga-button v-if="!showBtn">先维护 {{objMsg}}</saga-button>
+        <!-- <saga-button @click="checkVenders"></saga-button> -->
+      </div>
+    </div>
+    <div v-else class="saga-message">
+      <p>{{!!dataMessage ? dataMessage : "请确定该信息点是支持推荐的信息点"}}</p>
+    </div>
+    <venders-change
+      :create="isCreate"
+      v-if="dialog.visible"
+      ref="venders"
+      :dialog="dialog"
+      :infosKey="infosKey"
+      :types="types"
+      :fmData="fm"
+      @change="loadFm"
+      :title="isCreate ? '添加' + obj.name : '修改' + obj.name"
+    ></venders-change>
+  </div>
+</template>
+<script>
+    import sagaButton from "./sagaButton"
+    import vendersChange from "./vendersChange"
+    import getVenderRecommend from "./findId"
+    import tools from "@/utils/scan/tools"
+    import getJson from "@/utils/buildData/vendersUtils"
+    import buildJson from "@/utils/buildData/buildJson"
+    import cutHeader from "@/utils/scan/cutHeader"
+    import {
+        upDateTableMain,
+        getBasicMatch
+    } from "@/api/scan/request"
+    export default {
+        components: {
+            sagaButton,
+            vendersChange
+        },
+        data() {
+            return {
+                hasData: false,
+                fm: {},
+                infosKey: null,
+                dialog: {
+                    visible: false
+                },
+                createList: [],
+                changeList: [],
+                types: {},
+                headers: [],
+                message: "",
+                obj: {},
+                key: "",
+                isCreate: false,
+                showBtn: false,
+                createShow: false,
+                changeMsg: "", //修改的提示
+                dataMessage: "⬅请点击资产信息点",
+                falg: false, //上级页面传入的数值,用于实时请求
+                val: null, //上级传入的val
+                isSameForCreate: false,
+                isChangeFor: false,
+                isChangeVender: false,
+                isChangeId: true, //是否为修改id
+                noIdChangeVal: "",
+                elseBtnsShow: true, //是否显示修改按钮
+                msgTable: true,
+                content: {}, //厂商库信息点
+                objMsg: "相关信息点"
+            }
+        },
+        created() {},
+        mounted() {},
+        methods: {
+            //主页面重新加载
+            loadFm() {
+                this.$emit("loadData")
+            },
+            //根据id获得信息点名称
+            getName(code) {
+                if (!!code) {
+                    let name = ""
+                    this.headers.map(item => {
+                        if (item.InfoPointCode == code) {
+                            name = item.InfoPointName
+                        }
+                    })
+                    return name
+                } else {
+                    return ""
+                }
+            },
+            //修改
+            checkVenders() {
+                this.isCreate = false
+                this.dialog.visible = true
+                this.$nextTick(_ => {
+                    this.$refs.venders.getData()
+                })
+            },
+            //获取表头
+            changeObj() {
+                buildJson.map(item => {
+                    if (item.name == "型号") {
+                        item.options = []
+                        item.infosArr = []
+                        this.headers.map(child => {
+                            if (child.FirstTag == "技术参数" ||
+                                child.InfoPointCode == "Specification" ||
+                                child.InfoPointCode == "MaintainPeriod" ||
+                                child.InfoPointCode == "ServiceLife") {
+                                item.infosArr.push(child.InfoPointCode)
+                                let option = {
+                                    key: "contact.infos." + child.InfoPointCode,
+                                    label: child.InfoPointName,
+                                    optLabel: child.InfoPointCode,
+                                    type: child.DataType,
+                                    dataSource: child.DataSource,
+                                    FirstTag: child.FirstTag,
+                                    SecondTag: child.SecondTag
+                                }
+                                if (child.InfoPointCode == "Specification") {
+                                    option.key = "content.specificationName"
+                                }
+                                item.options.push(option)
+                            }
+                        })
+                        item.options = cutHeader(item.options)
+                    }
+                })
+            },
+            changeToNull() {
+                //   let param = {
+                //     FmId: this.fm.FmId,
+                //     Infos: {
+                //       [this.key]: null
+                //     }
+                //   }
+                //   this.updateMain(param)
+                console.log(this.noIdChangeVal, "this.noIdChangeVal")
+                this.fm.Infos[this.key] = this.noIdChangeVal
+            },
+            //上级页面传输的数据
+            randerData(idData, infosKey, headers, falg = false, val = null) {
+                this.isChangeVender = false
+                console.log(idData, infosKey, headers, falg, "falg")
+                this.falg = falg
+                this.val = val
+                this.fm = tools.deepCopyObj(idData)
+                this.headers = headers
+                this.changeObj()
+                this.infosKey = infosKey
+                this.message = ""
+                this.key = infosKey.split(".")[1]
+                this.obj = getJson(this.infosKey.split(".")[1])
+                console.log("数据请求", this.obj)
+                if (!!this.obj) {
+                    console.log("有data")
+                    this.hasData = true
+                    this.getDataForm()
+                } else {
+                    this.hasData = false
+                }
+            },
+            changeVender() {
+                // 修改厂商库中对应的值
+                console.log("修改厂商库中的值", this.obj, this.key)
+                let webArr = ["SupplierWeb", "InsurerWeb", "MaintainerWeb"],
+                    //三大厂商的key
+                    keysArr = ["DPInsurerID", "DPSupplierID", "DPMaintainerID"]
+                //如果是三大厂商的网址
+                if (webArr.indexOf(this.key) > -1) {
+                    let param = {
+                        venderId: this.fm.Infos[this.obj.infosKey],
+                        website: this.fm.Infos[this.key]
+                    }
+                    this.obj.updateVender(param, res => {
+                        this.updateKey(this.key, this.fm)
+                    })
+                    return false
+                } else if (keysArr.indexOf(this.obj.infosKey) > -1) {
+                    let param = {
+                        venderId: this.fm.Infos[this.obj.infosKey],
+                        projectId: this.$route.query.projId
+                    }
+                    //如果存在content的联系人
+                    console.log(this.content, "content")
+                    if (this.content.hasOwnProperty("contact")) {
+                        let contents = this.content.contact
+                        for (let k in contents) {
+                            param[k] = contents[k]
+                        }
+                    }
+                    param[[this.getKey(this.obj.options, this.key)]] = this.fm.Infos[this.key]
+                    this.obj.update(param, res => {
+                        this.updateKey(this.key, this.fm)
+                    })
+                    return false
+                } else {
+                    let param = {
+                        specificationId: this.fm.Infos.DPSpecificationID,
+                        infos: {
+                            [this.key]: this.fm.Infos[this.key]
+                        }
+                    }
+                    this.obj.updateVender(param, res => {
+                        this.updateKey(this.key, this.fm)
+                    })
+                    return false
+                }
+            },
+            updateKey(key, obj) {
+                let param = {
+                    FmId: obj.FmId,
+                    Infos: {
+                        [key]: null
+                    }
+                }
+                this.updateMain(param)
+            },
+            /**
+             * @param arr 传入的数组
+             * @param key 传入的key
+             * 
+             * @return key 对应的key
+             */
+            getKey(arr, key) {
+                let returnKey = ""
+                arr.map(item => {
+                    if (item.optLabel == key) {
+                        returnKey = item.key.split(".")[1]
+                        console.log(returnKey, item, "item")
+                    }
+                })
+                return returnKey
+            },
+            //有obj的信息时
+            getDataForm() {
+                let idArr = ["DPManufacturerID", "DPSupplierID", "DPInsurerID", "DPMaintainerID", "DPSpecificationID", "DPBrandID", "DPSpecificationID"]
+                //点击以下按钮触发按钮事件
+                let vendersArr = ["Manufacturer", "Supplier", "Maintainer", "Insurer", "Brand", "Specification"]
+                if (!!this.fm.Infos[this.obj.infosKey]) {
+                    this.falgChange(true)
+                } else {
+                    this.falgChange(false)
+                }
+            },
+            //falg为是否存在id
+            falgChange(falg) {
+                let vendersArr = ["Manufacturer", "Supplier", "Maintainer", "Insurer", "Brand", "Specification"]
+                if (this.val || !!this.fm.Infos[this.key]) {
+                    //存在id且单元格存在值
+                    if (falg) {
+                        if (this.falg && vendersArr.indexOf(this.key) > -1) {
+                            this.noIdDo()
+                        } else {
+                            this.getVendersList()
+                        }
+                    } else {
+                        // 没有id
+                        this.noIdDo()
+                    }
+                } else {
+                    //不存在值
+                    // this.isChangeFor = false
+                    // this.isSameForCreate = true
+                    // this.changeList = []
+                    this.noIdDo()
+                    // this.changeMsg = "请确定该单元格内存在值"
+                }
+            },
+            //没有id执行
+            noIdDo() {
+                console.log("没有id")
+                let param = {
+                        infoCode: this.key,
+                        infoValue: this.val || this.fm.Infos[this.key]
+                    },
+                    falg = true
+                this.createShow = true
+                this.showBtn = false
+                this.elseBtnsShow = true
+                if (this.key == "Brand") {
+                    param.manufacturerID = this.fm.Infos.DPManufacturerID
+                }
+                if (this.key == "Specification") {
+                    param.manufacturerID = this.fm.Infos.DPManufacturerID
+                    param.brandID = this.fm.Infos.DPBrandID
+                    param.eqFamily = this.fm.Family
+                }
+                for (let k in param) {
+                    if (!param[k]) {
+                        falg = false
+                    }
+                }
+                console.log(falg, "falg")
+                //如果传参中某个值为空不发生请求
+                if (!falg) {
+                    this.noShowTop12()
+                    return false
+                } else {
+                    this.elseBtnsShow = false
+                }
+                console.log(this.obj.infosArr[0], this.infosKey, "this.infosKey")
+                if (this.obj.infosArr[0] != this.key) {
+                    console.log("其他信息点")
+                    this.noShowTop12()
+                    return false
+                }
+                getVenderRecommend(param, res => {
+                    this.changeList = res.content || []
+                    this.isChangeId = true
+                    this.isSameForCreate = false
+                    this.isChangeFor = false
+                    console.log(this.changeList, "changeList")
+                    if (!!this.changeList && this.changeList.length == 1) {
+                        if (this.changeList[0].value == this.fm.Infos[this.key] &&
+                            this.changeList[0].id == this.fm.Infos["DP" + this.key + "ID"]) {
+                            this.isSameForCreate = true
+                            this.isChangeFor = true
+                            if (!!this.val && this.val != this.fm.Infos[this.key]) {
+                                this.isChangeFor = false
+                                this.isSameForCreate = false
+                            }
+                        }
+                    }
+                    if (res.content[0] && res.content[0].similarity == 100) {
+                        this.changeList = []
+                        this.isSameForCreate = true
+                        this.isChangeFor = false
+                    }
+                    if (this.changeList.length <= 0) {
+                        //   this.changeMsg = "不存在符合条件的推荐"
+                    }
+                })
+            },
+            //第一栏第二栏不显示
+            noShowTop12() {
+                if (!this.val && !this.fm.Infos[this.key]) {
+                    this.elseBtnsShow = false
+                }
+                console.log(this.obj.infosKey, this.fm.Infos)
+                //型号
+                if (this.obj.infosKey == "DPSpecificationID") {
+                    if (!this.fm.Infos.DPManufacturerID) {
+                        this.elseBtnsShow = true
+                        this.objMsg = "生产厂家"
+                    } else if (!this.fm.Infos.DPBrandID) {
+                        this.elseBtnsShow = true
+                        this.objMsg = "品牌"
+                    } else if (!this.fm.Infos.DPSpecificationID) {
+                        console.log("设备型号")
+                        this.elseBtnsShow = true
+                        this.objMsg = "设备型号"
+                    }
+                }
+                //品牌
+                if (this.obj.infosKey == "DPBrandID") {
+                    if (!this.fm.Infos.DPManufacturerID) {
+                        this.objMsg = "生产厂家"
+                    }
+                }
+                //生产厂家
+                if (this.obj.infosKey == "DPManufacturerID") {
+                    this.elseBtnsShow = false
+                }
+                //供应商
+                if (this.obj.infosKey == "DPSupplierID") {
+                    if (!this.fm.Infos.DPSupplierID) {
+                        console.log("没有供应商id")
+                        this.elseBtnsShow = false
+                        if (this.key != "Supplier") {
+                            this.elseBtnsShow = true
+                        }
+                        this.objMsg = "供应商单位名称"
+                    }
+                }
+                //维修商
+                if (this.obj.infosKey == "DPMaintainerID") {
+                    if (!this.fm.Infos.DPMaintainerID) {
+                        console.log("没有维修商id")
+                        this.elseBtnsShow = false
+                        if (this.key != "Maintainer") {
+                            this.elseBtnsShow = true
+                        }
+                        this.objMsg = "维修商单位名称"
+                    }
+                }
+                //保险公司
+                if (this.obj.infosKey == "DPInsurerID") {
+                    if (!this.fm.Infos.DPInsurerID) {
+                        console.log("没有保险id")
+                        this.elseBtnsShow = false
+                        if (this.key != "Insurer") {
+                            this.elseBtnsShow = true
+                        }
+                        this.objMsg = "保险公司名称"
+                    }
+                }
+                this.isSameForCreate = true
+                this.isChangeFor = true
+            },
+            //当前单元格内存在id且单元格存在值
+            getVendersList() {
+                //四大厂商名称
+                this.isChangeId = true
+                let venderIdArr = ["DPManufacturerID", "DPSupplierID", "DPInsurerID", "DPMaintainerID", "DPBrandID"],
+                    vendersArr = ["Manufacturer", "Supplier", "Maintainer", "Insurer", "Brand"],
+                    infosKey = this.obj.infosKey
+                this.showBtn = true
+                this.elseBtnsShow = true
+                //获取label
+                let ownLabel = ""
+                this.obj.options.map(item => {
+                    if (item.optLabel == this.key) {
+                        ownLabel = item.key
+                    }
+                })
+                if (venderIdArr.indexOf(infosKey) > -1) {
+                    let param = {
+                        venderId: this.fm.Infos[infosKey],
+                        projectId: this.$route.query.projId
+                    }
+                    if (infosKey == "DPBrandID") {
+                        param = {
+                            brandId: this.fm.Infos[infosKey]
+                        }
+                    }
+                    this.obj.getList(param, res => {
+                        console.log(this.key, this.obj.options, res, ownLabel, "ownLabel")
+                        let optArr = ownLabel.split("."),
+                            optContent = ""
+                        if (this.obj.infosKey == "DPBrandID") {
+                            optContent = res[optArr[0]][optArr[1]]
+                        } else {
+                            optContent = res.content[optArr[0]][optArr[1]]
+                        }
+                        if (optContent == (this.val || this.fm.Infos[this.key])) {
+                            //厂商库中的值与现有的值相等
+                            this.isChangeFor = true
+                            this.isSameForCreate = true
+                            let keysBtns = ["DPBrandID", "DPManufacturerID"]
+                            if (keysBtns.indexOf(this.obj.infosKey) > -1) {
+                                this.elseBtnsShow = false
+                            }
+                        } else {
+                            if (!optContent) {
+                                //如果厂商库中没有值
+                                console.log("没有该信息点")
+                                this.isChangeFor = true
+                                this.isChangeVender = true
+                                this.isSameForCreate = false
+                            } else {
+                                //有值
+                                console.log("有值,且值不同")
+                                this.isChangeId = false
+                                this.hasData = true
+                                this.content = res.content
+                                //修改的值(其实做置空操作)
+                                this.noIdChangeVal = optContent
+                                this.isChangeFor = false
+                                this.isSameForCreate = false
+                                this.isChangeVender = true
+                            }
+                        }
+                    })
+                }
+                if (infosKey == "DPSpecificationID") {
+                    let paramData = {
+                        specificationId: this.fm.Infos[infosKey]
+                    }
+                    this.obj.getList(paramData, res => {
+                        let optContent = res.content.infos[this.key]
+                        console.log(optContent, this.val, this.fm.Infos[this.key], "optContent")
+                        if (optContent == (this.val || this.fm.Infos[this.key])) {
+                            console.log("有值,且值相同")
+                            this.isChangeFor = true
+                            this.isSameForCreate = true
+                            if (this.key == "Specification") {
+                                this.elseBtnsShow = false
+                            } else {
+                                this.elseBtnsShow = true
+                            }
+                        } else {
+                            if (!optContent) {
+                                //如果厂商库中没有值
+                                console.log("没有该信息点")
+                                this.isChangeFor = true
+                                this.isChangeVender = true
+                                this.isSameForCreate = false
+                            } else {
+                                //有值
+                                console.log("有值,且值不同")
+                                this.isChangeId = false
+                                this.hasData = true
+                                //修改的值(其实做置空操作)
+                                this.noIdChangeVal = optContent
+                                this.isChangeFor = false
+                                this.isSameForCreate = false
+                                this.isChangeVender = true
+                            }
+                        }
+                    })
+                }
+                if (vendersArr.indexOf(this.key) > -1) {
+                    this.showBtn = true
+                }
+            },
+            //创建函数
+            create(item) {
+                // console.log(this.obj.infosKey)
+                // let param;
+                // if(this.obj.infosKey == "DPBrandID" || this.obj.infosKey == "DPManufacturerID"){
+                //     if(this.obj.infosKey == "DPBrandID"){
+                //         param = {
+                //             "venderId": this.fm.Infos.DPManufacturerID,     //String,必填,生产商id
+                //             "name": this.fm.Infos.Brand,              //String,必填,品牌名称   
+                //         }
+                //     }else{
+                //         param = {
+                //             "name": this.fm.Infos.Manufacturer,          
+                //         }
+                //     }
+                //     this.obj.createFunc(param,res=>{
+                //     })
+                // }
+                this.isCreate = true
+                this.dialog.visible = true
+                this.$nextTick(_ => {
+                    this.$refs.venders.getCreateData()
+                })
+            },
+            updateMain(param) {
+                upDateTableMain({
+                    ProjId: this.$route.query.projId,
+                    UserId: this.$route.query.userId
+                }, [param]).then(res => {
+                    if (res.data.Result == "success") {
+                        this.loadFm()
+                    } else {
+                        this.$message.error("保存出错")
+                    }
+                })
+            },
+            //点击按钮,对表格操作
+            getList(data) {
+                //   this.fm.Infos[this.key] = data.value
+                let infos = tools.deepCopyObj(this.fm.Infos)
+                infos[this.key] = data.value
+                let param = {
+                    "projectId": this.$route.query.projId,
+                    "criterias": [{
+                        id: this.fm.FmId,
+                        family: this.fm.Family,
+                        infos: infos
+                    }]
+                }
+                console.log(param, "paramparam")
+                this.getIdForVender(param)
+            },
+            //判断文案是否相同
+            getIdForVender(param) {
+                getBasicMatch(param).then(res => {
+                    if (res.data.result == "success") {
+                        let myParam = res.data.content.map(item => {
+                            return {
+                                Family: item.family,
+                                FmId: item.id,
+                                Infos: item.infos
+                            }
+                        })
+                        this.updateMain(myParam[0])
+                    } else {
+                        this.$message.error("请求错误" + res.data.resultMsg)
+                    }
+                }).catch(error => {
+                    this.$message.error(error)
+                })
+            },
+        }
+    }
+</script>
+<style lang="less" scoped>
+    .saga-recommend {
+        height: 100%;
+        overflow-y: auto; //   background-color: red;
+        .saga-gray {
+            color: #b7c3c8;
+        }
+        .saga-change-name {
+            padding: 8px;
+            min-height: 100px; // background-color: yellow;
+            border-bottom: 1px solid #ccc;
+            .saga-explain {
+                font-size: 17px;
+                font-weight: 600;
+            }
+        }
+    }
+    .saga-message {
+        height: 100vh;
+        line-height: 100vh;
+        font-size: 20px;
+        color: #b7c3c8;
+    }
+</style>

+ 23 - 0
src/components/data_admin/buildData/sagaButton.vue

@@ -0,0 +1,23 @@
+<template>
+  <div class="saga-button">
+    <el-button @click="clickButton" style="width: 100%; margin: 8px 0;">
+      <slot></slot>
+    </el-button>
+  </div>
+</template>
+<script>
+export default {
+  props: {
+  },
+  data() { return {} },
+  created() { },
+  mounted() { },
+  methods: {
+    clickButton() {
+      this.$emit("click")
+    }
+  }
+}
+</script>
+<style lang="less">
+</style>

+ 464 - 0
src/components/data_admin/buildData/style.less

@@ -0,0 +1,464 @@
+#app {
+    min-width: 1098px;
+    min-height: 767px;
+    position: relative;
+    overflow-x: auto;
+    .left-main {
+      width: calc(100% - 251px);
+      height: 100%;
+      position: relative;
+      float: left;
+    }
+    .right-main {
+      float: right;
+      height: 100%;
+      width: 250px;
+      border-left: 1px solid #ccc;
+    }
+  }
+  #buildData {
+    overflow: hidden;
+    height: 100%;
+    width: 100%;
+    flex-direction: column;
+    display: flex;
+    .icon {
+      position: absolute;
+      z-index: 99;
+      bottom: 20px;
+      left: 20px;
+    }
+    img::after {
+      content: "\e87d";
+      font-family: "iconfont" !important;
+      font-size: 30px;
+      font-style: normal;
+      -webkit-font-smoothing: antialiased;
+      -moz-osx-font-smoothing: grayscale;
+      font-family: FontAwesome;
+      color: rgb(100, 100, 100);
+      display: flex;
+      justify-content: center;
+      align-items: center;
+      position: absolute;
+      z-index: 2;
+      top: 0;
+      left: 0;
+      width: 100%;
+      height: 100%;
+      background-color: #ddd;
+    }
+    .Blue {
+      color: #409eff;
+    }
+    .img_view {
+      position: relative;
+      video {
+        width: 100%;
+        height: 100%;
+        border: 1px solid #606266;
+      }
+    }
+    .active_swiper {
+      border: 2px solid #409eff !important;
+    }
+    .build_header {
+      height: 3rem;
+      width: 100%;
+      border-bottom: 0.01rem solid #ccc;
+    }
+    .point_view {
+      position: absolute;
+      width: 100%;
+      overflow: hidden;
+      top: 3.1rem;
+      z-index: 2000;
+      background-color: #fff;
+    }
+    .build_label {
+      height: 18rem;
+      width: 100%;
+      position: relative;
+      font-size: 0.8rem;
+      .turn_left,
+      .turn_right {
+        position: absolute;
+        top: 0;
+        bottom: 0;
+        height: 100%;
+        line-height: 18rem;
+        width: 4rem;
+        z-index: 90;
+        // flex: 1;
+        i {
+          cursor: pointer;
+          font-size: 4rem;
+        }
+      }
+      .turn_left {
+        left: 0;
+      }
+      .turn_right {
+        right: 0;
+      }
+      .label_view {
+        height: 100%;
+        padding: 1rem 4rem;
+        border-bottom: 0.01rem solid #ccc;
+        .swiper-container {
+          width: 100%;
+          height: 100%;
+        }
+        .swiper-wrapper{
+          height: 92%;
+        }
+        .active_swiper{
+          height: 100%;
+        }
+        .swiper-slide {
+          background: #fff;
+          border: 1px solid #333;
+          height: 100%;
+          h3 {
+            font-size: 1.2rem;
+            font-weight: bold;
+            line-height: 3rem;
+          }
+          .all_view {
+            margin-top: 5rem;
+            text-align: center;
+          }
+          .msg_view {
+            margin-top: 4rem;
+            text-align: center;
+            height: 5.5rem;
+          }
+          // .msg_view:first-child{
+          //     margin-top: 2rem;
+          // }
+          .img_view {
+            height: 100%;
+            width: 100%;
+            overflow: hidden;
+            position: relative;
+            .title_view {
+              width: 100%;
+              height: 100%;
+              position: absolute;
+              left: 0px;
+              top: 0px;
+              // background: url("./../../static/property-grad.png") top left
+              //   repeat-x;
+              // width: 100%;
+              // position: absolute;
+              // opacity: 0.9;
+              color: #fff;
+              // background: rgba(0,0,0,0.1);
+              z-index: 88;
+              padding-left: 6px;
+            }
+            p.btn {
+              position: absolute;
+              right: 1rem;
+              bottom: 0.6rem;
+              cursor: pointer;
+              z-index: 99;
+            }
+          }
+        }
+        .first_tag {
+          padding: 4rem 0;
+          text-align: center;
+          h3 {
+            line-height: 4rem;
+          }
+        }
+      }
+    }
+    .label_show {
+      height: 3rem;
+      .label_btn {
+        width: 15rem;
+        height: 3rem;
+        line-height: 3rem;
+        margin: 0 auto;
+        text-align: center;
+        cursor: pointer;
+        background-color: #ccc;
+        border-radius: 0.2rem;
+        border-top-left-radius: 0;
+        border-top-right-radius: 0;
+        span,
+        i {
+          color: #606266;
+        }
+      }
+    }
+    .build_operate {
+      height: 3rem;
+      line-height: 3rem;
+      margin-top: 3rem;
+      .build_msg {
+        float: right;
+        font-size: 12px;
+        height: 1.5rem;
+        line-height: 1.5rem;
+        margin-top: 0.75rem;
+        padding: 0 1rem;
+        margin-right: 2rem;
+        background-color: #f3c0c0;
+        color: #000;
+        border-radius: 5px;
+      }
+      /* 定义keyframe动画,命名为blink */
+      @keyframes blink {
+        0% {
+          background-color: #cc0000;
+        }
+        100% {
+          background-color: #e99292;
+        }
+      }
+      /* 定义blink类*/
+      .blink {
+        color: #fff;
+        background-color: #cc0000;
+        animation: blink 3s linear infinite;
+      }
+      span {
+        margin-left: 1rem;
+        display: inline-block;
+        cursor: pointer;
+      }
+      span:first-child::after {
+        content: "|";
+        color: #000;
+        margin-left: 1rem;
+      }
+      .undo_btn {
+        cursor: pointer;
+        float: right;
+        margin-right: 1rem;
+      }
+    }
+    .build_table {
+      flex: 1;
+      overflow-y: hidden;
+      .data_page {
+        position: absolute;
+        width: 100%;
+        bottom: 1rem;
+        background-color: #fff;
+      }
+    }
+    .build_pic {
+      width: 100%;
+      height: 200px;
+      position: relative;
+      background-color: #fff;
+      left: 0;
+      bottom: 0;
+      right: 0;
+      padding: 0.4rem 4rem;
+      border-top: 0.01rem solid #ccc;
+      .pic_show {
+        position: absolute;
+        top: -2.3rem;
+        right: 2rem;
+        padding: 0.4rem 1rem;
+        border: 1px solid #dcdfe6;
+        margin-bottom: 3rem;
+        color: #606266;
+        background: #fff;
+        border-radius: 4px;
+        cursor: pointer;
+      }
+      .turn_left,
+      .turn_right {
+        position: absolute;
+        top: 0;
+        bottom: 0;
+        height: 100%;
+        width: 4rem;
+        z-index: 90;
+        // flex: 1;
+        i {
+          cursor: pointer;
+          font-size: 4rem;
+        }
+      }
+      .turn_left {
+        left: 0;
+      }
+      .turn_right {
+        right: 0;
+      }
+      .pic_view {
+        width: 100%;
+        height: 100%;
+      }
+      .swiper-container {
+        width: 100%;
+        height: 100%;
+      }
+      .swiper-slide {
+        padding: 0.6rem;
+        background: #fff;
+        border: 1px solid #333;
+        .img_view {
+          height: 100%;
+          width: 100%;
+          overflow: hidden;
+          position: relative;
+          p {
+            position: absolute;
+            bottom: 0;
+            right: 0;
+            left: 0;
+            background-color: rgba(175, 175, 175, 0.4);
+            text-align: center;
+          }
+        }
+      }
+      // .pic_view{
+      //     width: 100%;
+      //     height: 100%;
+      //     padding-left: 1rem 4rem;
+      // }
+    }
+    .modification {
+      .el-dialog__body {
+        .mod_title {
+          max-height: 8rem;
+          .qr_code,
+          .msg_main {
+            float: left;
+          }
+          .qr_code {
+            width: 35%;
+            height: 100%;
+            padding: 0 0.6rem 0.3rem;
+            img {
+              width: 100%;
+              display: block;
+              height: 100%;
+            }
+          }
+          .msg_main {
+            width: 55%;
+            p {
+              overflow: hidden;
+              text-overflow: ellipsis;
+              display: -webkit-box;
+              -webkit-line-clamp: 2;
+              -webkit-box-orient: vertical;
+            }
+            .input_view {
+              margin-top: 0.5rem;
+              position: relative;
+              input {
+                width: 100%;
+                height: 1.5rem;
+                padding-left: 0.5rem;
+                box-sizing: border-box;
+              }
+              i {
+                position: absolute;
+                right: 10px;
+                font-size: 18px;
+                top: 2px;
+                color: #409eff;
+                display: inline-block;
+                width: 20px;
+                cursor: pointer;
+                transition: all 0.4s;
+              }
+            }
+          }
+        }
+        .cant_mod {
+          width: 100%;
+          .table_header {
+            border: 1px solid #000;
+            border-bottom: none;
+            font-weight: 900;
+            padding-left: 0.5rem;
+          }
+          table {
+            width: 100%;
+            border-color: #b6ff00;
+            border-collapse: collapse;
+            border: 1px solid #000;
+            tr {
+              line-height: 1.5rem;
+              td {
+                border: 1px solid #000;
+                padding-left: 1rem;
+              }
+            }
+          }
+          .locale_pic {
+            p {
+              line-height: 1.8rem;
+              font-weight: 900;
+              margin-top: 0.5rem;
+              border-bottom: 1px solid #000;
+            }
+            div {
+              ul {
+                padding-left: 5px;
+                li {
+                  width: 45%;
+                  float: left;
+                  margin: 10px;
+                  height: 12rem;
+                  overflow: hidden;
+                  position: relative;
+                  img {
+                    width: 100%;
+                    height: 193px;
+                    display: block;
+                    border: 1px solid #000;
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+    .iframe_view {
+      position: fixed;
+      z-index: 99999;
+      top: 0;
+      bottom: 0;
+      left: 0;
+      right: 0;
+      background-color: rgba(0, 0, 0, 0.5);
+      .iframe_no {
+        position: fixed;
+        z-index: 99999;
+        border-radius: 50%;
+        cursor: pointer;
+        height: 80px;
+        overflow: hidden;
+        right: -40px;
+        top: -40px;
+        transition: background-color 0.15s;
+        width: 80px;
+        background-color: rgba(0, 0, 0, 0.6);
+        // background-color: #b6ff00;
+        .iconfont {
+          margin-top: 48px;
+          display: inline-block;
+          margin-left: 16px;
+          font-size: 16px;
+          color: #fff;
+        }
+      }
+      iframe {
+        width: 100%;
+        height: 100%;
+      }
+    }
+  }

+ 598 - 0
src/components/data_admin/buildData/vendersChange.vue

@@ -0,0 +1,598 @@
+<template>
+  <el-dialog :title="title" :visible.sync="dialog.visible" center>
+    <div class="dialog-height">
+      <h3>{{name}}</h3>
+      <p>您可以在此一次性维护厂商库中上述厂商的资料</p>
+      <div class="saga-view">
+        <div class="saga-mine">
+          <div class="saga-in" v-if="!create">
+            <div class="saga-label"></div>
+            <div class="saga-input">厂商库中已有的值</div>
+            <div class="saga-button">当前资产的值</div>
+          </div>
+          <div v-if="obj.infosKey == 'DPSpecificationID' && create">
+            <div style="line-height:32px;">
+              <el-switch
+                v-model="isCreateProduct"
+                @change="changeSwitch"
+                active-text="创建产品"
+                inactive-text="选择产品"
+              ></el-switch>
+            </div>
+            <div style="margin: 5px;">
+              {{isCreateProduct ? "创建产品" : "选择产品"}}
+              <el-input
+                style="width:250px;"
+                size="small"
+                v-if="isCreateProduct"
+                placeholder="请输入产品名"
+                v-model="productName"
+                clearable
+              ></el-input>
+              <el-select
+                size="small"
+                v-if="!isCreateProduct"
+                v-model="productId"
+                filterable
+                placeholder="请选择"
+              >
+                <el-option
+                  v-for="item in productOptions"
+                  :key="item.productId"
+                  :label="item.name"
+                  :value="item.productId"
+                ></el-option>
+              </el-select>
+            </div>
+          </div>
+          <div class="saga-ipnput-view">
+            <template v-for="(item,index) in labelList" v-if="obj.infosKey != 'DPSpecificationID' ">
+              <data-fill
+                v-if="isShow(item,index)"
+                :isCreated="create"
+                :renderData="item"
+                @change="changefillData"
+              ></data-fill>
+            </template>
+            <template v-if="obj.infosKey == 'DPSpecificationID'">
+              <div v-for="item in labelList">
+                <!-- 一级标签 -->
+                <h3 style="line-height:32px; color: green;">{{item.FirstTag}}</h3>
+                <div v-if="child.SecondTag != '设备厂家' || create" v-for="child in item.details">
+                  <!-- 二级标签 -->
+                  <h4 style="line-height:32px;padding-left:20px;color: #409EFF;">{{child.SecondTag}}</h4>
+                  <div v-for="detail in child.details">
+                    <data-fill
+                      v-if="detail.key"
+                      :isCreated="create"
+                      :renderData="detail"
+                      @change="changefillData"
+                    ></data-fill>
+                  </div>
+                </div>
+              </div>
+            </template>
+          </div>
+        </div>
+      </div>
+    </div>
+    <span slot="footer" class="dialog-footer">
+      <el-button type="primary" @click="isCreate">{{ create ? "创建" : " 保存并更新厂商库"}}</el-button>
+      <el-button @click="dialog.visible = false">取 消</el-button>
+    </span>
+  </el-dialog>
+</template>
+<script>
+import dataFill from "./dataFill"
+import getJson from "@/utils/buildData/vendersUtils"
+import {
+  upDateTableMain,
+  getProductList
+} from "@/api/scan/request"
+import cutHeader from "@/utils/scan/cutHeader"
+import tools from "@/utils/scan/tools"
+export default {
+  components: {
+    dataFill
+  },
+  props: {
+    dialog: {
+      type: Object,
+      default: function () {
+        return {
+          visible: false
+        }
+      }
+    },
+    types: {
+      type: Object
+    },
+    fmData: {
+      type: Object
+    },
+    infosKey: {
+      type: String
+    },
+    create: {
+      type: Boolean,
+      default: false
+    },
+    title: {
+      type: String,
+      default: ""
+    }
+  },
+  data() {
+    return {
+      name: "",
+      labelList: [],
+      obj: {},
+      isCreateProduct: true,
+      productName: "",
+      productId: "",
+      productOptions: [],
+      fm: {
+        Infos: {}
+      }
+    }
+  },
+  created() { },
+  mounted() { },
+  methods: {
+    isShow(item, index) {
+      let falg = false
+      console.log(item, index)
+      if (!item.key || index == 0) {
+        falg = false
+      } else {
+        falg = true
+      }
+      if (this.create) {
+        falg = true
+      }
+      return falg
+    },
+    //修改开关
+    changeSwitch() {
+      if (!this.isCreateProduct) {
+        let param = {
+          brandId: this.fm.Infos.DPBrandID,
+          familyCode: this.fm.Family
+        }
+        getProductList(param, res => {
+          this.productOptions = res.content
+        })
+      }
+    },
+    //获取创建信息
+    getCreateData() {
+      this.fm = tools.deepCopyObj(this.fmData)
+      console.log(this.gm, this.fmData, "fmData")
+      this.obj = getJson(this.infosKey.split(".")[1])
+      if (this.obj.infosKey != "DPSpecificationID") {
+        this.labelList = this.obj.options.map(item => {
+          let keyArr = item.key.split("."), data = ""
+          item.value = this.fm.Infos[item.optLabel] || ""
+          return item
+        })
+      } else {
+        this.labelList = this.obj.options.map(item => {
+          if (item.details && item.details.length) {
+            //一级标签
+            item.details.map(child => {
+              if (child.details && child.details.length) {
+                child.details.map(details => {
+                  details.value = this.fm.Infos[details.optLabel] || ""
+                  return details
+                })
+              }
+              return child
+            })
+          }
+          return item
+        })
+      }
+    },
+    //创建请求
+    createOwn() {
+      let venderIdArr = ["DPManufacturerID", "DPSupplierID", "DPInsurerID", "DPMaintainerID", "DPBrandID"]
+      console.log(this.fm)
+      if (venderIdArr.indexOf(this.obj.infosKey) > -1) {
+        let param = {}
+        param.name = this.getMess('vender.name')
+        if (this.obj.infosKey != "DPManufacturerID") {
+          param.website = this.getMess('vender.website')
+        }
+        //当其id为品牌id
+        if (this.obj.infosKey == "DPBrandID") {
+          param.name = this.getMess('content.name')
+          param.venderId = this.fm.Infos.DPManufacturerID
+        }
+        //新建
+        this.obj.createFunc(param, res => {
+          this.fm.Infos[this.obj.infosKey] = res.id
+          param = {}
+          param.venderId = this.fm.Infos[this.obj.infosKey]
+          param.projectId = this.$route.query.projId
+          //如果存在联系人请求
+          if (!!this.obj.update) {
+            if (this.obj.name == "生产商") {
+              param.name = this.getMess('vender.name')
+            } else {
+              param.phone = this.getMess('contact.phone')
+              param.name = this.getMess('contact.name')
+              param.fax = this.getMess('contact.fax')
+              param.email = this.getMess('contact.email')
+            }
+            //发起请求
+            this.obj.update(param, res => {
+              for (let k in this.labelList) {
+                this.changeFmData(this.labelList[k].optLabel, this.fm.Infos)
+              }
+              this.updateFm(this.fm)
+            })
+          } else {
+            for (let k in this.labelList) {
+              this.changeFmData(this.labelList[k].optLabel, this.fm.Infos)
+            }
+            if (this.obj.infosKey == "DPBrandID") {
+              this.fm.Infos.Brand = this.getMess('content.name')
+              this.fm.Infos.DPSpecificationID = null
+            }
+            //如果修改的是生产厂家,品牌型号清空
+            if (this.obj.infosKey == "DPManufacturerID") {
+              this.fm.Infos.DPBrandID = null
+              this.fm.Infos.DPSpecificationID = null
+            }
+            this.updateFm(this.fm)
+          }
+        })
+      }
+      let brandId = this.fm.Infos.DPBrandID
+      if (this.obj.infosKey == "DPSpecificationID") {
+        let param = tools.deepCopyObj(this.fm)
+        param.Infos = {}
+        //取infos中的数据
+        this.labelList.map(item => {
+          if (item.details && item.details.length) {
+            //一级标签
+            item.details.map(child => {
+              if (child.details && child.details.length) {
+                child.details.map(details => {
+                  if (!!details.value) {
+                    param.Infos[details.optLabel] = details.value || null
+                  }
+                })
+              }
+            })
+          }
+          return item
+        })
+        console.log(param, "param")
+        //创建产品且产品名为空
+        if (this.isCreateProduct && !this.productName) {
+          this.$message.error("请确定创建产品名不为空")
+          return
+        }
+        //选择产品,产品的id为空
+        if (!this.isCreateProduct && !this.productId) {
+          this.$message.error("请确定该型号所归属的产品")
+          return
+        }
+        //如果保养周期和使用寿命中有一个为空
+        // if (!param.Infos.MaintainPeriod || !param.Infos.ServiceLife || !param.Infos.Specification) {
+        //   this.$message.error("设备型号、保养周期和使用寿命为必填项")
+        //   return
+        // }
+        //是否是创建
+        if (this.isCreateProduct) {
+          let produceParam = {
+            brandId: brandId,
+            name: this.productName,
+            eqFamily: this.fm.Family
+          }
+          this.obj.createProduct(produceParam, res => {
+            let speParam = {
+              productId: res.id,
+              name: param.Infos.Specification,
+              infos: param.Infos
+            }
+            this.createSpecification(speParam)
+          })
+        } else {
+          let speParam = {
+            productId: this.productId,
+            name: param.Infos.Specification,
+            infos: param.Infos
+          }
+          this.createSpecification(speParam)
+        }
+      }
+    },
+    createSpecification(param) {
+      this.obj.createFunc(param, res => {
+        let updateParam = tools.deepCopyObj(this.fm)
+        updateParam.Infos = {}
+        updateParam.Infos.DPSpecificationID = res.id
+        this.labelList.map(item => {
+          if (item.details && item.details.length) {
+            //一级标签
+            item.details.map(child => {
+              if (child.details && child.details.length) {
+                child.details.map(details => {
+                  if (!!details.value) {
+                    updateParam.Infos[details.optLabel] = null
+                  }
+                })
+              }
+            })
+          }
+        })
+        console.log(updateParam, "updateParam")
+        this.updateFm(updateParam)
+      })
+    },
+    //判断是否创建
+    isCreate() {
+      if (this.create) {
+        this.createOwn()
+      } else {
+        this.update()
+      }
+    },
+    //修改默认填入信息
+    changefillData(data) {
+      this.labelList.map(item => {
+        if (item.key == data.key) {
+          item.value = item.oldValue
+        }
+      })
+    },
+    getData() {
+      this.fm = tools.copyArr(this.fmData)
+      console.log(this.fmData, this.fm)
+      this.isCreateShow = false
+      this.obj = {}
+      this.obj = getJson(this.infosKey.split(".")[1])
+      let venders = ["DPSupplierID", "DPInsurerID", "DPManufacturerID"]
+      if (!!this.obj) {
+        let param = {
+          venderId: this.fm.Infos[this.obj.infosKey],
+          projectId: this.$route.query.projId
+        }
+        if (this.obj.infosKey == "DPBrandID") {
+          param = {
+            brandId: this.fm.Infos[this.obj.infosKey]
+          }
+        }
+        if (this.obj.infosKey == "DPSpecificationID") {
+          param = {
+            specificationId: this.fm.Infos[this.obj.infosKey]
+          }
+        }
+        this.obj.getList(param, res => {
+          console.log(res, venders.indexOf(this.obj.infosKey))
+          if (venders.indexOf(this.obj.infosKey) > -1) {
+            this.name = res.content.vender.name
+          } else if (this.obj.infosKey == "DPBrandID") {
+            this.name = res.content.name
+          } else {
+            let content = res.content
+            this.name = content.venderName + '-' + content.brandName + '-' + content.productName + '-' + content.specificationName
+          }
+          this.labelList = []
+          if (this.obj.infosKey == "DPSpecificationID") {
+            this.labelList = this.obj.options.map(item => {
+              if (item.details && item.details.length) {
+                //一级标签
+                item.details.map(child => {
+                  if (child.details && child.details.length) {
+                    child.details.map(details => {
+                      let detailsKey = details.key.split("."),
+                        data = ""
+                      let resp = res.content
+                      for (let i = 0; i < detailsKey.length; i++) {
+                        if (!!resp[detailsKey[i]]) {
+                          data = resp[detailsKey[i]]
+                          resp = resp[detailsKey[i]]
+                        } else {
+                          data = ""
+                        }
+                      }
+                      details.value = data
+                      details.oldValue = this.fm.Infos[details.optLabel]
+                      return details
+                    })
+                  }
+                  return child
+                })
+              }
+              return item
+            })
+          } else {
+            this.labelList = this.obj.options.map(item => {
+              let keyArr = item.key.split(".")
+              let data = ""
+              let resp = res.content
+              for (let i = 0; i < keyArr.length; i++) {
+                if (!!resp[keyArr[i]]) {
+                  data = resp[keyArr[i]] || ""
+                  resp = resp[keyArr[i]]
+                } else {
+                  data = ""
+                }
+              }
+              item.value = data || ""
+              item.oldValue = this.fm.Infos[item.optLabel] || ""
+              return item
+            })
+          }
+        })
+      } else {
+        this.$message.error("该信息点不支持推荐")
+      }
+    },
+    //修改六大参数
+    update() {
+      if (!!this.obj) {
+        if (this.obj.name == "型号") {
+          this.updateSpecification()
+        } else {
+          this.updateVer()
+        }
+      }
+    },
+    updateSpecification() {
+      console.log("修改型号", this.obj)
+      let param = {
+        specificationId: this.fm.Infos.DPSpecificationID,
+        name: "",
+        infos: {}
+      }
+      console.log(this.labelList)
+      //   this.labelList.map(item => {
+      //     param.infos[item.optLabel] = item.value || null
+      //     if (item.optLabel == "Specification") {
+      //       param.name = item.value || null
+      //     }
+      //   })
+      this.labelList.map(item => {
+        if (item.details && item.details.length) {
+          item.details.map(child => {
+            if (child.details && child.details.length) {
+              child.details.map(details => {
+                param.infos[details.optLabel] = details.value || null
+                if (details.optLabel == "Specification") {
+                  param.name = details.value || null
+                }
+              })
+            }
+          })
+        }
+      })
+      console.log(param)
+      this.obj.updateVender(param, res => {
+        this.dialog.visible = false
+        this.$emit("change")
+      })
+    },
+    //修改供应商
+    updateVer() {
+      if (!!this.obj.updateVender) {
+        this.updateVender()
+      } else {
+        this.updatePhone()
+      }
+    },
+    //修改
+    updateVender() {
+      let param = {}
+      param.venderId = this.fm.Infos[this.obj.infosKey]
+      param.projectId = this.$route.query.projId
+      param.name = this.getMess('vender.name')
+      param.website = this.getMess('vender.website')
+      if (this.obj.infosKey == "DPBrandID") {
+        param = {
+          brandId: this.fm.Infos[this.obj.infosKey],
+          name: this.getMess('content.name')
+        }
+      }
+      console.log(param, "param")
+      this.obj.updateVender(param, res => {
+        this.updatePhone()
+      })
+    },
+    //修改厂商联系人信息
+    updatePhone() {
+      let param = {}
+      param.venderId = this.fm.Infos[this.obj.infosKey]
+      param.projectId = this.$route.query.projId
+      if (this.obj.name == "生产商") {
+        param.name = this.getMess('vender.name')
+      } else {
+        param.phone = this.getMess('contact.phone')
+        param.name = this.getMess('contact.name')
+        param.fax = this.getMess('contact.fax')
+        param.email = this.getMess('contact.email')
+      }
+      this.obj.update(param, res => {
+        for (let k in this.labelList) {
+          this.changeFmData(this.labelList[k].optLabel, this.fm.Infos)
+        }
+        // this.dialog.visible = false
+        this.updateFm(this.fm)
+      })
+    },
+    //修改资产
+    updateFm(param) {
+      let list = tools.copyArr(param)
+      upDateTableMain({
+        ProjId: this.$route.query.projId,
+        UserId: this.$route.query.userId
+      }, [list]).then(res => {
+        if (res.data.Result == "success") {
+          this.$emit("change")
+          console.log("venderChange")
+          this.dialog.visible = false
+        } else {
+          this.$message.error("请求错误:" + res.data.ResultMsg)
+        }
+      }).catch(_ => {
+        this.$message.error("请求发生错误")
+      })
+    },
+    changeFmData(key, infos) {
+      this.labelList.map(item => {
+        if (item.optLabel == key) {
+          if (item.value == infos[item.optLabel]) {
+            infos[item.optLabel] = null
+          }
+        }
+      })
+    },
+    getMess(key) {
+      let data = ""
+      this.labelList.map(item => {
+        if (item.key == key) {
+          data = item.value
+        }
+      })
+      return data
+    }
+  },
+  watch: {
+    dialog: {
+      deep: true,
+      handler: function (old, val) {
+        if (this.dialog.visible) {
+          this.getData()
+        }
+      }
+    }
+  }
+}
+</script>
+<style lang="less" scoped>
+.dialog-height {
+  max-height: 600px;
+  .saga-ipnput-view {
+    max-height: 500px;
+    overflow-y: auto;
+  }
+  .saga-in {
+    display: flex;
+    margin: 10px 0;
+    .saga-label {
+      flex-grow: 5;
+      width: 80px;
+    }
+    .saga-input {
+      flex-grow: 6;
+    }
+    .saga-button {
+      flex-grow: 5;
+      width: 120px;
+    }
+  }
+}
+</style>

Файловите разлики са ограничени, защото са твърде много
+ 951 - 0
src/components/data_admin/buildFamily.vue


+ 88 - 0
src/components/data_admin/drag.vue

@@ -0,0 +1,88 @@
+<template>
+  <div id="dragView">
+    <header @mousedown="mousedown">
+      <span>头部</span>
+      <span class="close_btn" @click="close">X</span>
+    </header>
+    <main>
+      <iframe :src="iframeSrc" frameborder="0"></iframe>
+    </main>
+  </div>
+</template>
+
+<script>
+  export default {
+    name: 'Window',
+    props: {
+      "iframeSrc": String
+    },
+    data() {
+      return {
+        title: '标题',
+        selectElement: ''
+      }
+    },
+    methods: {
+      mousedown(event) {
+        this.selectElement = document.getElementById('dragView')
+        var div1 = this.selectElement
+        this.isDowm = true
+        var distanceX = event.clientX - this.selectElement.offsetLeft
+        var distanceY = event.clientY - this.selectElement.offsetTop
+        document.onmousemove = function (ev) {
+          var oevent = ev || event
+          div1.style.left = oevent.clientX - distanceX + 'px'
+          div1.style.top = oevent.clientY - distanceY + 'px'
+        }
+        document.onmouseup = function () {
+          document.onmousemove = null
+          document.onmouseup = null
+        }
+      },
+      close(){
+        this.$emit('closeDrag')
+      }
+    }
+  }
+</script>
+
+<style lang="less" scoped>
+#dragView{
+    position: absolute;
+    z-index: 2001;
+    top: 332px;
+    left: 449px;
+    width: 300px;
+    height: 300px;
+    text-align: center;
+    border: 1px solid rgb(102, 102, 153);
+    background-color: rgb(255, 255, 255);
+    overflow: hidden;
+    header{
+      position: absolute;
+      width: 100%;
+      text-align: left;
+      height: 25px;
+      padding: 3px 3px 3px 10px;
+      margin: 0px;
+      color: rgb(255, 255, 255);
+      border: 1px solid rgb(102, 102, 153);
+      cursor: move;
+      background-color: rgb(102, 102, 153);
+      .close_btn{
+        color: #fff;
+        font-size: 15px;
+        cursor: pointer;
+        float: right;
+      }
+    }
+    main{
+      width: 100%;
+      height: 100%;
+      iframe{
+        width: 100%;
+        height: 100%;
+      }
+    }
+}
+</style>

+ 49 - 0
src/components/data_admin/input.vue

@@ -0,0 +1,49 @@
+<template>
+  <div class="build_input">
+        <i class="iconfont icon-sousuo"></i>
+        <input type="text" v-model="value" :placeholder="placeholder" @keyup.enter="search">
+    </div>
+</template>
+
+<script>
+export default {
+    props: [ 'placeholder'],
+    data(){
+        return{
+            value: ''
+        }
+    },
+    methods: {
+        search(){
+            this.$emit("search",this.value)
+        },
+    },
+}
+</script>
+
+<style lang="less" scoped>
+.build_input{
+    display: inline-block;
+    width: 23rem;
+    height: 2rem;
+    font-size: 1.4rem;
+    position: relative;
+    input{
+        width: 100%;
+        height: 100%;
+        padding-left: 2rem;
+        font-size: .8rem;
+        box-sizing: border-box;
+    }
+    .icon-sousuo{
+        position: absolute;
+        width: 2rem;
+        height: 2rem;
+        left: 0;
+        top: 3px;
+        bottom: 0;
+        line-height: 2rem;
+        text-align: center;
+    }
+}
+</style>

+ 155 - 0
src/components/data_admin/selectTime.vue

@@ -0,0 +1,155 @@
+<template>
+  <div class="select_time">
+    <span
+      v-for="(item,index) in timeArr"
+      @click="checkTime(item)"
+      class="bar"
+      :class="item == activeClass ? 'active' : ''"
+    :key="index">{{item}}</span>
+    <span @click="doCheck" :class="'自定义' == activeClass ? 'active' : ''">
+      自定义
+      <i v-show="valDate.length">{{valDate[0]}} ~ {{valDate[1]}}</i>
+      <div v-show="isShow" class="picker_view">
+        <i>扫楼时间:</i>
+        <el-date-picker
+          v-model="value"
+          type="daterange"
+          range-separator="至"
+          start-placeholder="开始日期"
+          end-placeholder="结束日期"
+          @change="getDate"
+        ></el-date-picker>
+      </div>
+    </span>
+    <div class="masked" v-if="isShow" @click="isShow = !isShow"></div>
+  </div>
+</template>
+
+<script>
+export default {
+  props: ['timeArr'],
+  data() {
+    return {
+      activeClass: '今天',
+      value: '',
+      isShow: false,
+      valDate: []
+    }
+  },
+  methods: {
+    getNowFormatDate(str) {
+      var date = new Date(str);
+      var seperator1 = "-";
+      var seperator2 = ":";
+      var month = date.getMonth() + 1;
+      var strDate = date.getDate();
+      if (month >= 1 && month <= 9) {
+        month = "0" + month;
+      }
+      if (strDate >= 0 && strDate <= 9) {
+        strDate = "0" + strDate;
+      }
+      let minutes = date.getMinutes() > 9 ? date.getMinutes() : "0" + date.getMinutes()
+      let hour = date.getHours() > 9 ? date.getHours() : "0" + date.getHours()
+      let seconds = date.getSeconds() > 9 ? date.getSeconds() : "0" + date.getSeconds()
+      var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate
+        + " " + hour + seperator2 + minutes
+        + seperator2 + seconds;
+      return currentdate;
+    },
+    checkTime(val) {
+      // 控制active显示
+      this.activeClass = val
+      let nowdate = new Date().setHours(0, 0, 0, 0)
+      let oldDate = ''
+      let oneDay = new Date()
+      this.valDate = []
+      switch (val) {
+        case '一个月内':
+          oldDate = new Date(new Date().setMonth(new Date().getMonth() - 1)).setHours(0, 0, 0, 0)
+          this.$emit('checkTime', [this.getNowFormatDate(oldDate), this.getNowFormatDate(new Date(oneDay))])
+          break;
+        case '一周内':
+          oldDate = new Date(nowdate - 7 * 24 * 3600 * 1000)
+          this.$emit('checkTime', [this.getNowFormatDate(oldDate), this.getNowFormatDate(new Date(oneDay))])
+          break;
+        case '近三天':
+          oldDate = new Date(nowdate - 3 * 24 * 3600 * 1000)
+          this.$emit('checkTime', [this.getNowFormatDate(oldDate), this.getNowFormatDate(new Date(oneDay))])
+          break;
+        case '昨天':
+          oldDate = new Date(nowdate - 24 * 3600 * 1000)
+          this.$emit('checkTime', [this.getNowFormatDate(oldDate), this.getNowFormatDate(new Date(nowdate))])
+          break;
+        case '今天':
+          oldDate = new Date(nowdate);
+          this.$emit('checkTime', [this.getNowFormatDate(oldDate), this.getNowFormatDate(new Date())])
+          break;
+        default:
+      }
+    },
+    doCheck() {
+      this.isShow = true
+    },
+    getDate() {
+      if (this.value == '' || this.value) {
+        this.$emit('checkTime', [this.getNowFormatDate(this.value[0]), this.getNowFormatDate(this.value[1])])
+        this.valDate[0] = this.getNowFormatDate(this.value[0]).split(' ')[0]
+        this.valDate[1] = this.getNowFormatDate(this.value[1]).split(' ')[0]
+        this.isShow = false
+        this.activeClass = '自定义'
+      } else {
+        this.isShow = false
+      }
+    }
+  }
+}
+</script>
+
+<style lang="less" scoped>
+.select_time {
+  font-size: 0.8rem;
+  display: inline-block;
+  margin-left: 2rem;
+  span {
+    cursor: pointer;
+    position: relative;
+    &.active {
+      color: #409eff;
+    }
+    .picker_view {
+      position: absolute;
+      width: 30rem;
+      bottom: -3rem;
+      left: -23rem;
+      height: 3rem;
+      padding-top: 0.5rem;
+      box-sizing: border-box;
+      z-index: 999;
+      background-color: rgba(255, 255, 255, 1);
+      padding-left: 1rem;
+      padding-right: 2rem;
+      border: 0.01rem solid #eee;
+      z-index: 2001;
+      i {
+        color: #000;
+      }
+    }
+  }
+  .bar::after {
+    content: "|";
+    margin-right: 0.2rem;
+    margin-left: 0.2rem;
+    color: #000;
+  }
+  .masked {
+    position: fixed;
+    left: 0;
+    top: 0;
+    right: 0;
+    bottom: 0;
+    opacity: 0;
+    z-index: 2;
+  }
+}
+</style>

+ 7 - 4
src/router/sagacloud.js

@@ -17,6 +17,9 @@ import spacelist from "@/views/business_space/business_list"
 
 /** 扫楼数据整理 */
 import buildAssets from "@/views/data_admin/buildAssets"
+import buildLog from "@/views/data_admin/buildLog"
+import buildUser from "@/views/data_admin/buildUser"
+import buildData from "@/views/data_admin/buildData"
 
 export default [
     { path: '/auth', name: 'Auth', component: Auth },
@@ -124,12 +127,12 @@ export default [
         name: 'LayoutMain',
         component: LayoutMain,
         children: [
-            { path: '', name: 'Dasboard', component: Dasboard },
-            { path: 'data', name: 'Dasboard', component: Dasboard },
+            { path: '', name: 'buildData', component: buildData },
+            { path: 'data', name: 'buildData', component: buildData},
             { path: 'plan', name: 'Dasboard', component: Dasboard },
             { path: 'abnormalprop', name: 'buildAssets', component: buildAssets },
-            { path: 'log', name: 'Dasboard', component: Dasboard },
-            { path: 'appuser', name: 'Dasboard', component: Dasboard },
+            { path: 'log', name: 'buildLog', component: buildLog },
+            { path: 'appuser', name: 'buildUser', component: buildUser },
         ]
     },
     //环境调节

+ 295 - 0
src/utils/buildData/buildJson.js

@@ -0,0 +1,295 @@
+import { physics } from '@/api/scan/config'
+import http from '@/api/scan/httpUtil'
+
+/**** 修改 */
+//修改创建维修商
+
+//生产商修改
+function updateVenderManufacturer(param, success) {
+    let url = `${physics}/venders/manufacturer/update`
+    http.postJson(url, param, success)
+}
+
+//保险商修改
+function updateVenderInsurer(param, success) {
+    let url = `${physics}/venders/insurance/update`
+    http.postJson(url, param, success)
+}
+
+//保险商修改
+function updateVenderMaintainer(param, success) {
+    let url = `${physics}/venders/maintainer/update`
+    http.postJson(url, param, success)
+}
+
+//供应商修改
+function updateVenderSupplier(param, success) {
+    let url = `${physics}/venders/supplier/update`
+    http.postJson(url, param, success)
+}
+
+//品牌修改
+function updateVenderBrand(param, success) {
+    let url = `${physics}/venders/manufacturer/brand/update`
+    http.postJson(url, param, success)
+}
+
+//型号修改
+function updateVenderSpecification(param, success) {
+    let url = `${physics}/venders/manufacturer/specification/update`
+    http.postJson(url, param, success)
+}
+
+/** 获取 */
+function getList(param, success) {
+    let url = `${physics}/venders/basic/vender/query`
+    http.postJson(url, param, success)
+}
+
+function getManufacturer(param, success) {
+    let url = `${physics}/venders/manufacturer/brand/findOne`
+    http.postJson(url, param, success)
+}
+
+function getSpecification(param, success) {
+    let url = `${physics}/venders/manufacturer/specification/findOne`
+    http.postJson(url, param, success)
+}
+
+/** 创建 */
+//创建品牌
+function createBrand(param, success) {
+    let url = `${physics}/venders/manufacturer/brand/create`
+    http.postJson(url, param, success)
+}
+//创建生产商
+function createManufacturer(param, success) {
+    let url = `${physics}/venders/manufacturer/create`
+    http.postJson(url, param, success)
+}
+//创建供应商
+function createSupplier(param, success) {
+    let url = `${physics}/venders/supplier/create`
+    http.postJson(url, param, success)
+}
+//创建保险商
+function createInsurance(param, success) {
+    let url = `${physics}/venders/insurance/create`
+    http.postJson(url, param, success)
+}
+//创建维修商
+function createMaintainance(param, success) {
+    let url = `${physics}/venders/maintainance/create`
+    http.postJson(url, param, success)
+}
+
+//创建产品
+function createProduct(param, success) {
+    let url = `${physics}/venders/manufacturer/product/create`
+    http.postJson(url, param, success)
+}
+
+//创建型号
+function createSpecification(param, success) {
+    let url = `${physics}/venders/manufacturer/specification/create`
+    http.postJson(url, param, success)
+}
+
+/***  联系人信息 */
+//添加修改维修商联系信息
+function updateMaintainance(param, success) {
+    let url = `${physics}/venders/maintainance/link/create`
+    http.postJson(url, param, success)
+}
+
+//修改创建供应商联系人
+function updateSupplier(param, success) {
+    let url = `${physics}/venders/supplier/link/create`
+    http.postJson(url, param, success)
+}
+//修改创建保险商联系人
+function updateInsurance(param, success) {
+    let url = `${physics}/venders/insurance/link/create`
+    http.postJson(url, param, success)
+}
+
+
+
+let arr = [{
+        name: "生产商",
+        infosArr: ["Manufacturer"],
+        createFunc: createManufacturer,
+        getList: getList,
+        infosKey: "DPManufacturerID",
+        update: "",
+        updateVender: updateVenderManufacturer,
+        options: [{
+            key: "vender.name",
+            label: "生产商名称",
+            optLabel: "Manufacturer",
+            type: "Str"
+        }]
+    },
+    {
+        name: "品牌",
+        infosArr: ["Brand"],
+        infosKey: "DPBrandID",
+        createFunc: createBrand,
+        getList: getManufacturer,
+        update: "",
+        options: [{
+            key: "content.name",
+            label: "品牌",
+            optLabel: "Brand",
+            type: "Str"
+        }],
+        updateVender: updateVenderBrand
+    },
+    {
+        name: "保险商",
+        infosArr: ["Insurer", "InsurerContactor", "InsurerPhone", "InsurerEmail", "InsurerWeb", "InsurerFax"],
+        createFunc: createInsurance,
+        getList: getList,
+        infosKey: "DPInsurerID",
+        getWebSite: "",
+        updateVender: updateVenderInsurer,
+        update: updateInsurance,
+        options: [{
+                key: "vender.name",
+                label: "保险公司名称",
+                optLabel: "Insurer",
+                type: "Str"
+            },
+            {
+                key: "vender.website",
+                label: "保险公司网址",
+                optLabel: "InsurerWeb",
+                type: "Str"
+            },
+            {
+                key: "contact.name",
+                label: "联系人",
+                optLabel: "InsurerContactor",
+                type: "Str"
+            },
+            {
+                key: "contact.phone",
+                label: "联系人电话",
+                optLabel: "InsurerPhone",
+                type: "Num"
+            }, {
+                key: "contact.email",
+                label: "联系人邮箱",
+                optLabel: "InsurerEmail",
+                type: "Str"
+            }, {
+                key: "contact.fax",
+                label: "联系人传真",
+                optLabel: "InsurerFax",
+                type: "Str"
+            }
+        ],
+    },
+    {
+        name: "维修商",
+        infosArr: ["Maintainer", "MaintainerContactor", "MaintainerPhone", "MaintainerEmail", "MaintainerWeb", "MaintainerFax"],
+        createFunc: createMaintainance,
+        updateVender: updateVenderMaintainer,
+        options: [{
+                key: "vender.name",
+                label: "维修商单位名称",
+                optLabel: "Maintainer",
+                type: "Str"
+            },
+            {
+                key: "vender.website",
+                label: "维修商网址",
+                optLabel: "MaintainerWeb",
+                type: "Str"
+            }, {
+                key: "contact.name",
+                label: "联系人",
+                optLabel: "MaintainerContactor",
+                type: "Str"
+            },
+            {
+                key: "contact.phone",
+                label: "联系人电话",
+                optLabel: "MaintainerPhone",
+                type: "Num"
+            }, {
+                key: "contact.email",
+                label: "联系人邮箱",
+                optLabel: "MaintainerEmail",
+                type: "Str"
+            }, {
+                key: "contact.fax",
+                label: "联系人传真",
+                optLabel: "MaintainerFax",
+                type: "Str"
+            }
+        ],
+        getList: getList,
+        update: updateMaintainance,
+        infosKey: "DPMaintainerID",
+        getWebSite: "",
+    },
+    {
+        name: "供应商",
+        infosArr: ["Supplier", "SupplierContactor", "SupplierPhone", "SupplierEmail", "SupplierWeb", "SupplierFax"],
+        createFunc: createSupplier,
+        updateVender: updateVenderSupplier,
+        options: [{
+                key: "vender.name",
+                label: "供应商单位名称",
+                optLabel: "Supplier",
+                type: "Str"
+            },
+            {
+                key: "vender.website",
+                label: "供应商网址",
+                optLabel: "SupplierWeb",
+                type: "Str"
+            }, {
+                key: "contact.name",
+                label: "联系人",
+                optLabel: "SupplierContactor",
+                type: "Str"
+            },
+            {
+                key: "contact.phone",
+                label: "联系人电话",
+                optLabel: "SupplierPhone",
+                type: "Num"
+            }, {
+                key: "contact.email",
+                label: "联系人邮箱",
+                optLabel: "SupplierEmail",
+                type: "Str"
+            }, {
+                key: "contact.fax",
+                label: "联系人传真",
+                optLabel: "SupplierFax",
+                type: "Str"
+            }
+        ],
+        getList: getList,
+        update: updateSupplier,
+        infosKey: "DPSupplierID",
+        getWebSite: "",
+    },
+    {
+        name: "型号",
+        infosArr: ["specificationName"],
+        getList: getSpecification,
+        createFunc: createSpecification,
+        createProduct: createProduct,
+        update: "",
+        options: [],
+        updateVender: updateVenderSpecification,
+        infosKey: "DPSpecificationID",
+        getWebSite: ""
+    }
+]
+
+export default arr

+ 20 - 0
src/utils/buildData/vendersUtils.js

@@ -0,0 +1,20 @@
+import arr from "./buildJson"
+
+function getJson(infosKey) {
+    let obj = {}
+    arr.map(item => {
+        item.infosArr.map(child => {
+            if (child.indexOf(infosKey) > -1) {
+                obj = item
+                obj.falg = true
+            }
+        })
+    })
+    if (obj.falg) {
+        return obj
+    } else {
+        return undefined
+    }
+}
+
+export default getJson

+ 43 - 0
src/utils/scan/cutHeader.js

@@ -0,0 +1,43 @@
+//处理头部函数
+export default function cutHeader(arr) {
+    let first = {}
+        //一级循环出来一级标签
+    arr.map(item => {
+            if (!!first[item.FirstTag] && first[item.FirstTag].length) {} else {
+                first[item.FirstTag] = []
+            }
+            first[item.FirstTag].push(item)
+        })
+        // 循环出第二级标签
+    let sound = []
+    for (let key in first) {
+        let obj = {
+            FirstTag: key,
+            details: {}
+        }
+        first[key].map(item => {
+            if (!!obj.details[item.SecondTag] && obj.details[item.SecondTag].length) {
+
+            } else {
+                obj.details[item.SecondTag] = []
+            }
+            obj.details[item.SecondTag].push(item)
+        })
+        sound.push(obj)
+    }
+    // 循环出制定的数据结构
+    let newArr = sound.map(item => {
+        let copyarr = Object.assign(item.details, {})
+        for (let k in item.details) {
+            if (item.details instanceof Array) {} else {
+                item.details = []
+            }
+            item.details.push({
+                SecondTag: k,
+                details: copyarr[k]
+            })
+        }
+        return item
+    })
+    return newArr
+}

+ 70 - 0
src/utils/scan/hasontableUtils.js

@@ -0,0 +1,70 @@
+const handsonUtils = {
+    /**
+     * 获取被排序后的数组
+     *
+     * @param changeData 发生改变的数据
+     * @param source     数组
+     *
+     * @return array     经过排序后或者经过搜索后的数组
+     */
+    getParam: function(changeData, source, hot, trimmedArr) {
+        let param = "";
+        //被筛选过后的数组
+        // let trimmedArr = this.trimmedRows();
+        //是否启用了排序
+        let isSort = hot.getPlugin("columnSorting").isSorted();
+        if (trimmedArr.length && isSort) {
+            //排序后的数组
+            let sortArr = hot.getPlugin("columnSorting").rowsMapper.__arrayMap;
+            param = changeData.map(item => {
+                return hot.getSourceDataAtRow(trimmedArr[sortArr[item[0]]]);
+            });
+        } else if (isSort) {
+            //排序后的数组
+            let sortArr = hot.getPlugin("columnSorting").rowsMapper.__arrayMap;
+            param = changeData.map(item => {
+                return hot.getSourceDataAtRow(sortArr[item[0]]);
+            });
+        } else if (trimmedArr.length) {
+            param = changeData.map(item => {
+                return hot.getSourceDataAtRow(trimmedArr[item[0]]);
+            });
+        } else {
+            param = changeData.map(item => {
+                return hot.getSourceDataAtRow(item[0]);
+            });
+        }
+        return param;
+    },
+
+    /**
+     * 
+     * @param {handsontable修改参数} changeData 
+     * @param {*} source 
+     * @param {handsontabele实例} hot 
+     * @param {排序数组} trimmedArr
+     * 
+     * @return 修改数值的前一个对象 
+     */
+    getUnshiftParam: function(changeData, source, hot, trimmedArr) {
+        //是否启用了排序
+        let isSort = hot.getPlugin("columnSorting").isSorted();
+        if (trimmedArr.length && isSort) {
+            //排序后的数组
+            let sortArr = hot.getPlugin("columnSorting").rowsMapper.__arrayMap;
+            return hot.getSourceDataAtRow(trimmedArr[sortArr[changeData[0][0] - 1]])
+        } else if (isSort) {
+            //排序后的数组
+            let sortArr = hot.getPlugin("columnSorting").rowsMapper.__arrayMap;
+            return hot.getSourceDataAtRow(sortArr[changeData[0][0] - 1])
+        } else if (trimmedArr.length) {
+            //进行了筛选
+            return hot.getSourceDataAtRow(trimmedArr[changeData[0][0] - 1])
+        } else {
+            //没有进行排序和筛选
+            return hot.getSourceDataAtRow(changeData[0][0] - 1);
+        }
+    },
+}
+
+export default handsonUtils

Файловите разлики са ограничени, защото са твърде много
+ 2044 - 0
src/views/data_admin/buildData/index.vue


+ 459 - 0
src/views/data_admin/buildLog/index.vue

@@ -0,0 +1,459 @@
+<!--
+  revit扫楼日志
+ -->
+<template>
+    <div id="build_log">
+        <div class="search_header">
+            <build-input :placeholder="placeholder" @search="search"></build-input>
+            <em @click="showDic" class="dong_dic">
+                <i class="iconfont icon-wenti"></i>
+                <i style="font-size:12px;">动作说明</i>
+            </em>
+            <build-time :timeArr="timeArr" @checkTime="checkTime"></build-time>
+            <div class="derived_btn" @click="downExcel">
+                <i class="iconfont icon-excelwenjian"></i>
+                <i class="excel">导出到Excel</i>
+            </div>
+            <div class="derived_btn" @click="refresh">
+                <i class="iconfont icon-shuaxin"></i>
+                <i class="excel">刷新</i>
+            </div>
+        </div>
+        <div class="log_view" v-loading="loading">
+            <div id="log"></div>
+            <div v-if="noData" class="no_data">暂无数据</div>
+        </div>
+        <div class="log_page">
+            <el-pagination
+                @size-change="handleSizeChange"
+                @current-change="handleCurrentChange"
+                :current-page.sync="currentPage"
+                :page-sizes="pageSizeArr"
+                :page-size="pageSize"
+                layout="total, sizes, prev, pager, next, jumper"
+                :total="pageCount"
+            ></el-pagination>
+        </div>
+        <el-dialog class="log_dialog" title="动作说明" :visible.sync="dic">
+            <dl>二维码</dl>
+            <dt>查询设备资产</dt>
+            <dt>查询点位标签</dt>
+            <dl>信标</dl>
+            <dt>创建信标</dt>
+            <dt>批量删除信标</dt>
+            <dt>查询信标</dt>
+            <dt>批量更新信标</dt>
+            <dl>建筑</dl>
+            <dt>下载建筑信息</dt>
+            <dt>根据建筑ID获得楼层信息</dt>
+            <dt>根据项目ID获得建筑列表</dt>
+            <dl>扫楼用户</dl>
+            <dt>扫楼用户切换项目</dt>
+            <dt>创建扫楼用户</dt>
+            <dt>删除扫楼用户</dt>
+            <dt>扫楼用户登录</dt>
+            <dt>查询扫楼用户</dt>
+            <dt>批量更新扫楼用户</dt>
+            <dt>扫楼用户获得验证码</dt>
+            <dl>扫楼用户日志</dl>
+            <dt>导出扫楼用户日志</dt>
+            <dt>查看扫楼用户日志</dt>
+            <dl>数据字典</dl>
+            <dt>查看所有设备族</dt>
+            <dt>设备族信息点</dt>
+            <dl>模板</dl>
+            <dt>打印标签模板</dt>
+            <dl>点位标签</dl>
+            <dt>创建点位标签</dt>
+            <dt>批量删除点位标签</dt>
+            <dt>查询点位标签</dt>
+            <dt>批量更新扫楼用户</dt>
+            <dl>设备资产</dl>
+            <dt>创建设备资产</dt>
+            <dt>批量删除设备资产</dt>
+            <dt>异常设备资产</dt>
+            <dt>设备族列表</dt>
+            <dt>按标签分组查询修改信息</dt>
+            <dt>查询设备资产</dt>
+            <dt>查询设备资产(专供revit)</dt>
+            <dt>批量更新设备资产</dt>
+            <dl>项目</dl>
+            <dt>登记项目(在扫楼app中登录项目信息)</dt>
+            <dt>查询项目信息</dt>
+            <dt>更新项目信息</dt>
+        </el-dialog>
+    </div>
+</template>
+
+<script>
+import buildInput from '@/components/data_admin/input'
+import buildTime from '@/components/data_admin/selectTime'
+
+
+import {
+    getBuildLog,//获取日志
+    dowmloadLog//下载日志
+} from '@/api/scan/request'
+
+import axios from 'axios'
+import {
+    mapGetters,
+    mapActions
+} from "vuex"
+
+export default {
+    components: {
+        'build-input': buildInput,
+        'build-time': buildTime
+    },
+    data() {
+        return {
+            placeholder: '请输入操作人、动作、对象id、等关键字搜索',
+            timeArr: ['一个月内', '一周内', '近三天', '昨天', '今天'],
+            checkTimeArr: [],
+            myHot: '',
+            filter: '',
+            pageNum: 1,
+            pageSize: 10,
+            logData: [],
+            resrtData: [],
+            pageSizeArr: [10, 30, 50, 100, 150, 200],
+            pageCount: 0,
+            currentPage: 1,
+            noData: false,//有无数据
+            // ProjId: this.$store.state.projectId,//url获取项目id this.$route.query.projId
+            // UserId: this.$route.query.userId,//url获取用户id this.$route.query.userId
+            loading: false,
+            dic: false,
+        }
+    },
+    created() {
+        this.checkTimeArr = [this.getNowFormatDate(new Date().setHours(0, 0, 0, 0)), this.getNowFormatDate(new Date())]
+        this.getLogData()
+    },
+    mounted() {
+    },
+    computed: {
+        ...mapGetters("peojMess", [
+        "projectId",
+        "userId",
+        "secret"
+    ])
+    },
+    methods: {
+        showDic() {
+            this.dic = true
+        },
+        //下载excel
+        downExcel() {
+            let param = {
+                'startTime': this.checkTimeArr[0],
+                'endTime': this.checkTimeArr[1],
+                'filter': this.filter,
+                "ProjId": this.projectId,
+                "UserId": this.userId,
+                "Comming": "revit",
+            }
+            axios({
+                method: 'post',
+                url: 'api/ScanBuilding/service/user_log/export',
+                data: param,
+                responseType: 'blob'
+            })
+                .then(function (res) {
+                    var blob = new Blob([res.data], {
+                        type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8'
+                    });
+                    var fileName = res.headers['content-disposition'];
+                    if (fileName)
+                        fileName = fileName.substring(fileName.indexOf('=') + 1);
+                    if ('download' in document.createElement('a')) { // 非IE下载
+                        const elink = document.createElement('a')
+                        elink.download = fileName
+                        elink.style.display = 'none'
+                        elink.href = URL.createObjectURL(blob)
+                        document.body.appendChild(elink)
+                        elink.click()
+                        URL.revokeObjectURL(elink.href) // 释放URL 对象
+                        document.body.removeChild(elink)
+                    } else { // IE10+下载
+                        navigator.msSaveBlob(blob, fileName)
+                    }
+                })
+                .catch(function (err) {
+                    console.dirxml(err);
+                })
+        },
+
+        //选择一页个数
+        handleSizeChange(val) {
+            this.loading = true
+            if (this.myHot) {
+                this.myHot.destroy()
+                this.myHot = ''
+            }
+            this.pageSize = val
+            this.getLogData()
+        },
+
+        //选择页数
+        handleCurrentChange(val) {
+            this.loading = true
+            if (this.myHot) {
+                this.myHot.destroy()
+                this.myHot = ''
+            }
+            this.pageNum = val
+            this.getLogData()
+        },
+
+        //刷新
+        refresh() {
+            this.loading = true
+            if (this.myHot) {
+                this.myHot.destroy()
+                this.myHot = ''
+            }
+            this.pageNum = this.currentPage = 1
+            this.getLogData()
+        },
+
+        //搜索
+        search(val) {
+            this.loading = true
+            if (this.myHot) {
+                this.myHot.destroy()
+                this.myHot = ''
+            }
+            this.filter = val
+            this.pageNum = this.currentPage = 1
+            this.getLogData()
+        },
+
+        //选择时间
+        checkTime(val) {
+            this.loading = true
+            if (this.myHot) {
+                this.myHot.destroy()
+                this.myHot = ''
+            }
+            this.pageNum = this.currentPage = 1
+            this.checkTimeArr = val
+            this.getLogData()
+        },
+
+        //获取log数据
+        getLogData() {
+            let param = {
+                'startTime': this.checkTimeArr[0],
+                'endTime': this.checkTimeArr[1],
+                'filter': this.filter,
+                'pageNum': this.pageNum,
+                'pageSize': this.pageSize,
+                "ProjId": this.projectId,
+                "UserId": this.userId
+            }
+            getBuildLog(
+                param
+            ).then(
+                result => {
+                    this.logData = result.data.LogList
+                    this.pageCount = result.data.Count
+                    this.loading = false
+                    if (this.pageCount) {
+                        this.noData = false
+                        if (this.myHot) {
+                            this.myHot.loadData(this.delArr(this.logData))
+                        } else {
+                            this.populateHot()
+                        }
+                    } else {
+                        if (this.myHot) {
+                            this.myHot.destroy()
+                            this.myHot = ''
+                        }
+                        this.noData = true
+                    }
+                }
+            )
+        },
+
+        mouseOver(event, coords, TD) {
+            if (coords.col == 6) {
+                TD.setAttribute('title', this.resrtData[coords.row])
+            }
+        },
+
+        //处理操作说明
+        delArr(arr) {
+            if (arr.length) {
+                let newArr = this.deepCopy(arr).map(
+                    (item, index) => {
+                        this.resrtData[index] = item.Note
+                        let noteArr = item.Note.split('\n')
+                        if (noteArr.length > 2) {
+                            item.Note = noteArr[0] + '\n' + noteArr[1] + '\n ...'
+                        }
+                        return item
+                    }
+                )
+                return newArr
+            }
+        },
+
+        //生成实例
+        populateHot() {
+            var container1 = document.getElementById('log')
+            var options = {
+                data: this.delArr(this.logData),
+                colHeaders: ['时间', '来源', '操作人', '手机', '动作', '对象id', '操作说明'],
+                manualColumnResize: true,
+                manualColumnMove: true,
+                stretchH: 'last',
+                readOnly: true,
+                columns: [
+                    {
+                        data: 'CreateTime',
+                    },
+                    {
+                        data: 'Comming',
+                    },
+                    {
+                        data: 'UserName',
+                    },
+                    {
+                        data: 'Phone',
+                    },
+                    {
+                        data: 'Action',
+                    },
+                    {
+                        data: 'projectId'
+                    },
+                    {
+                        data: 'Note',
+                    }
+                ],
+                afterOnCellMouseOver: this.mouseOver
+            }
+            this.myHot = new Handsontable(container1, options)
+            // this.getTd()
+            document.getElementById('hot-display-license-info').style.display = 'none'
+        },
+
+        //处理时间
+        getNowFormatDate(str) {
+            var date = new Date(str);
+            var seperator1 = "-";
+            var seperator2 = ":";
+            var month = date.getMonth() + 1;
+            var strDate = date.getDate();
+            if (month >= 1 && month <= 9) {
+                month = "0" + month;
+            }
+            if (strDate >= 0 && strDate <= 9) {
+                strDate = "0" + strDate;
+            }
+            var currentdate = date.getFullYear() + seperator1 + month + seperator1 + strDate
+                + " " + date.getHours() + seperator2 + date.getMinutes()
+                + seperator2 + date.getSeconds();
+            return currentdate;
+        },
+
+        //工具函数浅复制深拷贝,防止共用存储空间
+        deepCopy(obj) {
+            var out = [], i = 0, len = obj.length;
+            for (; i < len; i++) {
+                if (obj[i] instanceof Array) {
+                    out[i] = deepcopy(obj[i]);
+                }
+                else out[i] = obj[i];
+            }
+            return out;
+        },
+
+        //字符处理,将\n转换成<br/>
+        changeBr(str) {
+            return str.replace(/\n/g, "<br/>")
+        }
+    }
+}
+</script>
+
+<style lang="less" scoped>
+#app {
+  min-width: 1098px;
+  min-height: 767px;
+  position: relative;
+  overflow-x: auto;
+}
+#build_log {
+  width: 100%;
+  height: 100%;
+  overflow: hidden;
+  box-sizing: border-box;
+  dl {
+    font-size: 20px;
+    font-weight: 600;
+  }
+  dt {
+    margin-left: 20px;
+    line-height: 25px;
+  }
+  .search_header {
+    min-width: 1098px;
+    padding-top: 0.4rem;
+    padding-left: 1rem;
+    padding-right: 1rem;
+    height: 3rem;
+    margin-bottom: 1rem;
+    background-color: #eee;
+    .dong_dic {
+      cursor: pointer;
+    }
+    .derived_btn {
+      width: 6rem;
+      border: 1px solid #777;
+      text-align: center;
+      font-size: 0.6rem;
+      height: 1.6rem;
+      line-height: 1.6rem;
+      cursor: pointer;
+      background-color: #ccc;
+      border-radius: 0.1rem;
+      float: right;
+      margin-right: 1rem;
+      margin-top: 0.2rem;
+      .icon-excelwenjian {
+        font-size: 1rem;
+        margin-bottom: -0.1rem;
+      }
+      .excel {
+        font-size: 12px;
+        display: inline-block;
+        line-height: 1.4rem;
+      }
+    }
+  }
+  .log_view {
+    position: absolute;
+    left: 0;
+    padding-left: 1rem;
+    padding-right: 1rem;
+    top: 3rem;
+    bottom: 3rem;
+    right: 0;
+    overflow-y: auto;
+    box-sizing: border-box;
+  }
+  .log_page {
+    position: fixed;
+    bottom: 0;
+    width: 100%;
+    left: 0;
+    right: 0;
+    height: 3rem;
+    background-color: #fff;
+  }
+}
+</style>

+ 504 - 0
src/views/data_admin/buildUser/index.vue

@@ -0,0 +1,504 @@
+<!--
+  revit扫楼人员管理
+ -->
+<template>
+  <div id="build_user">
+    <div class="search_header">
+      <build-input :placeholder="placeholder" @search="search"></build-input>
+      <div class="inline_block" @click="tableAddUser">
+        <i class="iconfont icon-addpeople_fill"></i>
+        <i>添加扫楼人员</i>
+      </div>
+      <div class="inline_block" @click="undo">
+        <i class="iconfont icon-undo"></i>
+        <i>撤回</i>
+      </div>
+      <div class="inline_block" @click="refresh">
+        <i class="iconfont icon-shuaxin"></i>
+        <i>刷新</i>
+      </div>
+    </div>
+    <div class="user_view" v-loading="loading">
+      <div id="user"></div>
+      <div class="no_data" v-show="noData">暂无数据</div>
+    </div>
+    <div class="user_page">
+      <el-pagination
+        @size-change="handleSizeChange"
+        @current-change="handleCurrentChange"
+        :current-page.sync="currentPage"
+        :page-sizes="pageSizeArr"
+        :page-size="pageSize"
+        layout="total, sizes, prev, pager, next, jumper"
+        :total="pageCount"
+      ></el-pagination>
+    </div>
+    <el-dialog title="提示" :visible.sync="dialogVisible" :before-close="handleClose">
+      <span>{{msg}}</span>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="dialogVisible = false">取 消</el-button>
+        <el-button type="primary" @click="dialogVisible = false">确 定</el-button>
+      </span>
+    </el-dialog>
+    <el-dialog title="提示" :visible.sync="deldialog">
+      <span>你确定删除用户{{delString}}吗?</span>
+      <span slot="footer" class="dialog-footer">
+        <el-button @click="refresh">取 消</el-button>
+        <el-button type="primary" @click="delTrue">确 定</el-button>
+      </span>
+    </el-dialog>
+  </div>
+</template>
+
+<script>
+import buildInput from "@/components/data_admin/input";
+import buildTime from "@/components/data_admin/selectTime";
+import {
+    mapGetters,
+    mapActions
+} from 'vuex'
+import {
+  getUser, //获取扫楼用户
+  loadUser, //修改
+  delUser, //删除
+  addUser //添加
+} from "@/api/scan/request";
+import Handsontable from "handsontable-pro"
+import 'handsontable-pro/dist/handsontable.full.css'
+import zhCN from 'handsontable-pro/languages/zh-CN';
+export default {
+  components: {
+    "build-input": buildInput,
+    "build-time": buildTime
+  },
+  data() {
+    return {
+      placeholder: "请输入姓名、联系电话、登录名、备注等关键字搜索",
+      checkTimeArr: [], //选择到的时间周期
+      myHot: "", //表格实例
+      row: "",
+      col: "",
+      dialogVisible: false,
+      deldialog: false,
+      msg: "",
+      pageNum: 1,
+      pageSize: 10,
+      pageSizeArr: [5, 10, 20, 30, 50],
+      pageCount: 0,
+      currentPage: 1,
+      filter: "",
+      userData: [],
+      delString: "",
+      delArr: [],
+      noData: false,
+      // ProjId: this.$route.query.projId, //url获取项目id this.$route.query.projId /Pj1101080047/Pj1101080001
+      // UserId: this.$route.query.userId, //url获取用户id this.$route.query.userId/25518428919955458
+      loading: false, //loading动画
+      deepArr: [] //删除时使用的数组
+    };
+  },
+  mounted() {
+    this.getUserTable();
+    //   this.populateHot()
+  },
+  computed: {
+    ...mapGetters("peojMess", [
+        "projectId",
+        "userId",
+        "secret"
+    ])
+  },
+  methods: {
+    //获取用户表格
+    getUserTable() {
+      let param = {
+        filter: this.filter,
+        pageNum: this.pageNum,
+        pageSize: this.pageSize,
+        ProjId: this.projectId,
+        UserId: this.userId
+      };
+
+      getUser(param).then(result => {
+        this.userData = result.data.UserList;
+        this.pageCount = result.data.Count;
+        this.loading = false;
+        //存储一个数组防止删除操作找寻不到删除的该数组
+        this.deepArr = this.deepCopy(result.data.UserList);
+        if (this.userData.length) {
+          this.noData = false;
+          if (this.myHot) {
+            this.myHot.loadData(result.data.UserList);
+          } else {
+            this.populateHot();
+          }
+        } else {
+          this.noData = true;
+          if (this.myHot) {
+            this.myHot.destroy();
+            this.myHot = "";
+          }
+        }
+      });
+    },
+
+    //删除用户
+    delUser(UserList) {
+      let param = {
+        ProjId: this.projectId,
+        UserId: this.userId,
+        UserList: UserList
+      };
+      delUser(param).then(result => {
+        if (result.data.Result == "success") {
+          this.getUserTable();
+          return;
+        } else {
+          this.msg = "请求出错";
+          this.dialogVisible = true;
+        }
+      });
+    },
+
+    //更新用户
+    loadUser(UserList) {
+      let param = {
+        ProjId: this.projectId,
+        UserId: this.userId,
+        UserList: UserList
+      };
+      loadUser(param).then(result => {
+        if (result.data.Result == "success") {
+          return;
+        } else {
+          this.msg = "请求出错";
+          this.dialogVisible = true;
+        }
+      });
+    },
+
+    //请求接口添加用户
+    addUser(User) {
+      let param = {
+        ProjId: this.projectId,
+        UserId: this.userId,
+        User: User
+      };
+      addUser(param).then(result => {
+        if (result.data.Result == "success") {
+          this.userData[0].UserId = result.data.UserId;
+          this.userData[0].ProjId = this.projectId;
+          return;
+        } else {
+          this.msg = "请确定手机号码未重复";
+          this.dialogVisible = true;
+        }
+      });
+    },
+
+    //表格添加用户
+    tableAddUser() {
+      let param = {
+        Note: "",
+        Phone: "",
+        UserName: ""
+      };
+      //判断是否有第一个用户
+      if (this.userData[0]) {
+        //有的话判断第一个用户是否是空值,空值禁止再次添加
+        if (this.userData[0].Phone && this.userData[0].UserName) {
+          this.userData.unshift(param);
+          this.deepArr.unshift(param);
+          this.pageCount += 1;
+          this.myHot.destroy();
+          this.myHot = "";
+          this.populateHot();
+          this.noData = false;
+        } else {
+          return;
+        }
+      } else {
+        //没有第一个用户再次生成表格
+        this.userData.unshift(param);
+        this.deepArr.unshift(param);
+        this.pageCount += 1;
+        this.myHot = "";
+        this.populateHot();
+        this.noData = false;
+      }
+    },
+
+    //撤回
+    undo() {
+      this.myHot.undo();
+    },
+
+    //搜索
+    search(val) {
+      this.loading = true;
+      if (this.myHot) {
+        this.myHot.destroy();
+        this.myHot = "";
+      }
+      this.filter = val;
+      this.pageNum = this.currentPage = 1;
+      this.getUserTable();
+    },
+
+    //一页的个数
+    handleSizeChange(val) {
+      this.loading = true;
+      this.pageSize = val;
+      this.myHot.destroy();
+      this.myHot = "";
+      this.getUserTable();
+    },
+
+    //当前页
+    handleCurrentChange(val) {
+      this.loading = true;
+      this.pageNum = val;
+      this.myHot.destroy();
+      this.myHot = "";
+      this.getUserTable();
+    },
+
+    //刷新
+    refresh() {
+      this.loading = true;
+      this.myHot.destroy();
+      this.myHot = "";
+      this.deldialog = false;
+      this.getUserTable();
+    },
+
+    //弹窗关闭
+    handleClose(done) { },
+
+    //表格单元格单击时触发
+    callBack(event, coords, td) {
+      var row = coords.row;
+      var col = coords.col;
+      if (row != 0 && col != 0) {
+        var ss = this.myHot.getCell(row, col, true); //取出点击Cell
+        (this.row = row), (this.col = col);
+      }
+    },
+
+    //单元格修改内容触发
+    tdClick(changeData, source) {
+      // changeData 是一个数组,第一个元素(数组),记录所有修改信息
+      if (!changeData) return;
+      let rep = /^1(3|4|5|7|8)\d{9}$/;
+      let indexArr = changeData.map(item => {
+        return item[0];
+      });
+      // let dataArr
+      let param = indexArr.map((item, index) => {
+        if (
+          !rep.test(this.userData[item].Phone) &&
+          this.userData[item].ProjId
+        ) {
+          this.msg = "手机号码格式错误";
+          this.dialogVisible = true;
+          return this.userData[item];
+        } else if (this.userData[item].UserName.length < 0) {
+          this.msg = "姓名不可少于一个字符";
+          this.dialogVisible = true;
+          return this.userData[item];
+        } else {
+          return this.userData[item];
+        }
+      });
+
+      //处理好数据,请求接口
+      if (param[0].ProjId) {
+        this.loadUser(param);
+      } else {
+        //当数据没有projId时走添加接口
+        if (param[0].Phone != "" && param[0].UserName.length > 2) {
+          if (rep.test(param[0].Phone)) {
+            this.addUser(param[0]);
+          } else {
+            this.msg = "手机号码格式错误";
+            this.dialogVisible = true;
+            return;
+          }
+        } else {
+          return;
+        }
+      }
+    },
+
+    delTrue() {
+      this.delUser(this.delArr);
+      this.deldialog = false;
+    },
+
+    //处理右键删除
+    removeUser(index, amout) {
+      this.deldialog = true;
+      this.delString = "";
+      this.delArr = [];
+      let i = index + amout;
+      for (; index < i; index++) {
+        if (index + 1 == i) {
+          this.delString += this.deepArr[index].UserName;
+        } else {
+          this.delString += this.deepArr[index].UserName + "、";
+        }
+        this.delArr.push(this.deepArr[index].UserId);
+      }
+    },
+
+    //表格渲染生成
+    populateHot() {
+      var container1 = document.getElementById("user");
+      let maxRow = "";
+      //当当前页数*当前页个数小于总个数时,当前表格行数为当前页数
+      if (this.pageCount >= this.pageSize * this.currentPage) {
+        maxRow = this.pageSize;
+      } else {
+        maxRow = this.pageCount % this.pageSize;
+      }
+      var options = {
+        data: this.userData,
+        colHeaders: ["姓名", "联系电话/登录名", "备注"],
+        manualColumnResize: true, //允许改变表头宽度
+        manualColumnMove: true, //允许拉动表头
+        stretchH: "last", //最后一行填充
+        maxRows: maxRow,
+        contextMenu: {
+          items: {
+            remove_row: {
+              name: "删除用户"
+            }
+          }
+        },
+        columns: [
+          {
+            data: "UserName"
+          },
+          {
+            data: "Phone",
+            type: "numeric"
+          },
+          {
+            data: "Note"
+          }
+        ],
+        // beforeRemoveRow: this.removeUser,
+        afterRemoveRow: this.removeUser
+      };
+      this.myHot = new Handsontable(container1, options);
+      //表格数据发生改变
+      this.myHot.addHook("afterChange", this.tdClick);
+      // this.myHot.afterRemoveRow()
+
+      //删除前
+      // this.myHot.removeHook('beforeInit', this.removeUser);
+      //添加单击事件
+      // Handsontable.hooks.add('afterOnCellMouseDown',this.callBack,this.myHot)
+      document.getElementById("hot-display-license-info").style.display =
+        "none";
+    },
+
+    //工具函数浅复制深拷贝,防止共用存储空间
+    deepCopy(obj) {
+      var out = [],
+        i = 0,
+        len = obj.length;
+      for (; i < len; i++) {
+        if (obj[i] instanceof Array) {
+          out[i] = deepcopy(obj[i]);
+        } else out[i] = obj[i];
+      }
+      return out;
+    }
+  }
+};
+</script>
+
+<style lang="less" scoped>
+#app {
+  min-width: 1098px;
+  min-height: 767px;
+  position: relative;
+  overflow-x: auto;
+}
+#build_user {
+  width: 100%;
+  // padding-top: .4rem;
+  // padding-left: 1rem;
+  // padding-right: 1rem;
+  box-sizing: border-box;
+  .search_header {
+    height: 3rem;
+    padding-top: 0.4rem;
+    box-sizing: border-box;
+    padding-left: 1rem;
+    padding-right: 1rem;
+    background-color: #eee;
+    width: 100%;
+    .derived_btn {
+      width: 8rem;
+      border: 1px solid #777;
+      text-align: center;
+      font-size: 0.6rem;
+      height: 1.6rem;
+      line-height: 1.6rem;
+      cursor: pointer;
+      background-color: #ccc;
+      border-radius: 0.1rem;
+      float: right;
+      margin-right: 3rem;
+      margin-top: 0.2rem;
+      .icon-excelwenjian {
+        font-size: 1rem;
+        margin-bottom: -0.1rem;
+      }
+    }
+    .inline_block {
+      float: right;
+      margin-left: 3rem;
+      padding: 0 0.8rem;
+      font-size: 0.8rem;
+      height: 2rem;
+      line-height: 2rem;
+      color: #000;
+      text-align: center;
+      border-radius: 0.8rem;
+      cursor: pointer;
+      .iconfont {
+        font-size: 1rem;
+      }
+    }
+  }
+  .user_view {
+    position: absolute;
+    width: 100%;
+    top: 3.5rem;
+    left: 0;
+    right: 0;
+    bottom: 0;
+    overflow-y: auto;
+    // #user{
+    //     table{
+    //         tr{
+    //             td:first-child{
+    //                 text-align: center;
+    //             }
+    //         }
+    //     }
+    // }
+  }
+  .user_page {
+    position: fixed;
+    height: 3rem;
+    left: 0;
+    bottom: 0;
+    right: 0;
+    width: 100%;
+  }
+}
+</style>