Bläddra i källkod

协作补上lid和部分形象进度代码

laiguoran 4 år sedan
förälder
incheckning
ca643310ae

+ 14 - 1
app/controller/schedule_controller.js

@@ -22,11 +22,17 @@ module.exports = app => {
             return _.map(scheduleLedgerList, 'ledger_id');
         }
 
+        async _getLastPlanMonth(ctx) {
+            const lastMonth = await ctx.service.scheduleMonth.getLastPlanMonth();
+            return lastMonth ? lastMonth[0].yearmonth : null;
+        }
+
         async index(ctx) {
             try {
                 const renderData = {
                     tender: ctx.tender.data,
                     tenderMenu: this.menu.tenderMenu,
+                    planMonth: await this._getLastPlanMonth(ctx),
                     scheduleLedgerList: await this._getSelectedLedgerList(ctx),
                     preUrl: '/tender/' + ctx.tender.id,
                 };
@@ -52,12 +58,13 @@ module.exports = app => {
         async plan(ctx) {
             const tender = ctx.tender;
             const schedule = await ctx.service.schedule.getDataByCondition({ tid: tender.id });
-            const scheduleMonth = await ctx.service.scheduleMonth.getAllDataByCondition({ tid: tender.id });
+            const scheduleMonth = await ctx.service.scheduleMonth.getAllDataByCondition({ where: { tid: tender.id }, orders: [['yearmonth', 'asc']] });
             const renderData = {
                 tender: tender.data,
                 tenderInfo: tender.info,
                 schedule,
                 scheduleMonth,
+                planMonth: await this._getLastPlanMonth(ctx),
                 measureType,
                 mode: scheduleConst.plan_mode,
                 scheduleLedgerList: await this._getSelectedLedgerList(ctx),
@@ -122,6 +129,12 @@ module.exports = app => {
                     case 'mode':
                         responseData.data = await ctx.service.schedule.saveMode(data.postData);
                         break;
+                    case 'addmonth':
+                        responseData.data = await ctx.service.scheduleMonth.add(data.postData);
+                        break;
+                    case 'delmonth':
+                        responseData.data = await ctx.service.scheduleMonth.del(data.postData);
+                        break;
                     default: throw '参数有误';
                 }
                 ctx.body = responseData;

+ 181 - 11
app/public/js/schedule_plan.js

@@ -32,15 +32,16 @@ $(function () {
     };
     const ledgerTree = createNewPathTree('base', treeSetting);
 
+    const static_cols = [
+        {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', readOnly: true, cellType: 'tree'},
+        {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@', readOnly: true},
+        {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true},
+        {title: '经济指标', colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
+        {title: '总设计|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+        {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
+    ];
+
     const ledgerSpreadSetting = {
-        cols: [
-            {title: '编号', colSpan: '1', rowSpan: '2', field: 'code', hAlign: 0, width: 145, formatter: '@', readOnly: true, cellType: 'tree'},
-            {title: '名称', colSpan: '1', rowSpan: '2', field: 'name', hAlign: 0, width: 185, formatter: '@', readOnly: true},
-            {title: '单位', colSpan: '1', rowSpan: '2', field: 'unit', hAlign: 1, width: 50, formatter: '@', readOnly: true},
-            {title: '经济指标', colSpan: '1', rowSpan: '2', field: 'dgn_price', hAlign: 2, width: 60, type: 'Number', readOnly: true},
-            {title: '总设计|工程量', colSpan: '2|1', rowSpan: '1|1', field: 'dgn_qty1', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-            {title: '|金额(万元)', colSpan: '|1', rowSpan: '|1', field: 'total_price', hAlign: 2, width: 70, type: 'Number', readOnly: true},
-        ],
         emptyRows: 0,
         headRows: 2,
         headRowHeight: [25, 25],
@@ -53,22 +54,54 @@ $(function () {
             colWidth: true,
         }
     };
+    const monthsCols = [];
+    if(scheduleMonth.length > 0) {
+        for (const sm of scheduleMonth) {
+            const yearmonth = sm.yearmonth.split('-')[0] + '年' + parseInt(sm.yearmonth.split('-')[1]) + '月';
+            const cols = {title: yearmonth + '|计划工程量', colSpan: '2|1', rowSpan: '1|1', field: sm.yearmonth+'_gcl', hAlign: 2, width: 90, type: 'Number', readOnly: 'readOnly.gcl'};
+            const cols2 = {title: '|计划金额(万元)', colSpan: '|1', rowSpan: '|1', field: sm.yearmonth+'_tp', hAlign: 2, width: 90, type: 'Number', readOnly: 'readOnly.tp'};
+            monthsCols.push(cols);
+            monthsCols.push(cols2);
+        }
+    }
+    const spreadHeaderCols = static_cols.concat(monthsCols);
+    ledgerSpreadSetting.cols = spreadHeaderCols;
+
+    const ledgerCol = {
+        readOnly: {
+            tp: function (data) {
+                let flag = data.is_leaf;
+                if (data.is_leaf) {
+                    flag = schedule && schedule.mode === mode.tp;
+                }
+                return !flag;
+            },
+            gcl: function (data) {
+                let flag = data.is_leaf;
+                if (data.is_leaf) {
+                    flag = schedule && schedule.mode === mode.gcl;
+                }
+                return !flag;
+            },
+        },
+    };
 
     sjsSettingObj.setFxTreeStyle(ledgerSpreadSetting, sjsSettingObj.FxTreeStyle.jz);
     if (thousandth) sjsSettingObj.setTpThousandthFormat(ledgerSpreadSetting);
+    SpreadJsObj.initSpreadSettingEvents(ledgerSpreadSetting, ledgerCol);
     SpreadJsObj.initSheet(ledgerSpread.getActiveSheet(), ledgerSpreadSetting);
     SpreadJsObj.selChangedRefreshBackColor(ledgerSpread.getActiveSheet());
 
     postData('/tender/' + getTenderId() + '/schedule/ledger/load', {}, function (data) {
-        console.log(data, selectedLedgerList);
-        const treeData = [];
+        let treeData = [];
         for(const sl of selectedLedgerList) {
             const one = _.find(data, { 'ledger_id' : sl });
             treeData.push(one);
         }
+        treeData = setLeafData(treeData);
         ledgerTree.loadDatas(treeData);
         treeCalc.calculateAll(ledgerTree);
-        // console.log(ledgerTree);
+        console.log(ledgerTree);
         SpreadJsObj.loadSheetData(ledgerSpread.getActiveSheet(), SpreadJsObj.DataType.Tree, ledgerTree);
     }, null, true);
 
@@ -132,6 +165,113 @@ $(function () {
             $('#mode-tips').show();
             $('#mode-cancel').show();
             $('#mode').modal('hide');
+            schedule.mode = _self.data('mode');
+            SpreadJsObj.reLoadSheetData(ledgerSpread.getActiveSheet());
+        })
+    });
+
+    // 月份添加
+    $('#add-month').click(function () {
+        const range = $('#month-range').val();
+        if(range === '') {
+            toastr.error('请选择计划周期时间');
+            return;
+        }
+        const addMonthList = [];
+        const cycle = range.split(' ~ ');
+        if(cycle.length === 1) {
+            addMonthList.push(cycle[0]);
+        } else {
+            // 多个月份
+            const back_year = parseInt(cycle[1].split('-')[0]);
+            const back_month = parseInt(cycle[1].split('-')[1]);
+            const front_year = parseInt(cycle[0].split('-')[0]);
+            const front_month = parseInt(cycle[0].split('-')[1]);
+            if(back_year > front_year) {
+                const num = getDistanceMonth(cycle[0], cycle[1]);
+                let j = 1;
+                for (let i = 0; i <= num; i++) {
+                    if(front_month + i > 12*j) {
+                        j = j + 1;
+                    }
+                    const m = (front_month + i)%12 === 0 ? 12 : (front_month + i)%12;
+                    addMonthList.push((front_year + (j-1)) + '-' + (m < 10 ? '0' + m : m));
+                }
+            } else if (back_year === front_year) {
+                // 小于1年并没有跨年
+                for (let i = front_month; i <= back_month; i++) {
+                    addMonthList.push(back_year + '-' + (i < 10 ? '0' + i : i));
+                }
+            }
+        }
+        // 判断是否已添加本月份
+        if (addMonthList.length > 0) {
+            const hadmonth = [];
+            for (const m of addMonthList) {
+                const one = _.find(scheduleMonth, { yearmonth: m });
+                console.log(one, m);
+                if (one) {
+                    hadmonth.push(m);
+                }
+            }
+            if (hadmonth.length > 0) {
+                let html = '';
+                for (const hm of hadmonth) {
+                    html += `<div class="alert alert-danger">${hm} 已创建</div>`;
+                }
+                $('#add-month-error-list').html(html);
+                $('#add-month-error-list').show();
+                return;
+            }
+        } else {
+            toastr.error('请选择计划周期时间');
+            return;
+        }
+        $('#add-month-error-list').html('');
+        $('#add-month-error-list').hide();
+        const _self = $(this);
+        postData(window.location.pathname + '/save', {type: 'addmonth', postData: addMonthList}, function (result) {
+            _self.addClass('disabled').attr('disabled', true);
+            toastr.success('新增成功');
+            setTimeout(function () {
+                window.location.reload();
+            }, 500)
+
+        })
+    });
+
+    $('#month-table input[type="checkbox"]').click(function () {
+        const selectedMonth = [];
+        $('#month-table input:checkbox:checked').each(function () {
+            selectedMonth.push('「' + $(this).parents('td').siblings('td').text() + '」');
+        });
+        if(selectedMonth.length > 0) {
+            $('#del-month-list').text(selectedMonth.join(''));
+            $('#del-month-list').parent().show();
+            $('#del-month').removeAttr('disabled');
+        } else {
+            $('#del-month-list').parent().hide();
+            $('#del-month').attr('disabled', true);
+        }
+    });
+
+    $('#del-month').click(function () {
+        const selectedMonth = [];
+        $('#month-table input:checkbox:checked').each(function () {
+            selectedMonth.push($(this).parents('td').siblings().text());
+        });
+        if (selectedMonth.length === 0) {
+            toastr.error('请选择删除的计划周期');
+            return;
+        }
+        const _self = $(this);
+        postData(window.location.pathname + '/save', {type: 'delmonth', postData: selectedMonth}, function (result) {
+            _self.addClass('disabled').attr('disabled', true);
+            toastr.success('删除成功');
+            setTimeout(function () {
+                window.location.reload();
+            }, 500)
+
         })
     });
 
@@ -153,3 +293,33 @@ $(function () {
         }
     });
 });
+// 月份间隔
+function getDistanceMonth(startTime,endTime){
+    startTime = new Date(startTime);
+    endTime = new Date(endTime);
+    var dateToMonth = 0;
+    var startDate=startTime.getDate() + startTime.getHours()/24 + startTime.getMinutes()/24/60;
+    var endDate=endTime.getDate()  +endTime.getHours()/24 + endTime.getMinutes()/24/60;
+    if(endDate >= startDate){
+        dateToMonth = 0;
+    }else{
+        dateToMonth = -1;
+    }
+    let yearToMonth = (endTime.getYear() - startTime.getYear()) * 12;
+    let monthToMonth = endTime.getMonth() - startTime.getMonth();
+    return yearToMonth + monthToMonth + dateToMonth;
+}
+function setLeafData(tree) {
+    const newtree = [];
+    for (const t of tree) {
+        const child = _.find(tree, { 'ledger_pid': t.ledger_id });
+        if (!child && !t.is_leaf) {
+            t.is_leaf = true;
+        }
+        for(const m of scheduleMonth) {
+            t[m.yearmonth] = m.sj_gcl !== null || m.sj_tp !== null;
+        }
+        newtree.push(t);
+    }
+    return newtree;
+}

+ 7 - 3
app/service/ledger_cooperation.js

@@ -28,9 +28,13 @@ module.exports = app => {
             if (data.pwd === '' && info) {
                 await this.deleteById(info.id);
             } else if (data.pwd !== '' && !info) {
-                const result = await this.db.insert(this.tableName, data);
-                data.id = result.insertId;
-                data.sign_path = null;
+                const ledgerInfo = await this.ctx.service.ledger.getDataByCondition({ ledger_id: data.ledger_id });
+                if (!ledgerInfo) {
+                    data.lid = ledgerInfo.id;
+                    const result = await this.db.insert(this.tableName, data);
+                    data.id = result.insertId;
+                    data.sign_path = null;
+                }
             } else if (data.pwd !== '' && info) {
                 data.id = info.id;
                 await this.db.update(this.tableName, data);

+ 11 - 0
app/service/schedule_ledger_month.js

@@ -0,0 +1,11 @@
+'use strict';
+
+module.exports = app => {
+    class ScheduleLedgerMonth extends app.BaseService {
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'schedule_ledger_month';
+        }
+    }
+    return ScheduleLedgerMonth;
+};

+ 38 - 0
app/service/schedule_month.js

@@ -6,6 +6,44 @@ module.exports = app => {
             super(ctx);
             this.tableName = 'schedule_month';
         }
+
+        async getLastPlanMonth() {
+            const sql = 'SELECT `yearmonth` FROM ?? WHERE `tid` = ? ORDER BY `yearmonth` DESC Limit 0,1';
+            const sqlParam = [this.tableName, this.ctx.tender.id];
+            return await this.db.query(sql, sqlParam);
+        }
+
+        async add(data) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                const insertData = [];
+                for (const m of data) {
+                    insertData.push({ tid: this.ctx.tender.id, yearmonth: m });
+                }
+                if (insertData.length > 0) await transaction.insert(this.tableName, insertData);
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
+
+        async del(data) {
+            const transaction = await this.db.beginTransaction();
+            try {
+                for (const m of data) {
+                    const delData = { tid: this.ctx.tender.id, yearmonth: m };
+                    await transaction.delete(this.tableName, delData);
+                    await transaction.delete(this.ctx.service.scheduleLedgerMonth.tableName, delData);
+                }
+                await transaction.commit();
+                return true;
+            } catch (err) {
+                await transaction.rollback();
+                throw err;
+            }
+        }
     }
     return ScheduleMonth;
 };

+ 1 - 1
app/view/schedule/index.ejs

@@ -4,7 +4,7 @@
         <div class="title-main d-flex">
             <% include ../tender/tender_sub_mini_menu.ejs %>
             <h2>
-                计划至至 2020年12月
+                <% if (planMonth) { %>计划至 <%- planMonth.split('-')[0] %>年<%- parseInt(planMonth.split('-')[1]) %>月 <% } %>
             </h2>
             <div class="ml-auto">
                 <a href="/tender/<%- ctx.tender.id %>/schedule/ledger" class="btn btn-sm btn-outline-primary">进度台帐</a>

+ 3 - 1
app/view/schedule/plan.ejs

@@ -4,7 +4,7 @@
         <div class="title-main d-flex">
             <% include ../tender/tender_sub_mini_menu.ejs %>
             <h2>
-                计划至至 2020年12月
+                <% if (planMonth) { %>计划至 <%- planMonth.split('-')[0] %>年<%- parseInt(planMonth.split('-')[1]) %>月 <% } %>
             </h2>
             <div class="ml-auto">
                 <a href="#mode" data-toggle="modal" data-target="#mode" class="btn btn-sm btn-outline-primary">计算方式</a>
@@ -27,5 +27,7 @@
     const measureType = JSON.parse('<%- JSON.stringify(measureType) %>');
     const schedule = JSON.parse('<%- JSON.stringify(schedule) %>');
     const scheduleMonth = JSON.parse('<%- JSON.stringify(scheduleMonth) %>');
+    const monthList = _.map(scheduleMonth, 'yearmonth');
+    console.log(monthList);
     const mode = JSON.parse('<%- JSON.stringify(mode) %>');
 </script>

+ 13 - 9
app/view/schedule/plan_modal.ejs

@@ -8,13 +8,14 @@
             <div class="modal-body">
                 <div class="form-group">
                     <label>计划周期</label>
-                    <input class="datepicker-here form-control" placeholder="点击选择时间" data-view="months" data-min-view="months" data-date-format="yyyy-MM" data-range="true" data-multiple-dates-separator=" ~ " data-language="zh" type="text">
+                    <input id="month-range" readonly class="datepicker-here form-control" placeholder="点击选择时间" data-view="months" data-min-view="months" data-date-format="yyyy-MM" data-range="true" data-multiple-dates-separator=" ~ " data-language="zh" type="text">
+                </div>
+                <div id="add-month-error-list" style="display: none">
                 </div>
-                <div class="alert alert-danger">2020-05 已创建</div>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
-                <button type="button" class="btn btn-sm btn-primary" >确认新增</button>
+                <button type="button" class="btn btn-sm btn-primary" id="add-month">确认新增</button>
             </div>
         </div>
     </div>
@@ -27,17 +28,20 @@
                 <h5 class="modal-title">管理计划</h5>
             </div>
             <div class="modal-body">
-                <table class="table table-bordered table-hover">
+                <table class="table table-bordered table-hover" id="month-table">
                     <tr><th>计划月</th><th width="100">删除</th></tr>
-                    <tr><td>2020-1</td><td></td></tr>
-                    <tr><td>2020-2</td><td><label><input type="checkbox"></label></td></tr>
-                    <tr><td>2020-3</td><td><label><input type="checkbox"></label></td></tr>
+                    <% for (const m of scheduleMonth) { %>
+                    <tr>
+                        <td><%- m.yearmonth %></td>
+                        <td><% if (m.sj_gcl === null && m.sj_tp === null) { %><label></label><input type="checkbox" value="<%- m.id %>"><% } %></td>
+                    </tr>
+                    <% } %>
                 </table>
-                <div class="alert alert-danger">确认删除「2020-2」「2020-3」计划进度?删除后,数据无法恢复,请谨慎操作。</div>
+                <div class="alert alert-danger" style="display: none">确认删除<span id="del-month-list"></span>计划进度?删除后,数据无法恢复,请谨慎操作。</div>
             </div>
             <div class="modal-footer">
                 <button type="button" class="btn btn-sm btn-secondary" data-dismiss="modal">取消</button>
-                <button type="button" class="btn btn-sm btn-danger" >确认删除</button>
+                <button type="button" class="btn btn-sm btn-danger" disabled id="del-month" >确认删除</button>
             </div>
         </div>
     </div>