Просмотр исходного кода

新建建设项目,输入建设项目名称,点击下一步无反应。隔长时间重复操作才能新建建设项目

zhongzewei 6 лет назад
Родитель
Сommit
ca19567d0e

Разница между файлами не показана из-за своего большого размера
+ 1 - 0
lib/x2js/xml2json.min.js


+ 17 - 1
web/building_saas/css/main.css

@@ -39,6 +39,22 @@ a{
 .form-check .form-check-label,.form-radio .form-check-label{
     cursor: pointer;
 }
+.custom-file-sm,.custom-file-sm .custom-file-label{
+    height: calc(1.5em + .5rem + 2px);
+    padding-top: .25rem;
+    padding-bottom: .25rem;
+    padding-left: .5rem;
+}
+.custom-file-sm .custom-file-label:after{
+    height: calc(1.4em + .5rem + 2px);
+    padding-top: .25rem;
+    padding-bottom: .25rem;
+    font-size: .875rem;
+}
+.custom-file-sm input{
+    height: calc(1.5em + .5rem + 2px);
+    font-size: .875rem;
+}
 /*自定义css*/
 .login-body,.login-html{
     height:100%;
@@ -647,4 +663,4 @@ a{
         white-space: nowrap;
         max-width:80px;
     }
-}
+}

+ 33 - 14
web/building_saas/main/js/models/exportStandardInterface.js

@@ -32,6 +32,8 @@ const XMLStandard = (function () {
         [fixedFlag.MEASURE]: '1200',
         [fixedFlag.CONSTRUCTION_ORGANIZATION]: '120201',
         [fixedFlag.SAFETY_CONSTRUCTION]: '1204',
+        [fixedFlag.PROJECT_COMPLETE_ARCH_FEE]: '10041',
+        [fixedFlag.HOUSE_QUALITY_ACCEPT_FEE]: '1206',
         [fixedFlag.OTHER]: '1300',
         [fixedFlag.CHARGE]: '800',
         [fixedFlag.TAX]: '900',
@@ -87,41 +89,54 @@ const XMLStandard = (function () {
                     rst.filterAttrs.push(data);
                     continue;
                 }
-                let isFail = false;
+                let isFail = false,
+                    tempFail = '';
                 if (data.minLen && data.value.length < data.minLen){
                     isFail = true;
-                    rst.failHints.push(`“${data.name}”字符数不可小于${data.minLen}个`);
+                    tempFail = `“${data.name}”字符数不可小于${data.minLen}个`;
+                    //rst.failHints.push(`“${data.name}”字符数不可小于${data.minLen}个`);
                 } else if (data.maxLen && data.value.length > data.maxLen) {
                     isFail = true;
-                    rst.failHints.push(`“${data.name}”字符数不可大于${data.maxLen}个`);
+                    tempFail = `“${data.name}”字符数不可大于${data.maxLen}个`;
+                    //rst.failHints.push(`“${data.name}”字符数不可大于${data.maxLen}个`);
                 } else if (data.enumeration && !data.enumeration.includes(data.value)) {
                     isFail = true;
-                    rst.failHints.push(`“${data.name}”只能从“${data.enumeration.join(';')}”中选择`);
+                    tempFail = `“${data.name}”只能从“${data.enumeration.join(';')}”中选择`;
+                    //rst.failHints.push(`“${data.name}”只能从“${data.enumeration.join(';')}”中选择`);
                 } else if (data.type && data.type === TYPE.DATE && !dateReg.test(data.value)) {
                     isFail = true;
-                    rst.push(`“${data.name}”日期格式必须是YYYY-MM-DD`);
+                    tempFail = `“${data.name}”日期格式必须是YYYY-MM-DD`;
+                    //rst.push(`“${data.name}”日期格式必须是YYYY-MM-DD`);
                 } else if (data.type && data.type === TYPE.INT && !Number.isInteger(parseFloat(data.value))) {
                     isFail = true;
-                    rst.failHints.push(`“${data.name}”必须为整数`);
+                    tempFail = `“${data.name}”必须为整数`;
+                    //rst.failHints.push(`“${data.name}”必须为整数`);
                 } else if (data.type && data.type === TYPE.DECIMAL && isNaN(parseFloat(data.value))) {
                     isFail = true;
-                    rst.failHints.push(`“${data.name}”必须为数值`)
+                    tempFail = `“${data.name}”必须为数值`;
+                    //rst.failHints.push(`“${data.name}”必须为数值`)
                 } else if (data.type && data.type === TYPE.NUM2) {
                     let v = parseFloat(data.value);
                     if (isNaN(v)) {
                         isFail = true;
+                        tempFail = `“${data.name}”必须为数值`;
                         rst.failHints.push(`“${data.name}”必须为数值`);
                     } else if (!data.value.length || (data.value.split('.').length > 1 && data.value.split('.')[1].length > 2)){
                         isFail = true;
-                        rst.failHints.push(`“${data.name}”小数位数不得多于两位`);
+                        //tempFail = `“${data.name}”小数位数不得多于两位`;
+                        //rst.failHints.push(`“${data.name}”小数位数不得多于两位`);
                     }
                 } else if (data.type && data.type === TYPE.BOOL && !['true', 'false'].includes(data.value.toString())) {
                     isFail = true;
-                    rst.failHints.push(`“${data.name}”必须为true或false`);
+                    tempFail = `“${data.name}”必须为true或false`;
+                    //rst.failHints.push(`“${data.name}”必须为true或false`);
                 }
                 if (!isFail || data.required) {
                     rst.filterAttrs.push(data);
                 }
+                if (isFail && data.required && tempFail) {
+                    rst.failHints.push(tempFail);
+                }
             }
             return rst;
         }
@@ -1268,14 +1283,18 @@ const XMLStandard = (function () {
                 if (rationData.adjustState) {
                     viewCode += '换';
                 }
-                //子目类型 补充定额为“1”,标准定额无换算为“0”,标准定额有换算为“2”,其他待完善……
+                //子目类型 补充定额为“1”,标准定额无换算为“0”,标准定额有换算为“2”,安装费用,即自动生成的安装子目,为“3”,子目级人材机,即量价、与定额同级的人材机 其他待完善……
                 let subType;
-                if (rationData.from === 'cpt') {
+                if (rationData.type === rationType.ration && rationData.from === 'cpt') {
                     subType = '1';
-                } else if (!rationData.adjustState) {
+                } else if (rationData.type === rationType.ration && !rationData.adjustState) {
                     subType = '0';
-                } else {
+                } else if (rationData.type === rationType.ration && rationData.adjustState) {
                     subType = '2';
+                } else if (rationData.type === rationType.install) {
+                    subType = '3';
+                } else if (rationData.type === rationType.volumePrice) {
+                    subType = '6';
                 }
                 let rationSource = {
                     viewCode: viewCode,
@@ -1420,7 +1439,7 @@ const XMLStandard = (function () {
                             feeRate: node.data.feeRate !== '' ? node.data.feeRate : 100,
                             fees: node.data.fees,
                             remark: node.data.remark,
-                            feeType: FEE_TYPE[fixedFlag.CONSTRUCTION_ORGANIZATION]
+                            feeType: FEE_TYPE[getNodeFlag(node)] || FEE_TYPE['0']
                         };
                         let formula = new FormulaCalcMeasure(source);
                         parent.children.push(formula);

+ 103 - 0
web/building_saas/main/js/models/importStandardInterface.js

@@ -0,0 +1,103 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/5/14
+ * @version
+ */
+/*
+* 尽可能减少服务器压力,前端提取后端所需数据
+* */
+const ImportXML = (() => {
+    //读取文件转换为utf-8编码的字符串
+    function readAsTextSync(file) {
+        return new Promise((resolve, reject) => {
+            let fr = new FileReader();
+            fr.readAsText(file);    //默认utf-8,如果出现乱码,得看导入文件是什么编码
+            fr.onload = function () {
+                resolve(this.result);
+            };
+            fr.onerror = function () {
+                reject('读取文件失败,请重试。');
+            }
+        });
+    }
+    /*
+    * 根据字段数组获得所要字段的值 eg: 要获取标段下的单项工程: ['标段', '单项工程'];
+    * @param {Object}obj原始对象 {Array}fields字段数组
+    * */
+    function getValue(obj, fields) {
+        let cur = obj;
+        for (let field of fields) {
+            if (!cur[field]) {
+                return '';
+            }
+            cur = cur[field];
+        }
+        return cur || '';
+    }
+    function plainType(v) {
+        return Object.prototype.toString.call(v).slice(8, -1);
+    }
+    return function () {
+        /*
+        * 获取某字段的值,返回数组
+        * */
+        function arrayValue(source, fields) {
+            let target = getValue(source, fields);
+            if (plainType(target) === 'Object') {
+                target = [target];
+            } else if (plainType(target) !== 'Array') {
+                target = []
+            }
+            return target;
+        }
+        //标段
+        function project(source) {
+            return {
+                name: getValue(source, ['标段', '_项目名称']),
+                engs: eng(source)
+            };
+        }
+        //单项工程
+        function eng(source) {
+            let engSrcs = arrayValue(source, ['标段', '单项工程']),
+                rst = [];
+            for (let src of engSrcs) {
+                rst.push({
+                    name: getValue(src, ['_名称']),
+                    tenders: tender(src)
+                });
+            }
+            return rst;
+        }
+        //单位工程
+        function tender(engSrc) {
+            let tenderSrcs = arrayValue(engSrc, ['单位工程']),
+                rst = [];
+            for (let src of tenderSrcs) {
+                rst.push({
+                    name: getValue(src, ['_名称']),
+                    engineering: getValue(src, ['_专业']),
+                });
+            }
+            return rst;
+        }
+        this.extractData = async (file) => {
+            //将二进制文件转换成字符串
+            let xmlStr = await readAsTextSync(file);
+            //将xml格式良好的字符串转换成对象
+            let x2js = new X2JS();
+            let xmlObj = x2js.xml_str2json(xmlStr);
+            if (!xmlObj) {
+                throw '无有效数据。';
+            }
+            console.log(xmlObj);
+            //提取数据
+            console.log(project(xmlObj));
+            return project(xmlObj);
+        };
+    };
+})();

+ 128 - 0
web/building_saas/pm/html/project-management.html

@@ -745,9 +745,135 @@
         </div>
     </div>
 </div>
+<!--导入标准接口-->
+<div class="modal fade" id="importInterface" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title"><i class="fa fa-sticky-note-o"></i> 导入接口文件</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="progress" style="height: 1px;">
+                <div class="progress-bar" role="progressbar" style="width: 50%;"></div>
+            </div>
+            <div class="modal-body">
+                <form>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">选择文件</label>
+                        <div class="col">
+                            <div class="custom-file custom-file-sm">
+                                <input type="file" class="custom-file-input" id="customFile" accept=".xml,.qtf,.QTF,.xlsx" lang="zh">
+                                <label class="custom-file-label" for="customFile" style="white-space: nowrap; overflow: hidden;">请选择导入文件</label>
+                            </div>
+                            <div class="alert alert-success mt-3" id="uploadAlert" role="alert" style="display: none;"></div>
+                        </div>
+                    </div>
+                </form>
+                <form class="hidden-area selFile">
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">建设项目</label>
+                        <div class="col">
+                            <input type="text" class="form-control form-control-sm" value="建设项目名称" readonly="">
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">计价规则</label>
+                        <div class="col">
+                            <select class="form-control form-control-sm">
+                                <option selected>赣建价[2017]7号</option>
+                                <option value="1">One</option>
+                                <option value="2">Two</option>
+                                <option value="3">Three</option>
+                            </select>
+                        </div>
+                    </div>
+                </form>
+            </div>
+            <div class="modal-footer">
+                <a id="import-next" href="javascript:void(0)" data-toggle="modal" data-target="#import2" class="btn btn-primary">下一步</a>
+            </div>
+        </div>
+        <div class="modal-content" style="display: none">
+            <div class="modal-header">
+                <h5 class="modal-title"><i class="fa fa-sticky-note-o"></i> 导入接口文件</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="progress" style="height: 1px;">
+                <div class="" role="progressbar " style="width: 50%;"></div>  <div class="progress-bar" role="progressbar" style="width: 50%;"></div>
+            </div>
+            <div class="modal-body">
+                <form>
+                    <p>该文件共有10个单位工程待导入</p>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">单项工程</label>
+                        <div class="col">
+                            <input id="tbc-engName" type="text" class="form-control form-control-sm" value="AA单项工程" readonly="">
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">单位工程</label>
+                        <div class="col">
+                            <input id="tbc-tenderName" type="text" class="form-control form-control-sm" value="XXXX单位" readonly="">
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">工程专业</label>
+                        <div class="col">
+                            <select id="tbc-engineering" class="form-control form-control-sm" readonly>
+                                <option selected>建筑工程</option>
+                                <option value="1">One</option>
+                                <option value="2">Two</option>
+                                <option value="3">Three</option>
+                            </select>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">费用标准</label>
+                        <div class="col">
+                            <select class="form-control form-control-sm">
+                                <option selected>建筑工程</option>
+                                <option value="1">One</option>
+                                <option value="2">Two</option>
+                                <option value="3">Three</option>
+                            </select>
+                        </div>
+                    </div>
+                    <div class="form-group row">
+                        <label for="staticEmail" class="col-auto col-form-label col-form-label-sm">计算程序</label>
+                        <div class="col">
+                            <select class="form-control form-control-sm">
+                                <option selected>标准模板</option>
+                                <option value="1">One</option>
+                                <option value="2">Two</option>
+                                <option value="3">Three</option>
+                            </select>
+                        </div>
+                    </div>
+                    <div class="d-flex justify-content-center">
+                        <div class="btn-group btn-group-sm " role="group">
+                            <button id="tbc-prev" type="button" class="btn btn-outline-primary" disabled="">上一工程</button>
+                            <a id="tbc-info" class="btn btn-outline-secondary disabled">1/10 已确认</a>
+                            <button id="tbc-next" type="button" class="btn btn-outline-primary ">下一工程</button>
+                        </div>
+                    </div>
+                </form>
+            </div>
+            <div class="modal-footer">
+                <a id="import-prev" href="javascript:void(0);" data-toggle="modal" data-target="#import1" class="btn btn-primary">上一步</a>
+                <button type="button" class="btn btn-primary">确认导入</button>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+            </div>
+        </div>
+    </div>
+</div>
 <!-- JS. -->
 <script src = "/lib/spreadjs/sheets/gc.spread.sheets.all.11.1.2.min.js"></script>
 <script>GC.Spread.Sheets.LicenseKey = '<%- LicenseKey %>';</script>
+<!--<script src="/lib/x2js/xml2json.min.js"></script>-->
 <!-- inject:js -->
 <script src="/web/building_saas/js/global.js"></script>
 <script src="/public/web/uuid.js"></script>
@@ -764,6 +890,8 @@
 <script src="/public/web/socket/connection.js"></script>
 <script src="/web/building_saas/pm/js/pm_ajax.js"></script>
 <script src="/web/building_saas/pm/js/pm_newMain.js"></script>
+<!--<script src="/web/building_saas/main/js/models/importStandardInterface.js"></script>
+<script src="/web/building_saas/pm/js/pm_import.js"></script>-->
 <script src="/web/building_saas/pm/js/pm_gc.js"></script>
 <script src="/web/building_saas/pm/js/pm_share.js"></script>
 <!-- zTree -->

+ 166 - 0
web/building_saas/pm/js/pm_import.js

@@ -0,0 +1,166 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Zhong
+ * @date 2019/5/15
+ * @version
+ */
+
+const importView = (() => {
+    let xmlObj = null;  //导入xml转化后的对象
+    let tbcObj = null;  //待确认对象
+    //显示、隐藏提示相关信息
+    function showUploadAlert(success, msg){
+        if(!success){
+            $('#uploadAlert').removeClass('alert-success');
+            $('#uploadAlert').addClass('alert-danger');
+        } else{
+            $('#uploadAlert').removeClass('alert-danger');
+            $('#uploadAlert').addClass('alert-success');
+        }
+        $('#uploadAlert').text(msg);
+        $('#uploadAlert').show();
+    }
+    /*
+     * 获取单位工程数据(将所有单项工程里的单位工程放到一起,含有单项工程的一些信息)
+     * @param {Object} xmlObj @return {Array}
+     * */
+    function getTenderDatas(xmlObj) {
+        if (!xmlObj || !xmlObj.engs) {
+            return [];
+        }
+        let rst = [];
+        for (let eng of xmlObj.engs) {
+            if (Array.isArray(eng.tenders)) {
+                for (let tender of eng.tenders) {
+                    tender.engName = eng.name;
+                }
+                rst = [...rst, ...eng.tenders];
+            }
+        }
+        return rst;
+    }
+    //待确认界面相关
+    class TBC {
+        constructor(xmlObj) {
+            this.datas = getTenderDatas(xmlObj);
+            this.curIdx = 0;
+            this.init();
+        }
+        //初始化
+        init() {
+            this.next(0);   //初始化的时候,显示第第一份数据
+            $('#importInterface .modal-content:eq(1) p:eq(0)').text(`该文件共有${this.datas.length}个单位工程待导入`);  //信息统计信息
+        }
+        //下一工程
+        next(idx = null) {
+            this.curIdx = idx !== null ? idx : this.curIdx + 1;
+            let curData = this.datas[this.curIdx];
+            //显示这个工程的相关信息
+            $('#tbc-engName').val(curData.engName || '');
+            $('#tbc-tenderName').val(curData.name || '');
+            $('#tbc-engineering').val(curData.engineering || '');
+            curData.confirmed = true;   //增加确认信息(已读)
+            if (this.curIdx === this.datas.length -1) { //到最后一个数据了,无法点击下一工程
+                $('#tbc-next').prop('disabled', true);
+            }
+            if (this.curIdx !== 0) {    //不为第一个数据,可以点击上一工程
+                $('#tbc-prev').prop('disabled', false);
+            }
+            //更新x/x信息
+            $('#tbc-info').text(`${this.curIdx + 1}/${this.datas.length} 已确认`);
+        }
+        //上一工程
+        prev(idx = null) {
+            this.curIdx = idx !== null ? idx : this.curIdx - 1;
+            let curData = this.datas[this.curIdx];
+            $('#tbc-engName').val(curData.engName || '');
+            $('#tbc-tenderName').val(curData.name || '');
+            $('#tbc-engineering').val(curData.engineering || '');
+            if (this.curIdx === 0) {    //到第一个数据了,无法点击上一工程
+                $('#tbc-prev').prop('disabled', true);
+            }
+            if (this.curIdx !== this.datas.length -1 ) {    //不为最后一个数据了,可以点击下一工程
+                $('#tbc-next').prop('disabled', false);
+            }
+            //更新x/x信息
+            $('#tbc-info').text(`${this.curIdx + 1}/${this.datas.length} 已确认`);
+        }
+    }
+    function eventListen() {
+        //选择文件
+        $('#customFile').change(async function() {
+            let file = $(this)[0].files[0];
+            if (file) {
+                let reg = /(xml|XML|qtf|QTF)$/g;
+                if(file.name && !reg.test(file.name)){
+                    $('.selFile').hide();
+                    showUploadAlert(false, '请选择xml或qtf文件。');
+                    $(this).val('');
+                    return;
+                }
+                $('.custom-file-label').text(`${file.name}`);   //设置选择框文本
+                $('#uploadAlert').hide();
+                $.bootstrapLoading.start();
+                $('#loadingPage').css('z-index', '2000');
+                //转换数据
+                let importXML = new ImportXML();
+                try {
+                    xmlObj = await importXML.extractData(file);
+                    $('.selFile input').val(xmlObj && xmlObj.name ? xmlObj.name : '');
+                    $('.selFile').show();   //显示建设项目、计价规则
+                } catch (err) {
+                    showUploadAlert(false, '请选择xml或qtf文件。');
+                    $(this).val('');
+                }
+                $.bootstrapLoading.end();
+            }
+        });
+        //下一步
+        $('#import-next').click(function () {
+            let file = $('#customFile')[0].files[0];
+            if (!file) {
+                showUploadAlert(false, '请选择导入文件。');
+                return;
+            }
+            let projectName = $('.selFile input').val();
+            if (!projectName) {
+                showUploadAlert(false, '不存在有效建设项目。');
+                return;
+            }
+            $('#importInterface .modal-content:eq(0)').hide();  //隐藏第一步内容
+            $('#importInterface .modal-content:eq(1)').show();  //显示第二步内容
+            console.log(getTenderDatas(xmlObj));
+            console.log(xmlObj);
+            tbcObj = new TBC(xmlObj);
+        });
+        //上一步
+        $('#import-prev').click(function () {
+            $('#importInterface .modal-content:eq(0)').show();  //显示第一步内容
+            $('#importInterface .modal-content:eq(1)').hide();  //隐藏第二步内容
+        });
+        //待确认-下一工程
+        $('#tbc-next').click(function () {
+            tbcObj.next();
+        });
+        //待确认-上一工程
+        $('#tbc-prev').click(function () {
+            tbcObj.prev();
+        });
+        //导入窗口消失后
+        $('#importInterface').on('hidden.bs.modal', function () {
+            xmlObj = null;  //重置数据
+            tbcObj = null;
+            $('#importInterface .modal-content:eq(0)').show();  //显示第一步内容
+            $('#importInterface .modal-content:eq(1)').hide();  //隐藏第二步内容
+            $('#customFile').val('');    //清除选择
+            $('.custom-file-label').text('');   //设置选择框文本
+            $('#uploadAlert').hide();   //隐藏提示
+            $('.selFile').hide();   //隐藏建设项目及计价规则
+        });
+    }
+    return {eventListen};
+})();
+

+ 12 - 1
web/building_saas/pm/js/pm_newMain.js

@@ -340,6 +340,13 @@ const projTreeObj = {
                 }, 200);
             }
         },
+        importInterface: {
+            name: '导入标准接口',
+            icon: 'fa-cloud-upload',
+            callback: function () {
+                $('#importInterface').modal('show');
+            }
+        },
         manageFiles: {
             name: "管理相关文件",
             icon: 'fa-list',
@@ -410,6 +417,7 @@ const projTreeObj = {
                 "copyTo": me.contextMenuItems.copyTo,
                 "spr2": '--------',
                 "share": me.contextMenuItems.share,
+                //"importInterface": me.contextMenuItems.importInterface,
                 "spr3": '--------',
                 "manageFiles": me.contextMenuItems.manageFiles,
                 "refreshSummary": me.contextMenuItems.refreshSummary
@@ -2370,6 +2378,9 @@ $(document).ready(function() {
     $('#tender-feeStandard').change(function () {
        changeFeeStandard();
     });
+
+    //导入相关
+    //importView.eventListen();
 });
 function changeEngineering(){
     featureData = null;
@@ -2964,7 +2975,7 @@ function validProjectName(name) {
     if (selected && selected.data.projType === projectType.folder) {
         parent = selected ? selected : projTreeObj.tree._root;
     } else {
-        if ([projectType.tender, projectType.engineering].includes(selected.data.projType)) {
+        if (selected && [projectType.tender, projectType.engineering].includes(selected.data.projType)) {
             selected = selected.parent.data.projType === projectType.project ? selected.parent : selected.parent.parent;
         }
         parent = selected ? selected.parent : projTreeObj.tree._root;