Browse Source

Merge branch 'master' of http://smartcost.f3322.net:3000/SmartCost/ConstructionCost

zhangweicheng 7 năm trước cách đây
mục cha
commit
a639b28937

+ 112 - 3
modules/glj/controllers/glj_controller.js

@@ -10,6 +10,7 @@ import GLJTypeConst from "../../common/const/glj_type_const";
 import GLJListModel from "../models/glj_list_model";
 import UnitPriceModel from "../models/unit_price_model";
 import MixRatioModel from "../models/mix_ratio_model";
+import UnitPriceFileModel from "../models/unit_price_file_model";
 
 const ProjectModel = require('../../pm/models/project_model').project;
 class GLJController extends BaseController {
@@ -54,11 +55,12 @@ class GLJController extends BaseController {
             // 获取使用该单价文件的项目数据
             let tenderData = await ProjectModel.getTenderByUnitPriceFileId(unitPriceFileId);
             let usedTenderList = [];
-            let usedUnitPriceName = '';
+            let usedUnitPriceInfo = {};
             if (tenderData !== null) {
                 for (let tmp of tenderData) {
                     usedTenderList.push(tmp.name);
-                    usedUnitPriceName = tmp.property.unitPriceFile.name;
+                    usedUnitPriceInfo.name = tmp.property.unitPriceFile.name;
+                    usedUnitPriceInfo.id = tmp.property.unitPriceFile.id;
                 }
             }
 
@@ -75,7 +77,7 @@ class GLJController extends BaseController {
                 hostname: request.hostname,
                 roomId: unitPriceFileId,
                 GLJTypeConst: JSON.stringify(GLJTypeConst),
-                usedUnitPriceName: usedUnitPriceName
+                usedUnitPriceInfo: usedUnitPriceInfo
             };
         } catch (error) {
             responseData.err = 1;
@@ -243,6 +245,113 @@ class GLJController extends BaseController {
     }
 
     /**
+     * 获取项目与单价文件对应的数据
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async getProjectInfo(request, response) {
+        let projectId = request.body.project_id;
+        projectId = parseInt(projectId);
+        let responseData = {
+            err: 0,
+            data: null
+        };
+        try {
+            let sessionUserData = request.session.sessionUser;
+            // 获取对应用户所有的建设项目数据
+            let projectList = await ProjectModel.getUserProjectData(sessionUserData.ssoId);
+            if (projectList === null) {
+                throw '没有找到对应的项目数据';
+            }
+            // 转换mongoose数据
+            projectList = JSON.stringify(projectList);
+            projectList = JSON.parse(projectList);
+
+            let result = {
+                self: [],
+                other: []
+            };
+            for (let index in projectList) {
+                // 获取对应建设项目下所有的单位工程id
+                let idList = await ProjectModel.getTenderByProjectId(projectList[index].ID);
+                if (idList.length <= 0) {
+                    continue;
+                }
+
+                // 获取对应的单价文件
+                let unitPriceFileModel = new UnitPriceFileModel();
+                let unitPriceFileData = await unitPriceFileModel.getDataByTenderId(idList);
+                projectList[index].unitPriceList = unitPriceFileData;
+
+                // 归类
+                if (idList.indexOf(projectId) >= 0) {
+                    result.self = unitPriceFileData;
+                } else {
+                    result.other.push(projectList[index]);
+                }
+            }
+            responseData.data = result;
+            response.json(responseData);
+
+        } catch (error) {
+            responseData.err = 1;
+            response.json(responseData);
+        }
+    }
+
+    /**
+     * 更改单价文件
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async changeUnitPriceFile(request, response) {
+        let projectId = request.body.project_id;
+        let changeUnitPriceId = request.body.change_id;
+        let responseData = {
+            err: 0,
+            msg: ''
+        };
+        try {
+            let currentUnitPriceId = await ProjectModel.getUnitPriceFileId(projectId);
+
+            // 获取即将更改的单价文件信息
+            let unitPriceFileModel = new UnitPriceFileModel();
+            let targetUnitPriceFile = await unitPriceFileModel.findDataByCondition({id: changeUnitPriceId});
+            if (targetUnitPriceFile === null) {
+                throw '没有找到对应的单价文件';
+            }
+
+            // 查找对应单价文件的项目工料机数据
+            let unitPriceModel = new UnitPriceModel();
+            let copyResult = await unitPriceModel.copyNotExist(currentUnitPriceId, changeUnitPriceId);
+            // 复制成功后更改project数据
+            if (!copyResult) {
+                throw '复制数据失败';
+            }
+
+            let changeUnitPriceFileInfo = {
+                id: targetUnitPriceFile.id,
+                name: targetUnitPriceFile.name
+            };
+            let result = ProjectModel.changeUnitPriceFileInfo(projectId, changeUnitPriceFileInfo);
+            if (!result) {
+                throw '切换单价文件失败!';
+            }
+
+        } catch (error) {
+            console.log(error);
+            responseData.err = 1;
+            responseData.msg = error;
+        }
+
+        response.json(responseData);
+    }
+
+    /**
      * 模拟定额插入
      *
      * @param {object} request

+ 48 - 0
modules/glj/models/unit_price_model.js

@@ -213,6 +213,54 @@ class UnitPriceModel extends BaseModel {
         return result.ok !== undefined && result.ok === 1;
     }
 
+    /**
+     * 复制单价文件数据
+     *
+     * @param {Number} currentUnitPriceId
+     * @param {Number} changeUnitPriceId
+     * @return {Promise}
+     */
+    async copyNotExist(currentUnitPriceId, changeUnitPriceId) {
+        let result = false;
+        // 首先查找原单价文件id下的数据
+        let currentUnitList = await this.findDataByCondition({unit_price_file_id: currentUnitPriceId}, null, false);
+        if (currentUnitList === null) {
+            return result;
+        }
+        // 过滤mongoose格式
+        currentUnitList = JSON.stringify(currentUnitList);
+        currentUnitList = JSON.parse(currentUnitList);
+
+        let codeList = [];
+        for (let tmp of currentUnitList) {
+            if (codeList.indexOf(tmp.code) >= 0) {
+                continue;
+            }
+            codeList.push(tmp.code);
+        }
+
+        // 查找即将更替的单价文件是否存在对应的工料机数据
+        let condition = {unit_price_file_id: changeUnitPriceId, code: {"$in": codeList}};
+        let targetUnitList = await this.findDataByCondition(condition, null, false, 'code');
+
+        // 如果没有重叠的数据则原有的数据都复制一份
+        let insertData = [];
+        for (let tmp of currentUnitList) {
+            if (targetUnitList !== null && targetUnitList[tmp.code] !== undefined) {
+                continue;
+            }
+            // 删除原有id信息
+            delete tmp._id;
+            delete tmp.id;
+            tmp.unit_price_file_id = changeUnitPriceId;
+            insertData.push(tmp);
+        }
+
+        return insertData.length > 0 ? this.add(currentUnitList) : true;
+
+    }
+
+
 }
 
 export default UnitPriceModel;

+ 2 - 0
modules/glj/routes/glj_router.js

@@ -17,6 +17,8 @@ router.post('/getData', gljController.init, gljController.getGljList);
 router.post('/update', gljController.init, gljController.updateData);
 router.post('/get-ratio', gljController.init, gljController.getRatio);
 router.post('/delete-ratio', gljController.init, gljController.deleteMixRatio);
+router.post('/get-project-info', gljController.init, gljController.getProjectInfo);
+router.post('/change-file', gljController.init, gljController.changeUnitPriceFile);
 
 router.get('/test', gljController.init, gljController.test);
 router.get('/testModify', gljController.init, gljController.testModify);

+ 34 - 0
modules/pm/models/project_model.js

@@ -299,6 +299,40 @@ ProjectsDAO.prototype.getUnitPriceFileId = async function(projectId) {
     return result;
 };
 
+/**
+ * 获取当前用户的建设项目数据
+ *
+ * @param {Number} userId
+ * @return {Promise}
+ */
+ProjectsDAO.prototype.getUserProjectData = async function(userId) {
+    let projectList = await Projects.find({
+        '$or': [
+            {'userID': userId, 'deleteInfo': null, projType: 'Project'},
+            {'userID': userId, 'deleteInfo.deleted': {'$in': [null, false]}, projType: 'Project'}
+            ]
+    }, {_id: 0, name: 1, ID: 1});
+
+    return projectList;
+};
+
+/**
+ * 更改项目属性中的单价文件
+ *
+ * @param {Number} projectId
+ * @param {Object} changeInfo
+ * @return {Promise}
+ */
+ProjectsDAO.prototype.changeUnitPriceFileInfo = async function(projectId, changeInfo) {
+    projectId = parseInt(projectId);
+    if (isNaN(projectId) || projectId <= 0) {
+        return false;
+    }
+    let result = await Projects.update({ID: projectId}, {"property.unitPriceFile": changeInfo});
+
+    return result.ok === 1;
+};
+
 module.exports ={
     project: new ProjectsDAO(),
     projType: projectType

+ 48 - 2
modules/users/models/log_model.js

@@ -9,6 +9,7 @@ import BaseModel from "../../common/base/base_model";
 import LogType from "../../common/const/log_type_const";
 import LogSchema from "./schema/log";
 import UAParser from "ua-parser-js";
+import Request from "request";
 
 class LogModel extends BaseModel {
 
@@ -57,11 +58,13 @@ class LogModel extends BaseModel {
      * @param {Object} request
      * @return {Promise}
      */
-    addLoginLog(userId, request) {
+    async addLoginLog(userId, request) {
         let ip = request.connection.remoteAddress;
         ip = ip.split(':');
         ip = ip[3] === undefined ? '' : ip[3];
 
+        let ipInfo = await this.getIpInfoFromApi(ip);
+
         let userAgentObject = new UAParser(request.headers['user-agent']);
         let osInfo = userAgentObject.getOS();
         let cpuInfo = userAgentObject.getCPU();
@@ -69,7 +72,8 @@ class LogModel extends BaseModel {
         let message = {
             os: osInfo.name + ' ' + osInfo.version + ' ' + cpuInfo.architecture,
             browser: browserInfo.name + ' ' + browserInfo.version,
-            ip: ip
+            ip: ip,
+            ip_info: ipInfo
         };
 
         return this.addLog(userId, LogType.LOGIN_LOG, message);
@@ -99,6 +103,48 @@ class LogModel extends BaseModel {
         return logList
     }
 
+    /**
+     * 获取ip信息
+     *
+     * @param {String} ip
+     * @return {Promise}
+     */
+    async getIpInfoFromApi(ip) {
+        let result = '';
+        if (ip === '') {
+            return result;
+        }
+
+        if (ip === '127.0.0.1') {
+            return '服务器本机访问';
+        }
+
+        let getData = {
+            url: 'http://ip.taobao.com/service/getIpInfo.php?ip=' + ip,
+            encoding: 'utf8'
+        };
+        return new Promise(function (resolve, reject) {
+            try {
+                // 请求接口
+                Request.get(getData, function (err, getResponse, body) {
+                    if (err) {
+                        throw '请求错误';
+                    }
+                    if (getResponse.statusCode !== 200) {
+                        throw '获取数据失败!';
+                    }
+                    let responseData = JSON.parse(body);
+                    let ipData = responseData.data !== undefined ? responseData.data : [];
+                    if (ipData.ip === undefined) {
+                        throw '接口数据有误';
+                    }
+                    resolve(ipData.region + ipData.city + ' ' + ipData.isp);
+                });
+            } catch (error) {
+                reject([]);
+            }
+        });
+    }
 }
 
 export default LogModel;

+ 9 - 5
modules/users/models/schema/log.js

@@ -9,18 +9,22 @@ import mongoose from "mongoose";
 
 let Schema = mongoose.Schema;
 let collectionName = 'log';
+let messageSchema = new Schema({
+    ip: String,
+    ip_info: String,
+    browser: String,
+    os: String
+}, {_id: false});
 let modelSchema = {
     // 日志类型
     type: {
-        type: Number,
-        index: true
+        type: Number
     },
     // 日志内容
-    message: Schema.Types.Mixed,
+    message: messageSchema,
     // 关联用户id
     user_id: {
-        type: String,
-        index: true
+        type: String
     },
     // 创建时间
     create_time: Number

+ 2 - 2
web/building_saas/css/main.css

@@ -244,7 +244,7 @@ body {
     max-width: 500px;
     margin: 150px auto;
 }
-.poj-list, .side-content {
+.poj-list, .side-content ,.form-view{
     overflow: auto;
 }
 .poj-list span.poj-icon {
@@ -307,4 +307,4 @@ body {
 }
 .gc-column-header-cell{
     text-align: center!important;
-}
+}

+ 50 - 0
web/building_saas/glj/html/glj_index.html

@@ -1,3 +1,8 @@
+<style type="text/css">
+    .copy{
+        display: none;
+    }
+</style>
 <div class="toolsbar px-1">
     <div class="form-inline py-1">
         <label class="mx-2">当前使用:<span id="used-name"></span>(<a href="#" id="pop-dj" data-original-title="" title=""><span id="used-count">0</span> 单位工程使用</a>)
@@ -45,6 +50,51 @@
         </div>
     </div>
 </div>
+<!--弹出更换-->
+<div class="modal fade" id="change-dj" data-backdrop="static">
+    <div class="modal-dialog" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">更换单价文件</h5>
+                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                    <span aria-hidden="true">&times;</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <div class="form-group">
+                    <label class="custom-control custom-radio">
+                        <input name="change-type" type="radio" class="custom-control-input" checked="checked" value="0">
+                        <span class="custom-control-indicator"></span>
+                        <span class="custom-control-description">从本建设项目中选择</span>
+                    </label>
+                    <label class="custom-control custom-radio">
+                        <input name="change-type" type="radio" class="custom-control-input" value="1">
+                        <span class="custom-control-indicator"></span>
+                        <span class="custom-control-description">从其他建设项目中复制</span>
+                    </label>
+                </div>
+                <!--从本建设项目中选择-->
+                <div class="form-group select option">
+                    <label id="current-project-name"></label>
+                    <select class="form-control" id="self-file"></select>
+                </div>
+                <!--从其他建设项目中复制-->
+                <div class="form-group copy option">
+                    <label>选择建设项目</label>
+                    <select class="form-control" id="other-project"></select>
+                </div>
+                <div class="form-group copy option">
+                    <select class="form-control" id="other-file"></select>
+                    <small class="form-text text-muted">你选择的单价文件将复制一份至新项目,不会影响原建设项目的单价文件。</small>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                <a href="javascript:void(0);" class="btn btn-primary" id="change-file-confirm">确定</a>
+            </div>
+        </div>
+    </div>
+</div>
 <script type="text/javascript" src="/web/building_saas/glj/js/project_glj.js"></script>
 <script type="text/javascript" src="/web/building_saas/glj/js/composition.js"></script>
 <script type="text/javascript" src="/web/building_saas/glj/js/socket.js"></script>

+ 118 - 5
web/building_saas/glj/js/project_glj.js

@@ -19,7 +19,9 @@ let GLJTypeConst = [];
 // spreadjs载入数据所需
 let jsonData = [];
 let mixRatioConnectData = [];
-
+// 单价文件相关
+let usedUnitPriceInfo = {};
+let otherFileData = {};
 let currentTag = '';
 let isChanging = false;
 $(document).ready(function () {
@@ -27,6 +29,118 @@ $(document).ready(function () {
         init();
     });
 
+    // 单价文件切换弹框
+    $('#change-dj').on('shown.bs.modal', function () {
+        // 获取当前建设项数据
+        let projectName = projectInfoObj.projectInfo.fullFolder !== undefined &&
+            projectInfoObj.projectInfo.fullFolder.length > 0 ? projectInfoObj.projectInfo.fullFolder[0] : '';
+        $("#current-project-name").text(projectName);
+
+        // 获取切换单价文件相关数据
+        $.ajax({
+            url: '/glj/get-project-info',
+            type: 'post',
+            data: {project_id: scUrlUtil.GetQueryString('project')},
+            dataType: 'json',
+            success: function(response) {
+                if (response.err === 1) {
+                    alert('数据传输错误!');
+                    return false;
+                }
+                let data = response.data;
+                // 本项目中的单价文件
+                if (data.self.length > 0) {
+                    let selfFileHtml = '';
+                    for(let tmp of data.self) {
+                        let select = usedUnitPriceInfo === tmp.id ? ' selected="selected"' : '';
+                        selfFileHtml += '<option'+ select +' value="'+ tmp.id +'">'+ tmp.name +'</option>';
+                    }
+                    $("#self-file").html(selfFileHtml);
+                }
+
+                // 其他建设项目数据
+                if (data.other.length > 0) {
+                    let otherProjectHtml = '';
+                    let otherFileHtml = '';
+                    for(let tmp of data.other) {
+                        otherProjectHtml += '<option value="'+ tmp.ID +'">'+ tmp.name +'</option>';
+                        otherFileData[tmp.ID] = tmp.unitPriceList;
+                        if (otherFileHtml !== '') {
+                            continue;
+                        }
+                        for(let unitPrice of tmp.unitPriceList) {
+                            otherFileHtml += '<option value="'+ unitPrice.id +'">'+ unitPrice.name +'</option>';
+                        }
+                    }
+                    $("#other-project").html(otherProjectHtml);
+                    $("#other-file").html(otherFileHtml);
+                }
+            }
+        });
+    });
+
+    // 从其他建设项目中复制 选择建设项目
+    $("#other-project").change(function() {
+        let projectId = $(this).val();
+        if (otherFileData[projectId] === undefined) {
+            return false;
+        }
+        let otherFileHtml = '';
+        for(let unitPrice of otherFileData[projectId]) {
+            otherFileHtml += '<option value="'+ unitPrice.id +'">'+ unitPrice.name +'</option>';
+        }
+        $("#other-file").html(otherFileHtml);
+    });
+
+    // 单价文件选项切换
+    $("input[name='change-type']").change(function() {
+        let type = $(this).val();
+        type = parseInt(type);
+        $("#change-dj .option").hide();
+        if (type === 0) {
+            $(".option.select").show();
+        } else {
+            $(".option.copy").show();
+        }
+    });
+
+    // 单价文件切换确认
+    $("#change-file-confirm").click(function() {
+        if (isChanging) {
+            return false;
+        }
+        let type = $("input[name='change-type']:checked").val();
+        type = parseInt(type);
+        let changeUnitPriceId = 0;
+        if (type === 0) {
+            // 从本项目中选择
+            changeUnitPriceId = $("#self-file").val();
+        } else {
+            // 从其他项目中复制
+            changeUnitPriceId = $("#other-file").val();
+        }
+        $.ajax({
+            url: '/glj/change-file',
+            type: 'post',
+            data: {project_id: scUrlUtil.GetQueryString('project'), change_id: changeUnitPriceId},
+            error: function() {
+                isChanging = false;
+            },
+            beforeSend: function() {
+                isChanging = true;
+            },
+            success: function(response) {
+                isChanging = false;
+                if (response.err === 1) {
+                    let msg = response.msg !== undefined ? response.msg : '未知错误';
+                    alert(msg);
+                    return false;
+                }
+                $('#change-dj').modal("hide");
+            }
+        });
+    });
+
     // 是否主动更改数据
     // $("#message").on('click', '#load-data', function() {
     //     $("#notify").slideUp('fast');
@@ -77,14 +191,13 @@ function init() {
             GLJTypeConst = data.constData.GLJTypeConst !== undefined ? JSON.parse(data.constData.GLJTypeConst) : GLJTypeConst;
 
             let usedTenderList = data.usedTenderList !== undefined ? data.usedTenderList : [];
-            let usedUnitFileName = data.constData.usedUnitPriceName !== undefined ?
-                data.constData.usedUnitPriceName : '';
+            usedUnitPriceInfo = data.constData.usedUnitPriceInfo !== undefined ?
+                data.constData.usedUnitPriceInfo : {};
             // 存入缓存
             projectObj.project.projectGLJ.datas = jsonData;
-            console.log(projectObj.project);
 
             spreadInit();
-            unitPriceFileInit(usedUnitFileName, usedTenderList);
+            unitPriceFileInit(usedUnitPriceInfo.name, usedTenderList);
         }
     });
 

+ 102 - 0
web/building_saas/main/html/main.html

@@ -56,6 +56,9 @@
         <nav class="navbar navbar-toggleable-lg justify-content-between navbar-light p-0">
             <ul class="nav navbar-nav px-1">
                 <li class="nav-item">
+                    <a class="nav-link" href="#" aria-expanded="false" data-toggle="modal" data-target="#poj-set"><i class="fa fa-cube"></i> 项目属性</a>
+                </li>
+                <li class="nav-item">
                     <a class="nav-link" href="#" aria-haspopup="true" aria-expanded="false"><i class="fa fa-sliders"></i> 选项</a>
                 </li>
                 <li class="nav-item dropdown">
@@ -409,6 +412,104 @@
 
         </div>
     </div>
+    <!--弹出项目属性-->
+    <div class="modal fade" id="poj-set" data-backdrop="static">
+        <div class="modal-dialog modal-lg" role="document">
+            <div class="modal-content">
+                <div class="modal-header">
+                    <h5 class="modal-title">项目属性</h5>
+                    <button type="button" class="close" data-dismiss="modal" aria-label="Close">
+                        <span aria-hidden="true">&times;</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+                    <div class="row">
+                        <div class="col-3">
+                            <ul class="nav flex-column nav-pills" role="tablist">
+                                <li class="nav-item"><a class="nav-link active" data-toggle="pill" href="#poj-settings-1" role="tab">基本信息</a></li>
+                                <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-2" role="tab">工程特征</a></li>
+                                <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-3" role="tab">指标信息</a></li>
+                                <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-4" role="tab">取费方式</a></li>
+                                <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-5" role="tab">清单工程精度</a></li>
+                                <li class="nav-item"><a class="nav-link" data-toggle="pill" href="#poj-settings-6" role="tab" id="tab_poj-settings-6">人工单价调整</a></li>
+                            </ul>
+                        </div>
+                        <div class="col-9">
+                            <div class="tab-content">
+                                <!--基本信息-->
+                                <div class="tab-pane fade show active" id="poj-settings-1" role="tabpanel">
+                                    <div class="modal-auto-height">
+                                        基本信息
+                                    </div>
+                                </div>
+                                <!--工程特征-->
+                                <div class="tab-pane fade" id="poj-settings-2" role="tabpanel">
+                                    <div class="modal-auto-height">
+                                        工程特征
+                                    </div>
+                                </div>
+                                <!--指标信息-->
+                                <div class="tab-pane fade" id="poj-settings-3" role="tabpanel">
+                                    <div class="modal-auto-height">
+                                        指标信息
+                                    </div>
+                                </div>
+                                <!--取费方式-->
+                                <div class="tab-pane fade" id="poj-settings-4" role="tabpanel">
+                                    <div class="modal-auto-height">
+                                        <fieldset class="form-group">
+                                            <div class="form-check">
+                                                <label class="form-check-label">
+                                                    <input class="form-check-input" name="optionsRadios" id="optionsRadios1" value="option1" checked="" type="radio">
+                                                    子目含量取费
+                                                </label>
+                                            </div>
+                                            <div class="form-check">
+                                                <label class="form-check-label">
+                                                    <input class="form-check-input" name="optionsRadios" id="optionsRadios2" value="option2" type="radio">
+                                                    子目单价取费(反算):清单综合合价=清单综合单价*清单工程量
+                                                </label>
+                                            </div>
+                                            <div class="form-check">
+                                                <label class="form-check-label">
+                                                    <input class="form-check-input" name="optionsRadios" id="optionsRadios3" value="option3" type="radio">
+                                                    子目单价取费(正算):清单综合合价=∑子目综合合价
+                                                </label>
+                                            </div>
+                                            <div class="form-check">
+                                                <label class="form-check-label">
+                                                    <input class="form-check-input" name="optionsRadios" id="optionsRadios4" value="option4" type="radio">
+                                                    清单单价取费
+                                                </label>
+                                            </div>
+                                        </fieldset>
+                                    </div>
+                                </div>
+                                <!--清单工程精度-->
+                                <div class="tab-pane fade" id="poj-settings-5" role="tabpanel">
+                                    <div class="modal-auto-height">
+                                        清单工程精度
+                                    </div>
+                                </div>
+                                <!--人工单价调整-->
+                                <div class="tab-pane fade" id="poj-settings-6" role="tabpanel">
+                                    <div class="row px-3">
+                                        <select class="col-4 form-control form-control-sm"><option>渝建[2016]71号</option><option>渝建[2017]78号</option></select>
+                                    </div>
+                                    <div style="height:8px;"></div>
+                                    <div class="modal-auto-height" id="labourCoeSpread" />
+                                </div>
+                            </div>
+                        </div>
+                    </div>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                    <a href="" class="btn btn-primary">确定</a>
+                </div>
+            </div>
+        </div>
+    </div>
     <!--弹出列设置-->
     <div class="modal fade" id="column" data-backdrop="static">
         <div class="modal-dialog modal-lg" role="document">
@@ -514,6 +615,7 @@
     <script type="text/javascript" src="/web/building_saas/main/js/views/sub_view.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/fee_rate_view.js"></script>
     <script type="text/javascript" src="/web/building_saas/main/js/views/sub_fee_rate_views.js"></script>
+    <script type="text/javascript" src="/web/building_saas/main/js/views/project_property_labour_coe_view.js"></script>
 
 
    <!-- <script src="/web/building_saas/fee_rates/fee_rate.js"></script>-->

+ 15 - 15
web/building_saas/main/js/models/calc_program.js

@@ -511,7 +511,7 @@ let calcTemplates = [
                 feeRateID: 104,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费",
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]",
                 memo: "渝建发[2014]27号"
             },
             {
@@ -523,7 +523,7 @@ let calcTemplates = [
                 feeRateID: 304,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费"
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]"
             },
             {
                 ID: "13",
@@ -534,7 +534,7 @@ let calcTemplates = [
                 feeRateID: 704,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费",
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]",
                 memo: "同定额包干费"
             },
             {
@@ -899,7 +899,7 @@ let calcTemplates = [
                 feeRateID: 102,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费",
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]",
                 memo: "渝建发[2014]27号"
             },
             {
@@ -911,7 +911,7 @@ let calcTemplates = [
                 feeRateID: 302,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费"
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]"
             },
             {
                 ID: "13",
@@ -922,7 +922,7 @@ let calcTemplates = [
                 feeRateID: 702,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费",
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]",
                 memo: "同定额包干费"
             },
             {
@@ -1482,7 +1482,7 @@ let calcTemplates = [
                 feeRate: 0.3,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费",
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]",
                 memo: "渝建发[2014]27号"
             },
             {
@@ -1494,7 +1494,7 @@ let calcTemplates = [
                 feeRateID: 303,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费"
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]"
             },
             {
                 ID: "13",
@@ -1505,7 +1505,7 @@ let calcTemplates = [
                 feeRateID: 703,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费",
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]",
                 memo: "同定额包干费"
             },
             {
@@ -1676,7 +1676,7 @@ let calcTemplates = [
                 feeRateID: 106,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费",
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]",
                 memo: "渝建发[2014]27号"
             },
             {
@@ -1688,7 +1688,7 @@ let calcTemplates = [
                 feeRateID: 306,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费"
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]"
             },
             {
                 ID: "13",
@@ -1699,7 +1699,7 @@ let calcTemplates = [
                 feeRateID: 706,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费",
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]",
                 memo: "同定额包干费"
             },
             {
@@ -2452,7 +2452,7 @@ let calcTemplates = [
                 feeRateID: 105,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费",
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]",
                 memo: "渝建发[2014]27号"
             },
             {
@@ -2464,7 +2464,7 @@ let calcTemplates = [
                 feeRateID: 305,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费"
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]"
             },
             {
                 ID: "13",
@@ -2475,7 +2475,7 @@ let calcTemplates = [
                 feeRateID: 705,
                 expression: "@('3') + @('5') + @('7')",
                 compiledExpr: "",
-                statement: "定额基价人工费",
+                statement: "[定额基价人工费]+[定额基价材料费]+[定额基价机械费]",
                 memo: "同定额包干费"
             },
             {

+ 87 - 0
web/building_saas/main/js/views/project_property_labour_coe_view.js

@@ -0,0 +1,87 @@
+/**
+ * Created by CSL on 2017-09-22.
+ * 项目属性之人工系数。
+ */
+let labourCoeView = {
+    datas: [],
+    spread: null,
+    sheet: null,
+
+    buildSheet: function (){
+        let me = this;
+        me.datas = calcLabourCoes;
+
+        if (me.spread) {
+            me.spread.destroy();
+            me.spread = null;
+        };
+        me.spread = new GC.Spread.Sheets.Workbook($("#labourCoeSpread")[0], { sheetCount: 1 });
+        me.spread.options.tabStripVisible = false;
+        me.spread.options.showVerticalScrollbar = false;
+        me.spread.options.showHorizontalScrollbar = false;
+        me.spread.options.rowHeight = 50;
+        let sheetArea = GC.Spread.Sheets.SheetArea;
+        let sheet = me.spread.getSheet(0);
+        me.sheet = sheet;
+        sheet.suspendPaint();
+        sheet.suspendEvent();
+        sheet.setColumnCount(1, sheetArea.viewport);
+        sheet.setColumnWidth(0, 180, sheetArea.viewport);
+        sheet.setRowCount(1, sheetArea.colHeader);
+        sheet.setRowCount(20, sheetArea.viewport);
+        sheet.setRowHeight(0, 30, sheetArea.colHeader);
+
+        sheet.resumeEvent();
+        sheet.resumePaint();
+    },
+
+    loadData(){          // 树结构转换二维表显示,行列转换
+        let me = this;
+        let libArr = [];
+        for (let v of me.datas) {if (!v.ParentID) libArr.push(v);};
+
+        // 行名称
+        let row = 0;
+        for (let v of me.datas) {
+            if (v.ParentID == libArr[0].ID) {
+                me.sheet.setText(row, 0, v.name, GC.Spread.Sheets.SheetArea.viewport);
+                row++;
+            };
+        };
+
+        me.sheet.setColumnCount(libArr.length + 1, GC.Spread.Sheets.SheetArea.viewport);    // 还多一列行名称
+        me.sheet.setRowCount(row, GC.Spread.Sheets.SheetArea.viewport);
+        me.sheet.setText(0, 0, "定额工种", GC.Spread.Sheets.SheetArea.colHeader);
+        me.sheet.options.isProtected = true;
+        me.sheet.getRange(-1, 1, -1, libArr.length + 1, GC.Spread.Sheets.SheetArea.viewport).locked(false); 
+
+        // 列名称
+        for (let c = 0; c <= libArr.length - 1; c++) {
+            me.sheet.setText(0, c + 1, libArr[c].name, GC.Spread.Sheets.SheetArea.colHeader);
+            me.sheet.setColumnWidth(c + 1, 100, GC.Spread.Sheets.SheetArea.colHeader);
+            // 值明细
+            let libID = libArr[c].ID;
+            for (let r = 0; r < row; r++) {
+                let rowName = me.sheet.getText(r, 0);
+                for (let v of me.datas) {
+                    if ((v.ParentID == libID) && (v.name == rowName)) {
+                        me.sheet.setValue(r, c + 1, v.coe);
+                        break;
+                    };
+                };
+            };
+        };
+    },
+
+    showData(){
+        let me = this;
+        me.buildSheet();
+        me.loadData();
+    }
+};
+
+$(document).ready(function(){
+    $("#tab_poj-settings-6").on('shown.bs.tab', function (e) {
+        labourCoeView.showData();
+    });
+});

+ 1 - 0
web/building_saas/main/js/views/std_bills_lib.js

@@ -108,6 +108,7 @@ var billsLibObj = {
         var showJobsAndFeatures = function (node) {
             $('#stdBillsJobTab').show();
             $('#stdBillsRemarkTab').hide();
+            billsLibObj.refreshBillsRelaSpread();
             billsLibObj.checkBillsRelaSpread();
             showJobs(getBillsJobs(node));
             showFeatures(getBillsFeatures(node));

+ 1 - 1
web/users/html/user-safe.html

@@ -103,7 +103,7 @@
                             <td><%= log.message.os %></td>
                             <td><%= log.message.browser %></td>
                             <td><%= moment(log.create_time).format('YYYY-MM-DD HH:mm:ss') %></td>
-                            <td>(<%= log.message.ip %>)</td>
+                            <td><%= log.message.ip_info %>(<%= log.message.ip %>)</td>
                         </tr>
                         <% }) %>
                         </tbody>