Parcourir la source

标准清单导入相关

zhongzewei il y a 7 ans
Parent
commit
da88814a02

+ 2 - 0
modules/all_models/compilation.js

@@ -53,6 +53,8 @@ let modelSchema = {
     description: String,
     description: String,
     //代码覆盖路径
     //代码覆盖路径
     overWriteUrl:String,
     overWriteUrl:String,
+    //例题建设项目ID
+    example: Array,
     // 发布时间
     // 发布时间
     release_time: {
     release_time: {
         type: Number,
         type: Number,

+ 52 - 1
modules/bills_lib/controllers/bills_permissionController.js

@@ -2,10 +2,12 @@
  * Created by Zhong on 2017/8/2.
  * Created by Zhong on 2017/8/2.
  */
  */
 let billsController = require("./bills_lib_controllers");
 let billsController = require("./bills_lib_controllers");
+let billsLibDao = require("./../models/bills_lib_interfaces");
 import baseController from "../../common/base/base_controller";
 import baseController from "../../common/base/base_controller";
 import fs from 'fs';
 import fs from 'fs';
 import path from 'path';
 import path from 'path';
 import multiparty from 'multiparty';
 import multiparty from 'multiparty';
+const excel = require("node-xlsx");
 const uuidV1 = require('uuid/v1');
 const uuidV1 = require('uuid/v1');
 
 
 const shareDir = 'public/share/images';
 const shareDir = 'public/share/images';
@@ -68,6 +70,56 @@ class billsPermContr extends baseController{
         billsController.isUsed(req, res);
         billsController.isUsed(req, res);
     }
     }
     /*
     /*
+     * 导入标准清单(确定节点结构:深度数组)
+     * */
+    importBills(req, res){
+        let form = new multiparty.Form({uploadDir: './public'});
+        const allowHeader = ['application/vnd.ms-excel', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'];
+        let uploadFullName;
+        form.parse(req, async function (err, fields, files) {
+            try {
+                const file = typeof files.file !== 'undefined' ? files.file[0] : null;
+                if (err || !file) {
+                    throw '上传失败。';
+                }
+                if (file.headers['content-type'] === undefined || allowHeader.indexOf(file.headers['content-type']) < 0) {
+                    throw '不支持该类型';
+                }
+                const billsLibId = typeof fields.billsLibId !== 'undefined' && fields.billsLibId.length > 0 ? fields.billsLibId[0] : null;
+                if (!billsLibId) {
+                    throw '请选择一个清单库。';
+                }
+                let hasData = await billsLibDao.hasData(billsLibId);
+                if (hasData) {
+                    throw '请新建一个新的清单库,或删除库中的清单后再导入。';
+                }
+                // 重命名文件名
+                uploadFullName = './public/' + file.originalFilename;
+                fs.renameSync(file.path, uploadFullName);
+                const sheet = excel.parse(uploadFullName);
+                if (sheet[0] === undefined || sheet[0].data === undefined || sheet[0].data.length <= 0) {
+                    throw 'excel没有对应数据';
+                }
+                //插入清单
+                await billsLibDao.importBills(billsLibId, sheet[0].data);
+                // 删除文件
+                if(uploadFullName && fs.existsSync(uploadFullName)){
+                    fs.unlinkSync(uploadFullName);
+                }
+                res.json({error: 0, data: null, msg: ''});
+
+            } catch (err) {
+                console.log(err);
+                // 删除文件
+                if(uploadFullName && fs.existsSync(uploadFullName)){
+                    fs.unlinkSync(uploadFullName);
+                }
+                res.json({error: 1, data: null, msg: err});
+            }
+        });
+    }
+
+    /*
     *上传图片
     *上传图片
     * */
     * */
     uploadImg(req, res){
     uploadImg(req, res){
@@ -172,7 +224,6 @@ class billsPermContr extends baseController{
             res.json({error: 1, data: {pageCount: 1, currentImgsUrl: []}, message: err});
             res.json({error: 1, data: {pageCount: 1, currentImgsUrl: []}, message: err});
         }
         }
     }
     }
-
 }
 }
 
 
 export default billsPermContr;
 export default billsPermContr;

+ 198 - 1
modules/bills_lib/models/bills_lib_interfaces.js

@@ -11,6 +11,7 @@ let ItemCharacter = mongoose.model('std_bills_lib_itemCharacter');
 let moment = require("moment");
 let moment = require("moment");
 let billsGuidanceLib = mongoose.model('std_billsGuidance_lib');
 let billsGuidanceLib = mongoose.model('std_billsGuidance_lib');
 const engLibModel = mongoose.model('engineering_lib');
 const engLibModel = mongoose.model('engineering_lib');
+let uuid = require('uuid');
 let billsLibDao = function(){};
 let billsLibDao = function(){};
 
 
 
 
@@ -3091,7 +3092,203 @@ billsLibDao.prototype.edUpdateItem = function(data, callback){
         }
         }
     });
     });
 };
 };
-//
+
+billsLibDao.prototype.hasData = async function (billsLibId) {
+    let bills = await Bills.findOne({billsLibId: billsLibId});
+    if (bills) {
+        return true;
+    }
+    return false;
+};
+
+billsLibDao.prototype.importBills = async function (billsLibId, sheetData) {
+    //实际节点深度数组,下标等于深度,元素为该为上一个该深度清单数据, 数组长度-1等于最大深度
+    let depthArr = [];
+    const deepest = 10000;
+    //深度的值,并不是真正的深度,只是三种类型节点(顶节点、中间节点、底节点)的深度值,节点根据深度值与深度数组最大深度的比较,对深度数组进行更新,
+    //并且确定父子上下关系
+    function getDepthValue(code){
+        let midReg = /\.{1,}/g;
+        //root
+        if (code.length === 1) {
+            return 0;
+        }
+        if (midReg.test(code)) {
+            return code.match(midReg).length;
+        }
+        return deepest;
+    }
+    let billsDatas = [],
+        jobMapping = {},
+        itemMapping = {};
+    function getDivideData(data){
+        let rst = [];
+        let divideReg = /[\n,\r]/g,
+            prefixReg = /\d+\.{1}/g; //前缀 1. 2.
+        let divideArr = data.split(divideReg);
+        for (let dData of divideArr) {
+            if (dData !== '') {
+                rst.push(dData.replace(prefixReg, ''));
+            }
+        }
+        return rst;
+    }
+    //设置总工作内容/项目特征映射
+    function setBillsSubMapping(subData, mapping){
+        for (let data of subData) {
+            if (!mapping[data]) {
+                let code = Object.keys(mapping).length + 1;
+                mapping[data] = {billsLibId: billsLibId, code: code, content: data, deleted: false};
+            }
+        }
+    }
+    let row = -1;
+    //从表格中获取清单数据
+    for (let rowData of sheetData) {
+        row++;
+        if (row === 0) {
+            continue;
+        }
+        let bills = {
+            deleted: false,
+            billsLibId: billsLibId,
+            parent: null,
+            ID: uuid.v1(),
+            ParentID: -1,
+            NextSiblingID: -1,
+            code: typeof rowData[0] !== 'undefined' ? rowData[0] : '',
+            name: typeof rowData[1] !== 'undefined' ? rowData[1] : '',
+            unit: typeof rowData[2] !== 'undefined' ? rowData[2] : '',
+            ruleText: typeof rowData[3] !== 'undefined' ? rowData[3] : '',
+            recharge: '',
+        };
+        let jobData = typeof rowData[4] !== 'undefined' ? getDivideData(rowData[4]) : [],
+            itemData = typeof rowData[5] !== 'undefined' ? getDivideData(rowData[5]) :[];
+        bills.jobData = jobData;
+        bills.itemData = itemData;
+        setBillsSubMapping(jobData, jobMapping);
+        setBillsSubMapping(itemData, itemMapping);
+        billsDatas.push(bills);
+    }
+    //设置工作内容、项目特征id
+    async function setSubId(moduleName, subMapping) {
+        let idx = 0,
+            subCount = Object.keys(subMapping).length;
+        let subCounter = await counter.counterDAO.getIDAfterCount(moduleName, subCount);
+        for (let mapping in subMapping) {
+            let id = subCounter.sequence_value - (subCount - 1) + idx;
+            let sub = subMapping[mapping];
+            sub.id = id;
+            idx++;
+        }
+    }
+    await setSubId(counter.moduleName.billsLib_jobs, jobMapping);
+    await setSubId(counter.moduleName.billsLib_items, itemMapping);
+    //获得清单、工作内容/项目特征关联数组
+    //subDatas为清单工作内容/项目特征的字符串数组 eg: ['场内运输', '开挖'];
+    //mapping为总工作内容/项目特征字符串映射 eg: {'场内运输': {content: '场内运输', id: 1, code: 1, deleted: false}}
+    function getBillsSubRef(subDatas, mapping) {
+        let rst = [];
+        for (let i = 0; i < subDatas.length; i++) {
+            let data = subDatas[i];
+            if (mapping[data]) {
+                rst.push({id: mapping[data].id, serialNo: i + 1});
+            }
+        }
+        return rst;
+    }
+    //设置完整的清单数据(树结构、工作内容/项目特征)
+    for (let i = 0; i < billsDatas.length; i++) {
+        let bills = billsDatas[i],
+            preBills = billsDatas[i - 1];
+        //树结构相关设置
+        let maxDepth = depthArr.length - 1;
+        let depthV = getDepthValue(bills.code);
+        //前节点为最底层节点,且这个节点为最底层节点,则深度相同
+        let preIsDeepest = preBills && getDepthValue(preBills.code) === deepest ? true : false;
+        if (preIsDeepest && depthV === deepest) {
+            depthV = maxDepth;
+        }
+        if (depthV > maxDepth) {
+            let parent = depthArr[depthArr.length - 1];
+            if (parent) {
+                bills.ParentID = parent.ID;
+                bills.parent = parent;
+            }
+            depthArr.push(bills);
+        } else {
+            let parent = depthArr[depthV -1];
+            if (parent) {
+                bills.ParentID = parent.ID;
+                bills.parent = parent;
+            }
+            depthArr[depthV].NextSiblingID = bills.ID;
+            depthArr.splice(depthV, 1);
+            if (depthV < maxDepth) { //切割
+                depthArr = depthArr.slice(0, depthV);
+            }
+            depthArr.push(bills);
+        }
+        //工作内容项目特征
+        bills.jobs = getBillsSubRef(bills.jobData, jobMapping);
+        bills.items = getBillsSubRef(bills.itemData, itemMapping);
+    }
+    function getSectionInfo(bills){
+        let parentIDs = [];
+        let sectionInfo = {first: null, second: null, third: null};
+        getParent(bills);
+        if(parentIDs[parentIDs.length - 1]){
+            sectionInfo.first = parentIDs[parentIDs.length - 1];
+        }
+        if(parentIDs[parentIDs.length - 2]){
+            sectionInfo.second = parentIDs[parentIDs.length - 2];
+        }
+        if(parentIDs[parentIDs.length - 3]){
+            sectionInfo.third = parentIDs[parentIDs.length - 3];
+        }
+        return sectionInfo;
+        function getParent(bills){
+            if(bills.parent){
+                parentIDs.push(bills.parent.ID);
+                getParent(bills.parent);
+            }
+        }
+    }
+    //设置sectionInfo
+    for (let bills of billsDatas) {
+        bills.sectionInfo = getSectionInfo(bills);
+    }
+    //插入清单
+    let bulks = [];
+    for (let bills of billsDatas) {
+        delete bills.parent;
+        bulks.push({insertOne: {document: bills}});
+    }
+    if (bulks.length > 0) {
+        await Bills.bulkWrite(bulks);
+    }
+    //清除工作内容、项目特征
+    await JobContent.remove({billsLibId: billsLibId});
+    await ItemCharacter.remove({billsLibId: billsLibId});
+    function getSubBulks(subMapping) {
+        let rst = [];
+        for (let mapping in subMapping) {
+            let sub = subMapping[mapping];
+            rst.push({insertOne: {document: sub}});
+        }
+        return rst;
+    }
+    //插入工作内容
+    let jobBulks = getSubBulks(jobMapping);
+    if (jobBulks.length > 0) {
+        await JobContent.bulkWrite(jobBulks);
+    }
+    //插入项目特征
+    let itemBulks = getSubBulks(itemMapping);
+    if (itemBulks.length > 0) {
+        await ItemCharacter.bulkWrite(itemBulks);
+    }
+};
 
 
 
 
 module.exports = new billsLibDao();
 module.exports = new billsLibDao();

+ 2 - 0
modules/bills_lib/routes/bills_lib_routes.js

@@ -29,6 +29,8 @@ module.exports =function (app) {
     billsRouter.post("/deleteStdBillsLib", billsLibContr.auth, billsLibContr.init, billsLibContr.deleteStdBillsLib);
     billsRouter.post("/deleteStdBillsLib", billsLibContr.auth, billsLibContr.init, billsLibContr.deleteStdBillsLib);
     billsRouter.post("/renameStdBillsLib", billsLibContr.auth, billsLibContr.init, billsLibContr.renameStdBillsLib);
     billsRouter.post("/renameStdBillsLib", billsLibContr.auth, billsLibContr.init, billsLibContr.renameStdBillsLib);
     billsRouter.post("/getStdBillsLibName", billsLibContr.auth, billsLibContr.init, billsLibContr.getStdBillsLibName);
     billsRouter.post("/getStdBillsLibName", billsLibContr.auth, billsLibContr.init, billsLibContr.getStdBillsLibName);
+    //导入清单
+    billsRouter.post('/importBills', billsContr.importBills);
     //上传图片
     //上传图片
     billsRouter.post('/uploadImg', billsContr.uploadImg);
     billsRouter.post('/uploadImg', billsContr.uploadImg);
     //删除图片
     //删除图片

+ 16 - 1
modules/users/controllers/compilation_controller.js

@@ -238,7 +238,10 @@ class CompilationController extends BaseController {
         } catch (error) {
         } catch (error) {
             console.log(error);
             console.log(error);
         }
         }
-
+        //example Array to example String
+        if (selectedCompilation.example) {
+            selectedCompilation.example = selectedCompilation.example.join(';');
+        }
         let renderData = {
         let renderData = {
             section: section,
             section: section,
             valuationId: valuationId,
             valuationId: valuationId,
@@ -548,6 +551,18 @@ class CompilationController extends BaseController {
             response.json({err: 1, msg: err, data: null});
             response.json({err: 1, msg: err, data: null});
         }
         }
     }
     }
+    async setExample(request, response){
+        let compilationId = request.body.id,
+            example = request.body.example;
+        try {
+            let compilationModel = new CompilationModel();
+            await compilationModel.setExample(compilationId, example);
+            response.json({err: 0, msg: 'success', data: null});
+        }
+        catch (err){
+            response.json({err: 1, msg: err, data: null});
+        }
+    }
 
 
     /**
     /**
      * 模板设置页面
      * 模板设置页面

+ 15 - 1
modules/users/models/compilation_model.js

@@ -36,7 +36,7 @@ class CompilationModel extends BaseModel {
      */
      */
     async getCompilationList(fields = null) {
     async getCompilationList(fields = null) {
         // 筛选字段
         // 筛选字段
-        let field = fields == null ?{_id: 1, name: 1, is_release: 1, categoryID: 1, description: 1,overWriteUrl: 1, "ration_valuation.id": 1, "ration_valuation.name": 1, "ration_valuation.enable": 1,
+        let field = fields == null ?{_id: 1, name: 1, is_release: 1, categoryID: 1, description: 1,overWriteUrl: 1,example: 1, "ration_valuation.id": 1, "ration_valuation.name": 1, "ration_valuation.enable": 1,
             "bill_valuation.id": 1, "bill_valuation.name": 1, "bill_valuation.enable": 1}:fields;
             "bill_valuation.id": 1, "bill_valuation.name": 1, "bill_valuation.enable": 1}:fields;
         let compilationData = await this.findDataByCondition({name: {$ne: ''}}, field, false);
         let compilationData = await this.findDataByCondition({name: {$ne: ''}}, field, false);
 
 
@@ -95,6 +95,20 @@ class CompilationModel extends BaseModel {
         return await this.updateById(compilationId, {overWriteUrl: overWriteUrl, priceProperties: priceProp, consumeAmtProperties: consumeAmtProp});
         return await this.updateById(compilationId, {overWriteUrl: overWriteUrl, priceProperties: priceProp, consumeAmtProperties: consumeAmtProp});
     }
     }
 
 
+    /*
+    * 设置例题
+    * @param {String} compilationId
+    * @param {Array} example
+    * @return {Promise}
+    * */
+    async setExample(compilationId, example) {
+        let data = [];
+        for (let projId of example) {
+            data.push(parseInt(projId));
+        }
+        return await this.updateById(compilationId, {example: data});
+    }
+
     /**
     /**
      * 新增计价规则
      * 新增计价规则
      *
      *

+ 1 - 0
modules/users/routes/compilation_route.js

@@ -22,6 +22,7 @@ module.exports = function (app) {
     router.post('/add', compilationController.auth, compilationController.init, compilationController.addCompilation);
     router.post('/add', compilationController.auth, compilationController.init, compilationController.addCompilation);
     router.post('/setDescription', compilationController.auth, compilationController.init, compilationController.setDescription);
     router.post('/setDescription', compilationController.auth, compilationController.init, compilationController.setDescription);
     router.post('/setOverWriteUrl', compilationController.auth, compilationController.init, compilationController.setOverWriteUrl);
     router.post('/setOverWriteUrl', compilationController.auth, compilationController.init, compilationController.setOverWriteUrl);
+    router.post('/setExample', compilationController.auth, compilationController.init, compilationController.setExample);
     router.post('/add-valuation', compilationController.auth, compilationController.init, compilationController.addValuation);
     router.post('/add-valuation', compilationController.auth, compilationController.init, compilationController.addValuation);
     router.post('/save-valuation', compilationController.auth, compilationController.init, compilationController.saveValuation);
     router.post('/save-valuation', compilationController.auth, compilationController.init, compilationController.saveValuation);
     router.post('/update-engineer', compilationController.auth, compilationController.init, compilationController.updateEngineer);
     router.post('/update-engineer', compilationController.auth, compilationController.init, compilationController.updateEngineer);

+ 7 - 7
web/maintain/billsGuidance_lib/html/zhiyin.html

@@ -44,13 +44,13 @@
                   <div class="main-content col-lg-4 p-" style="margin: 0; padding: 0;">
                   <div class="main-content col-lg-4 p-" style="margin: 0; padding: 0;">
                     <div class="toolsbar px-1 d-flex justify-content-between">
                     <div class="toolsbar px-1 d-flex justify-content-between">
                       <div class="tools-btn btn-group align-top">
                       <div class="tools-btn btn-group align-top">
-                        <a id="insert" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-reply-all" aria-hidden="true"></i> 插入</a>
-                        <a id="del" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-remove" aria-hidden="true"></i> 删除</a>
-                        <a id="upLevel" href="javascript:void(0);" class="btn btn-sm disabled" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-arrow-left" aria-hidden="true"></i> 升级</a>
-                        <a id="downLevel" href="javascript:void(0);" class="btn btn-sm disabled" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-arrow-right" aria-hidden="true"></i> 降级</a>
-                        <a id="downMove" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-arrow-down" aria-hidden="true"></i> 下移</a>
-                        <a id="upMove" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-arrow-up" aria-hidden="true"></i> 上移</a>
-                        <a id="expandContract" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title=""><i class="fa fa-minus-square-o" aria-hidden="true"></i> 收起定额</a>
+                        <a id="insert" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="插入"><i class="fa fa-reply-all" aria-hidden="true"></i> 插入</a>
+                        <a id="del" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="删除"><i class="fa fa-remove" aria-hidden="true"></i></a>
+                        <a id="upLevel" href="javascript:void(0);" class="btn btn-sm disabled" data-toggle="tooltip" data-placement="bottom" title="升级"><i class="fa fa-arrow-left" aria-hidden="true"></i></a>
+                        <a id="downLevel" href="javascript:void(0);" class="btn btn-sm disabled" data-toggle="tooltip" data-placement="bottom" title="降级"><i class="fa fa-arrow-right" aria-hidden="true"></i></a>
+                        <a id="downMove" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="下移"><i class="fa fa-arrow-down" aria-hidden="true"></i></a>
+                        <a id="upMove" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="上移"><i class="fa fa-arrow-up" aria-hidden="true"></i></a>
+                        <a id="expandContract" href="javascript:void(0);" class="btn btn-sm" data-toggle="tooltip" data-placement="bottom" title="收起定额"><i class="fa fa-minus-square-o" aria-hidden="true"></i> 收起定额</a>
                       </div>
                       </div>
                     </div>
                     </div>
                       <div class="main-top-content">
                       <div class="main-top-content">

+ 96 - 2
web/maintain/bills_lib/html/main.html

@@ -32,7 +32,7 @@
                   <div class="col-md-8">
                   <div class="col-md-8">
                     <div class="warp-p2 mt-3">
                     <div class="warp-p2 mt-3">
                       <table class="table table-hover table-bordered">
                       <table class="table table-hover table-bordered">
-                        <thead><tr><th>清单规则名称</th><th width="160">添加时间</th><th width="90">操作</th></tr></thead>
+                        <thead><tr><th>清单规则名称</th><th width="160">添加时间</th><th width="90">操作</th><th width="90">导入</th></tr></thead>
                         <tbody id="showArea">
                         <tbody id="showArea">
                           <!--<tr><td><a href="qingdan.html">XX清单规则</a></td><td>2017-01-01 </td><td><a href="javacript:void(0);" data-toggle="modal" data-target="#edit" title="编辑"><i class="fa fa-pencil-square-o"></i></a> <a href="javacript:void(0);" data-toggle="modal" data-target="#del" class="text-danger" title="删除"><i class="fa fa-remove"></i></a></td></tr>
                           <!--<tr><td><a href="qingdan.html">XX清单规则</a></td><td>2017-01-01 </td><td><a href="javacript:void(0);" data-toggle="modal" data-target="#edit" title="编辑"><i class="fa fa-pencil-square-o"></i></a> <a href="javacript:void(0);" data-toggle="modal" data-target="#del" class="text-danger" title="删除"><i class="fa fa-remove"></i></a></td></tr>
                           <tr><td><a href="qingdan.html">XX清单规则</a></td><td>2017-01-01 </td><td><a href="javacript:void(0);" data-toggle="modal" data-target="#edit" title="编辑"><i class="fa fa-pencil-square-o"></i></a> <a href="javacript:void(0);" data-toggle="modal" data-target="#del" class="text-danger" title="删除"><i class="fa fa-remove"></i></a></td></tr>
                           <tr><td><a href="qingdan.html">XX清单规则</a></td><td>2017-01-01 </td><td><a href="javacript:void(0);" data-toggle="modal" data-target="#edit" title="编辑"><i class="fa fa-pencil-square-o"></i></a> <a href="javacript:void(0);" data-toggle="modal" data-target="#del" class="text-danger" title="删除"><i class="fa fa-remove"></i></a></td></tr>
@@ -116,10 +116,39 @@
             </div>
             </div>
         </div>
         </div>
     </div>
     </div>
+    <!--弹出导入数据-->
+    <div class="modal fade" id="import" data-backdrop="static" style="display: none;" aria-hidden="true">
+        <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">×</span>
+                    </button>
+                </div>
+                <div class="modal-body">
+                    <div class="alert alert-warning" role="alert">
+                        导入操作会覆盖数据,请谨慎操作!!
+                    </div>
+                    <form>
+                        <div class="form-group">
+                            <label>请选择Excel格式文件</label>
+                            <input class="form-control-file" type="file" accept=".xlsx,.xls" name="import_data"/>
+                        </div>
+                    </form>
+                </div>
+                <div class="modal-footer">
+                    <button type="button" class="btn btn-primary" id="data-import">确定导入</button>
+                    <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
+                </div>
+            </div>
+        </div>
+    </div>
     <!-- JS. -->
     <!-- JS. -->
     <script src="/lib/jquery/jquery.min.js"></script>
     <script src="/lib/jquery/jquery.min.js"></script>
     <script src="/lib/tether/tether.min.js"></script>
     <script src="/lib/tether/tether.min.js"></script>
     <script src="/lib/bootstrap/bootstrap.min.js"></script>
     <script src="/lib/bootstrap/bootstrap.min.js"></script>
+    <script src="/public/web/PerfectLoad.js"></script>
     <script src="/public/web/common_ajax.js"></script>
     <script src="/public/web/common_ajax.js"></script>
     <script src="/web/maintain/bills_lib/scripts/global.js"></script>
     <script src="/web/maintain/bills_lib/scripts/global.js"></script>
     <script src="/web/maintain/bills_lib/scripts/bills_lib_ajax.js"></script>
     <script src="/web/maintain/bills_lib/scripts/bills_lib_ajax.js"></script>
@@ -223,7 +252,72 @@
                 alert("请输入名称!");
                 alert("请输入名称!");
             }
             }
         });
         });
-        //test es6
+        //清空选择
+        $('#import').on('shown.bs.modal', function () {
+            $("input[name='import_data']").val('');
+        });
+        let selLibId = -1;
+        $("#showArea").on("click", ".import-data", function () {
+            let id = $(this).data("id");
+            id = parseInt(id);
+            if (isNaN(id) || id <= 0) {
+                return false;
+            }
+            selLibId = id;
+            $("#import").modal("show");
+        });
+        //导入数据
+        $("#data-import").click(function() {
+            $.bootstrapLoading.start();
+            const self = $(this);
+            try {
+                let formData = new FormData();
+                let file = $("input[name='import_data']")[0];
+                if (file.files.length <= 0) {
+                    throw '请选择文件!';
+                }
+                formData.append('file', file.files[0]);
+                // 获取库id
+                if (selLibId <= 0) {
+                    return false;
+                }
+                formData.append('billsLibId', selLibId);
+                $.ajax({
+                    url: '/stdBillsEditor/importBills',
+                    type: 'POST',
+                    data: formData,
+                    cache: false,
+                    contentType: false,
+                    processData: false,
+                    beforeSend: function() {
+                        self.attr('disabled', 'disabled');
+                        self.text('上传中...');
+                    },
+                    success: function(response){
+                        self.removeAttr('disabled');
+                        self.text('确定导入');
+                        if (response.error === 0) {
+                            $.bootstrapLoading.end();
+                            // 成功则关闭窗体
+                            $('#import').modal("hide");
+                        } else {
+                            $.bootstrapLoading.end();
+                            const message = response.msg !== undefined ? response.msg : '上传失败!';
+                            alert(message);
+                        }
+                    },
+                    error: function(){
+                        $.bootstrapLoading.end();
+                        alert("与服务器通信发生错误");
+                        self.removeAttr('disabled');
+                        self.text('确定导入');
+                    }
+                });
+            } catch(error) {
+                alert(error);
+                $.bootstrapLoading.end();
+            }
+        });
     });
     });
 </script>
 </script>
 
 

+ 6 - 2
web/maintain/bills_lib/scripts/bills_lib_ajax.js

@@ -68,7 +68,9 @@ var mainAjax = {
                             "<td>"+createDateFmt+" </td>" +
                             "<td>"+createDateFmt+" </td>" +
                             "<td><a href='javascript:void(0);' data-toggle='modal' data-target='#edit' title='编辑'>" +
                             "<td><a href='javascript:void(0);' data-toggle='modal' data-target='#edit' title='编辑'>" +
                             "<i class='fa fa-pencil-square-o'></i></a> <a href='javascript:void(0);' data-toggle='modal' data-target='#del' class='text-danger' title='删除'>" +
                             "<i class='fa fa-pencil-square-o'></i></a> <a href='javascript:void(0);' data-toggle='modal' data-target='#del' class='text-danger' title='删除'>" +
-                            "<i class='fa fa-remove'></i></a></td></tr>");
+                            "<i class='fa fa-remove'></i></a></td>" +
+                            "<td><a class='btn btn-secondary btn-sm import-data' href='javacript:void(0);' data-id='"+ id +"' title='导入数据'><i class='fa fa-sign-in fa-rotate-90'></i>导入</a></td>"+
+                            "</tr>");
                         var newHref = "stdBills?billsLibId="+id;
                         var newHref = "stdBills?billsLibId="+id;
                         $("#tempId td:first a").attr("href", newHref);
                         $("#tempId td:first a").attr("href", newHref);
                         $("#tempId").attr("id", id);
                         $("#tempId").attr("id", id);
@@ -92,7 +94,9 @@ var mainAjax = {
                     $("#showArea").append(
                     $("#showArea").append(
                         "<tr id='tempId'><td><a href='stdBills'>"+billsLibName+"</a></td><td>"+createDateFmt+" </td><td><a href='javascript:void(0);' data-toggle='modal' data-target='#edit' title='编辑'>" +
                         "<tr id='tempId'><td><a href='stdBills'>"+billsLibName+"</a></td><td>"+createDateFmt+" </td><td><a href='javascript:void(0);' data-toggle='modal' data-target='#edit' title='编辑'>" +
                         "<i class='fa fa-pencil-square-o'></i></a> <a href='javascript:void(0);' data-toggle='modal' data-target='#del' class='text-danger' title='删除'>" +
                         "<i class='fa fa-pencil-square-o'></i></a> <a href='javascript:void(0);' data-toggle='modal' data-target='#del' class='text-danger' title='删除'>" +
-                        "<i class='fa fa-remove'></i></a></td></tr>"
+                        "<i class='fa fa-remove'></i></a></td>" +
+                        "<td><a class='btn btn-secondary btn-sm import-data' href='javacript:void(0);' data-id='"+ id +"' title='导入数据'><i class='fa fa-sign-in fa-rotate-90'></i>导入</a></td>" +
+                        "</tr>"
                     );
                     );
                     var newHref = "stdBills?billsLibId="+id;
                     var newHref = "stdBills?billsLibId="+id;
                     $("#tempId td:first a").attr("href", newHref);
                     $("#tempId td:first a").attr("href", newHref);

+ 40 - 0
web/users/js/compilation.js

@@ -5,6 +5,19 @@
  * @date 2017/7/28
  * @date 2017/7/28
  * @version
  * @version
  */
  */
+
+const delayTime = 500;
+let keyupTime;
+function delayKeyup(callback) {
+    let nowTime = Date.now();
+    keyupTime = nowTime;
+    setTimeout(function () {
+        if (nowTime - keyupTime == 0 && callback) {
+            callback();
+        }
+    }, delayTime);
+}
+
 $(document).ready(function() {
 $(document).ready(function() {
     let isAdding = false;
     let isAdding = false;
     let model = '';
     let model = '';
@@ -281,6 +294,33 @@ $(document).ready(function() {
         });
         });
     });
     });
 
 
+    //例题建设项目ID, 用英文字符;分隔建设项目ID
+    $('#example').keyup(function () {
+        let exampleVal = $(this).val();
+        let tempExample = exampleVal.split(/[;,;]/g),
+            example = [];
+        for (let te of tempExample) {
+            let intTe = parseInt(te);
+            if (!isNaN(intTe)) {
+                example.push(intTe);
+            }
+        }
+        example = Array.from(new Set(example));
+        delayKeyup(function () {
+            $.ajax({
+                url: '/compilation/setExample',
+                type: 'post',
+                dataType: "json",
+                data: {id: id, example: example},
+                success: function(response) {
+                    if (response.err !== 0) {
+                        alert('更改失败');
+                    }
+                }
+            });
+        });
+    });
+
     // 计价规则启用/禁止
     // 计价规则启用/禁止
     $(".enable").click(function() {
     $(".enable").click(function() {
         let goingChangeStatus = switchChange($(this));
         let goingChangeStatus = switchChange($(this));

+ 1 - 0
web/users/views/compilation/index.html

@@ -100,6 +100,7 @@
             <table class="table">
             <table class="table">
                 <tr><td><p>软件版本介绍</p><textarea id="description" class="form-control" placeholder="请简要描述改版本"><%= selectedCompilation.description%></textarea></td></tr>
                 <tr><td><p>软件版本介绍</p><textarea id="description" class="form-control" placeholder="请简要描述改版本"><%= selectedCompilation.description%></textarea></td></tr>
                 <tr><td><span>重写路径:</span><input class="form-control" type="text" id="overWriteUrl" value="<%= selectedCompilation.overWriteUrl%>"></td></tr>
                 <tr><td><span>重写路径:</span><input class="form-control" type="text" id="overWriteUrl" value="<%= selectedCompilation.overWriteUrl%>"></td></tr>
+               <!-- <tr><td><span>例题建设项目ID:</span><input class="form-control" type="text" id="example" value="<%= selectedCompilation.example%>"></td></tr>-->
                 <tr><td><p>显示办事处销售信息</p>
                 <tr><td><p>显示办事处销售信息</p>
                     <select class="form-control" style="width:200px" id="category-select">
                     <select class="form-control" style="width:200px" id="category-select">
                         <% categoryList.forEach(function(category) { %>
                         <% categoryList.forEach(function(category) { %>