瀏覽代碼

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

TonyKang 8 年之前
父節點
當前提交
c39d9ef510

+ 2 - 0
modules/common/base/base_controller.js

@@ -37,6 +37,8 @@ class BaseController {
      * @return {void}
      */
     init(request, response, next) {
+        response.locals.title = 'test';
+
         // moment工具
         response.locals.moment = Moment;
 

+ 13 - 0
modules/common/const/setting_type_const.js

@@ -0,0 +1,13 @@
+/**
+ * 个人设置类型常量
+ *
+ * @author CaiAoLin
+ * @date 2017/7/27
+ * @version
+ */
+let settingType = {
+    // 偏好设置
+    PREFERENCE: 1
+};
+
+export default settingType;

+ 1 - 1
modules/common/helper/mongoose_helper.js

@@ -53,7 +53,7 @@ class MongooseHelper {
         let self = this;
         let limit = 0;
         let skip = 0;
-        if (Object.keys(option).length > 0) {
+        if (option !== null && Object.keys(option).length > 0) {
             limit = option.pageSize !== undefined ? option.pageSize : limit;
             skip = option.offset !== undefined ? option.offset : skip;
         }

+ 1 - 1
modules/glj/models/glj_list_model.js

@@ -59,7 +59,7 @@ class GLJListModel extends BaseModel {
                 this.model.schema.path('glj_id').required(true);
                 this.model.schema.path('project_id').required(true);
                 this.model.schema.path('code').required(true);
-                this.model.schema.path('name').required(true);
+                // this.model.schema.path('name').required(true);
                 break;
         }
     }

+ 2 - 1
modules/glj/models/schemas/glj.js

@@ -24,7 +24,8 @@ let modelSchema = {
     // 名称
     name: {
         type: String,
-        index: true
+        index: true,
+        default: ''
     },
     // 是否暂估 (0为否 1为是)
     is_evaluate: {

+ 8 - 1
modules/users/controllers/boot_controller.js

@@ -17,8 +17,15 @@ class BootController extends BaseController {
      * @param {object} response
      * @return {void}
      */
-    boot(request, response) {
+    async boot(request, response) {
         let userModel = new UserModel();
+        let sessionUser = request.session.sessionUser;
+        // 判断是否已填写信息
+        let userData = await userModel.findDataByCondition({_id: sessionUser.id});
+        if (userData.company !== '' && userData.real_name !== '') {
+            return response.redirect('/pm');
+        }
+
         let renderData = {
             provinceList: userModel.province,
             companyTypeList: userModel.companyType,

+ 8 - 5
modules/users/controllers/login_controller.js

@@ -6,7 +6,7 @@
  * @version
  */
 import UserModel from "../models/user_model";
-
+import SettingModel from "../models/setting_model";
 
 class LoginController {
 
@@ -35,7 +35,7 @@ class LoginController {
     async login(request, response) {
         let account = request.body.account;
         let password = request.body.pw;
-        let userExist = true;
+        let preferenceSetting = {};
 
         try {
             // 调用接口验证登录信息
@@ -60,8 +60,11 @@ class LoginController {
             };
             request.session.sessionUser = sessionUser;
             // 记录用户数据到数据库
-            let [result, exist] = await userModel.markUser(sessionUser, request);
-            userExist = exist;
+            let result = await userModel.markUser(sessionUser, request);
+
+            // 获取偏好设置
+            let settingModel = new SettingModel();
+            preferenceSetting = await settingModel.getPreferenceSetting(request.session.sessionUser.id);
 
             if (!result) {
                 throw '标记用户信息失败!';
@@ -71,7 +74,7 @@ class LoginController {
             console.log(error);
             return response.json({error: 1, msg: error});
         }
-        response.json({error: 0, msg: '', exist: userExist ? 1 : 0});
+        response.json({error: 0, msg: '', login_ask: preferenceSetting.login_ask});
     }
 
 }

+ 58 - 0
modules/users/controllers/user_controller.js

@@ -9,6 +9,8 @@ import UserModel from "../models/user_model";
 import BaseController from "../../common/base/base_controller";
 import LogType from "../../common/const/log_type_const";
 import LogModel from "../models/log_model";
+import SettingModel from "../models/setting_model";
+import SettingType from "../../common/const/setting_type_const";
 
 class UserController extends BaseController {
 
@@ -113,6 +115,62 @@ class UserController extends BaseController {
         response.render('users/html/user-safe', renderData);
     }
 
+    /**
+     * 偏好设置页面
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async preferences(request, response) {
+        let sessionUserData = request.session.sessionUser;
+        let preferenceSetting = {};
+        try {
+            // 获取配置信息
+            let settingModel = new SettingModel();
+            preferenceSetting = await settingModel.getPreferenceSetting(sessionUserData.id);
+
+        } catch(error) {
+            console.log(error);
+        }
+
+        let renderData = {
+            preferenceSetting: preferenceSetting
+        };
+        response.render('users/html/user-set', renderData);
+    }
+
+    /**
+     * 保存偏好设置
+     *
+     * @param {object} request
+     * @param {object} response
+     * @return {void}
+     */
+    async savePreferences(request, response) {
+        let loginAsk = request.body.login_ask;
+        loginAsk = parseInt(loginAsk);
+        let selectVersion = request.body.select_version;
+        selectVersion = parseInt(selectVersion);
+        let sessionUserData = request.session.sessionUser;
+
+        try {
+            let data = {
+                login_ask: loginAsk,
+                select_version: loginAsk === 0 ? selectVersion : -1
+            };
+            let settingModel = new SettingModel();
+            let result = await settingModel.save(sessionUserData.id, SettingType.PREFERENCE, data);
+            if (!result) {
+                throw '保存失败';
+            }
+        } catch (error) {
+            console.log(error);
+        }
+
+        response.redirect(request.headers.referer);
+    }
+
 }
 
 export default UserController;

+ 31 - 0
modules/users/models/schema/setting.js

@@ -0,0 +1,31 @@
+/**
+ * 个人设置数据结构
+ *
+ * @author CaiAoLin
+ * @date 2017/7/27
+ * @version
+ */
+import mongoose from "mongoose";
+
+let Schema = mongoose.Schema;
+let collectionName = 'setting';
+let modelSchema = {
+    // 设置类型
+    type: {
+        type: Number,
+        index: true
+    },
+    // 设置内容
+    data: {
+        type: Schema.Types.Mixed,
+    },
+    // 关联用户id
+    user_id: {
+        type: String,
+        index: true
+    },
+    // 创建时间
+    create_time: Number
+};
+let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
+export {model as default, collectionName as collectionName};

+ 134 - 0
modules/users/models/setting_model.js

@@ -0,0 +1,134 @@
+/**
+ * 个人设置业务逻辑
+ *
+ * @author CaiAoLin
+ * @date 2017/7/27
+ * @version
+ */
+import BaseModel from "../../common/base/base_model";
+import SettingType from "../../common/const/setting_type_const";
+import SettingSchema from "./schema/setting";
+
+class SettingModel extends BaseModel {
+
+    /**
+     * 偏好设置默认
+     *
+     * @var {Object}
+     */
+    preferenceDefault = {
+        login_ask: 1,
+        select_version: -1
+    };
+
+    /**
+     * 设置场景
+     *
+     * @param {string} scene
+     * @return {void}
+     */
+    setScene(scene = '') {
+        switch (scene) {
+            // 新增数据的验证规则
+            case 'add':
+                this.model.schema.path('type').required(true);
+                this.model.schema.path('data').required(true);
+                this.model.schema.path('user_id').required(true);
+                break;
+            case 'update':
+                this.model.schema.path('data').required(true);
+                break;
+        }
+    }
+
+    /**
+     * 构造函数
+     */
+    constructor() {
+        let parent = super();
+        parent.model = SettingSchema;
+        parent.init();
+    }
+
+    /**
+     * 获取设置信息
+     *
+     * @param {String} userId
+     * @param {Number} type
+     * @return {Promise}
+     */
+    async getSetting(userId, type) {
+        let condition = {
+            user_id: userId,
+            type: type
+        };
+
+        let settingData = await this.findDataByCondition(condition);
+        return settingData !== null && Object.keys(settingData).length > 0 ?
+            settingData.data : {};
+    }
+
+    /**
+     * 保存设置
+     *
+     * @param {String} userId
+     * @param {Number} type
+     * @param {Object} data
+     * @return {Promise}
+     */
+    async save(userId, type, data) {
+        let result = false;
+        if (typeof data === 'string' && data === '') {
+            return result;
+        }
+        if (typeof data === 'object' && Object.keys(data).length <= 0) {
+            return result;
+        }
+
+        // 查找是否有对应数据
+        let condition = {
+            user_id: userId,
+            type: type
+        };
+        let counter = await this.db.count(condition);
+        let saveData = {};
+
+        if (counter > 0) {
+            // 存在则更新
+            saveData = {
+                data: data
+            };
+            this.setScene('add');
+            let updateResult = await this.db.update(condition, saveData);
+            result = updateResult.ok === 1;
+        } else {
+            saveData = {
+                user_id: userId,
+                type: type,
+                data: data,
+                create_time: new Date().getTime()
+            };
+            this.setScene('update');
+            let insertResult = await this.db.create(saveData);
+            result = Object.keys(insertResult).length > 0;
+        }
+
+        return result;
+    }
+
+    /**
+     * 获取个人偏好设置
+     *
+     * @param {String} userId
+     * @return {Promise}
+     */
+    async getPreferenceSetting(userId) {
+        let setting = await this.getSetting(userId, SettingType.PREFERENCE);
+        setting = Object.keys(setting).length <= 0 ? this.preferenceDefault : setting;
+
+        return setting;
+    }
+
+}
+
+export default SettingModel;

+ 8 - 10
modules/users/models/user_model.js

@@ -87,20 +87,18 @@ class UserModel extends BaseModel {
         let userDataFromDb = await this.findDataByName(userData.username);
         let result = false;
 
-        // 信息是否补全
-        let info = false;
-        if (userDataFromDb.length <= 0) {
+        if (userDataFromDb === null) {
             // 不存在用户则入库
             result = await this.addUser(userData);
+            userDataFromDb = result;
         } else {
-            info = true;
             // 存在则新增登录信息
             let logModel = new LogModel();
             result = await logModel.addLoginLog(userDataFromDb._id, request);
         }
         request.session.sessionUser.id = userDataFromDb._id;
 
-        return [result, info];
+        return result;
     }
 
     /**
@@ -111,10 +109,10 @@ class UserModel extends BaseModel {
     setScene(scene = '') {
         switch (scene) {
             case 'saveInfo':
-                this.db.model.schema.path('real_name').required(true);
-                this.db.model.schema.path('company').required(true);
-                this.db.model.schema.path('province').required(true);
-                this.db.model.schema.path('area').required(true);
+                this.model.schema.path('real_name').required(true);
+                this.model.schema.path('company').required(true);
+                this.model.schema.path('province').required(true);
+                this.model.schema.path('area').required(true);
                 break;
         }
     }
@@ -126,7 +124,7 @@ class UserModel extends BaseModel {
      * @return {object}
      */
     findDataByName(username) {
-        return this.db.model.find({username: username});
+        return this.db.findOne({username: username});
     }
 
     /**

+ 2 - 0
modules/users/routes/user_route.js

@@ -16,6 +16,8 @@ module.exports = function (app) {
 // action定义区域
     router.get('/info', userController.init, userController.info);
     router.get('/safe', userController.init, userController.safe);
+    router.get('/preferences', userController.init, userController.preferences);
+    router.post('/save-preferences', userController.init, userController.savePreferences);
     router.post('/info', userController.init, userController.saveData);
     app.use('/user',router);
 };

+ 21 - 23
public/calc_util.js

@@ -16,10 +16,11 @@ let executeObj = {
     currentTpl : null,
     currentRationItem: null,
     currentFeeRateFile: null,
-    at: function(code) {
+    at: function(ID) {
         let me = executeObj,
             rst = 0;
-        rst = me.currentTpl.compileAssistantObj[code].unitFee;
+        rst = me.currentTpl.compileAssistantObj[ID].unitFee;
+        rst = parseFloat(rst);
         return rst;
     },
     base: function(calcBaseCode) {
@@ -74,7 +75,8 @@ class calculation {
         let me = this;
         me.hasCompiled = false;
         me.errs = [];
-        let private_extract_code = function(str, idx){
+
+        let private_extract_ID = function(str, idx){
             let rst = '', lBracket = 0, rBracket = 0, firstIdx = idx, lastIdx = 0;
             for (let i = idx; i < str.length; i++) {
                 if (str[i] === '(') {
@@ -99,30 +101,28 @@ class calculation {
             return rst;
         };
         let private_parse_ref = function(item, itemIdx){
-            let expr = item.expression.split('at(').join('A(');
-            item.expression = expr;
+            //let expr = item.expression.split('at(').join('@(');
+            //item.expression = expr;
             //console.log('expression: ' + expr);
-            let idx = expr.indexOf('A(', 0);
+            let idx = item.expression.indexOf('@(', 0);
             while (idx >= 0) {
-                let code = private_extract_code(expr, idx);
-                //console.log('提取code: ' + code);
-                if (code.length > 0) {
-                    let subItem = me.compileAssistantObj[code];
+                let ID = private_extract_ID(item.expression, idx);
+                if (ID.length > 0) {
+                    let subItem = me.compileAssistantObj[ID];
                     if (subItem) {
-                        if (subItem.code !== item.code) {
-                            private_parse_ref(subItem, me.compileAssistantObj[code + "_idx"]);
+                        if (subItem.ID !== item.ID) {
+                            private_parse_ref(subItem, me.compileAssistantObj[ID + "_idx"]);
                         } else {
-                            me.errs.push("There exists the self refer code: " + code);
+                            me.errs.push("There exists the self refer ID: " + ID);
                         }
                     } else {
-                        me.errs.push("There exists the invalid code by which could not find the item: " + code);
-                        console.log('invalid code: ' + code);
+                        me.errs.push("There exists the invalid ID by which could not find the item: " + ID);
+                        console.log('invalid ID: ' + ID);
                     }
                 }
-                idx = expr.indexOf('A(', idx + code.length + 3);
+                idx = item.expression.indexOf('@(', idx + ID.length + 3);
             }
             if (me.calcTpl.compiledSeq.indexOf(itemIdx) < 0) {
-                //console.log('the code ready to push: ' + item.code);
                 me.calcTpl.compiledSeq.push(itemIdx);
             }
         };
@@ -134,7 +134,7 @@ class calculation {
         let private_compile_items = function() {
             for (let idx of me.calcTpl.compiledSeq) {
                 let item = me.calcTpl.calcItems[idx];
-                item.compiledExpr = item.expression.split('A(').join('$CE.at(');
+                item.compiledExpr = item.expression.split('@(').join('$CE.at(');
                 item.compiledExpr = item.compiledExpr.split('base(').join('$CE.base(');
                 item.compiledExpr = item.compiledExpr.split('fee(').join('$CE.fee(');
                 item.compiledExpr = item.compiledExpr.split('factor(').join('$CE.factor(');
@@ -157,8 +157,8 @@ class calculation {
             private_comile_feeFile();
             for (let i = 0; i < me.calcTpl.calcItems.length; i++) {
                 let item = me.calcTpl.calcItems[i];
-                me.compileAssistantObj[item.code] = item;
-                me.compileAssistantObj[item.code + "_idx"] = i;
+                me.compileAssistantObj[item.ID] = item;
+                me.compileAssistantObj[item.ID + "_idx"] = i;
             }
             //2. second round -> go!
             for (let i = 0; i < me.calcTpl.calcItems.length; i++) {
@@ -171,8 +171,6 @@ class calculation {
                 console.log('errors: ' + me.errs.toString());
             }
         }
-        //console.log(me.compileAssistantObj);
-        //console.log(me.calcTpl.compiledSeq);
     };
     calculate( $RATION){
         let me = this;
@@ -185,7 +183,7 @@ class calculation {
             for (let idx of me.calcTpl.compiledSeq) {
                 let item = me.calcTpl.calcItems[idx];
                 item.unitFee = eval(item.compiledExpr);
-                item.totalFee = eval(item.unitFee * 5);     // AAAAA 5为测试值 $RATION.data.Quantity
+                item.totalFee = item.unitFee * 3;     // AAAAA 5为测试值 $RATION.data.Quantity
             }
         }
     }

+ 148 - 0
web/building_saas/main/js/calc/bills_calc.js

@@ -68,6 +68,154 @@ let nodeCalcObj = {
     }
 };
 
+let baseCalcField = [
+    {
+        ID: 1,
+        // 序号
+        serialNo: '一',
+        // 费用代号
+        code: "A",
+        // 名称
+        name: "定额直接费",
+        // 计算基数
+        dispExpr: "A1+A2+A3",
+        // 基数说明
+        statement: "人工费+材料费+机械费",
+        // 费率
+        feeRate: null,
+        // 费用类别
+        type: 'RationDirect',
+        // 备注
+        memo: ''
+    }, {
+        ID: 2,
+        // 序号
+        serialNo: '1',
+        // 费用代号
+        code: "A1",
+        // 名称
+        name: "人工费",
+        // 计算基数
+        dispExpr: "H_J",
+        // 基数说明
+        statement: "合计",
+        // 费率
+        feeRate: 0,
+        // 费用类别
+        type: 'labour',
+        // 备注
+        memo: ''
+    }, {
+        ID: 3,
+        // 序号
+        serialNo: '2',
+        // 费用代号
+        code: "A2",
+        // 名称
+        name: "材料费",
+        // 计算基数
+        dispExpr: "H_J",
+        // 基数说明
+        statement: "合计",
+        // 费率
+        feeRate: 100,
+        // 费用类别
+        type: 'material',
+        // 备注
+        memo: ''
+    }, {
+        ID: 4,
+        // 序号
+        serialNo: '3',
+        // 费用代号
+        code: "A3",
+        // 名称
+        name: "机械费",
+        // 计算基数
+        dispExpr: "H_J",
+        // 基数说明
+        statement: "合计",
+        // 费率
+        feeRate: 0,
+        // 费用类别
+        type: 'machine',
+        // 备注
+        memo: ''
+    }, {
+        ID: 5,
+        // 序号
+        serialNo: '二',
+        // 费用代号
+        code: "A4",
+        // 名称
+        name: "管理费",
+        // 计算基数
+        dispExpr: "A",
+        // 基数说明
+        statement: "定额直接费",
+        // 费率
+        feeRate: 0,
+        // 费用类别
+        type: 'management',
+        // 备注
+        memo: ''
+    }, {
+        ID: 6,
+        // 序号
+        serialNo: '三',
+        // 费用代号
+        code: "B",
+        // 名称
+        name: "利润",
+        // 计算基数
+        dispExpr: "A",
+        // 基数说明
+        statement: "定额直接费",
+        // 费率
+        feeRate: 0,
+        // 费用类别
+        type: 'profit',
+        // 备注
+        memo: ''
+    }, {
+        ID: 7,
+        // 序号
+        serialNo: '四',
+        // 费用代号
+        code: "C",
+        // 名称
+        name: "风险费用",
+        // 计算基数
+        dispExpr: "",
+        // 基数说明
+        statement: "",
+        // 费率
+        feeRate: null,
+        // 费用类别
+        type: 'risk',
+        // 备注
+        memo: ''
+    }, {
+        ID: 8,
+        // 序号
+        serialNo: '',
+        // 费用代号
+        code: "",
+        // 名称
+        name: "综合单价",
+        // 计算基数
+        dispExpr: "A+B",
+        // 基数说明
+        statement: "定额直接费+利润",
+        // 费率
+        feeRate: NaN,
+        // 费用类别
+        type: 'common',
+        // 备注
+        memo: ''
+    }
+];
+
 class BillsCalcHelper {
     constructor (project, CalcFlag) {
         this.project = project;

+ 13 - 0
web/building_saas/main/js/calc/calc_fees.js

@@ -2,6 +2,19 @@
  * Created by Mai on 2017/7/21.
  */
 
+let feeType = [
+    {type: 'common', name: '工程造价'},
+    {type: 'labour', name: '人工费'},
+    {type: 'material', name: '材料费'},
+    {type: 'machine', name: '机械费'},
+    {type: 'rationDirect', name: '定额直接费'},
+    {type: 'management', name: '企业管理'},
+    {type: 'profit', name: '利润'},
+    {type: 'risk', name: '风险费'},
+    // 模拟用户新增
+    {type: 'fee1', name: '甲供材料费'}
+];
+
 let calcFees = {
     findFee: function (data, fieldName) {
         if (!data.fees) {

+ 12 - 16
web/building_saas/main/js/models/bills.js

@@ -159,28 +159,24 @@ var Bills = {
             return this.tree.insertByData(newData, parentId, nextSiblingId);
         };
         bills.prototype.deleteBills = function (node) {
+            let deleteNode = function (node) {
+                this.project.Ration.deleteByBills([node]);
+                this.project.VolumePrice.deleteByBills([node]);
+                return this.tree.delete(node);
+            }
             var deleteData = this.tree.getDeleteData(node);
             var ration_glj =projectObj.project.ration_glj;
-          //  project.beginUpdate('deleteBills');
-            //project.push(ModuleNames.bills, tools.coverseTreeUpdateData(deleteData, this.project.ID()));
-            //project.endUpdate();
-            var moudles =[ModuleNames.bills,ModuleNames.ration_glj];
-            var deleteDatas=[tools.coverseTreeUpdateData(deleteData, this.project.ID()),ration_glj.getDeleteDataByBills(deleteData)];
+            let modules =[ModuleNames.bills, ModuleNames.ration, ModuleNames.ration_glj, ModuleNames.volume_price];
+            let deleteDatas=[tools.coverseTreeUpdateData(deleteData, this.project.ID()),
+                this.project.Ration.getDeleteDataByBill([node]), ration_glj.getDeleteDataByBills(deleteData),
+                this.project.VolumePrice.getDeleteDataByBills([node])
+            ];
             project.ration_glj.deleteByBills(deleteData);
             project.quantity_detail.deleteByBills(deleteData);
-            project.pushNow('deleteBILL', moudles, deleteDatas);
-            this.delete(deleteData);
+            project.pushNow('deleteBills', modules, deleteDatas);
 
-           // return this.tree.delete(node);
+            return this.tree.delete(node);
         };
-        bills.prototype.delete=function(deleteData){
-            for(var i=0;i<deleteData.length;i++){
-                var billID = deleteData[i].data.ID;
-                 this.datas =_.filter(this.datas,(bill)=>{
-                    return bill.ID!=billID;
-                });
-            }
-        }
 
 
         bills.prototype.upMoveBills = function (node) {

+ 30 - 5
web/building_saas/main/js/models/ration.js

@@ -158,7 +158,7 @@ var Ration = {
                     newRation = data.updateData;
                 }
             });
-            this.project.pushNow('insertRation', [this.getSourceType()], [updateData]);
+            this.project.pushNow('insertRation', [this.getSourceType(), this.project.projCounter()], [updateData, this.getCounterData()]);
 
             newRation.ID = this.getNewRationID();
             if (preRation) {
@@ -178,16 +178,41 @@ var Ration = {
             updateData.push({'updateType': 'ut_delete', 'updateData': {'ID': rationData.ID, 'projectID': this.project.ID()}});
             return updateData;
         };
-        ration.prototype.getDeleteDataByBill = function (node) {
-            console.log(node);
-        };
-
         ration.prototype.delete = function (ration) {
             var ration_glj =projectObj.project.ration_glj;
             this.project.pushNow('deleteRation', [this.getSourceType(),ration_glj.getSourceType()], [this.getDeleteData(ration),ration_glj.getDeleteDataByRation(ration)]);
 
+            project.ration_glj.deleteByRation(ration);
+            project.ration_coe.deleteByRation(ration);
+            project.quantity_detail.deleteByRation(ration);
             this.datas.splice(this.datas.indexOf(ration), 1);
         };
+        ration.prototype.getDeleteDataByBill = function (nodes) {
+            let updateData = [];
+            for (let node of nodes) {
+                if (node.children.length > 0) {
+                    updateData = updateData.concat(this.getDeleteDataByBills[node.children]);
+                } else {
+                    let rations = this.getBillsSortRation(node.getID());
+                    for (let r of rations) {
+                        updateData.push({'updateType': 'ut_delete', 'updateData': {'ID': r.ID, 'projectID': this.project.ID()}});
+                    }
+                }
+            }
+            return updateData;
+        };
+        ration.prototype.deleteByBills = function (nodes) {
+            for (let node of nodes) {
+                if (node.children.length > 0) {
+                    this.deleteByBills([node.children]);
+                } else {
+                    let rations = this.getBillsSortRation(node.getID());
+                    for (let r of rations) {
+                        this.datas.splice(this.datas.indexOf(r), 1);
+                    }
+                }
+            }
+        }
 
         ration.prototype.getChangePosUpdateData = function (ration1, ration2) {
             var updateData = [];

+ 64 - 46
web/building_saas/main/js/models/ration_calc.js

@@ -221,149 +221,167 @@ let calcTemplate = {
     compiledSeq: [],
     calcItems: [
         {
+            ID: "1",
             code: "1",
             name: "基价直接工程费",
-            dispExpr: "A2+A5+A6+A10",
-            expression: "A('2') + A('5') + A('6') + A('10')",
+            dispExpr: "F2+F5+F6+F10",
+            expression: "@('2') + @('5') + @('6') + @('10')",
             compiledExpr: "",
             statement: "基价人工费+基价材料费+基价机械费+未计价材料费"
         },
         {
-            code: "2",
+            ID: "2",
+            code: "1.1",
             name: "基价人工费",
-            dispExpr: "A3+A4",
-            expression: "A('3') + A('4')",
+            dispExpr: "F3+F4",
+            expression: "@('3') + @('4')",
             compiledExpr: "",
             statement: "定额基价人工费+定额人工单价(基价)调整"
         },
         {
-            code: "3",
+            ID: "3",
+            code: "1.1.1",
             name: "定额基价人工费",
-            dispExpr: "定额基价人工费",
+            dispExpr: "[定额基价人工费]",
             expression: "base('定额基价人工费').toFixed(2)",
             compiledExpr: "",
             statement: "定额基价人工费"
         },
         {
-            code: "4",
-            name: "定额人工单价(基价)调整",
-            dispExpr: "A3*[1.89-1]",
-            expression: "A('3') * (1.89-1)",
+            ID: "4",
+            code: "1.1.2",
+            name: "[定额人工单价(基价)调整]",
+            dispExpr: "F3*(1.89-1)",
+            expression: "@('3') * (1.89-1)",
             compiledExpr: "",
             statement: "定额基价人工费*[定额人工单价(基价)调整系数-1]",
             memo: "渝建发(2013)51"
         },
         {
-            code: "5",
+            ID: "5",
+            code: "1.2",
             name: "基价材料费",
-            dispExpr: "定额基价材料费",
+            dispExpr: "[定额基价材料费]",
             expression: "base('定额基价材料费')",
             compiledExpr: "",
             statement: "定额基价材料费"
         },
         {
-            code: "6",
+            ID: "6",
+            code: "1.3",
             name: "基价机械费",
-            dispExpr: "A7+A9",
-            expression: "A('7') + A('9')",
+            dispExpr: "F7+F9",
+            expression: "@('7') + @('9')",
             compiledExpr: "",
             statement: "定额基价机械费+定额机上人工单价(基价)调整"
         },
         {
-            code: "7",
+            ID: "7",
+            code: "1.3.1",
             name: "定额基价机械费",
-            dispExpr: "定额基价机械费",
+            dispExpr: "[定额基价机械费]",
             expression: "base('定额基价机械费')",
             compiledExpr: "",
             statement: "定额基价机械费"
         },
         {
-            code: "8",
+            ID: "8",
+            code: "1.3.1.1",
             name: "其中:定额基价机上人工费",
-            dispExpr: "定额基价机上人工费",
+            dispExpr: "[定额基价机上人工费]",
             expression: "base('定额基价机上人工费')",
             compiledExpr: "",
             statement: "定额基价机上人工费"
         },
         {
-            code: "9",
+            ID: "9",
+            code: "1.3.2",
             name: "定额机上人工单价(基价)调整",
-            dispExpr: "A8*[1.89-1]",
-            expression: "A('8') * (1.89-1)",
+            dispExpr: "F8*(1.89-1)",
+            expression: "@('8') * (1.89-1)",
             compiledExpr: "",
             statement: "定额基价机上人工费*[定额机上人工单价(基价)调整系数-1]"
         },
         {
-            code: "10",
+            ID: "10",
+            code: "1.4",
             name: "未计价材料费",
-            dispExpr: "主材费+设备费",
+            dispExpr: "[主材费]+[设备费]",
             expression: "base('主材费') + base('设备费')",
             compiledExpr: "",
             statement: "主材费+设备费"
         },
         {
-            code: "11",
+            ID: "11",
+            code: "2",
             name: "企业管理费",
-            dispExpr: "A3",
-            expression: "A('3')",
+            dispExpr: "F3",
+            expression: "@('3')*8.21 / 100",
             compiledExpr: "",
             statement: "定额基价人工费",
             memo: "渝建发[2014]27号"
         },
         {
-            code: "12",
+            ID: "12",
+            code: "3",
             name: "利润",
-            dispExpr: "A3",
-            expression: "A('3')",
+            dispExpr: "F3",
+            expression: "@('3')*6.5 / 100",
             compiledExpr: "",
             statement: "定额基价人工费"
         },
         {
-            code: "13",
+            ID: "13",
+            code: "4",
             name: "风险因素",
-            dispExpr: "A3",
-            expression: "A('3')",
+            dispExpr: "F3",
+            expression: "@('3')*3 / 100",
             compiledExpr: "",
             statement: "定额基价人工费",
             memo: "同定额包干费"
         },
         {
-            code: "14",
+            ID: "14",
+            code: "5",
             name: "人材机价差",
-            dispExpr: "A15+A16+A17",
-            expression: "A('15') + A('16') + A('17')",
+            dispExpr: "F15+F16+F17",
+            expression: "@('15') + @('16') + @('17')",
             compiledExpr: "",
             statement: "人工费价差+材料费价差+机械费价差"
         },
         {
-            code: "15",
+            ID: "15",
+            code: "5.1",
             name: "人工费价差",
-            dispExpr: "信息价或市场价格-调整后的定额人工费(基价)",
+            dispExpr: "[市场价格人工费]-[调整后的定额人工费(基价)]",
             expression: "base('市场价格人工费') - base('定额基价人工费(调整后)')",
             compiledExpr: "",
             statement: "市场价格人工费-调整后的定额人工费(基价)"
         },
         {
-            code: "16",
+            ID: "16",
+            code: "5.2",
             name: "材料费价差",
-            dispExpr: "信息价或市场价格-定额基价材料费",
+            dispExpr: "[市场价格材料费]-[定额基价材料费]",
             expression: "base('市场价格材料费') - base('定额基价材料费(调整后)')",
             compiledExpr: "",
             statement: "市场价格材料费-定额基价材料费"
         },
         {
-            code: "17",
+            ID: "17",
+            code: "5.3",
             name: "机械费价差",
-            dispExpr: "信息价或市场价格-调整后的定额基价机械费(基价)",
+            dispExpr: "[市场价格机械费]-[调整后的定额基价机械费(基价)]",
             expression: "base('市场价格机械费') - base('定额基价机械费(调整后)')",
             compiledExpr: "",
             statement: "市场价格机械费-调整后的定额基价机械费(基价)"
         },
         {
-            code: "18",
+            ID: "18",
+            code: "6",
             name: "综合单价",
-            dispExpr: "A1+A11+A12+A13+A14",
-            expression: "A('1') + A('11') + A('12') + A('13') + A('14')",
+            dispExpr: "F1+F11+F12+F13+F14",
+            expression: "@('1') + @('11') + @('12') + @('13') + @('14')",
             compiledExpr: "",
             statement: "基价直接工程费+企业管理费+利润+风险因素+人材机价差"
         }

+ 51 - 2
web/building_saas/main/js/models/volume_price.js

@@ -35,6 +35,9 @@ var VolumePrice = {
 
             loadData (datas) {
                 this.datas = datas;
+                for (let data of datas) {
+                    this.maxID(data.ID);
+                }
             };
             setMaxID (ID) {
                 this.maxID(ID);
@@ -55,6 +58,15 @@ var VolumePrice = {
                 return arr;
             };
 
+            getCounterData (count) {
+                var updateData = {'projectID': this.getProject().ID()};
+                if (count) {
+                    updateData[this.getSourceType()] = this.maxID() + count;
+                } else {
+                    updateData[this.getSourceType()] = this.maxID() + 1;
+                }
+                return updateData;
+            };
             getInsertVolumePriceData (billsID, pre) {
                 let bv = this.getBillsSortVolumePrice(billsID);
                 let updateData = [];
@@ -70,7 +82,7 @@ var VolumePrice = {
                 return updateData;
             };
             insertVolumePrice (billsID, pre) {
-                tools.owner.pushNow('insertVolumePrice', [this.getSourceType()], [this.getInsertVolumePriceData(billsID, pre)]);
+                tools.owner.pushNow('insertVolumePrice', [this.getSourceType(), this.getProject().projCounter()], [this.getInsertVolumePriceData(billsID, pre), this.getCounterData()]);
 
                 let bv = this.getBillsSortVolumePrice(billsID), newVP = null;
                 if (pre) {
@@ -85,7 +97,44 @@ var VolumePrice = {
                     this.datas.push(newVP);
                 }
                 return newVP;
-            }
+            };
+
+            getDeleteData (volumePrice) {
+                var updateData = [];
+                updateData.push({'updateType': 'ut_delete', 'updateData': {'ID': volumePrice.ID, 'projectID': this.getProject().ID()}});
+                return updateData;
+            };
+            delete (volumePrice) {
+                this.getProject().pushNow('deleteVolumePrice', [this.getSourceType()], [this.getDeleteData(volumePrice)]);
+                this.datas.splice(this.datas.indexOf(volumePrice), 1);
+            };
+
+            getDeleteDataByBills (nodes) {
+                let updateData = [];
+                for (let node of nodes) {
+                    if (node.children.length > 0) {
+                        updateData = updateData.concat(this.getDeleteDataByBills[node.children]);
+                    } else {
+                        let vps = this.getBillsSortVolumePrice(node.getID());
+                        for (let vp of vps) {
+                            updateData.push({'updateType': 'ut_delete', 'updateData': {'ID': vp.ID, 'projectID': this.getProject().ID()}});
+                        }
+                    }
+                }
+                return updateData;
+            };
+            deleteByBills (nodes) {
+                for (let node of nodes) {
+                    if (node.children.length > 0) {
+                        this.deleteByBills([node.children]);
+                    } else {
+                        let vps = this.getBillsSortVolumePrice(node.getID());
+                        for (let vp of vps) {
+                            this.datas.splice(this.datas.indexOf(vp), 1);
+                        }
+                    }
+                }
+            };
         }
 
         return new volumePrice();

+ 12 - 7
web/building_saas/main/js/views/project_view.js

@@ -82,10 +82,12 @@ var projectObj = {
                     gljOprObj.showDataIfRationSelect(node);
 
                     // CSL.2017.07.25
-                    if(node.sourceType=="ration" && SubActiveSheetNameIs('JSCX')){
-                        rationCalcView.showData(node);
-                    }else{
-                        if (SubActiveSheetNameIs('JSCX')) {
+                    if (SubActiveSheetNameIs('JSCX')) {
+                        if (node.sourceType === that.project.Bills.getSourceType()) {
+                            rationCalcView.clearData();
+                        } else if (node.sourceType==='ration') {
+                            rationCalcView.showData(node);
+                        } else {
                             rationCalcView.clearData();
                         }
                     }
@@ -182,6 +184,12 @@ var projectObj = {
                             if (selected.sourceType === project.Bills.getSourceType()) {
                                 project.Bills.deleteBills(selected.source);
                                 controller.delete();
+                            } else if (selected.sourceType === project.Ration.getSourceType()) {
+                                project.Ration.delete(selected.source);
+                                controller.delete();
+                            } else if (selected.sourceType === project.VolumePrice.getSourceType()) {
+                                project.VolumePrice.delete(selected.source);
+                                controller.delete();
                             };
                         }
                     }
@@ -238,9 +246,6 @@ $('#delete').click(function () {
             controller.delete();
         } else if (selected.sourceType === project.Ration.getSourceType()) {
             project.Ration.delete(selected.source);
-            project.ration_glj.deleteByRation(selected.source);
-            project.ration_coe.deleteByRation(selected.source);
-            project.quantity_detail.deleteByRation(selected.source);
             controller.delete();
         } else if (selected.sourceType === project.VolumePrice.getSourceType()) {
             project.VolumePrice.delete(selected.source);

+ 2 - 2
web/building_saas/main/js/views/ration_calc_view.js

@@ -65,9 +65,9 @@ let rationCalcView = {
 
     setting: {
         header: [
-            {headerName: "费用代号", headerWidth: 75, dataCode: "code", dataType: "String", formatter: "A"+"0", hAlign: "center"},
+            {headerName: "费用代号", headerWidth: 75, dataCode: "code", dataType: "String", hAlign: "left"},
             {headerName: "费用名称", headerWidth: 200, dataCode: "name", dataType: "String"},
-            {headerName: "计算基数", headerWidth: 180, dataCode: "dispExpr", dataType: "String"},
+            {headerName: "计算基数", headerWidth: 280, dataCode: "dispExpr", dataType: "String"},
             {headerName: "基数说明", headerWidth: 220, dataCode: "statement", dataType: "String"},
             {headerName: "费率", headerWidth: 80, dataCode: "feeRate", dataType: "Number"},   // precision: 3
             {headerName: "单价", headerWidth: 100, dataCode: "unitFee", dataType: "Number"},  // execRst

+ 1 - 1
web/building_saas/main/js/views/sub_view.js

@@ -60,7 +60,7 @@ $("#linkJSCX").click(function(){        // 计算程序
     subSpread.setActiveSheetIndex(4);
     rationCalcView.initSheet(subSpread.getSheet(4));
     let sel = projectObj.mainController.tree.selected;
-    if (sel.sourceType == 'ration'){
+    if (sel != null && sel.sourceType == 'ration'){
         rationCalcView.showData(sel);
     }
     else{

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

@@ -31,7 +31,7 @@
                             <a class="nav-link" href="user-buy.html">产品购买</a>
                         </li>
                         <li class="nav-item">
-                            <a class="nav-link" href="user-set.html">偏好设置</a>
+                            <a class="nav-link" href="/user/preferences">偏好设置</a>
                         </li>
                     </ul>
                 </div>

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

@@ -37,7 +37,7 @@
                             <a class="nav-link" href="user-buy.html">产品购买</a>
                         </li>
                         <li class="nav-item">
-                            <a class="nav-link" href="user-set.html">偏好设置</a>
+                            <a class="nav-link" href="/user/preferences">偏好设置</a>
                         </li>
                     </ul>
                 </div>

+ 86 - 0
web/users/html/user-set.html

@@ -0,0 +1,86 @@
+<!DOCTYPE html>
+<html lang="en">
+
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
+    <meta http-equiv="x-ua-compatible" content="ie=edge">
+    <title>偏好设置-Smartcost</title>
+    <link rel="stylesheet" href="/lib/bootstrap/css/bootstrap.min.css">
+    <link rel="stylesheet" href="/web/building_saas/css/main.css">
+    <link rel="stylesheet" href="/lib/font-awesome/font-awesome.min.css">
+</head>
+
+<body>
+    <div class="header">
+        <%include ../../common/html/header.html %>
+    </div>
+    <div class="main">
+        <div class="poj-manage container-fluid">
+            <div class="row">
+                <div class="col-lg-2">
+                    <div class="poj-cate mt-3">
+                        <ul class="nav nav-pills flex-column">
+                            <li class="nav-item">
+                                <a class="nav-link" href="user-info.html">账号资料</a>
+                            </li>
+                            <li class="nav-item">
+                                <a class="nav-link" href="user-safe.html">账号安全</a>
+                            </li>
+                            <li class="nav-item">
+                                <a class="nav-link" href="user-buy.html">产品购买</a>
+                            </li>
+                            <li class="nav-item">
+                                <a class="nav-link active" href="user-set.html">偏好设置</a>
+                            </li>
+                        </ul>
+                    </div>
+                </div>
+                <div class="col-lg-10">
+                    <div class="col-lg-4">
+                        <legend class="my-3">偏好设置</legend>
+                        <form method="post" action="/user/save-preferences">
+                            <div class="form-group">
+                                <label class="form-control-label">登录时选择版本</label>
+                                <div>
+                                    <label class="custom-control custom-radio">
+                                      <input name="login_ask" type="radio" class="custom-control-input" value="1"
+                                        <% if(preferenceSetting.login_ask === 1) { %>checked="checked" <% } %>>
+                                      <span class="custom-control-indicator"></span>
+                                      <span class="custom-control-description">每次询问</span>
+                                    </label>
+                                    <label class="custom-control custom-radio">
+                                      <input name="login_ask" type="radio" class="custom-control-input" value="0"
+                                        <% if(preferenceSetting.login_ask === 0) { %>checked="checked" <% } %>>
+                                      <span class="custom-control-indicator"></span>
+                                      <span class="custom-control-description">指定版本</span>
+                                    </label>
+                                </div>
+                            </div>
+                            <div class="form-group">
+                                <label class="form-control-label">指定版本</label>
+                                <select class="form-control" name="select_version">
+                                  <option value="1" <% if(preferenceSetting.select_version === 1) { %>selected="selected" <% } %>>广东版(专业版)</option>
+                                  <option value="2" <% if(preferenceSetting.select_version === 2) { %>selected="selected" <% } %>>重庆版(免费版)</option>
+                                </select>
+                            </div>
+                            <div class="form-group mt-3">
+                                <button class="btn btn-primary" type="submit">确认</button>
+                            </div>
+                        </form>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <!-- JS. -->
+    <script src="/lib/jquery/jquery.min.js"></script>
+    <script src="/lib/tether/tether.min.js"></script>
+    <script src="/lib/bootstrap/bootstrap.min.js"></script>
+    <script src="/web/building_saas/js/global.js"></script>
+</body>
+<script type="text/javascript">
+    autoFlashHeight();
+</script>
+
+</html>

+ 1 - 1
web/users/js/login.js

@@ -21,7 +21,7 @@ $(document).ready(function () {
             data: {"account": account, "pw": pw},
             success: function (response) {
                 if (response.error === 0) {
-                    if (response.exist == 1) {
+                    if (response.login_ask === 0) {
                         location.href = '/pm';
                     } else {
                         $('#ver').modal('show');