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

1. 台账分解、台账修订、计量台账、清单对比、清单汇总、多期比较,选中多个单元格受,提示合计等信息
2. 模板,选中模板,显示创建人、创建时间

MaiXinRong 2 недель назад
Родитель
Сommit
09ff393e9a

+ 7 - 1
app/controller/template_controller.js

@@ -97,7 +97,13 @@ module.exports = app => {
                 for (const f of filter) {
                     switch(f) {
                         case 'detail':
-                            result[f] = await this.ctx.service.calcTmpl.getTemplate(data.id, data.type);
+                            const detail = await this.ctx.service.calcTmpl.getTemplate(data.id, data.type);
+                            const user = await this.ctx.service.projectAccount.getDataById(detail.create_user_id);
+                            detail.user_name = user.name;
+                            detail.user_company = user.company;
+                            detail.user_role = user.role;
+                            detail.create_time_str = this.ctx.moment(detail.create_time).format('YYYY-MM-DD HH:mm:ss');
+                            result[f] = detail;
                             break;
                         default:
                             throw '未知数据类型';

+ 2 - 0
app/public/js/ledger.js

@@ -1571,6 +1571,7 @@ $(document).ready(function() {
 
     sjsSettingObj.setFxTreeStyle(ledgerSpreadSetting, sjsSettingObj.FxTreeStyle.jz);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(ledgerSpreadSetting);
+    ledgerSpreadSetting.tipsSum = true;
     ledgerTreeCol.initSpreadSetting(ledgerSpreadSetting);
     ledgerSpreadSetting.headColWidth = [50];
     ledgerSpreadSetting.rowHeader = [
@@ -2351,6 +2352,7 @@ $(document).ready(function() {
             },
         },
     ];
+    posSpreadSetting.tipsSum = true;
     SpreadJsObj.initSheet(posSpread.getActiveSheet(), posSpreadSetting);
     //绑定计量单元编辑事件
     const posOperationObj = {

+ 5 - 0
app/public/js/ledger_gather.js

@@ -62,6 +62,7 @@ $(document).ready(() => {
             key: 'ledger-gather-gcl',
             colWidth: true,
         },
+        tipsSum: true,
         getColor: function (sheet, data, row, col, defaultColor) {
             return data
                 ? $('#compare-tag')[0].checked && data.compare_differ
@@ -98,6 +99,7 @@ $(document).ready(() => {
             key: 'ledger-gather-leafXmj',
             colWidth: true,
         },
+        tipsSum: true,
     };
     if (thousandth) sjsSettingObj.setTpThousandthFormat(leafXmjSpreadSetting);
     SpreadJsObj.initSheet(leafXmjSpread.getActiveSheet(), leafXmjSpreadSetting);
@@ -125,6 +127,7 @@ $(document).ready(() => {
             key: 'ledger-gather-leafXmj',
             colWidth: true,
         },
+        tipsSum: true,
     };
     if (thousandth) sjsSettingObj.setTpThousandthFormat(gatherLeafXmjSpreadSetting);
     const gatherLeafXmjSheet = gatherLeafXmjSpread.getActiveSheet();
@@ -154,6 +157,7 @@ $(document).ready(() => {
             key: 'ledger-gather-ancGcl',
             colWidth: true,
         },
+        tipsSum: true,
     };
     if (thousandth) sjsSettingObj.setTpThousandthFormat(gatherAncGclSpreadSetting);
     const gatherAncGclSheet = gatherAncGclSpread.getActiveSheet();
@@ -182,6 +186,7 @@ $(document).ready(() => {
             key: 'ledger-gather-change',
             colWidth: true,
         },
+        tipsSum: true,
     };
     if (thousandth) sjsSettingObj.setTpThousandthFormat(changeSpreadSetting);
     const changeSheet = changeSpread.getActiveSheet();

+ 4 - 0
app/public/js/measure_compare.js

@@ -34,6 +34,7 @@ const billsSpreadSetting = {
     defaultRowHeight: 21,
     readOnly: true,
     selectedBackColor: '#fffacd',
+    tipsSum: true,
 };
 const posSpreadSetting = {
     baseCols: [
@@ -55,6 +56,7 @@ const posSpreadSetting = {
     font: '12px 微软雅黑',
     readOnly: true,
     selectedBackColor: '#fffacd',
+    tipsSum: true,
 };
 const exportBillsSpreadSetting = {
     baseCols: [
@@ -112,6 +114,7 @@ const gclSpreadSetting = {
     headerFont: '12px 微软雅黑',
     font: '12px 微软雅黑',
     readOnly: true,
+    tipsSum: true,
 };
 const leafXmjSpreadSetting = {
     baseCols: [
@@ -138,6 +141,7 @@ const leafXmjSpreadSetting = {
     headerFont: '12px 微软雅黑',
     font: '12px 微软雅黑',
     readOnly: true,
+    tipsSum: true,
 };
 const exportGclSpreadSetting = {
     baseCols: [

+ 7 - 2
app/public/js/pos_calc_tmpl.js

@@ -289,16 +289,21 @@ $(document).ready(() => {
 
         const loadTemplateDetail = async function(template) {
             const result = await postDataAsync('load', {filter: 'detail', id: template.id, type: 'posCalc'});
-            if (result && result.detail) template.col_set = result.detail.col_set;
+            if (result && result.detail) {
+                template.col_set = result.detail.col_set;
+                template.user_name = result.detail.user_name;
+                template.create_time_str = result.detail.create_time_str;
+            }
         };
         const refreshTemplate = async function() {
             if (!curTemplate) {
-                // todo 隐藏模板详细界面
+                $('#detail-user-info').html('');
             } else {
                 $('dd[templateId]').removeClass('bg-warning');
                 $(`dd[templateId=${curTemplate.id}]`).addClass('bg-warning');
                 if (!curTemplate.col_set) await loadTemplateDetail(curTemplate);
                 detailObj.loadDetail(curTemplate);
+                $('#detail-user-info').html(`新建人:${curTemplate.user_name}(${curTemplate.create_time_str})`);
             }
         };
         const setCurTemplate = function(template) {

+ 2 - 0
app/public/js/revise.js

@@ -95,6 +95,7 @@ $(document).ready(() => {
             },
         },
     ];
+    billsSpreadSetting.tipsSum = true;
     billsSpreadSetting.getColor = function(sheet, data, row, col, defaultColor) {
         if (!data) return defaultColor;
         return data.used ? spreadColor.revise.used : defaultColor;
@@ -105,6 +106,7 @@ $(document).ready(() => {
     const posSheet = posSpread.getActiveSheet();
     posSpreadSetting.cols.push({title: '截止本期合同计量|数量', colSpan: '3|1', rowSpan: '1|1', field: 'end_contract_qty', hAlign: 2, width: 60, readOnly: true, type: 'Number'},
         {title: '|完成率(%)', colSpan: '1', rowSpan: '|1', field: 'end_percent', hAlign: 2, width: 80, readOnly: true, type: 'Number'});
+    posSpreadSetting.tipsSum = true;
     sjsSettingObj.setGridSelectStyle(posSpreadSetting);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(posSpreadSetting);
     SpreadJsObj.initSheet(posSheet, posSpreadSetting);

+ 82 - 1
app/public/js/spreadjs_rela/spreadjs_zh.js

@@ -27,6 +27,31 @@ proto.dottedLine = function (x1, y1, x2, y2, interval = 4) {
     }
 };
 
+const textUtils = {
+    getStringListDisplayWidth: function(sheet, font, strList) {
+        const xs = sheet.getParent().xs;
+        const ctx = xs.childNodes[0].getContext("2d");
+        ctx.font = font;
+        const widths = strList.map(x => { return ctx.measureText(x).width; });
+        return Math.max(...widths);
+    },
+    getTextDisplayWidth: function(sheet, font, str) {
+        const xs = sheet.getParent().xs;
+        const ctx = xs.childNodes[0].getContext("2d");
+        ctx.font = font;
+        return ctx.measureText(str).width;
+    },
+    getTextAutoHeight: function(sheet, font, str, displayWidth) {
+        const xs = sheet.getParent().xs;
+        const ctx = xs.childNodes[0].getContext("2d");
+        ctx.font = font;
+        const textMertrices = ctx.measureText(str);
+        const fontHeight = textMertrices.fontBoundingBoxAscent + textMertrices.fontBoundingBoxDescent;
+        const textRow = Math.ceil(textMertrices.width / displayWidth);
+        return textRow * fontHeight + 2 + (textRow - 1) * 1;
+    }
+}
+
 // 简写Spread常量
 const spreadNS = GC.Spread.Sheets;
 // 授权码
@@ -245,6 +270,61 @@ const SpreadJsObj = {
             }
         });
     },
+    selChangedTipsSum: function(sheet) {
+        sheet.bind(spreadNS.Events.SelectionChanged, function(e, info) {
+            let sum = 0, count = 0, average = 0;
+            const sel = info.newSelections[0];
+            if (sel) {
+                for (let iRow = sel.row; iRow < sel.row + sel.rowCount; iRow++) {
+                    if (!info.sheet.getRowVisible(iRow)) continue;
+                    for (let iCol = sel.col; iCol < sel.col + sel.colCount; iCol++) {
+                        if (!info.sheet.getColumnVisible(iCol)) continue;
+                        const text = info.sheet.getText(iRow, iCol);
+                        if (text) {
+                            count++;
+                            const value = _.toNumber(text);
+                            sum = ZhCalc.add(sum, _.isNaN(value) ? 0 : value);
+                        }
+                    }
+                }
+            }
+            if (count > 1) {
+                const maxHintWidth = 200, indent = 10;
+                average = ZhCalc.div(sum, count);
+                const text = [`合计:${sum}`, `计数:${count}`, `平均值:${average}`];
+                let sumTip = $('#spread-sum-tip')[0];
+                if (!sumTip) {
+                    sumTip = document.createElement("div");
+                    $(sumTip).css("position", "absolute")
+                        .css("border", "1px #C0C0C0 solid")
+                        .css("box-shadow", "1px 2px 5px rgba(0,0,0,0.4)")
+                        .css("font", "9pt Arial")
+                        .css("background", "white")
+                        .css("padding", 5)
+                        .css("z-index", 999)
+                        .css("max-width", maxHintWidth)
+                        .css("word-wrap", "break-word")
+                        .attr("id", 'spread-sum-tip');
+                    document.body.insertBefore(sumTip, null);
+                }
+                const hitinfo = info.sheet.getCellRect(sel.row, sel.col + sel.colCount);
+                const pos = SpreadJsObj.getObjPos(info.sheet.getParent().qo);
+                const showTop = Math.min(pos.y + hitinfo.y + indent, window.innerHeight - 72); // 52(w)+10(p)+10(i)
+                let showLeft = pos.x + hitinfo.x + indent;
+                if (showLeft > window.innerWidth - maxHintWidth) {
+                    const textWidth = textUtils.getStringListDisplayWidth(info.sheet, "9pt Arial", text);
+                    showLeft = Math.min(showLeft, window.innerWidth - textWidth - 10 - indent);
+                }
+                $(sumTip).html(text.join('<br/>')).css("top", showTop).css("left", showLeft);
+
+                setTimeout(()=>{ if (sumTip) $(sumTip).show("fast");}, 100);
+                // setTimeout(()=>{ if (sumTip) $(sumTip).hide();}, 5000);
+            } else {
+                const sumTip = $('#spread-sum-tip');
+                if (sumTip) sumTip.hide();
+            }
+        });
+    },
     selChangedRefreshBackColor: function (sheet) {
         sheet.bind(spreadNS.Events.SelectionChanged, function (e, info) {
             const rows = [];
@@ -418,6 +498,7 @@ const SpreadJsObj = {
         if (setting.selectedBackColor) {
             SpreadJsObj.selChangedRefreshBackColor(sheet);
         }
+        if (setting.tipsSum) SpreadJsObj.selChangedTipsSum(sheet);
         this.endMassOperation(sheet);
         if (!setting.invalidCopyFilterHiddenRow) this.copyFilterHiddenRow(sheet);
     },
@@ -972,7 +1053,7 @@ const SpreadJsObj = {
                 for (const [iCol, col] of sheet.zh_setting.cols.entries()) {
                     sheet.getCell(i, iCol).backColor(SpreadJsObj._getBackColor(sheet, data, i, col));
                 }
-            };
+            }
             this.endMassOperation(sheet);
         } catch (err) {
             this.endMassOperation(sheet);

+ 2 - 0
app/public/js/stage.js

@@ -770,6 +770,7 @@ $(document).ready(() => {
     // if (ratioCol) ratioCol.field = tenderInfo.display.stage.correct ? 'end_correct_percent' : 'end_gather_percent';
     const ratioCol = ledgerSpreadSetting.cols.find(x => {return x.field === 'end_final_1_percent' || x.field === 'end_correct_1_percent'});
     if (ratioCol) ratioCol.field = tenderInfo.display.stage.correct ? 'end_correct_1_percent' : 'end_final_1_percent';
+    ledgerSpreadSetting.tipsSum = true;
     ledgerSpreadSetting.imageClick = function (data, hitinfo) {
         const col = hitinfo.sheet.zh_setting.cols[hitinfo.col];
         switch (col.field) {
@@ -869,6 +870,7 @@ $(document).ready(() => {
         { field: 'qc_qty', showImage: posQcColShowImage },
         { field: 'qc_minus_qty', showImage: posQcColShowImage }
     ]);
+    posSpreadSetting.tipsSum = true;
     posSpreadSetting.imageClick = function (data, hitinfo) {
         const col = hitinfo.sheet.zh_setting.cols[hitinfo.col];
         switch (col.field) {

+ 4 - 0
app/public/js/stage_gather.js

@@ -64,14 +64,17 @@ $(document).ready(function () {
     };
     sjsSettingObj.setOrgPriceCol(gclSpreadSetting.cols, [{ field: 'org_price' }]);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(gclSpreadSetting);
+    gclSpreadSetting.tipsSum = true;
     SpreadJsObj.initSheet(gclSpread.getActiveSheet(), gclSpreadSetting);
     // 初始化所属项目节
     const leafXmjSpread = SpreadJsObj.createNewSpread($('#leaf-xmj-spread')[0]);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(leafXmjSpreadSetting);
+    leafXmjSpreadSetting.tipsSum = true;
     SpreadJsObj.initSheet(leafXmjSpread.getActiveSheet(), leafXmjSpreadSetting);
 
     const gatherLeafXmjSpread = SpreadJsObj.createNewSpread($('#leaf-xmj-gather-spread')[0]);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(gatherLeafXmjSpreadSetting);
+    gatherLeafXmjSpreadSetting.tipsSum = true;
     const gatherLeafXmjSheet = gatherLeafXmjSpread.getActiveSheet();
     SpreadJsObj.initSheet(gatherLeafXmjSheet, gatherLeafXmjSpreadSetting);
 
@@ -106,6 +109,7 @@ $(document).ready(function () {
             key: 'ledger-gather-change',
             colWidth: true,
         },
+        tipsSum: true,
     };
     if (thousandth) sjsSettingObj.setTpThousandthFormat(changeSpreadSetting);
     const changeSheet = changeSpread.getActiveSheet();

+ 4 - 2
app/service/calc_tmpl.js

@@ -48,7 +48,7 @@ const PosCalc = (function(){
             { title: '数量', width: 80, type: 'num', field: 'qty', decimal: 2, },
         ]
     };
-    return { EmptySpreadCache, BaseSpreadColSetting, ValidColInfo, TestData };
+    return { EmptySpreadCache, BaseSpreadColSetting, ValidColInfo, TestData, ValidCount: 50 };
 })();
 const Cost = (function(){
     const EmptySpreadCache = {
@@ -76,7 +76,7 @@ const Cost = (function(){
         { key: 'memo', name: '长文本', fields: ['memo1', 'memo2'], valid: ['title', 'width'], def: { title: '长文本', width: 120, type: 'memo'} },
     ];
     ValidColInfo.forEach(vci => { return vci.count = vci.fields.length; });
-    return { EmptySpreadCache, BaseSpreadColSetting, ValidColInfo };
+    return { EmptySpreadCache, BaseSpreadColSetting, ValidColInfo, ValidCount: 10 };
 })();
 function randomWord(randomFlag, min, max){
     let str = "",
@@ -338,6 +338,8 @@ module.exports = app => {
 
         async _addTemplate(name, type) {
             if (ValidTemplateType.indexOf(type) < 0) throw '新增的模板类型非法';
+            const count = await this.count({pid: this.ctx.session.sessionProject.id, type});
+            if (count > this.TemplateRela[type].ValidCount) throw '已达模板使用上限';
 
             const relaConst = this.TemplateRela[type];
             const insertData = {

+ 1 - 0
app/view/template/pos_calc.ejs

@@ -14,6 +14,7 @@
                         <a href="javascript: void(0);" class="btn btn-sm btn-light text-primary" id="reset"> 重置</a>
                         <a href="javascript: void(0);" class="btn btn-sm btn-light text-primary" id="save"> 保存</a>
                     </div>
+                    <div id="detail-user-info" class="ml-auto"></div>
                 </div>
             </div>
         </div>