Browse Source

Merge branch 'master' of http://192.168.1.41:3000/SmartCost/ConstructionCost

zhangweicheng 5 năm trước cách đây
mục cha
commit
6aa3bbdc72

+ 2 - 0
config/gulpConfig.js

@@ -32,6 +32,7 @@ module.exports = {
     ],
     login_jspaths:[
         'public/web/url_util.js',
+        'public/web/syntax-detection.js',
         'web/users/js/gt.js',
         'web/users/js/login.js'
     ],
@@ -40,6 +41,7 @@ module.exports = {
         'lib/jquery-contextmenu/jquery.contextMenu.css'
     ],
     pm_jspaths:[
+        'public/web/syntax-detection.js',
         'public/web/uuid.js',
         'public/web/date_util.js',
         'public/web/upload_cdn.js',

+ 6 - 4
modules/users/facade/online_facade.js

@@ -12,7 +12,7 @@ let logs_model = mongoose.model("online_logs");
 
 async function getOnlineInfo(filter) {
     let datas = [];
-    let logs = await logs_model.find(filter);
+    let logs = await logs_model.find(filter, null, { sort: {_id: -1}});
     let less = 0;
     for(let l of logs){
         let d = getTimeString(l.online_times);
@@ -52,11 +52,13 @@ async function setOnlineTimes(userList,condition){
 
 
 function getTimeString(times) {
-    let s = "",perHour = 1000 * 60 * 60,perMin = 1000 * 60;
-    let hour = parseInt(times/perHour);
+    let s = "",perHour = 1000 * 60 * 60,perMin = 1000 * 60,perDay = 24*perHour;
+    let day = parseInt(times/perDay);
+    let hour = parseInt(parseInt(times % perDay) / perHour);
     let min = parseInt((times % perHour)/perMin);
     let less =  (times % perHour)%perMin;//不够一分钟的时间
+    if(day > 0) s = s+`${day}天`;
     if(hour > 0) s = s+`${hour}小时`;
     if(min > 0)  s= s+`${min}分钟`;
     return {s:s,less:less}
-}
+}

+ 186 - 0
public/web/syntax-detection.js

@@ -0,0 +1,186 @@
+/** 
+ * 浏览器兼容性,特性检查
+ * 参考列表: http://kangax.github.io/compat-table/es6/
+ * 同内核的不同的浏览器需要处理,比如qq浏览器登陆成功后,ie浏览器登陆页面会自动跳转到项目管理页面。因此项目管理页面也需要检测
+*/
+function checkSyntax() {
+    'use strict';
+    try {
+        // 一些在词法、语法分析阶段就会报错的代码,必须要用window.Function或者eval包裹,否则直接报错且无法被捕获
+        // 不使用eval的原因:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/eval
+        if (typeof window.Function === 'undefined') {
+            return false;
+        }
+
+        // 声明
+        Function('let a = 1;')();
+        Function('const b = 1;')();
+        Function('class A {}')();
+
+        // 模板字符串
+        Function('var a = 1; var str = `${a}`;')();
+
+        // 对象简单表示
+        Function("var foo = 'foo'; var simple = { foo, t() {} };")();
+
+        // 对象属性表示
+        Function("var attr = 'a'; var obj = {[attr]: 1}")();
+
+        // 对象super
+        Function('var proto = { p: 1 }; var obj = { superF() { return super.p } }; Object.setPrototypeOf(obj, proto)')();
+
+        // 对象getter setter
+        Function('var tObj = { get a() {}, set a(v) {} }')();
+
+        // 扩展运算符
+        Function('var obj = { foo: 1 }; var obj1 = { ...obj }; var arr = [1]; var arr1 = [...arr];')();
+
+        // 解构
+        Function('var obj = { foo: 1 }; var { foo } = obj; var arr = [1]; var [one] = arr;')();
+
+        // 可选链 ?. es2020
+        //Function('var obj = { a: { b: 1 } }; obj?.a?.b')();
+
+        // of迭代
+        Function('for (var i of [1]) {}')();
+
+        // 默认参数
+        Function('function defaultParams(a = 1) {}')();
+
+        // rest参数
+        Function('function restParams(...args) {}')();
+
+        // arrow function
+        Function('var arrowF = () => {};')();
+
+        // generator function
+        Function('function* gen() {}')();
+
+        // async function es2017
+        Function('async function tAsync() {}')();
+
+        // Symbol Promise Set Map Proxy Reflect
+        if (typeof Symbol === 'undefined' ||
+            typeof Promise === 'undefined' ||
+            typeof Set === 'undefined' ||
+            typeof Map === 'undefined' ||
+            typeof Proxy === 'undefined' ||
+            typeof Reflect === 'undefined') {
+            return false;
+        }
+        // buffer相关
+        if (typeof ArrayBuffer === 'undefined' ||
+            typeof Uint8Array === 'undefined' ||
+            typeof DataView === 'undefined') {
+            return false;
+        }
+
+        // 部分字符串方法
+        var stringPrototypeFuncs = [
+            'includes',
+            'codePointAt',
+            'normalize',
+            'repeat',
+            //'matchAll', es2020
+            'padStart',
+            'padEnd',
+            //'trimStart', es2019
+            //'trimEnd'
+        ];
+        var stringStaticFuncs = [
+            'fromCodePoint',
+            'raw'
+        ];
+        for (var i = 0; i < stringPrototypeFuncs.length; i++) {
+            var f = stringPrototypeFuncs[i];
+            if (!String.prototype[f]) {
+                throw new SyntaxError('String.prototype ' + f);
+            }
+        }
+        for (var i = 0; i < stringStaticFuncs.length; i++) {
+            var f = stringStaticFuncs[i];
+            if (!String[f]) {
+                throw new SyntaxError('String ' + f);
+            }
+        }
+
+        // 部分数组方法
+        var arrayPrototypeFuncs = [
+            'find',
+            'findIndex',
+            'fill',
+            'keys',
+            'values',
+            'entries',
+            //'flat', // es2019
+            //'flatMap',
+            'includes'
+        ];
+        var arrayStaticFuncs = [
+            'from',
+            'of'
+        ];
+        for (var i = 0; i < arrayPrototypeFuncs.length; i++) {
+            var f = arrayPrototypeFuncs[i];
+            if (!Array.prototype[f]) {
+                throw new SyntaxError('Array.prototyp ' + f);
+            }
+        }
+        for (var i = 0; i < arrayStaticFuncs.length; i++) {
+            var f = arrayStaticFuncs[i];
+            if (!Array[f]) {
+                throw new SyntaxError('Array ' + f);
+            }
+        }
+
+        // 对象部分方法
+        var objectStaticFuncs = [
+            'is',
+            'assign',
+            'getOwnPropertyDescriptors',
+            'setPrototypeOf',
+            'values',
+            'entries',
+            //'fromEntries' // es2020
+        ];
+        for (var i = 0; i < objectStaticFuncs.length; i++) {
+            var f = objectStaticFuncs[i];
+            if (!Object[f]) {
+                throw new SyntaxError('Object ' + f);
+            }
+        }
+
+    } catch (err) {
+        console.log(err);
+        return false;
+    }
+    return true;
+}
+
+function showBrowserTip() {
+    var html = '<div class="modal fade" id="browser" data-backdrop="static">' +
+        '<div class="modal-dialog modal-lg" role="document">' +
+        '<div class="modal-content">' +
+            '<div class="modal-body">' +
+                '<h5>浏览器版本过低,可能会有安全风险;</h5>' +
+                '<h5>请更新 「浏览器」 或者 使用 「纵横Z+造价工作平台」 登录。</h5>' +
+                '<div class="row my-4">' +
+                    '<div class="col-6">' +
+                        '<div class="text-center"><a href="https://www.microsoft.com/zh-cn/edge" class="btn btn-primary" target="_blank">下载 Microsoft Edge</a></div>' +
+                    '</div>' +
+                    '<div class="col-6">' +
+                        '<div class="text-center"><a href="https://smartcost.com.cn/downloadzplus" class="btn btn-primary" target="_blank">下载 纵横Z+造价工作平台</a></div>' +
+                    '</div></div></div></div></div></div>';
+    $('body').append(html);
+    $('#browser').modal('show');
+}
+
+$(document).ready(function () {
+    // 浏览器兼容性
+    var isCompat = checkSyntax();
+    if (!isCompat) {
+        $('#inputEmail').blur();
+        showBrowserTip();
+        return false;
+    }
+});

+ 2 - 2
test/unit/reports/test_rpt_test_template.js

@@ -72,7 +72,7 @@ let userId_me = "5b6a60b1c4ba33000dd417c0"; //我的
 // demoPrjId = 2260; //QA:
 // demoPrjId = 5029; //
 // demoPrjId = 5029; //项目名称过长
-demoPrjId = 22032; //
+demoPrjId = 11355; //
 // demoPrjId = 4107; //UAT:
 //*/
 let userId_Dft = userId_Leng;
@@ -117,7 +117,7 @@ test('测试 - 测试模板啦: ', function (t) {
                     let dt = new Date();
                     fsUtil.writeObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataObject_" + dt.getTime() + "_测试模板.jsp");
                     let tplData = rptDataUtil.assembleData(rawDataObj);
-                    // fsUtil.writeObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataAfterCacl_测试模板.jsp");
+                    fsUtil.writeObjToFile(rawDataObj, "D:/GitHome/ConstructionCost/tmp/rptTplRawDataAfterCacl_" + dt.getTime() + "测试模板.jsp");
                     // fsUtil.writeObjToFile(tplData, "D:/GitHome/ConstructionCost/tmp/rptTplAssembledData_测试模板.jsp");
                     //it's time to build the report!!!
                     let printCom = JpcEx.createNew();

+ 4 - 3
web/building_saas/main/js/views/std_ration_lib.js

@@ -201,13 +201,12 @@ var rationLibObj = {
          */
         //@param {String}sectionName(章节名称) {Array}datas(定额数据)
         function simplifyName(sectionName, datas){
-            debugger;
             if (!sectionName || !datas || datas.length === 0) {
                 return;
             }
             //提取需要匹配的章节名称
             // 去掉后缀
-            const suffixReg = /[((]编码[::]\w+[))]/;
+            const suffixReg = /[((]编码[::][\w、]+[))]/;
             const tempName = sectionName.split(suffixReg)[0];
             // 获取第一个空格后的内容
             const sReg = /\s(.+)/;
@@ -227,7 +226,9 @@ var rationLibObj = {
                     continue;
                 }
                 let matchName = nameArr[0];
-                if (matchName === target) {
+                const matchNameWithoutSpace = matchName.replace(/\s/g, '');
+                const targetWithoutSpace = target.replace(/\s/g, '');
+                if (matchNameWithoutSpace === targetWithoutSpace) {
                     nameArr.shift();
                     data.name = nameArr.join(' ');
                 }

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

@@ -930,6 +930,7 @@
     console.log(billValuation);
 </script>
 <!-- inject:js -->
+<script type="text/javascript" src="/public/web/syntax-detection.js"></script>
 <script src="/web/building_saas/js/global.js"></script>
 <script src="/public/web/uuid.js"></script>
 <script src="/public/web/date_util.js"></script>

+ 1 - 1
web/building_saas/report/js/rpt_print.js

@@ -88,7 +88,7 @@ let rptPrintHelper = {
 
 function getActualBorderStyle(cell, styles, mergeBorderStyle, pageBorderArea, borderStr) {
     let rst = styles[cell[JV.PROP_STYLE]][borderStr];
-    if (parseFloat(rst[JV.PROP_LINE_WEIGHT]) === 1) {
+    if (rst && parseFloat(rst[JV.PROP_LINE_WEIGHT]) === 1) {
         rst[JV.PROP_LINE_WEIGHT] = 0.5;
     }
     if (mergeBorderStyle) {

+ 1 - 0
web/users/html/login.html

@@ -180,6 +180,7 @@
     <script src="/public/web/url_util.js"></script>
     <script src="/lib/popper/popper.min.js"></script>
     <script src="/lib/bootstrap/bootstrap.min.js"></script>
+    <script type="text/javascript" src="/public/web/syntax-detection.js"></script>
     <script src="/web/building_saas/js/global.js"></script>
     <script type="text/javascript" src="/web/users/js/gt.js"></script>
     <script type="text/javascript" src="/web/users/js/login.js"></script>