Selaa lähdekoodia

Merge branch '1.0.0_online' of http://smartcost.f3322.net:3000/SmartCost/ConstructionOperation into 1.0.0_online

TonyKang 7 vuotta sitten
vanhempi
commit
74f9c52fb3

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 12 - 1
config/config.js


+ 2 - 0
modules/all_models/compilation.js

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

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

@@ -2,10 +2,12 @@
  * Created by Zhong on 2017/8/2.
  */
 let billsController = require("./bills_lib_controllers");
+let billsLibDao = require("./../models/bills_lib_interfaces");
 import baseController from "../../common/base/base_controller";
 import fs from 'fs';
 import path from 'path';
 import multiparty from 'multiparty';
+const excel = require("node-xlsx");
 const uuidV1 = require('uuid/v1');
 
 const shareDir = 'public/share/images';
@@ -68,6 +70,56 @@ class billsPermContr extends baseController{
         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){
@@ -172,7 +224,6 @@ class billsPermContr extends baseController{
             res.json({error: 1, data: {pageCount: 1, currentImgsUrl: []}, message: err});
         }
     }
-
 }
 
 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 billsGuidanceLib = mongoose.model('std_billsGuidance_lib');
 const engLibModel = mongoose.model('engineering_lib');
+let uuid = require('uuid');
 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();

+ 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("/renameStdBillsLib", billsLibContr.auth, billsLibContr.init, billsLibContr.renameStdBillsLib);
     billsRouter.post("/getStdBillsLibName", billsLibContr.auth, billsLibContr.init, billsLibContr.getStdBillsLibName);
+    //导入清单
+    billsRouter.post('/importBills', billsContr.importBills);
     //上传图片
     billsRouter.post('/uploadImg', billsContr.uploadImg);
     //删除图片

+ 2 - 0
modules/material_replace_lib/controllers/material_replace_controller.js

@@ -34,6 +34,7 @@ class ReplaceController extends BaseController{
             let gljLib = await  materialFacade.findGLJLibByComID(compilationId);
             let billsList = await materialFacade.findBillsByLibID(libID);
             //let templateDatas = await materialFacade.getTemplateDatasByLibID(libID);
+            //let stdBills = await  materialFacade.getStdBillsByLib(billsLibId);
 
             let randerData = {
                 title:'材料替换库',
@@ -45,6 +46,7 @@ class ReplaceController extends BaseController{
                 billsLibId:billsLibId,
                 gljLibID:gljLib.ID,
                 libID:libID,
+                //stdBills:JSON.stringify(stdBills),
                 LicenseKey:config.getLicenseKey(process.env.NODE_ENV),
                 layout: 'maintain/common/html/edit_layout'
             };

+ 4 - 0
modules/material_replace_lib/facade/material_replace_facade.js

@@ -76,6 +76,10 @@ let materialReplaceLib = {
     },
     getMaterialByBillsID : async function(billsID){
        return  await replaceMaterialModel.find({billsItemID:billsID});
+    },
+    getStdBillsByLib:async function(libID){
+        let bills = await stdBillsModel.find({billsLibId: libID},['ID','code','name','items']);
+        return bills;
     }
 };
 function prepareDatas(data) {//整理数据

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

@@ -238,7 +238,10 @@ class CompilationController extends BaseController {
         } catch (error) {
             console.log(error);
         }
-
+        //example Array to example String
+        if (selectedCompilation.example) {
+            selectedCompilation.example = selectedCompilation.example.join(';');
+        }
         let renderData = {
             section: section,
             valuationId: valuationId,
@@ -548,6 +551,18 @@ class CompilationController extends BaseController {
             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) {
         // 筛选字段
-        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;
         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});
     }
 
+    /*
+    * 设置例题
+    * @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('/setDescription', compilationController.auth, compilationController.init, compilationController.setDescription);
     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('/save-valuation', compilationController.auth, compilationController.init, compilationController.saveValuation);
     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="toolsbar px-1 d-flex justify-content-between">
                       <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 class="main-top-content">

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

@@ -32,7 +32,7 @@
                   <div class="col-md-8">
                     <div class="warp-p2 mt-3">
                       <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">
                           <!--<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 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. -->
     <script src="/lib/jquery/jquery.min.js"></script>
     <script src="/lib/tether/tether.min.js"></script>
     <script src="/lib/bootstrap/bootstrap.min.js"></script>
+    <script src="/public/web/PerfectLoad.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/bills_lib_ajax.js"></script>
@@ -223,7 +252,72 @@
                 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>
 

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

@@ -68,7 +68,9 @@ var mainAjax = {
                             "<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-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;
                         $("#tempId td:first a").attr("href", newHref);
                         $("#tempId").attr("id", id);
@@ -92,7 +94,9 @@ var mainAjax = {
                     $("#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='编辑'>" +
                         "<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;
                     $("#tempId td:first a").attr("href", newHref);

+ 77 - 0
web/maintain/material_replace_lib/html/edit_新编辑版本.html

@@ -0,0 +1,77 @@
+<nav class="navbar navbar-toggleable-lg justify-content-between navbar-light p-0 second_header">
+    <ul class="nav nav-tabs" role="tablist">
+        <li class="nav-item">
+            <a class="nav-link active px-3" href="javascript: void(0);">材料替换</a>
+        </li>
+    </ul>
+</nav>
+
+<div class="main">
+    <div class="content" >
+        <div class="container-fluid" >
+            <div class="row">
+                <div class="tools-bar p-1 d-flex justify-content-between col-lg-12" style="background: #f7f7f7;">
+                    <div class="input-group input-group-sm col-lg-4">
+                        <input class="form-control" placeholder="搜索定位" type="text" id = 'keyword'>
+                        <span class="input-group-btn">
+                              <button class="btn btn-secondary" type="button"><i class="fa fa-search"></i></button>
+                            </span>
+                        <a class="btn btn-sm btn-link"  style="color: #0275d8;cursor:pointer" data-toggle="modal" data-target="#guize"">关于规则</a>
+                    </div>
+                </div>
+                <div class="main-content col-lg-4 p-0">
+                    <div class="main-data" id="billsSpread"></div>
+                </div>
+                <div class="col-lg-4 main-side p-0">
+
+                </div>
+                <div class="col-lg-4 main-side p-0" id="materialSpread"></div>
+
+            </div>
+        </div>
+        <input type="hidden" id="libID" value="<%= libID %>">
+        <input type="hidden" id="gljLibID" value="<%= gljLibID %>">
+        <input type="hidden" id="billsLibId" value="<%= billsLibId %>">
+        <div style="display: none">
+            <textarea  id = "testStd" type="hidden"><%= stdBills %></textarea>
+        </div>
+
+    </div>
+</div>
+
+<!--弹出关于规则-->
+<div class="modal fade" id="guize" 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">×</span>
+                </button>
+            </div>
+            <div class="modal-body">
+                <table class="table table-bordered">
+                    <thead><tr><th width="90">规则名称</th><th>规则解释</th></tr></thead>
+                    <tr><td>规则1</td><td>材料及规格:MU5烧结页岩空心砖</td></tr>
+                    <tr><td>规则2</td><td>1.混凝土种类:商品混凝土<br>2.混凝土强度等级:C30</td></tr>
+                </table>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
+            </div>
+        </div>
+    </div>
+
+</div>
+
+<script type="text/javascript">
+    //自适应高度
+    $(".main-data").height($(window).height()-$(".header").height()-$(".tools-bar").height()-$(".navbar").height()-16);
+    let billsList = '<%- billsList %>';
+
+</script>
+<script type="text/javascript" src="/lib/jquery-contextmenu/jquery.contextMenu.js"></script>
+<script type="text/javascript" src="/public/web/sheet/sheet_common.js"></script>
+<script type="text/javascript" src="/public/web/sheet/sheet_data_helper.js"></script>
+
+<script type="text/javascript" src="/web/maintain/material_replace_lib/js/material_replace_edit.js"></script>

+ 478 - 0
web/maintain/material_replace_lib/js/material_replace_edit_新编辑版本.js

@@ -0,0 +1,478 @@
+/**
+ * Created by zhang on 2018/8/23.
+ */
+
+let materialOjb = {
+    billsSpread:null,
+    materialSpread:null,
+    allBills:JSON.parse(billsList),
+    billsList:JSON.parse(billsList),
+    stdBills:JSON.parse($("#testStd").val()),
+    materialList:[],
+    billsTreeSetting: {
+        treeCol: 0,
+        emptyRows: 0,
+        headRows: 1,
+        headRowHeight: [40],
+        defaultRowHeight: 21,
+        cols: [{
+            width: 200,
+            readOnly: true,
+            head: {
+                titleNames: ["项目编码"],
+                spanCols: [1],
+                spanRows: [1],
+                vAlign: [1],
+                hAlign: [1],
+                font: ["Arial"]
+            },
+            data: {
+                field: "code",
+                vAlign: 1,
+                hAlign: 0,
+                font: "Arial"
+            }
+        }, {
+            width: 200,
+            readOnly: true,
+            head: {
+                titleNames: ["项目名称"],
+                spanCols: [1],
+                spanRows: [1],
+                vAlign: [1],
+                hAlign: [1],
+                font: ["Arial"]
+            },
+            data: {
+                field: "name",
+                vAlign: 1,
+                hAlign: 0,
+                font: "Arial"
+            }
+        }]
+    },
+   /* billsSetting:{
+        header: [
+            {headerName: "清单编号", headerWidth: 180, dataCode: "code", dataType: "String",formatter: "@"},
+            {headerName: "清单名称", headerWidth: 240, dataCode: "name", dataType: "String"},
+            {headerName: "规则", headerWidth: 150, dataCode: "rule", hAlign: "left", dataType: "String",cellType:'comboBox',editorValueType:true,options:[{text:"规则1",value:1},{text:"规则2",value:2}]}
+        ],
+        view: {
+            lockColumns: [1]
+        },
+        headerHeight:45
+    },*/
+    materialSetting:{
+        header: [
+            {headerName: "材料编号", headerWidth: 180, dataCode: "code", dataType: "String",formatter: "@"},
+            {headerName: "材料名称", headerWidth: 240, dataCode: "name", dataType: "String",cellType:'tipsCell'},
+            {headerName: "规格", headerWidth: 150, dataCode: "specs", hAlign: "left", dataType: "String",cellType:'tipsCell'}
+        ],
+        view: {
+            lockColumns: [1,2]
+        },
+        headerHeight:45
+    },
+    initSpread:function () {
+      /*  if(!this.billsSpread){
+            this.billsSpread = SheetDataHelper.createNewSpread($("#billsSpread")[0]);
+        }
+        if(!this.materialSpread){
+            this.materialSpread = SheetDataHelper.createNewSpread($("#materialSpread")[0]);
+        }
+        this.billsSheet = this.billsSpread .getSheet(0);
+        sheetCommonObj.initSheet(this.billsSheet,this.billsSetting, 30);
+        this.billsSheet.name('billsSheet');
+        this.billsSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onBillsValueChange);
+        this.billsSheet.bind(GC.Spread.Sheets.Events.SelectionChanged,this.onBillsSelectionChange);
+        this.billsSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onBillsRangeChange);
+
+        this.initRightClick("billsSpread",this.billsSpread);
+
+
+        this.materialSheet = this.materialSpread .getSheet(0);
+        sheetCommonObj.initSheet(this.materialSheet,this.materialSetting, 30);
+        this.materialSheet.name('materialSheet');
+        this.materialSheet.bind(GC.Spread.Sheets.Events.ValueChanged, this.onMaterialValueChange);
+        this.materialSheet.bind(GC.Spread.Sheets.Events.EditStarting, this.onMaterialEditStarting);
+        this.materialSheet.bind(GC.Spread.Sheets.Events.RangeChanged, this.onMaterialRangeChange);
+        this.initRightClick("materialSpread",this.materialSpread);
+        this.refreshSheet();*/
+
+    },
+    canDelete : function (sheet) {
+        let me = this;
+        let sel =  sheet.getSelections()[0];
+        let datas = sheet.name() == 'billsSheet'?me.billsList:me.materialList;
+        if(sel.row === undefined || sel.row < 0) return false ;//一行都没选中时,不能删除
+        if((sel.row + sel.rowCount) > datas.length) return false;//选中了空行,不能删除
+        return true;
+    },
+    deleteBills : async function(sheet){
+        let me = this,deleteList = [];
+        let sel = sheet.getSelections()[0];
+        for(let i = 0;i<sel.rowCount;i++){
+            if(me.billsList[sel.row + i]) deleteList.push(getDeleteDatas(me.billsList[sel.row + i]));
+        }
+        if(deleteList.length > 0) await me.saveBills(deleteList);
+        function getDeleteDatas(tem) {
+            return {type:'delete', ID:tem.ID}
+        }
+
+    },
+    deleteMaterial:async function(sheet){
+        let me = this,deleteList = [];
+        let sel = sheet.getSelections()[0];
+        for(let i = 0; i<sel.rowCount;i++){
+            if(me.materialList[sel.row + i]) deleteList.push(me.getMaterialUpdateData(null,me.materialList[sel.row + i].ID,true));
+        }
+        if(deleteList.length > 0) await me.saveMaterial(deleteList);
+    },
+    initRightClick : function(id,spread) {
+        let me = this;
+        let sheet = spread.getActiveSheet();
+        $.contextMenu({
+            selector: '#'+id,
+            build: function ($trigger, e) {
+                me.rightClickTarget = SheetDataHelper.safeRightClickSelection($trigger, e, spread);
+                return me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.viewport ||
+                    me.rightClickTarget.hitTestType === GC.Spread.Sheets.SheetArea.rowHeader;
+            },
+            items: {
+                "delete": {
+                    name: "删除",
+                    icon: 'fa-trash-o',
+                    disabled: function () {
+                        return !me.canDelete(sheet);
+                    },
+                    callback: function (key, opt) {
+                        sheet.name() == 'billsSheet' ? me.deleteBills(sheet):me.deleteMaterial(sheet);
+                       console.log( me.rightClickTarget);
+                    }
+                }
+            }
+        });
+    },
+    refreshSheet:async function(){
+        this.getBillsList();
+        sheetCommonObj.showData(this.billsSheet,this.billsSetting,this.billsList);
+        this.billsSheet.setRowCount(this.billsList.length + 30);
+        this.showMaterialList();
+    },
+    getBillsList:function () {
+        let keyword = $("#keyword").val();
+        if(isDef(keyword)&&keyword!==''){
+            this.billsList = _.filter(this.allBills,function (item) {
+                return item.code.indexOf(keyword)!=-1 || item.name.indexOf(keyword)!=-1;
+            })
+        }else {
+            this.billsList = this.allBills;
+        }
+        this.billsList = _.sortBy(this.billsList,'code');
+    },
+    getMateriaList:async function () {
+        let billsItemID =  this.getCurrentBillsID();
+        if(billsItemID){
+            this.materialList = await this.getMaterialByBillsID(billsItemID)//getMaterialByBills
+        }else {
+            this.materialList = [];
+        }
+    },
+    showMaterialList:async function () {
+        await this.getMateriaList();
+        this.refreshMaterialSheet();
+    },
+    refreshMaterialSheet:function () {
+        this.materialList = _.sortBy(this.materialList,'code');
+        sheetCommonObj.showData(this.materialSheet,this.materialSetting,this.materialList);
+        this.materialSheet.setRowCount(this.materialList.length + 30);
+    },
+    onBillsSelectionChange:function (sender,args) {
+        let me = materialOjb;
+        let nsel = args.newSelections?args.newSelections[0]:null;
+        let osel = args.oldSelections?args.oldSelections[0]:null;
+        if(nsel && osel && nsel.row != osel.row){
+            me.showMaterialList();
+            me.materialSheet.showRow(0, GC.Spread.Sheets.VerticalPosition.top);
+        }
+        args.sheet.repaint();
+    },
+    onBillsRangeChange:function (sender,args) {
+        let me = materialOjb;
+        let updateDatas = [];
+        if(args.action == GC.Spread.Sheets.RangeChangedAction.paste){
+            for(let c of args.changedCells){
+                let field = me.billsSetting.header[c.col].dataCode;
+                let newValue =  args.sheet.getCell(c.row,c.col).value();
+                let data = null;
+                if(me.validateBills(field,newValue)){
+                    if(c.row < me.billsList.length){
+                         data = me.getUpdateData(field,newValue,me.billsList[c.row].code);
+                    }else if(field == 'code'){//如果是在空白行粘贴,并且是编码列,则是新增,其它的忽略;
+                         data = me.getUpdateData(field,newValue,null);
+                    }
+                    if(data) updateDatas.push(data);
+                }else {
+                    break;
+                }
+            }
+            if(updateDatas.length > 0){
+                me.saveBills(updateDatas);
+                return;
+            }
+        }
+         me.refreshSheet();
+    },
+    onMaterialRangeChange:function(sender,args){
+        let me = materialOjb;
+        let updateDatas = [];
+        if(args.action == GC.Spread.Sheets.RangeChangedAction.paste){
+            for(let c of args.changedCells){
+                let code =  args.sheet.getCell(c.row,c.col).value(),data = null;
+                if(me.validateMaterial(code)){
+                    if(c.row < me.materialList.length){
+                         data = me.getMaterialUpdateData(code,me.materialList[c.row].ID);
+                    }else {//如果是在空白行粘贴,并且是编码列,则是新增,其它的忽略;
+                         data = me.getMaterialUpdateData(code,null);
+                    }
+                    if(data) updateDatas.push(data);
+                }else {
+                    break;
+                }
+            }
+            if(updateDatas.length > 0){
+                me.saveMaterial(updateDatas);
+                return;
+            }
+        }
+        me.showMaterialList();
+    },
+
+
+    onBillsValueChange: function(sender,args){
+        let me = materialOjb;
+        let field = me.billsSetting.header[args.col].dataCode;
+        let code = null;
+        if(args.row < me.billsList.length){
+            code = me.billsList[args.row].code;
+        }
+        if(me.validateBills(field,args.newValue)){
+            let data = me.getUpdateData(field,args.newValue,code);
+            if (data){
+                me.saveBills([data]);
+                return;
+            }
+        }
+        me.refreshSheet();
+    },
+    onMaterialEditStarting : function (sender,args) {
+        let me = materialOjb;
+        if(!me.getCurrentBillsID()) args.cancel = true; //如果没选中清单则不能编辑
+    },
+
+    onMaterialValueChange:function(sender,args){
+        let me = materialOjb;
+        let ID = null;
+        if(args.row < me.materialList.length){
+            ID = me.materialList[args.row].ID;
+        }
+        if(me.validateMaterial(args.newValue)){
+            let data = me.getMaterialUpdateData(args.newValue,ID);
+            if(data){
+                me.saveMaterial([data]);
+                return
+            }
+        }
+        me.showMaterialList();
+
+    },
+    validateMaterial:function (value) {
+        value = value.toString().replace(/[\s\r\n]/g, "");//去除空格换行等字符;
+        if(_.find(this.materialList,{code:value})){
+            alert("人材机:"+value+" 已存在");
+            return false;
+        }
+        return true;
+    },
+    validateBills:function (field,value) {
+        if(field == 'code'){
+            value = value.toString().replace(/[\s\r\n]/g, "");//去除空格换行等字符;
+            if(value.length !== 9){
+                alert("清单长度不正确");
+                return false;
+            }
+            if(_.find(this.billsList,{'code':value})) {
+                alert("清单:"+value+" 已存在");
+                return false;
+            }
+        }
+        return true;
+    },
+    getCurrentBillsID:function(){
+      let sel = this.billsSheet.getSelections()[0];
+      if(sel.row < this.billsList.length){
+           return this.billsList[sel.row].ID;
+      }
+      return null;
+    },
+    getMaterialUpdateData:function(code,ID,isDelete){
+        if(isDelete == true){
+            return {type:'delete', ID:ID}
+        }
+        code = code.toString().replace(/[\s\r\n]/g, "");//去除空格换行等字符;
+        if((!isDef(ID)||ID=='')&& code != null){//新增
+            let billsItemID = this.getCurrentBillsID();
+            return {
+                type:'add',
+                code:code,
+                billsItemID:billsItemID,
+                libID:$('#libID').val(),
+                gljLibID:parseInt($('#gljLibID').val())
+            }
+        }else { //替换材料
+            return {
+                type:'update',
+                ID:ID,
+                code:code,
+                gljLibID:parseInt($('#gljLibID').val())
+            }
+        }
+    },
+    getUpdateData:function (field,newValue,code) {
+        if(field == 'code'){
+            newValue = newValue.toString().replace(/[\s\r\n]/g, "");//去除空格换行等字符;
+            if((!isDef(code) || code =='')&&newValue!=null){//说明是新增
+                return {
+                    type:'add',
+                    code:newValue,
+                    libID:$('#libID').val(),
+                    billsLibId:parseInt($('#billsLibId').val())
+                }
+            }else {//说明是替换
+                return {
+                    type:'update',
+                    oldCode:code.toString(),
+                    newCode:newValue,
+                    libID:$('#libID').val(),
+                    billsLibId:parseInt($('#billsLibId').val())
+                }
+            }
+        }else if(isDef(code)){
+            let updateData = {};
+            updateData[field] = newValue;
+            return {
+                type:'update',
+                oldCode:code.toString(),
+                libID:$('#libID').val(),
+                updateData:updateData
+            }
+        }
+    },
+    saveMaterial:async function(datas){
+        try {
+            let result = await ajaxPost("/materialReplace/saveMaterial",datas);
+            let missCodes = [];
+            for(let r of result){
+                if(r.missCodes && r.missCodes.length >0) missCodes =missCodes.concat(r.missCodes);
+            }
+            if(missCodes.length > 0) alert(`没有找到人材机:${missCodes.join("、")}`);
+        }catch (err){
+            console.log(err);
+        }
+        this.showMaterialList();
+    },
+    saveBills:async function (datas) {
+        try {
+            let result = await ajaxPost("/materialReplace/saveBills",datas);
+            let missCodes = [];
+            for(let r of result){
+                if(r.missCodes && r.missCodes.length >0) missCodes =missCodes.concat(r.missCodes);
+                if(r.type == 'add'){
+                    this.allBills = this.allBills.concat(r.list);
+                }if(r.type == 'update'){
+                    for(let l of r.list){
+                       this.updateBillsCache(l.code,l.updateData);
+                    }
+                }if(r.type == 'delete'){
+                    _.remove(this.allBills,function (item) {
+                        return _.includes(r.list,item.ID)
+                    })
+                }
+            }
+            if(missCodes.length > 0) alert(`没有找到清单:${missCodes.join("、")}`);
+        }catch (err){
+            console.log(err);
+        }
+        this.refreshSheet();
+    },
+    saveDatas:async function (datas,type ='bills') {
+        try {
+            let currentList = type =='bills'?this.billsList:this.materialList;
+            let url = type =='bills'?"/materialReplace/saveBills":"/materialReplace/saveMaterial";
+            let text = type =='bills'?"清单":"人材机";
+            let result = await ajaxPost(url,datas);
+            let missCodes = [];
+            for(let r of result){
+                if(r.missCodes && r.missCodes.length >0) missCodes =missCodes.concat(r.missCodes);
+                if(r.type == 'add'){
+                    currentList = currentList.concat(r.list);
+                }if(r.type == 'update'){
+                    for(let l of r.list){
+                        type =='bills'?this.updateBillsCache(l.code,l.updateData):this.updateMaterialCache(l.ID,l.updateData);
+                    }
+                }if(r.type == 'delete'){
+                    _.remove(currentList,function (item) {
+                        return _.includes(r.list,item.ID)
+                    })
+                }
+            }
+            if(missCodes.length > 0) alert(`没有找到${text}:${missCodes.join("、")}`);
+        }catch (err){
+            console.log(err);
+        }
+
+    },
+    getMaterialByBillsID:async function(billsItemID){
+        try {
+            let result = await ajaxPost("/materialReplace/findMaterial",{billsItemID:billsItemID});
+            return result;
+        }catch (err){
+            console.log(err);
+            return [];
+        }
+    },
+    updateMaterialCache:function (ID,updateData) {
+        this.updateCache(this.materialList,{'ID':ID},updateData)
+    },
+
+    updateBillsCache:function (code,updateData) {
+         this.updateCache(this.allBills,{'code':code},updateData)
+    },
+
+    updateCache:function (list,condition,updateData) {
+        let item = _.find(list,condition);
+        for(let key in updateData){
+            item[key] = updateData[key]
+        }
+    }
+};
+let last = 0;
+
+$(document).ready(function () {
+    $("#keyword").on('input propertychange', function(event) {
+        last = event.timeStamp;//利用event的timeStamp来标记时间,这样每次事件都会修改last的值,注意last必需为全局变量
+        setTimeout(function () {    //设时延迟0.5s执行
+            if (last - event.timeStamp == 0) { //如果时间差为0(也就是你停止输入0.5s之内都没有其它的keyup事件发生)则做你想要做的事
+               materialOjb.refreshSheet();
+            }
+
+        }, 500);
+    })
+});
+
+function isDef(obj) {
+    return obj!==undefined && obj!==null;
+}
+
+materialOjb.initSpread();
+

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

@@ -5,6 +5,19 @@
  * @date 2017/7/28
  * @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() {
     let isAdding = false;
     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() {
         let goingChangeStatus = switchChange($(this));

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

@@ -100,6 +100,7 @@
             <table class="table">
                 <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>例题建设项目ID:</span><input class="form-control" type="text" id="example" value="<%= selectedCompilation.example%>"></td></tr>-->
                 <tr><td><p>显示办事处销售信息</p>
                     <select class="form-control" style="width:200px" id="category-select">
                         <% categoryList.forEach(function(category) { %>