Browse Source

回收站

zhongzewei 7 years ago
parent
commit
f5e3307ade

+ 23 - 0
modules/complementary_glj_lib/models/gljModel.js

@@ -37,8 +37,29 @@ class GljDao {
             else callback(false, data);
         })
     };
+    _exist(data, attr){
+        return data && data[attr] !== 'undefined' && data[attr];
+    }
+
+    sortToNumber(datas){
+        for(let i = 0, len = datas.length; i < len; i++){
+            let data = datas[i]._doc;
+            if(this._exist(data, 'basePrice')){
+                data['basePrice'] = parseFloat(data['basePrice']);
+            }
+            if(this._exist(data, 'component')){
+                for(let j = 0, jLen = data['component'].length; j < jLen; j++){
+                    let comGljObj = data['component'][j]._doc;
+                    if(this._exist(comGljObj, 'consumeAmt')){
+                        comGljObj['consumeAmt'] = parseFloat(comGljObj['consumeAmt']);
+                    }
+                }
+            }
+        }
+    }
     //获得用户的补充工料机和用户当前所在编办的标准工料机
     getGljItems (stdGljLibId, userId, compilationId, callback){
+        let me = this;
         let rst = {stdGljs: [], complementaryGljs: []};
         async.parallel([
             function (cb) {
@@ -47,6 +68,7 @@ class GljDao {
                         cb(err);
                     }
                     else{
+                        me.sortToNumber(stdGljs);
                         rst.stdGljs = stdGljs;
                         cb(null);
                     }
@@ -58,6 +80,7 @@ class GljDao {
                         cb(err);
                     }
                     else{
+                        me.sortToNumber(complementaryGljs);
                         rst.complementaryGljs = complementaryGljs;
                         cb(null);
                     }

+ 1 - 1
modules/complementary_glj_lib/models/schemas.js

@@ -9,7 +9,7 @@ let comGjlComponentSchema = new Schema(
     {
         isStd: Boolean, //组成物里的工料机是否是标准的,否则是补充的
         ID: Number,
-        consumeAmt: Number
+        consumeAmt: String
     },
     {_id: false},
     {versionKey: false}

+ 2 - 1
modules/fee_rates/facade/fee_rates_facade.js

@@ -262,7 +262,7 @@ async function changeFeeRateStandard(jdata){
     return doc;
 }
 
-async function newFeeRateFile(updateData){
+async function newFeeRateFile(userId, updateData){
     if(updateData.property !== null){
         let property = updateData.property;
         logger.info("Create new feeRate file for project :"+updateData.ID);
@@ -280,6 +280,7 @@ async function newFeeRateFile(updateData){
             let temA = feeFile.id.split("-");
             let libID = temA[1];
             let doc={
+                userID: userId,
                 rootProjectID:rootProjectID,
                 name:name
             };

+ 1 - 0
modules/fee_rates/models/fee_rates.js

@@ -49,6 +49,7 @@ mongoose.model('fee_rates', feeRatesSchema, 'fee_rates');
 let feeRateFileSchema = new Schema({
     ID: String,
     rootProjectID:Number,//顶层项目ID
+    userID:Number,
     name:String,
     libID: String,
     libName: String,

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

@@ -6,7 +6,7 @@
  * @version
  */
 import mongoose from "mongoose";
-
+let deleteSchema = require('../../../../public/models/delete_schema');
 let Schema = mongoose.Schema;
 let collectionName = 'unit_price_file';
 let modelSchema = {
@@ -23,6 +23,7 @@ let modelSchema = {
     user_id: Number,
     // 顶层projectId
     root_project_id: Number,
+    deleteInfo: deleteSchema
 };
 let model = mongoose.model(collectionName, new Schema(modelSchema, {versionKey: false, collection: collectionName}));
 export {model as default, collectionName as collectionName};

+ 11 - 0
modules/glj/models/unit_price_file_model.js

@@ -127,6 +127,17 @@ class UnitPriceFileModel extends BaseModel {
     }
 
     /**
+     * 根据建设项目id获取单价文件数据
+     *
+     * @param {Number} root_project_id
+     * @return {Promise}
+     */
+    async getDataByRootProject(root_project_id){
+        let condition = {root_project_id: root_project_id, deleteInfo: null};
+        return  await this.findDataByCondition(condition, null, false);
+    }
+
+    /**
      * 根据用户获取对应被删除的单价文件
      *
      * @param {String} userID

+ 62 - 25
modules/pm/controllers/pm_controller.js

@@ -58,6 +58,13 @@ module.exports = {
             }
         });
     },
+    updateFiles: async function(req, res){
+        let data = JSON.parse(req.body.data);
+        let updateDatas = data.updateDatas;
+        await ProjectsData.udpateUserFiles(req.session.sessionUser.ssoId, updateDatas, function (err, message, data) {
+            callback(req, res, err, message, data);
+        });
+    },
     copyProjects: function (req, res) {
         let data = JSON.parse(req.body.data);
         ProjectsData.copyUserProjects(req.session.sessionUser.ssoId, data.updateData, function (err, message, data) {
@@ -145,14 +152,14 @@ module.exports = {
             if (isNaN(projectId) && projectId <= 0) {
                 throw {msg: 'id数据有误!', err: 1};
             }
-            // 获取对应建设项目下所有的单位工程id
+            /*// 获取对应建设项目下所有的单位工程id
             let idList = await ProjectsData.getTenderByProjectId(projectId);
             if (idList.length <= 0) {
                 throw {msg: '不存在对应单位工程', err: 0};
-            }
+            }*/
             // 获取对应的单价文件
             let unitPriceFileModel = new UnitPriceFileModel();
-            let unitPriceFileData = await unitPriceFileModel.getDataByTenderId(idList);
+            let unitPriceFileData = await unitPriceFileModel.getDataByRootProject(projectId);
 
             if (unitPriceFileData === null) {
                 throw {msg: '不存在对应单价文件', err: 0};
@@ -194,50 +201,79 @@ module.exports = {
     },
 
     getGCDatas: async function(request, response) {
-        let userID = req.session.sessionUser.ssoId;
+        let userID = request.session.sessionUser.ssoId;
         let rst = [];
         let _projs = Object.create(null), _engs = Object.create(null), prefix = 'ID_';
         try{
             let gc_unitPriceFiles = await ProjectsData.getGCFiles(fileType.unitPriceFile, userID);
             let gc_feeRateFiles = await ProjectsData.getGCFiles(fileType.feeRateFile, userID);
             let gc_tenderFiles = await ProjectsData.getGCFiles(projType.tender, userID);
-                for(let i = 0, len = gc_unitPriceFiles.length; i < len; i++){
-                    let gc_uf = gc_unitPriceFiles[i];
-                    let theProj = _projs[prefix + gc_uf.root_project_id] || null;
-                    if(!theProj){
-                        theProj = _projs[prefix + gc_uf.root_project_id] = await ProjectsData.getProjectsByIds([gc_uf.root_project_id]);
+            for(let i = 0, len = gc_unitPriceFiles.length; i < len; i++){
+                let gc_uf = gc_unitPriceFiles[i];
+                let theProj = _projs[prefix + gc_uf.root_project_id] || null;
+                if(!theProj){
+                    let tempProj = await ProjectsData.getProjectsByIds([gc_uf.root_project_id]);
+                    if(tempProj.length > 0 && tempProj[0].projType !== projType.folder){
+                        theProj = _projs[prefix + gc_uf.root_project_id] = tempProj[0]._doc;
                         buildProj(theProj);
                     }
+                }
+                if(theProj){
                     theProj.unitPriceFiles.push(gc_uf);
                 }
-                for(let i = 0, len = gc_feeRateFiles.length; i < len; i++){
-                    let gc_ff = gc_feeRateFiles[i];
-                    let theProj = _projs[prefix + gc_ff.rootProjectID] || null;
-                    if(!theProj){
-                        theProj = _projs[prefix + gc_ff.rootProjectID] = await ProjectsData.getProjectsByIds([gc_ff.rootProjectID]);
+            }
+            for(let i = 0, len = gc_feeRateFiles.length; i < len; i++){
+                let gc_ff = gc_feeRateFiles[i];
+                let theProj = _projs[prefix + gc_ff.rootProjectID] || null;
+                if(!theProj){
+                    let tempProj = await ProjectsData.getProjectsByIds([gc_ff.rootProjectID]);
+                    if(tempProj.length > 0 && tempProj[0].projType !== projType.folder){
+                        theProj = _projs[prefix + gc_ff.rootProjectID] = tempProj[0]._doc;
                         buildProj(theProj);
                     }
+                }
+                if(theProj) {
                     theProj.feeRateFiles.push(gc_ff);
                 }
+            }
             if(gc_tenderFiles.length > 0){
                 for(let i = 0, len = gc_tenderFiles.length; i < len; i++){
                     let gc_t = gc_tenderFiles[i];
                     let theEng = _engs[prefix + gc_t.ParentID] || null;
                     if(!theEng){
-                        theEng = _engs[prefix + gc_t.ParentID] = await ProjectsData.getProjectsByIds([gc_t.ParentID]);
-                        theEng.children = [];
+                        let tempEngs = await ProjectsData.getProjectsByIds([gc_t.ParentID]);
+                        if(tempEngs.length > 0 && tempEngs[0].projType === projType.engineering){
+                            theEng = _engs[prefix + gc_t.ParentID] = tempEngs[0]._doc;
+                            theEng.children = [];
+                        }
                     }
-                    theEng.children.push(gc_t);
-                    let theProj = _projs[prefix + theEng.ParentID] || null;
-                    if(!theProj){
-                        theProj = _projs[prefix + theEng.ParentID] = await ProjectsData.getProjectsByIds([theEng.ParentID]);
-                        buildProj(theProj);
+                    if(theEng) {
+                        theEng.children.push(gc_t);
+                        let theProj = _projs[prefix + theEng.ParentID] || null;
+                        if(!theProj){
+                            let tempProj = await ProjectsData.getProjectsByIds([theEng.ParentID]);
+                            if(tempProj.length > 0 && tempProj[0].projType === projType.project){
+                                theProj = _projs[prefix + theEng.ParentID] = tempProj[0]._doc;
+                                buildProj(theProj);
+                            }
+                        }
+                        if(theProj) {
+                            let isExist = false;
+                            for(let j = 0, jLen = theProj.children.length; j < jLen; j++){
+                                if(theProj.children[j].ID === theEng.ID){
+                                    isExist = true;
+                                    break;
+                                }
+                            }
+                            if(!isExist){
+                                theProj.children.push(theEng);
+                            }
+                        }
                     }
-                    theProj.children.push(theEng);
                 }
             }
-            for(let i of _projs){
-                rst.push(i);
+            for(let i in _projs){
+                rst.push(_projs[i]);
             }
             function buildProj(proj){
                 proj.children = [];
@@ -253,7 +289,8 @@ module.exports = {
 
     recGC: function(request, response){
         let userID = request.session.sessionUser.ssoId;
-        let nodes = JSON.parse(request.body.nodes);
+        let data = JSON.parse(request.body.data);
+        let nodes = data.nodes;
         ProjectsData.recGC(userID, nodes, function (err, msg, data) {
             callback(request, response, err, msg, data);
         });

+ 154 - 32
modules/pm/models/project_model.js

@@ -1,10 +1,10 @@
 /**
  * Created by Mai on 2017/1/18.
  */
-import UnitPriceFileModel from "../../glj/models/unit_price_file_model";
+import mongoose from 'mongoose';
 import async_c from 'async';
+import UnitPriceFileModel from "../../glj/models/unit_price_file_model";
 import UnitPriceFiles from '../../glj/models/schemas/unit_price_file';
-import mongoose from 'mongoose';
 let FeeRateFiles = mongoose.model('fee_rate_file');
 let counter = require("../../../public/counter/counter.js");
 
@@ -93,7 +93,7 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, datas, callbac
                         callback(1, '新增单价文件失败.', null);
                         return;
                     }
-                    data.updateData.property.unitPriceFile.id = addResult.id + '';
+                    data.updateData.property.unitPriceFile.id = addResult.id;
                 }
                 newProject = new Projects(data.updateData);
                 // 查找同级是否存在同名数据
@@ -103,7 +103,7 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, datas, callbac
                     return;
                 }
                 if(data.updateData.projType==='Tender'){
-                    let  feeRateFileID = await feeRateFacade.newFeeRateFile(data.updateData);
+                    let  feeRateFileID = await feeRateFacade.newFeeRateFile(userId, data.updateData);
                     newProject.property.feeFile = feeRateFileID?feeRateFileID:-1;
 
                     // 新建人工系数文件 CSL, 2017.10.13
@@ -126,7 +126,54 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, datas, callbac
                 deleteInfo['deleteDateTime'] = new Date();
                 deleteInfo['deleteBy'] = userId;
                 data.updateData['deleteInfo'] = deleteInfo;
-                Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll);
+                //Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll);
+                //update
+                try{
+                    if(data.updateData.projType === projectType.project){
+                        let engineerings = await Projects.find({userID: userId, ParentID: data.updateData.ID});
+                        let isExist = false;
+                        if(engineerings.length > 0){
+                            for(let j = 0, jLen = engineerings.length; j < jLen; j++){
+                                let e_tenders = await Projects.find({userID: userId, ParentID: engineerings[j].ID});
+                                if(e_tenders.length > 0){
+                                    isExist = true;
+                                    break;
+                                }
+                            }
+                        }
+                        if(isExist){//fake
+                            await UnitPriceFiles.update({user_id: userId, root_project_id: data.updateData.ID}, {$set: {deleteInfo: deleteInfo}}, {multi: true});
+                            await FeeRateFiles.update({userID: userId, rootProjectID: data.updateData.ID}, {$set: {deleteInfo: deleteInfo}}, {multi: true});
+                            await Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll);
+                        }
+                        else {//true
+                            await UnitPriceFiles.remove({user_id: userId, root_project_id: data.updateData.ID});
+                            await FeeRateFiles.remove({userID: userId, rootProjectID: data.updateData.ID});
+                            //await Projects.update({userID: userId, NextSiblingID: data.updateData.ID, deleteInfo: null}, {$set: {NextSiblingID: data.NextSiblingID}});
+                            await Projects.remove({userID: userId, ID: data.updateData.ID}, updateAll);
+                        }
+                    }
+                    else if(data.updateData.projType === projectType.engineering){
+                        let tenders = await Projects.find({userID: userId, ParentID: data.updateData.ID});
+                        if(tenders.length > 0){//fake
+                            await Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll);
+                        }
+                        else {//true
+                            //await Projects.update({userID: userId, NextSiblingID: data.updateData.ID, deleteInfo: null}, {$set: {NextSiblingID: data.NextSiblingID}});
+                            await Projects.remove({userID: userId, ID: data.updateData.ID}, updateAll);
+                        }
+                    }
+                    else if(data.updateData.projType === projectType.tender){//fake
+                        await Projects.update({userID: userId, ID: data.updateData.ID}, data.updateData, updateAll);
+                    }
+                    else if(data.updateData.projType === projectType.folder){//true
+                        await Projects.remove({userID: userId, ID: data.updateData.ID}, updateAll);
+                    }
+                    else throw '未知文件类型,删除失败!';
+                }
+                catch (error){
+                    callback(1, error, null);
+                }
             } else {
                 hasError = true;
                 callback(1, '提交数据错误.', null);
@@ -134,6 +181,42 @@ ProjectsDAO.prototype.updateUserProjects = async function(userId, datas, callbac
         }
     }
 };
+
+ProjectsDAO.prototype.udpateUserFiles = async function (userId, datas, callback){
+    let updateType = {update: 'update', delete: 'delete'};
+    let deleteInfo = Object.create(null);
+    deleteInfo.deleted = true;
+    deleteInfo.deleteBy = userId;
+    deleteInfo.deleteDateTime = new Date();
+    try{
+        for(let i = 0, len = datas.length; i < len; i++){
+            let data = datas[i];
+            if(data.updateType === updateType.update && data.fileType === fileType.unitPriceFile){
+                await UnitPriceFiles.update({user_id: userId, id: parseInt(data.updateData.id)}, data.updateData);
+                await Projects.update({userID: userId, 'property.unitPriceFile.id': data.updateData.id}, {$set: {'property.unitPriceFile.name': data.updateData.name}});
+            }
+            else if(data.updateType === updateType.update && data.fileType === fileType.feeRateFile){
+                await FeeRateFiles.update({userID: userId, ID: data.updateData.ID}, data.updateData);
+                await Projects.update({userID: userId, 'property.feeFile.id': data.updateData.ID}, {$set: {'property.feeFile.name': data.updateData.name}});
+            }
+            else if(data.updateType === updateType.delete && data.fileType === fileType.unitPriceFile){
+                data.updateData.deleteInfo = deleteInfo;
+                await UnitPriceFiles.update({user_id: userId, id: parseInt(data.updateData.id)}, data.updateData);
+                await Projects.update({userID: userId, 'property.feeFile.id': data.updateData.id}, {$set: {'property.feeFile.name': data.updateData.name}});
+            }
+            else if(data.updateType === updateType.delete && data.fileType === fileType.feeRateFile){
+                data.updateData.deleteInfo = deleteInfo;
+                await FeeRateFiles.update({userID: userId, ID: data.updateData.ID}, data.updateData);
+            }
+            else throw '未知文件类型,删除失败'
+        }
+        callback(false, '删除成功', null);
+    }
+    catch(error){
+        callback(true, '删除失败', null);
+    }
+};
+
 ProjectsDAO.prototype.copyUserProjects = function (userId, datas, callback) {
     let data, project, updateLength = 0, hasError = false, deleteInfo = null, tempType = 1, i;
     let updateAll = function (err) {
@@ -250,41 +333,45 @@ ProjectsDAO.prototype.getGCFiles = async function (fileType, userID){
     }
     else {
         let isExist = false;
-        for(let type of projectType){
-            if(type === fileType) isExist = true;
-            break;
+        for(let type in projectType){
+            if(projectType[type] === fileType) {
+                isExist = true;
+                break;
+            }
         }
         if(!isExist) throw '不存在此项目类型!';
-        rst = await Projects.find({projType: fileType, 'deleteInfo.deleted': true});
+        rst = await Projects.find({userID: userID, projType: fileType, 'deleteInfo.deleted': true});
     }
     return rst;
 };
 
-ProjectsDAO.prototype.getFirstNodeID = async function (userID, projType) {
-    if(projType !== projectType.project) throw '只能为建设项目层';
-    let nodes = await Projects.find({userID: userID, projType: projType, deleteInfo: null});
+ProjectsDAO.prototype.getFirstNodeID = async function (userID, pid) {
+    let nodes = await Projects.find({userID: userID, ParentID: pid, deleteInfo: null});
     if(nodes.length === 0){
         return -1;
     }
     else {
+        let prefix = 'ID_';
         let chain = Object.create(null);
         for(let i = 0, len = nodes.length; i < len; i++){
+            let nodeDoc = nodes[i]._doc;
             let node = Object.create(null);
-            node.ID = nodes[i].ID;
-            node.NextSiblingID = nodes[i].NextSiblingID;
-            chain[node.ID] = node;
+            node.ID = nodeDoc.ID;
+            node.NextSiblingID = nodeDoc.NextSiblingID;
+            chain[prefix + node.ID] = node;
         }
         for(let i =0, len = nodes.length; i < len; i++){
-            let next = nodes[i].NextSiblingID > 0 ? chain[nodes[i].NextSiblingID] : null;
-            chain[nodes[i].ID].next = next;
+            let nodeDoc = nodes[i]._doc;
+            let next = nodeDoc.NextSiblingID > 0 ? chain[prefix + nodeDoc.NextSiblingID] : null;
+            chain[prefix + nodeDoc.ID].next = next;
             if(next){
-                next.pre = chain[nodes[i].ID]
+                next.pre = chain[prefix + nodeDoc.ID]
             }
         }
-        for(let node of chain){
-            let pre = node.pre || null;
+        for(let node in chain){
+            let pre = chain[node].pre || null;
             if(!pre){
-                return node.ID;
+                return chain[node].ID;
             }
         }
     }
@@ -292,34 +379,69 @@ ProjectsDAO.prototype.getFirstNodeID = async function (userID, projType) {
 
 ProjectsDAO.prototype.recGC = async function(userID, datas, callback){
     let functions = [];
+    let updateDatas = [];
     for(let i = 0, len = datas.length; i < len; i++){
-        if(datas[i].updateType === projectType.project && datas[i].updateData.NextSiblingID === undefined){//则为待查询NextSiblingID,前端无法查询
-            let firstNodeID = await this.getFirstNodeID(userID, projectType.project);
-            datas[i].updateData.NextSiblingID = firstNodeID;
+        if(datas[i].findData.ParentID !== undefined && datas[i].findData.NextSiblingID === -1 && !datas[i].findData.deleteInfo){//维护项目管理树
+            let findNode = await Projects.find(datas[i].findData);
+            if(findNode.length > 0){
+                datas[i].findData = Object.create(null);
+                datas[i].findData.ID = findNode[0].ID;
+                updateDatas.push(datas[i]);
+            }
         }
+        else {
+            if(datas[i].updateType === projectType.project && datas[i].updateData.NextSiblingID === undefined){//则为待查询NextSiblingID,前端无法查询
+                let projData = await Projects.find({userID: userID, ID: datas[i].findData.ID});//建设项目原本可能属于某文件夹、文件夹的存在需要判断
+                let projPid = projData[0].ParentID;
+                if(projPid !== -1){
+                    let projFolder = await Projects.find({userID: userID, ID: projPid});
+                    if(projFolder.length === 0){//文件夹已不存在
+                        projPid = -1;
+                        datas[i].updateData.ParentID = -1;
+                    }
+                }
+                let firstNodeID = await this.getFirstNodeID(userID, projPid);
+                datas[i].updateData.NextSiblingID = firstNodeID;
+            }
+            updateDatas.push(datas[i])
+        }
+    }
+    for(let i = 0, len = updateDatas.length; i < len; i ++){
         functions.push((function(data){
                 return function (cb) {
                     if(data.updateType === fileType.unitPriceFile){
-                        UnitPriceFiles.update(data.findData, data.updateData, function (err) {
+                        UnitPriceFiles.update({id: parseInt(data.findData.id)}, data.updateData, function (err) {
                             if(err) cb(err);
-                            else cb(false);
+                            else {
+                                Projects.update({userID: userID, 'property.unitPriceFile.id': data.findData.id}, {$set: {'property.unitPriceFile.name': data.updateData.name}}, function (err) {
+                                    if(err) cb(err);
+                                    else cb(false);
+                                });
+                            }
                         })
                     }
                     else if(data.updateType === fileType.feeRateFile){
                         FeeRateFiles.update(data.findData, data.updateData, function (err) {
                             if(err) cb(err);
-                            else cb(false);
+                            else {
+                                Projects.update({userID: userID, 'property.feeFile.id': data.findData.ID}, {$set: {'property.feeFile.name': data.updateData.name}}, function (err) {
+                                    if(err) cb(err);
+                                    else cb(false);
+                                });
+                            }
                         });
                     }
                     else{
-                        Projects.update(data.findData, data.updateData, function (err) {
-                            if(err)cb(err);
-                            else cb(false);
-                        });
+                        if(data){
+                            Projects.update(data.findData, data.updateData, function (err) {
+                                if(err)cb(err);
+                                else cb(false);
+                            });
+                        }
                     }
                 }
             }
-        )(datas[i]));
+        )(updateDatas[i]));
     }
     async_c.parallel(functions, function (err, results) {
         if(err) callback(err, 'fail', null);

+ 1 - 4
modules/pm/routes/pm_route.js

@@ -11,10 +11,6 @@ module.exports = function (app) {
 
     app.get('/pm', baseController.init, pmController.index);
 
-    app.get('/pm/gc',baseController.init, function (req, res) {
-        res.render('building_saas/pm/html/project-management-Recycle.html');
-    });
-
     let pmRouter = express.Router();
 
     pmRouter.use(function (req, res, next) {
@@ -47,6 +43,7 @@ module.exports = function (app) {
     pmRouter.post('/getNewProjectID', pmController.getNewProjectID);
     pmRouter.post('/getUnitFile', pmController.getUnitFileList);
     pmRouter.post('/getFeeRateFile', pmController.getFeeRateFileList);
+    pmRouter.post('/updateFiles', pmController.updateFiles);
     //GC
     pmRouter.post('/getGCDatas', pmController.getGCDatas);
     pmRouter.post('/recGC', pmController.recGC);

+ 1 - 0
web/building_saas/complementary_glj_lib/html/tools-gongliaoji.html

@@ -188,6 +188,7 @@
     <script type="text/javascript" src="/lib/ztree/jquery.ztree.core.js"></script>
     <script type="text/javascript" src="/lib/ztree/jquery.ztree.excheck.js"></script>
     <script type="text/javascript" src="/lib/ztree/jquery.ztree.exedit.js"></script>
+    <script type="text/javascript" src="/public/web/scMathUtil.js"></script>
     <script type="text/javascript" src="/public/web/treeDataHelper.js"></script>
     <script type="text/javascript" src="/public/web/QueryParam.js"></script>
     <script type="text/javascript" src="/web/building_saas/complementary_glj_lib/js/glj.js"></script>

+ 33 - 2
web/building_saas/complementary_glj_lib/js/glj.js

@@ -442,6 +442,12 @@ let repositoryGljObj = {
                         }
                         else if(rObj.basePrice !== me.currentEditingGlj.basePrice){//修改了单价,可修改单价的必为可成为组成物的
                             //寻找所有引用了此组成物的工料机,并从组成物中删去此工料机,并重算单价
+                            if(isNaN(parseFloat(rObj.basePrice))){
+                                alert('单价只能为数值!');
+                                args.sheet.setValue(args.row, args.col, me.currentEditingGlj.basePrice ? me.currentEditingGlj.basePrice : 0);
+                                return;
+                            }
+                            rObj.basePrice = !isNaN(parseFloat(rObj.basePrice))? scMathUtil.roundTo(parseFloat(rObj.basePrice), -2) : me.currentEditingGlj.basePrice;
                             let updateGljs = me.getUpdateGljs(rObj);
                             if(updateGljs.updateArr.length > 0 || updateGljs.updateBasePrcArr.length > 0){
                                 for(let i = 0; i < updateGljs.updateArr.length; i++){
@@ -451,7 +457,7 @@ let repositoryGljObj = {
                                     updateArr.push(updateGljs.updateBasePrcArr[i]);
                                 }
                             }
-                            rObj.basePrice = !isNaN(parseFloat(rObj.basePrice)) && (rObj.basePrice && typeof rObj.basePrice !== 'undefined') ? that.round(parseFloat(rObj.basePrice), 2) : 0;
+                            //rObj.basePrice = !isNaN(parseFloat(rObj.basePrice)) && (rObj.basePrice && typeof rObj.basePrice !== 'undefined') ? that.round(parseFloat(rObj.basePrice), 2) : 0;
                         }
                         rObj.component = me.currentGlj.component;
                         updateArr.push(rObj);
@@ -698,7 +704,7 @@ let repositoryGljObj = {
             if(!isExsit) isValid = false;
         }
         //
-        pasteObj.basePrice = !isNaN(parseFloat(pasteObj.basePrice)) && (pasteObj.basePrice && typeof pasteObj.basePrice !== 'undefined') ? that.round(parseFloat(pasteObj.basePrice), 2) :
+        pasteObj.basePrice = !isNaN(parseFloat(pasteObj.basePrice)) && (pasteObj.basePrice && typeof pasteObj.basePrice !== 'undefined') ? scMathUtil.roundTo(parseFloat(pasteObj.basePrice), 2) :
             me.currentCache[rowIdx].basePrice;
         if(pasteObj.basePrice !== me.currentCache[rowIdx].basePrice){
             reCalBasePrc = true;
@@ -951,6 +957,12 @@ let repositoryGljObj = {
     },*/
     mixUpdateRequest: function(updateArr, addArr, removeIds) {
         let me = repositoryGljObj;
+        if(updateArr.length > 0){
+            me.saveInString(updateArr);
+        }
+        if(addArr.length > 0){
+            me.saveInString(addArr);
+        }
         $.ajax({
             type:"POST",
             url:"complementartGlj/api/mixUpdateGljItems",
@@ -985,6 +997,25 @@ let repositoryGljObj = {
             }
         })
     },
+    saveInString: function (datas) {
+        for(let i = 0, len = datas.length; i < len; i++){
+            let data = datas[i];
+            if(_exist(data, 'basePrice')){
+                data['basePrice'] = data['basePrice'].toString();
+            }
+            if(_exist(data, 'component')){
+                for(let j = 0, jLen = data['component'].length; j < jLen; j++){
+                    let comGljObj = data['component'][j];
+                    if(_exist(comGljObj, 'consumeAmt')){
+                        comGljObj['consumeAmt'] = comGljObj['consumeAmt'].toString();
+                    }
+                }
+            }
+        }
+        function _exist(data, attr){
+            return data && data[attr] !== undefined && data[attr];
+        }
+    },
     getParentCache: function (nodes) {
         let me = repositoryGljObj, rst = [];
         for(let i = 0; i < me.complementaryGljList.length; i++){

+ 5 - 4
web/building_saas/complementary_glj_lib/js/gljComponent.js

@@ -309,7 +309,7 @@ let gljComponentOprObj = {
          if(args.col === 4 && me.currentEditingComponent.code && args.editingText && args.editingText.trim().length > 0){//消耗量
             let consumeAmt = parseFloat(args.editingText);
             if(!isNaN(consumeAmt) && consumeAmt !== me.currentEditingComponent.consumeAmt){
-                let roundCons = me.round(consumeAmt, 3);
+                let roundCons = scMathUtil.roundTo(consumeAmt, -3);
                 let component = that.currentGlj.component;
                 for(let i = 0; i < component.length; i++){
                     if(component[i].ID === that.currentComponent[args.row].ID){
@@ -430,7 +430,7 @@ let gljComponentOprObj = {
                 if(row + i < that.currentComponent.length){
                     let currentObj = that.currentComponent[row + i];
                     if(items[i].consumeAmt.trim().length > 0 && items[i].consumeAmt !== currentObj.consumeAmt){
-                        let roundCons = me.round(items[i].consumeAmt, 3);
+                        let roundCons = scMathUtil.roundTo(items[i].consumeAmt, 3);
                         isChange = true;
                         currentObj.consumeAmt = roundCons;
                         for(let j = 0; j < component.length; j++){
@@ -468,6 +468,7 @@ let gljComponentOprObj = {
     },
     updateComponent: function (updateArr) {
         let me = gljComponentOprObj, that = repositoryGljObj;
+        that.saveInString(updateArr);
         $.ajax({
             type: 'post',
             url: 'complementartGlj/api/updateComponent',
@@ -495,8 +496,8 @@ let gljComponentOprObj = {
     reCalGljBasePrc: function (component) {
         let me = gljComponentOprObj, gljBasePrc = 0;
         for(let i = 0; i < component.length; i++){
-            let roundBasePrc = me.round(component[i].basePrice, 2);
-            gljBasePrc += me.round(roundBasePrc * component[i].consumeAmt, 2);
+            let roundBasePrc = scMathUtil.roundTo(component[i].basePrice, -2);
+            gljBasePrc += scMathUtil.roundTo(roundBasePrc * component[i].consumeAmt, -2);
         }
         return gljBasePrc;
     }

+ 5 - 0
web/building_saas/pm/html/project-management-Recycle.html

@@ -1,6 +1,11 @@
 <div class="toolsbar">
     <legend class="m-0 pb-1">全部</legend>
 </div>
+<div class="top-content">
+    <div class="main-data-top" id="gc_waiting">
+        <p style="text-align: center; margin-top: 30px;">正在加载数据...</p>
+    </div>
+</div>
 <div class="poj-list">
     <table class="table table-hover table-sm mb-5" id="gcTree">
         <thead>

+ 23 - 2
web/building_saas/pm/html/project-management.html

@@ -177,7 +177,7 @@
                     <div class="col-md-6">
                         <legend>单价文件</legend>
                         <table class="table table-bordered table-hover table-sm" id="summary-project-unit-price-table">
-                            <thead><th></th><th>名称</th></thead>
+                            <thead><th></th><th>名称</th><th width="50">使用</th></thead>
                             <tbody>
                             <tr><td>1</td><td>A单价文件</td></tr>
                             <tr><td>2</td><td>B单价文件</td></tr>
@@ -188,7 +188,7 @@
                     <div class="col-md-6">
                         <legend>费率文件</legend>
                         <table class="table table-bordered table-hover table-sm" id="summary-project-fee-table">
-                            <thead><th></th><th>名称</th></thead>
+                            <thead><th></th><th>名称</th><th width="50">使用</th></thead>
                             <tbody>
                             <tr><td>1</td><td>A费率文件</td></tr>
                             <tr><td>2</td><td>B费率文件</td></tr>
@@ -501,6 +501,27 @@
         </div>
     </div>
 </div>
+<!--弹出删除 单价/费率 文件-->
+<div class="modal fade" id="del-wj" 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">
+                <h5 class="text-danger">删除 "C单价文件" ?</h5>
+                <p class="">删除后,你可以在回收站找到它。</p>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal" id="fileDelCancel">取消</button>
+                <a href="javascript:void(0);" class="btn btn-danger" id="fileDelConfirm">删除</a>
+            </div>
+        </div>
+    </div>
+</div>
 <!-- JS. -->
 <!-- inject:js -->
 <script src="/lib/jquery/jquery-3.2.1.min.js"></script>

+ 210 - 120
web/building_saas/pm/js/pm_gc.js

@@ -1,55 +1,10 @@
 /**
  * Created by Zhong on 2017/10/30.
  */
-//测试数据
-let deleteInfo = {deleteBy: 76075, deleteDateTime: '2017-10-31', deleted: true};
-let temp_gc_datas = [
-    {ID: 1, ParentID: -1, NextSiblingID: 7, name: 'testTreeA', projType: 'Project', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo,
-        unitPriceFiles: [{name: 'uA', id: 100, root_project_id: 1, user_id: 76075, deleteInfo: deleteInfo}, {name: 'uB', id: 101, root_project_id: 1, user_id: 76075, deleteInfo: deleteInfo}],
-        feeRateFiles: [{name: 'fA', ID: 'fr-1', rootProjectID: 1, userID: 76075, deleteInfo: deleteInfo}, {name: 'fB', ID: 'fr-2', rootProjectID: 1, userID: 76075, deleteInfo: deleteInfo}]},
-    {ID: 2, ParentID: 1, NextSiblingID: 3, name: 'enA', projType: 'Engineering', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo},
-    {ID: 3, ParentID: 1, NextSiblingID: -1, name: 'enB', projType: 'Engineering', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo},
-    {ID: 4, ParentID: 3, NextSiblingID: 5, name: 'tenderA', projType: 'Tender', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo, property: {feeFile: {id: 'fr-1', name: 'fA'}, unitPriceFile: {id: 100, name: 'uA'}}},
-    {ID: 5, ParentID: 3, NextSiblingID: 6, name: 'tenderB', projType: 'Tender', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo, property: {feeFile: {id: 'unD-1', name: 'unDF'}, unitPriceFile: {id: 100, name: 'uA'}}},
-    {ID: 6, ParentID: 3, NextSiblingID: -1, name: 'tenderC', projType: 'Tender', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo, property: {feeFile: {id: 'fr-2', name: 'fB'}, unitPriceFile: {id: 101, name: 'uB'}}},
-    {ID: 7, ParentID: -1, NextSiblingID: 10, name: 'testTreeB', projType: 'Project', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo,
-        unitPriceFiles: [{name: 'uC', id: 102, root_project_id: 7, user_id: 76075, deleteInfo: deleteInfo}, {name: 'uD', id: 103, root_project_id: 7, user_id: 76075, deleteInfo: deleteInfo}],
-        feeRateFiles: [{name: 'fC', ID: 'fr-3', rootProjectID: 7, userID: 76075, deleteInfo: deleteInfo}]},
-    {ID: 8, ParentID: 7, NextSiblingID: -1, name: 'enC', projType: 'Engineering', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo},
-    {ID: 9, ParentID: 8, NextSiblingID: -1, name: 'tenderD', projType: 'Tender', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo, property: {feeFile: {id: 'fr-3', name: 'fC'}, unitPriceFile: {id: 102, name: 'uC'}}},
-    {ID: 10, ParentID: -1, NextSiblingID: -1, name: 'testTreeC', projType: 'Project', userID: 76075, createDateTime: '2017-10-30', unitPriceFiles: [], feeRateFiles: [{name: 'fC', ID: 'fr-3', rootProjectID: 7, userID: 76075, deleteInfo: deleteInfo}]},
-    {ID: 11, ParentID: 10, NextSiblingID: -1, name: 'enD', projType: 'Engineering', userID: 76075, createDateTime: '2017-10-30'},
-    {ID: 12, ParentID: 11, NextSiblingID: -1, name: 'tenderE', projType: 'Tender', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo, property: {feeFile: {id: 'fr-3', name: 'fC'}, unitPriceFile: {id: 103, name: 'uD'}}},
-    {ID: 13, ParentID: 2, NextSiblingID: 14, name: 'tenderF', projType: 'Tender', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo, property: {feeFile: {id: 'unD-2', name: 'unDF2'}, unitPriceFile: {id: 102, name: 'uC'}}},
-    {ID: 14, ParentID: 2, NextSiblingID: 15, name: 'tenderG', projType: 'Tender', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo, property: {feeFile: {id: 'fr-3', name: 'fC'}, unitPriceFile: {id: 102, name: 'uC'}}},
-    {ID: 15, ParentID: 2, NextSiblingID: -1, name: 'tenderH', projType: 'Tender', userID: 76075, createDateTime: '2017-10-30', deleteInfo: deleteInfo, property: {feeFile: {id: 'qwqw', name: 'qweq'}, unitPriceFile: {id: 300, name: 'u30'}}}
-
-];
-
-/*function getTestDatas(){
-    let rst = [];
-    for(let i = 0; i < 1000; i ++){
-        let nid = i + 1 < 1000 ? i + 1 : -1;
-        let obj = {ID: i, ParentID: -1, NextSiblingID: nid, name : 'test' + i, projType: 'Project', userID: 76075, createDateTime: '2017-11-3', deleteInfo: deleteInfo,
-            unitPriceFiles: [{name: 'up' + i, id: i + 10000, deleteInfo: deleteInfo}], feeRateFiles: [{name: 'ff' + i, id: 'fr-' + i, deleteInfo: deleteInfo}]};
-        rst.push(obj);
-    }
-    return rst;
-}*/
 let gcTree = null;
 let decDate = null;//恢复后的名称后缀(时间+恢复)
-/*let projectType = {
-    folder: 'Folder',
-    tender: 'Tender',
-    project: 'Project',
-    engineering: 'Engineering'
-};*/
-let fileType = {
-    unitPriceFile: 'UnitPriceFile',
-    feeRateFile: 'FeeRateFile'
-};
 //恢复路径t = tender, e = engineering, p = project
-let recPath = {t: 'T', t_e: 'T_E', t_e_p: 'T_E_P', e: 'E', e_p: 'E_P', p: 'P'};
+const recPath = {t: 'T', t_e: 'T_E', t_e_p: 'T_E_P', e: 'E', e_p: 'E_P', p: 'P'};
 let gcTreeSetting = {
     tree: {
         id: 'ID',
@@ -103,9 +58,13 @@ let gcTreeSetting = {
             event: {
                 getText: function (html, node, text) {
                     if (node.data.projType === projectType.tender) {
-                        html.push(deleted(node) ?
-                            node.data.deleteInfo.deleteDateTime : '');
-                     //   html.push(text ? new Date(text).Format('yyyy-MM-dd') : '');
+                        if(deleted(node)){
+                            let localDateTime = new Date(node.data.deleteInfo.deleteDateTime).toLocaleDateString();
+                            html.push(new Date(localDateTime).Format('yyyy-MM-dd'));
+                        }
+                        else{
+                            html.push('');
+                        }
                     }
                 }
             }
@@ -117,7 +76,13 @@ let gcTreeSetting = {
             event: {
                 getText: function (html, node, text) {
                     if (node.data.projType === projectType.tender) {
-                      html.push(text ? text : '');
+                        if(deleted(node)){
+                            let localDateTime = new Date(text).toLocaleDateString();
+                            html.push(new Date(localDateTime).Format('yyyy-MM-dd'));
+                        }
+                        else{
+                            html.push('');
+                        }
                     }
                 }
             }
@@ -148,11 +113,6 @@ let gcTreeSetting = {
                         $('p', '#rePoj .modal-body').remove();
                         $('#rePoj .modal-header').html(v_getTitle(node));
                         $('#rePoj .modal-body').html(v_getMoBody(node, tenderNodes));
-                        console.log(node);
-                        console.log(node.preSibling());
-                        //test 获取更新的数据
-                        /*let updateDatas = m_getRecDatas(node);
-                        console.log(updateDatas);*/
                     });
                 }
             }
@@ -202,6 +162,7 @@ let gcTreeSetting = {
 
 $(document).ready(function () {
     $('#tab_pm_gc').on('show.bs.tab', function () {
+        $('#gc_waiting').show();
         gc_init();
         Tree = null;
     });
@@ -213,9 +174,12 @@ function gc_init(){
     let table = $('#gcTree');
     $('thead', table).remove();
     $('tbody', table).remove();
-    m_buildVirtualTree(temp_gc_datas);
-    gcTree = $.fn.treeTable.init(table, gcTreeSetting, temp_gc_datas);
-    //gcTree = $.fn.treeTable.init(table, gcTreeSetting, getTestDatas());
+    a_getGC(function (datas) {
+        m_buildVirtualTree(datas);
+        let normalDatas = m_VTreeToDatas(datas);
+        gcTree = $.fn.treeTable.init(table, gcTreeSetting, normalDatas);
+        $('#gc_waiting').hide();
+    });
 }
 
 //项目恢复模态框标题
@@ -294,6 +258,7 @@ function v_recFiles(project, fileIds, type){
                 let id = projFiles[i].id || projFiles[i].ID || null;
                 if(id && id === fileIds[j]){
                     isExist = true;
+                    break;
                 }
             }
             if(!isExist){
@@ -313,7 +278,12 @@ function v_removeNode(node){
     gcTree.removeNode(node);
     let parent = node.parent || null;
     if(parent && parent.children.length === 0 && parent.data !== undefined){
-        v_removeNode(parent);
+        if(parent.data.projType === projectType.project && fileEmpty(parent)){
+            v_removeNode(parent);
+        }
+        else if(parent.data.projType !== projectType.project){
+            v_removeNode(parent);
+        }
     }
 }
 
@@ -331,6 +301,9 @@ function v_refreshNode(node){
 //将获取的回收站中的数据建虚拟树
 function m_buildVirtualTree(datas){
     for(let i = 0, len = datas.length; i < len; i++){
+        if(datas[i].projType === projectType.project){
+            datas[i].ParentID = -1;
+        }
         let children = datas[i].children || null;
         if(children){
             m_buildVirtualTree(children);
@@ -345,6 +318,25 @@ function m_buildVirtualTree(datas){
     }
 }
 
+function m_VTreeToDatas(datas){
+    let rst = [];
+    let projs = datas;
+    rst = rst.concat(projs);
+    for(let i = 0, len = projs.length; i < len; i++){
+        let p_engs = projs[i].children || null;
+        if(p_engs){
+            rst = rst.concat(p_engs);
+            for(let j = 0, jLen = p_engs.length; j < jLen; j ++){
+                let e_tenders = p_engs[j].children || null;
+                if(e_tenders){
+                    rst = rst.concat(e_tenders);
+                }
+            }
+        }
+    }
+    return rst;
+}
+
 //获得当前节点的tenders数据,模态提示框用
 function m_getTenders(node){
     if(node.data.projType === projectType.tender) return [node];
@@ -412,6 +404,7 @@ function m_getRecDatas(oprNode){
             for(let i = 0, len = tenders.length; i < len; i++){
                 rstProj = rstProj.concat(getUpdateDatas(projectType.tender, tenders[i], true, false));
             }
+            rstProj = deWeightName(rstProj);
             //恢复单价、费率文件
             rstFile = rstFile.concat(getUpdateFiles(tenders, project));
         }
@@ -427,42 +420,54 @@ function m_getRecDatas(oprNode){
         path = recPath.p;
         let engineerings = oprNode.children;
         if(engineerings.length > 0){
-            let allTenders = [];
+            let allTenders = [], rstEngs = [];
             for(let i = 0, len = engineerings.length; i < len; i++){
                 //恢复单项工程
-                rstProj = rstProj.concat(getUpdateDatas(projectType.engineering, engineerings[i], false, false));
+                rstEngs = rstEngs.concat(getUpdateDatas(projectType.engineering, engineerings[i], false, false));
                 let tenders = engineerings[i].children;
                 allTenders = allTenders.concat(tenders);
+                let rstTends = [];
                 for(let j = 0, jLen = tenders.length; j < jLen; j++){
                     //恢复单位工程
-                    rstProj = rstProj.concat(getUpdateDatas(projectType.tender, tenders[j], false, false));
+                    rstTends = rstTends.concat(getUpdateDatas(projectType.tender, tenders[j], false, false));
                 }
+                //去除重名
+                rstTends = deWeightName(rstTends);
+                rstProj = rstProj.concat(rstTends);
             }
+            //去除重名
+            rstEngs = deWeightName(rstEngs);
+            rstProj = rstProj.concat(rstEngs);
             //恢复单价、费率文件
             rstFile = rstFile.concat(getUpdateFiles(allTenders, oprNode));
+
         }
         //恢复建设项目
         rstProj = rstProj.concat(getUpdateDatas(projectType.project, oprNode, false, false));
     }
-    console.log(path);
     rst.proj = rstProj;
     rst.file = rstFile;
     return rst;
 }
 
 //获得勾选的单价、费率文件的id
-function m_getFilesIds(nodes){
-    let rstSet = new Set();
+function m_getFilesObjs(nodes){
+    let rst = [];
     for(let i = 0, len = nodes.length; i < len; i++){
         let fileId = $(nodes[i]).attr('fileId') || null;
         if(fileId){
+            let dispName = $('td:eq(0)', $(nodes[i])[0].parentNode.parentNode)[0].textContent;
+            let name = dispName.slice(0, dispName.length - 4);
             if($(nodes[i]).attr('fileType') === fileType.unitPriceFile){
                 fileId = parseInt(fileId);
             }
-            rstSet.add(fileId);
+            let obj = Object.create(null);
+            obj.id = fileId;
+            obj.name = name;
+            rst.push(obj);
         }
     }
-    return Array.from(rstSet);
+    return rst;
 }
 
 function m_project(node){
@@ -481,21 +486,40 @@ function m_project(node){
 //点击单价文件、费率文件下的恢复操作(确认)
 function e_recFiles(btn){
     btn.bind('click', function () {
-        let recIds = m_getFilesIds($('[name = "fileItems"]:checked'));
-        let fileType = $('[name = "fileItems"]:checked').attr('fileType');
+        decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)';
+        let recObjs = m_getFilesObjs($('[name = "fileItems"]:checked'));
+        let recIds = [];
+        for(let i of recObjs){
+            recIds.push(i.id);
+        }
+        let type = $('[name = "fileItems"]:checked').attr('fileType');
         let selected = gcTree.selected();
         //backend
         let updateDatas = [];
-        for(let i = 0, len = recIds.length; i < len; i++){
-            updateDatas.push(getUpdateObj(fileType, {id: recIds[i]}, {deleteInfo: null}));
-        }
-        //front
-        if(recIds.length > 0){
-            v_recFiles(selected, recIds, fileType);
-            if(deleted(selected)){
-                delete selected.data.deleteInfo;
+        for(let i = 0, len = recObjs.length; i < len; i++){
+            let findData = type === fileType.unitPriceFile ? {id: recObjs[i].id} : {ID: recObjs[i].id};
+            updateDatas.push(getUpdateObj(type, findData, {deleteInfo: null, name: delPostFix(recObjs[i].name) + decDate}));
+        }
+        //恢复建设项目
+        if(updateDatas.length > 0 && deleted(selected)){
+            updateDatas.push(getUpdateObj(projectType.project, {ID: selected.data.ID}, {deleteInfo: null, name: delPostFix(selected.data.name) + decDate}));
+        }
+        updateDatas = deWeightName(updateDatas);
+        a_rec(updateDatas, caller);
+        function caller(){
+            //front
+            if(recIds.length > 0){
+                v_recFiles(selected, recIds, type);
+                if(deleted(selected)){
+                    delete selected.data.deleteInfo;
+                }
+                if(fileEmpty(selected) && selected.children.length === 0){
+                    gcTree.removeNode(selected);
+                }
+                else {
+                    gcTree.refreshNodesDom([selected]);
+                }
             }
-            gcTree.refreshNodesDom([selected]);
         }
     });
 }
@@ -508,20 +532,21 @@ function e_recProj(btn){
         let updateObj = m_getRecDatas(selected);
         let updateDatas = updateObj.proj.concat(updateObj.file);
         let fileObj = getRecFileObj(updateObj.file);
-        console.log(updateObj);
         //保存成功后回调front
-        //front
-        let project = m_project(selected);
-        if(project){
-            if(fileObj[fileType.unitPriceFile].length > 0){
-                v_recFiles(project, fileObj[fileType.unitPriceFile], fileType.unitPriceFile);
-            }
-            if(fileObj[fileType.feeRateFile].length > 0){
-                v_recFiles(project, fileObj[fileType.feeRateFile], fileType.feeRateFile);
+        a_rec(updateDatas, caller);
+        function caller() {
+            let project = m_project(selected);
+            if(project){
+                if(fileObj[fileType.unitPriceFile].length > 0){
+                    v_recFiles(project, fileObj[fileType.unitPriceFile], fileType.unitPriceFile);
+                }
+                if(fileObj[fileType.feeRateFile].length > 0){
+                    v_recFiles(project, fileObj[fileType.feeRateFile], fileType.feeRateFile);
+                }
             }
+            v_removeNode(selected);
+            v_refreshNode(selected);
         }
-        v_removeNode(selected);
-        v_refreshNode(selected);
     });
 }
 
@@ -529,6 +554,7 @@ function a_getGC(callback){
     $.ajax({
         type: 'post',
         url: '/pm/api/getGCDatas',
+        data: {data: JSON.stringify({user_id: userID})},
         dataType: 'json',
         timeout: 5000,
         success: function (result) {
@@ -538,14 +564,14 @@ function a_getGC(callback){
                 }
             }
         }
-    })
+    });
 }
 
 function a_rec(nodes, callback){
     $.ajax({
         type: 'post',
         url: '/pm/api/recGC',
-        data: {nodes: JSON.stringify(nodes)},
+        data: {data: JSON.stringify({user_id: userID, nodes: nodes})},
         dataType: 'json',
         timeout: 5000,
         success: function (result) {
@@ -558,14 +584,67 @@ function a_rec(nodes, callback){
     })
 }
 
+//去除重名,回收站不处理重名,只保证恢复到项目管理中不出现重名
+function deWeightName(datas){
+    let rst = [];
+    let _deWeight = Object.create(null), prefix = 'name_';
+    //按同名分组
+    for(let i = 0, len = datas.length; i < len; i++){
+        let data = datas[i];
+        let _names = _deWeight[prefix + data.updateData.name] || null;
+        if(!_names){
+            _names = _deWeight[prefix + data.updateData.name] = [];
+        }
+        if(_names){
+            _names.push(data);
+        }
+    }
+    for(let _name in _deWeight){
+        let sameNameDatas = _deWeight[_name];
+        let count = 0;
+        for(let i = 0, len = sameNameDatas.length; i < len; i++){
+            let postFix = '(' + count + ')';
+            if(i > 0){
+                sameNameDatas[i].updateData.name = sameNameDatas[i].updateData.name + postFix;
+            }
+            count ++;
+            rst.push(sameNameDatas[i]);
+        }
+    }
+    return rst;
+}
+
+//去除名称后缀(Date恢复)
+function delPostFix (str){
+    let rst = '';
+    rst = delPostRecFix(delPostNameFix(str));
+    return rst;
+}
+function delPostRecFix (str){
+    let rst = '';
+    let re = /(+[0-9]{2}-[0-9]{2}\s+[0-9]{2}:[0-9]{2}:[0-9]{2}恢复)/g;
+    rst = str.replace(re, '');
+    return rst;
+}
+function delPostNameFix (str){
+    let rst = '';
+    let re = /(+[0-9][0-9]*)/g;
+    rst = str.replace(re, '');
+    return rst;
+}
+
 function deleted(node){
-    return node.data.deleteInfo !== undefined && node.data.deleteInfo.deleted;
+    return node.data.deleteInfo !== undefined && node.data.deleteInfo && node.data.deleteInfo.deleted;
+}
+
+function fileEmpty(node){
+    return node.data.unitPriceFiles.length === 0 && node.data.feeRateFiles.length === 0;
 }
 
 function fIsExist(files, id, type){
     let isExist = false;
     for(let i = 0, len = files.length; i < len; i++){
-        if((type === fileType.unitPriceFile && files[i].id === id) || (type === fileType.feeRateFile && files[i].ID === id)){
+        if((type === fileType.unitPriceFile && files[i].id === parseInt(id)) || (type === fileType.feeRateFile && files[i].ID === id)){
             isExist = true;
             break;
         }
@@ -577,12 +656,12 @@ function getRecFileObj(files){
     let rst = Object.create(null);
     let rst_UF = [], rst_FF = [];
     for(let i = 0, len = files.length; i < len; i++){
-        if(files[i].findData !== undefined && files[i].findData.id !== undefined){
-            if(files[i].updateType === fileType.unitPriceFile){
+        if(files[i].findData !== undefined){
+            if(files[i].updateType === fileType.unitPriceFile && files[i].findData.id !== undefined){
                 rst_UF.push(files[i].findData.id);
             }
-            else if(files[i].updateType === fileType.feeRateFile){
-                rst_FF.push(files[i].findData.id);
+            else if(files[i].updateType === fileType.feeRateFile && files[i].findData.ID !== undefined){
+                rst_FF.push(files[i].findData.ID);
             }
         }
     }
@@ -601,56 +680,67 @@ function getUpdateObj(updateType, findData, updateData){
 
 function getUpdateDatas(updateType, node, mtNID, mtPM){
     let rst = [];
-    if(!decDate){
-        decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)';
-    }
+    decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)';
+    let newName = delPostFix(node.data.name) + decDate;
     if(updateType === projectType.tender || updateType === projectType.engineering){
-        //维护回收站树
-     /*   if(mtGC){
-            rst.push(getUpdateObj(updateType, {NextSiblingID: node.data.ID, 'deleteInfo.deleted': true}, {NextSiblingID: node.data.NextSiblingID}));
-        }*/
         //维护项目管理树
         if(mtPM){
             rst.push(getUpdateObj(updateType, {ParentID: node.data.ParentID, NextSiblingID: -1, deleteInfo: null}, {NextSiblingID: node.data.ID}));
         }
         //恢复
         if(mtNID){
-            rst.push(getUpdateObj(updateType, {ID: node.data.ID, name: node.data.name + decDate}, {deleteInfo: null, NextSiblingID: -1}));
+            rst.push(getUpdateObj(updateType, {ID: node.data.ID}, {name: newName, deleteInfo: null, NextSiblingID: -1}));
         }
         else {
-            rst.push(getUpdateObj(updateType, {ID: node.data.ID, name: node.data.name + decDate}, {deleteInfo: null}));
+            rst.push(getUpdateObj(updateType, {ID: node.data.ID}, {name: newName, deleteInfo: null}));
         }
     }
     else if(updateType === projectType.project){
-       /* //维护回收站树
-        if(mtGC){
-            rst.push(getUpdateObj(updateType, {NextSiblingID: node.data.ID, 'deleteInfo.deleted': true}, {NextSiblingID: node.data.NextSiblingID}));
-        }*/
         //恢复
-        rst.push(getUpdateObj(updateType, {ID: node.data.ID, name: node.data.name + decDate}, {deleteInfo: null}));//NextSibling为undefined,后端处理
+        rst.push(getUpdateObj(updateType, {ID: node.data.ID}, {deleteInfo: null, name: newName}));//NextSibling为undefined,后端处理
     }
     return rst;
 }
 //unitPriceFile or feeRateFile
 function getUpdateFiles(tenders, project){
-    let unitFiles = [], feeFiles = [], rst = [];
+    let rstUF = [], rstFF = [], rst = [];
+    let _unitFiles = Object.create(null), _feeFiles = Object.create(null), prefix = '_id';
+    decDate = '(' + new Date().Format('MM-dd hh:mm:ss') + '恢复)';
     for(let i = 0, len = tenders.length; i < len; i++){
         //恢复单价文件
         if(project && project.data.unitPriceFiles.length > 0 && fIsExist(project.data.unitPriceFiles, tenders[i].data.property.unitPriceFile.id, fileType.unitPriceFile)){
-            unitFiles.push(tenders[i].data.property.unitPriceFile.id);
+            //unitFiles.push(tenders[i].data.property.unitPriceFile.id);
+            let propId = tenders[i].data.property.unitPriceFile.id;
+            let propName = tenders[i].data.property.unitPriceFile.name;
+            let _uf = _unitFiles[prefix + propId] || null;
+            if(!_uf){
+                let obj = Object.create(null);
+                obj.id = parseInt(propId);
+                obj.name = propName;
+                _unitFiles[prefix + propId] = obj;
+            }
         }
         //恢复费率文件
         if(project && project.data.feeRateFiles.length > 0 && fIsExist(project.data.feeRateFiles, tenders[i].data.property.feeFile.id, fileType.feeRateFile)){
-            feeFiles.push(tenders[i].data.property.feeFile.id);
+            //feeFiles.push(tenders[i].data.property.feeFile.id);
+            let propId = tenders[i].data.property.feeFile.id;
+            let propName = tenders[i].data.property.feeFile.name;
+            let _ff = _feeFiles[prefix + propId] || null;
+            if(!_ff){
+                let obj = Object.create(null);
+                obj.id = propId;
+                obj.name = propName;
+                _feeFiles[prefix + propId] = obj;
+            }
         }
     }
-    let ufIds = Array.from(new Set(unitFiles));
-    let ffIds = Array.from(new Set(feeFiles));
-    for(let i = 0, len = ufIds.length; i < len; i++){
-        rst.push(getUpdateObj(fileType.unitPriceFile, {id: ufIds[i]}, {deleteInfo: null}));
+    for(let uf in _unitFiles){
+        rstUF.push(getUpdateObj(fileType.unitPriceFile, {id: _unitFiles[uf].id}, {deleteInfo: null, name: delPostFix(_unitFiles[uf].name) + decDate}));
     }
-    for(let i = 0, len = ffIds.length; i < len; i++){
-        rst.push(getUpdateObj(fileType.feeRateFile, {id: ffIds[i]}, {deleteInfo: null}));
+    for(let ff in _feeFiles){
+        rstFF.push(getUpdateObj(fileType.feeRateFile, {ID: _feeFiles[ff].id}, {deleteInfo: null, name: delPostFix(_feeFiles[ff].name) + decDate}));
     }
+    rst = rst.concat(deWeightName(rstUF));
+    rst = rst.concat(deWeightName(rstFF));
     return rst;
 }

+ 296 - 72
web/building_saas/pm/js/pm_main.js

@@ -12,12 +12,17 @@ let engineering = [];
 let feeRateData = [];
 let isSaving = false;
 let projectProperty = [];
+let fileDelObj = null;
 let projectType = {
     folder: 'Folder',
     tender: 'Tender',
     project: 'Project',
     engineering: 'Engineering'
 };
+let fileType = {
+    unitPriceFile: 'UnitPriceFile',
+    feeRateFile: 'FeeRateFile'
+};
 let ProjTreeSetting = {
     tree: {
         id: 'ID',
@@ -64,7 +69,6 @@ let ProjTreeSetting = {
                         html.push('class="'+ aClassName +'" ');
                     }
                     if (node && node.data) {
-                        //html.push('href="/main?project=', node.id(), '"');
                         html.push('href="javacript:void(0);"');
                     }
                     html.push('>', icon, '&nbsp;', text, '<a>');
@@ -123,14 +127,19 @@ let ProjTreeSetting = {
                 case projectType.project:
                     $("#add-engineering-btn").removeClass("disabled");
                     $("#add-project-btn").removeClass("disabled");
+                    $("#del-btn").removeClass("disabled");
                     break;
                 case projectType.folder:
+                    if(!node.children || node.children.length === 0){
+                        $("#del-btn").removeClass("disabled");
+                    }
                     $("#add-folder-btn").removeClass("disabled");
                     $("#add-project-btn").removeClass("disabled");
                     break;
                 case projectType.engineering:
                     $("#add-tender-btn").removeClass("disabled");
                     $("#add-engineering-btn").removeClass("disabled");
+                    $("#del-btn").removeClass("disabled");
                     break;
                 case projectType.tender:
                     $("#add-tender-btn").removeClass("disabled");
@@ -138,9 +147,9 @@ let ProjTreeSetting = {
                     $("#copy-to-btn").removeClass("disabled");
                     $("#share-btn").removeClass("disabled");
                     $("#cooperate-btn").removeClass("disabled");
+                    $("#del-btn").removeClass("disabled");
                     break;
             }
-            $("#del-btn").removeClass("disabled");
             $("#rename-btn").removeClass("disabled");
             $('td:eq(0)', node.row).append($('<i class="fa fa-sort" data-toggle="tooltip" data-placement="top" title="长安拖动"></i>'));
         }
@@ -161,6 +170,28 @@ $(document).ready(function() {
         $(".slide-sidebar").animate({width:"800"}).addClass("open");
     });
 
+    //单价、费率文件删除确认
+    $('#fileDelConfirm').click(function () {
+        if(fileDelObj && fileDelObj.id){
+            let updateObj = Object.create(null);
+            updateObj.updateType = 'delete';
+            updateObj.updateData = Object.create(null);
+            if(fileDelObj.fileType === fileType.unitPriceFile){
+                updateObj.updateData.id = fileDelObj.id;
+            }
+            else if(fileDelObj.fileType === fileType.feeRateFile){
+                updateObj.updateData.ID = fileDelObj.id;
+            }
+            updateObj.fileType = fileDelObj.fileType;
+            console.log(updateObj);
+            a_updateFiles([updateObj], function () {
+                fileDelObj = null;
+                $('#fileDelCancel').click();
+                //refresh front?
+            });
+        }
+    });
+
     // 新增建设项目点击
     $('#add-project-btn').click(function () {
         let selectedItem = Tree.selected();
@@ -253,9 +284,30 @@ $(document).ready(function() {
         }
 
         // 获取单价文件数据
-        getUnitFile(projectInfo.data.ID);
+        getUnitFile(projectInfo.data.ID, function (response) {
+            if (response.data.length <= 0) {
+                return false;
+            }
+            let unitFileHtml = '';
+            for(let tmp of response.data) {
+                unitFileHtml += '<option value="'+ tmp.id +'">'+ tmp.name +'</option>';
+            }
+            $("#unit-price").children("option:not(':first')").remove();
+            $("#unit-price").children("option").first().after(unitFileHtml);
+        });
         // 获取费率文件数据
-        getFeeRateFile(projectInfo.data.ID);
+        getFeeRateFile(projectInfo.data.ID, function (response) {
+            if (response.data.length <= 0) {
+                return false;
+            }
+            var first = $("#tender-fee-rate").children("option").first();
+            $("#tender-fee-rate").empty();
+            $("#tender-fee-rate").append(first);
+            for(let tmp of response.data) {
+                var option =  $("<option>").val(tmp.ID).text(tmp.name);
+                $("#tender-fee-rate").append(option);
+            }
+        });
     });
 
     // 新增单位工程
@@ -330,6 +382,7 @@ $(document).ready(function() {
         let dialog = $('#del');
         if (Tree) {
             updateData = GetDeleteUpdateData(Tree.selected());
+            console.log(updateData);
             UpdateProjectData(updateData, function () {
                 dialog.modal('hide');
                 Tree.removeNode(Tree.selected());
@@ -875,10 +928,12 @@ function GetDeleteUpdateData(node) {
     let datas = [], updateData,
         pre = node.preSibling(),
         deleteNodeData = function (node) {
-            var data = {};
+            var data = Object.create(null);
             data['updateType'] = 'delete';
-            data['updateData'] = {};
+            //data['NextSiblingID'] = node.data.NextSiblingID;
+            data['updateData'] = Object.create(null);
             data['updateData'][Tree.setting.tree.id] = node.id();
+            data['updateData']['projType'] = node.data.projType;
             if (node.data.projType === 'Tender') {
                 data['updateData']['FullFolder'] = GetFullFolder(node.parent);
             }
@@ -1085,7 +1140,7 @@ function getProperty(projectInfo) {
  * @param {Number} parentID
  * @return {void}
  */
-function getUnitFile(parentID) {
+function getUnitFile(parentID, callback) {
     parentID = parseInt(parentID);
     if (isNaN(parentID) && parentID <= 0) {
         return;
@@ -1106,15 +1161,9 @@ function getUnitFile(parentID) {
             if (response.error === 1) {
                 alert('获取失败!');
             } else {
-                if (response.data.length <= 0) {
-                    return false;
+                if(callback){
+                    callback(response);
                 }
-                let unitFileHtml = '';
-                for(let tmp of response.data) {
-                    unitFileHtml += '<option value="'+ tmp.id +'">'+ tmp.name +'</option>';
-                }
-                $("#unit-price").children("option:not(':first')").remove();
-                $("#unit-price").children("option").first().after(unitFileHtml);
             }
         }
     });
@@ -1127,7 +1176,7 @@ function getUnitFile(parentID) {
  * @param {Number} parentID
  * @return {void}
  */
-function getFeeRateFile(parentID) {
+function getFeeRateFile(parentID, callback) {
     parentID = parseInt(parentID);
     if (isNaN(parentID) && parentID <= 0) {
         return;
@@ -1148,15 +1197,8 @@ function getFeeRateFile(parentID) {
             if (response.error === 1) {
                 alert('获取失败!');
             } else {
-                if (response.data.length <= 0) {
-                    return false;
-                }
-                var first = $("#tender-fee-rate").children("option").first();
-                $("#tender-fee-rate").empty();
-                $("#tender-fee-rate").append(first);
-                for(let tmp of response.data) {
-                    var option =  $("<option>").val(tmp.ID).text(tmp.name);
-                    $("#tender-fee-rate").append(option);
+                if(callback){
+                    callback(response);
                 }
             }
         }
@@ -1179,76 +1221,258 @@ function setDataToSideBar() {
     $(target).show();
     $(target + '-name').html(name);
 
-    if (selectedItem.children.length <= 0) {
+    /*if (selectedItem.children.length <= 0) {
         return;
-    }
-    // 建设项目相关
-    let counter = 1;
-    let html = '';
-    for(let tmp of selectedItem.children) {
+    }*/
+    if(selectedItem.children.length > 0){
+        // 建设项目相关
+        let counter = 1;
+        let html = '';
+        for(let tmp of selectedItem.children) {
+            html += '<tr>' +
+                '<td>'+ counter +'</td>' +
+                '<td>'+ counter +'</td>' +
+                '<td>'+ tmp.data.name +'</td>' +
+                '<td></td>' +
+                '<td></td>' +
+                '<td></td>' +
+                '<td></td>' +
+                '</tr>';
+
+        }
         html += '<tr>' +
-            '<td>'+ counter +'</td>' +
-            '<td>'+ counter +'</td>' +
-            '<td>'+ tmp.data.name +'</td>' +
+            '<td>'+ (counter + 1) +'</td>' +
+            '<td> </td>' +
+            '<td>合计</td>' +
             '<td></td>' +
             '<td></td>' +
             '<td></td>' +
             '<td></td>' +
             '</tr>';
-
+        $(target + '-table tbody').html(html);
     }
-    html += '<tr>' +
-        '<td>'+ (counter + 1) +'</td>' +
-        '<td> </td>' +
-        '<td>合计</td>' +
-        '<td></td>' +
-        '<td></td>' +
-        '<td></td>' +
-        '<td></td>' +
-        '</tr>';
-    $(target + '-table tbody').html(html);
 
     // 加载单价文件与费率文件
     if (selectedItem.data.projType === projectType.project) {
         let engineeringData = selectedItem.children !== null && selectedItem.children.children !== null ?
             selectedItem.children : [];
-        if (engineeringData.length <= 0) {
+        /*if (engineeringData.length <= 0) {
             return;
-        }
-        let unitPriceFileHtml = '';
-        let feeFileHtml = '';
-        let unitPriceFileCounter = 1;
-        let feeFileCounter = 1;
+        }*/
         let unitPriceFileList = [];
         let feeFileList = [];
-        for(let engineering of engineeringData) {
-            let tenderData = engineering.children !== null ? engineering.children : [];
-            if (tenderData.length <= 0) {
-                continue;
+        let poj_tenders = getProjTenders(selectedItem);
+        getUnitFile(selectedItem.data.ID, function (response) {
+            unitPriceFileList = unitPriceFileList.concat(response.data);
+            $(target + '-unit-price-table tbody').empty();
+            set_file_table(target, poj_tenders, unitPriceFileList, fileType.unitPriceFile);
+        });
+        getFeeRateFile(selectedItem.data.ID, function (response) {
+            feeFileList = feeFileList.concat(response.data);
+            $(target + '-fee-table tbody').empty();
+            set_file_table(target, poj_tenders, feeFileList, fileType.feeRateFile);
+        });
+    }
+}
+
+//获取建设项目的全部单位工程
+function getProjTenders(proj) {
+    let rst = [];
+    let engineerings = proj.children || null;
+    if (engineerings) {
+        for (let i = 0, len = engineerings.length; i < len; i++) {
+            let e_tenders = engineerings[i].children || null;
+            if (e_tenders && e_tenders.length > 0) {
+                rst = rst.concat(e_tenders);
             }
-            for(let tmp of tenderData) {
-                tmp = tmp.data.property !== null ? tmp.data.property : null;
-                if(tmp === null) {
-                    continue;
-                }
+        }
+    }
+    return rst;
+}
+//单价、费率文件汇总信息的使用次数、使用该文件的单位工程
+function getUsedObj(tenders, fileId, type){
+    let rst = Object.create(null), usedCount = 0, usedInfo = '';
+    rst.usedCount = 0;
+    rst.usedInfo = null;
+    for(let i = 0, len = tenders.length; i < len; i++){
+        let theFile = type === fileType.unitPriceFile ? tenders[i].data.property.unitPriceFile || null : tenders[i].data.property.feeFile || null;
+        if(theFile && theFile.id == fileId){
+            usedCount ++;
+            usedInfo += tenders[i].data.name + '<br>';
+        }
+    }
+    if(usedCount > 0){
+        usedInfo = usedInfo.slice(0, usedInfo.length - 4);
+        rst.usedCount = usedCount;
+        rst.usedInfo = usedInfo;
+    }
+    return rst;
+}
 
-                if (tmp.feeFile !== undefined && feeFileList.indexOf(tmp.feeFile.name) < 0) {
-                    feeFileHtml += '<tr><td>'+ feeFileCounter +'</td><td>'+ tmp.feeFile.name +'</td></tr>';
-                    feeFileCounter++;
-                    feeFileList.push(tmp.feeFile.name);
+//单价、费率文件汇总界面交互
+function bindEvents_file_table(jqS, usedObj, targetBody, type){
+    //悬浮显示删除和重命名按钮
+    $(jqS).hover(function(){
+        $('p',this).show();
+    },function(){
+        $('p', this).hide();
+    });
+    //删除
+    if(usedObj.usedCount > 0){//不可删除
+        $(jqS + ' p a:eq(0)').addClass('disabled');
+        $(jqS + ' p a:eq(0)').removeAttr('data-target');
+    }
+    else {
+        $(jqS + ' p a:eq(0)').on('click', function () {
+            let dispName = $(jqS + ' div:eq(0)')[0].childNodes[0].textContent;
+            //刷新删除弹出框内容
+            let delData = '删除"' + dispName + '"?';
+            $('#del-wj .modal-body h5').text(delData);
+            let attrId = $(jqS).attr('id');
+            let id = attrId.slice(5, attrId.length);
+            if(type === fileType.unitPriceFile){
+                id = parseInt(id);
+            }
+            let obj = Object.create(null);
+            obj.fileType = type;
+            obj.id = id;
+            fileDelObj = obj;
+        });
+    }
+    //重命名
+    $(jqS + ' p a:eq(1)').on('click', function () {
+        let fileObjs = getFileObj(targetBody, type);
+        let orgDispName = $(jqS + ' div:eq(0)')[0].childNodes[0].textContent;
+        let postFix = orgDispName.slice(orgDispName.length - 4, orgDispName.length);
+        let orgName = orgDispName.slice(0, orgDispName.length - 4);
+        $(jqS + ' input').val(orgName);
+        $(jqS + ' div:eq(0)').hide();
+        $(jqS + ' div:eq(1)').show();
+        //确认重命名
+        $(jqS + ' .btn-success').on('click', function () {
+            let attrId = $(jqS).attr('id');
+            let id = attrId.slice(5, attrId.length);
+            let newName = $(jqS + ' input').val().trim();
+            if(newName !== orgName){
+                if(hasThisFileName(fileObjs, newName)){
+                    alert('本建设项目已存在该文件名,请重新输入!');
+                    $(jqS + ' input').val(orgName);
+                    return;
                 }
-
-                if (tmp.unitPriceFile !== undefined && unitPriceFileList.indexOf(tmp.unitPriceFile.name) < 0) {
-                    unitPriceFileHtml += '<tr><td>'+ unitPriceFileCounter +'</td><td>'+ tmp.unitPriceFile.name +'单价文件</td></tr>';
-                    unitPriceFileCounter++;
-                    unitPriceFileList.push(tmp.unitPriceFile.name);
+                if(newName.trim().length === 0){
+                    alert('文件名不可为空!');
+                    $(jqS + ' input').val(orgName);
+                    return;
+                }
+                //ajax
+                let updateObj = Object.create(null);
+                updateObj.fileType = type;
+                updateObj.updateType = 'update';
+                updateObj.updateData = Object.create(null);
+                if(type === fileType.unitPriceFile){
+                    updateObj.updateData.id = parseInt(id);
+                    //updateObj.updateData.id = id;
+                }
+                else if(type === fileType.feeRateFile){
+                    updateObj.updateData.ID = id;
                 }
+                updateObj.updateData.name = newName;
+                a_updateFiles([updateObj], function () {
+                    let newDispName = newName + postFix;
+                    $(jqS + ' div:eq(0)')[0].childNodes[0].textContent = newDispName;
+                    $(jqS + ' div:eq(0)').show();
+                    $(jqS + ' div:eq(1)').hide();
+                });
+                console.log(updateObj);
             }
+            let newDispName = newName + postFix;
+            $(jqS + ' div:eq(0)')[0].childNodes[0].textContent = newDispName;
+            $(jqS + ' div:eq(0)').show();
+            $(jqS + ' div:eq(1)').hide();
+        });
+        //取消重命名
+        $(jqS + ' .btn-secondary').on('click', function () {
+            $(jqS + ' div:eq(0)').show();
+            $(jqS + ' div:eq(1)').hide();
+        });
+    });
+    //悬浮框显示使用该文件的单位工程
+    $($(jqS)[0].nextSibling).popover({
+            placement:"bottom",
+            html:true,
+            trigger:"hover", //| focus
+            content: usedObj.usedInfo ? usedObj.usedInfo : ''
+        }
+    );
+}
 
-            $(target + '-unit-price-table tbody').html(unitPriceFileHtml);
-            $(target + '-fee-table tbody').html(feeFileHtml);
+//更新单价、费率文件(删除、重命名)
+function a_updateFiles(updateDatas, callback){
+    $.ajax({
+        type: 'post',
+        url: '/pm/api/updateFiles',
+        data: {data: JSON.stringify({user_id: userID, updateDatas: updateDatas})},
+        dataType: 'json',
+        success: function (result){
+            if(!result.error && callback){
+                callback();
+            }
         }
+    })
+}
 
+function set_file_table(target, poj_tenders, fileList, type){
+    let fileCounter = 1;
+    for(let i = 0, len = fileList.length; i < len; i++){
+        let fileId = type === fileType.unitPriceFile ? fileList[i].id : fileList[i].ID;
+        let usedObj = getUsedObj(poj_tenders, fileId, type);
+        let usedHtml = usedObj.usedCount > 0 ?  '<td class="text-center"><a href="javascript:void(0);">' + usedObj.usedCount + '</a></td>' : '<td class="text-center">' + usedObj.usedCount + '</td>';
+        let hoverHtml = '<p style="display: none"><a class="btn btn-sm" href="javascript:void(0);" data-toggle="modal" data-target="#del-wj">删除</a><a class="btn btn-sm" href="javascript:void(0);">重命名</a></p></div>';
+        let renHtml = '<div class="input-group" style="display: none;">'
+            + '<input class="form-control form-control-sm" value="">'
+            + '<span class="input-group-btn">'
+            + '<button class="btn btn-success btn-sm" type="button"><i class="fa fa-check"></i></button>'
+            + '</span>'
+            + '<span class="input-group-btn">'
+            + '<button class="btn btn-secondary btn-sm" type="button"><i class="fa fa-remove"></i></button>'
+            + '</span>'
+            + '</div></td>';
+        let fileTypeStr = type === fileType.unitPriceFile ? '单价文件' : '费率文件';
+        let fileHtml = '<tr><td>' + fileCounter + '</td><td id="file_' + fileId + '"><div>' + fileList[i].name + fileTypeStr + hoverHtml + renHtml + usedHtml + '</tr>';
+        fileCounter++;
+        let targetBody = type === fileType.unitPriceFile ? target + '-unit-price-table tbody' : target + '-fee-table tbody';
+        $(targetBody).append(fileHtml);
+        let jqS = '#file_' + fileId;
+        bindEvents_file_table(jqS, usedObj, targetBody, type);
     }
+}
+
+function getFileObj(jqS, type){
+    let rst = [];
+    let trs = $('tr', jqS);
+    for(let i = 0, len = trs.length; i < len; i++){
+        let td = $('td:eq(1)', trs[i])[0];
+        let dispName = td.childNodes[0].childNodes[0].textContent;
+        let name = dispName.slice(0, dispName.length - 4);
+        let attrId = $(td).attr('id');
+        let id = attrId.slice(5, attrId.length);
+        if(type === fileType.unitPriceFile){
+            id = parseInt(id);
+        }
+        let obj = Object.create(null);
+        obj.id = id;
+        obj.name = name;
+        rst.push(obj);
+    }
+    return rst;
+    //let orgDispName = $(jqS + ' div:eq(0)')[0].childNodes[0].textContent;
+}
 
-}
+function hasThisFileName(fileObjs, name){
+    for(let i = 0, len = fileObjs.length; i < len; i++){
+        if(fileObjs[i].name === name){
+            return true;
+        }
+    }
+    return false;
+}