Przeglądaj źródła

变更令生成功能

laiguoran 6 lat temu
rodzic
commit
0441047417
79 zmienionych plików z 30894 dodań i 3714 usunięć
  1. 1 1
      app/const/audit.js
  2. 11 11
      app/const/change.js
  3. 5 5
      app/const/tender_info.js
  4. 97 77
      app/controller/change_controller.js
  5. 10 5
      app/controller/project_controller.js
  6. 94 6
      app/extend/helper.js
  7. 187 0
      app/public/css/datatable/dataTables.bootstrap.css
  8. 1 0
      app/public/css/datatable/dataTables.bootstrap.min.css
  9. 206 0
      app/public/css/datatable/dataTables.bootstrap4.css
  10. 1 0
      app/public/css/datatable/dataTables.bootstrap4.min.css
  11. 118 0
      app/public/css/datatable/dataTables.foundation.css
  12. 1 0
      app/public/css/datatable/dataTables.foundation.min.css
  13. 481 0
      app/public/css/datatable/dataTables.jqueryui.css
  14. 1 0
      app/public/css/datatable/dataTables.jqueryui.min.css
  15. 102 0
      app/public/css/datatable/dataTables.semanticui.css
  16. 1 0
      app/public/css/datatable/dataTables.semanticui.min.css
  17. 48 0
      app/public/css/datatable/fixedColumns.bootstrap.css
  18. 1 0
      app/public/css/datatable/fixedColumns.bootstrap.min.css
  19. 52 0
      app/public/css/datatable/fixedColumns.bootstrap4.css
  20. 1 0
      app/public/css/datatable/fixedColumns.bootstrap4.min.css
  21. 18 0
      app/public/css/datatable/fixedColumns.dataTables.css
  22. 1 0
      app/public/css/datatable/fixedColumns.dataTables.min.css
  23. 31 0
      app/public/css/datatable/fixedColumns.foundation.css
  24. 1 0
      app/public/css/datatable/fixedColumns.foundation.min.css
  25. 12 0
      app/public/css/datatable/fixedColumns.jqueryui.css
  26. 1 0
      app/public/css/datatable/fixedColumns.jqueryui.min.css
  27. 40 0
      app/public/css/datatable/fixedColumns.semanticui.css
  28. 1 0
      app/public/css/datatable/fixedColumns.semanticui.min.css
  29. 99 0
      app/public/css/datatable/fixedheadertable.css
  30. 448 0
      app/public/css/datatable/jquery.dataTables.css
  31. 1 0
      app/public/css/datatable/jquery.dataTables.min.css
  32. 18 0
      app/public/css/datatable/tablecloth.css
  33. 81 0
      app/public/js/change_calculation.js
  34. 49 1
      app/public/js/change_detail.js
  35. 517 11
      app/public/js/change_set.js
  36. 182 0
      app/public/js/datatable/dataTables.bootstrap.js
  37. 8 0
      app/public/js/datatable/dataTables.bootstrap.min.js
  38. 184 0
      app/public/js/datatable/dataTables.bootstrap4.js
  39. 8 0
      app/public/js/datatable/dataTables.bootstrap4.min.js
  40. 1632 0
      app/public/js/datatable/dataTables.fixedColumns.js
  41. 35 0
      app/public/js/datatable/dataTables.fixedColumns.min.js
  42. 174 0
      app/public/js/datatable/dataTables.foundation.js
  43. 8 0
      app/public/js/datatable/dataTables.foundation.min.js
  44. 164 0
      app/public/js/datatable/dataTables.jqueryui.js
  45. 9 0
      app/public/js/datatable/dataTables.jqueryui.min.js
  46. 212 0
      app/public/js/datatable/dataTables.semanticui.js
  47. 9 0
      app/public/js/datatable/dataTables.semanticui.min.js
  48. 38 0
      app/public/js/datatable/fixedColumns.bootstrap.js
  49. 5 0
      app/public/js/datatable/fixedColumns.bootstrap.min.js
  50. 38 0
      app/public/js/datatable/fixedColumns.bootstrap4.js
  51. 5 0
      app/public/js/datatable/fixedColumns.bootstrap4.min.js
  52. 38 0
      app/public/js/datatable/fixedColumns.dataTables.js
  53. 38 0
      app/public/js/datatable/fixedColumns.foundation.js
  54. 5 0
      app/public/js/datatable/fixedColumns.foundation.min.js
  55. 38 0
      app/public/js/datatable/fixedColumns.jqueryui.js
  56. 5 0
      app/public/js/datatable/fixedColumns.jqueryui.min.js
  57. 38 0
      app/public/js/datatable/fixedColumns.semanicui.js
  58. 38 0
      app/public/js/datatable/fixedColumns.semanticui.js
  59. 5 0
      app/public/js/datatable/fixedColumns.semanticui.min.js
  60. 53 0
      app/public/js/datatable/jlzf-change-table.js
  61. 15296 0
      app/public/js/datatable/jquery.dataTables.js
  62. 166 0
      app/public/js/datatable/jquery.dataTables.min.js
  63. 706 0
      app/public/js/datatable/jquery.fixedheadertable.js
  64. 20 0
      app/public/js/datatable/jquery.fixedheadertable.min.js
  65. 808 0
      app/public/js/datatable/jquery.tablesorter.js
  66. 184 0
      app/public/js/datatable/tablecloth.js
  67. 2 0
      app/router.js
  68. 158 62
      app/service/change.js
  69. 6 4
      app/service/change_att.js
  70. 74 12
      app/service/change_audit.js
  71. 28 0
      app/service/change_audit_list.js
  72. 10 15
      app/service/change_company.js
  73. 3 3
      app/service/deal_bills.js
  74. 6 5
      app/service/project_account.js
  75. 7 2
      app/view/change/index.ejs
  76. 229 58
      app/view/change/info.ejs
  77. 70 187
      app/view/change/info_modal.ejs
  78. 7413 3248
      package-lock.json
  79. 2 1
      package.json

+ 1 - 1
app/const/audit.js

@@ -101,4 +101,4 @@ module.exports = {
         auditStatusClass,
     },
     filter,
-};
+};

+ 11 - 11
app/const/change.js

@@ -12,10 +12,10 @@ module.exports = {
     // 变更类型
     type: {
         pos: {
-            value: 1, name: 'A.位置',
+            value: 1, name: 'A.数量',
         },
         num: {
-            value: 2, name: 'B.数量',
+            value: 2, name: 'B.位置',
         },
         structure: {
             value: 3, name: 'C.结构',
@@ -33,19 +33,19 @@ module.exports = {
     // 变更类别
     class: {
         A: {
-            value: 1, name: 'A类变更(设计变更)',
+            value: 1, name: 'A类变更',
         },
         B: {
-            value: 2, name: 'B类变更(施工措施变)',
+            value: 2, name: 'B类变更',
         },
         C: {
-            value: 3, name: 'C类变更(计划变更)',
+            value: 3, name: 'C类变更',
         },
         D: {
-            value: 4, name: 'D类变更(条件变更)',
+            value: 4, name: 'D类变更',
         },
         E: {
-            value: 5, name: 'E类变更(新增工程)',
+            value: 5, name: 'E类变更',
         },
     },
     // 变更性质
@@ -54,13 +54,13 @@ module.exports = {
             value: 1, name: '一般设计变更',
         },
         more: {
-            value: 1, name: '较大设计变更',
+            value: 2, name: '较大设计变更',
         },
         great: {
-            value: 1, name: '重大设计变更',
+            value: 3, name: '重大设计变更',
         },
     },
-    //费用承担方
+    // 费用承担方
     charge: {
         partyA: {
             value: 1, name: '业主',
@@ -69,4 +69,4 @@ module.exports = {
             value: 2, name: '承包人',
         },
     },
-}
+}

+ 5 - 5
app/const/tender_info.js

@@ -76,7 +76,7 @@ const defaultInfo = {
         tao: { unit: '套', value: 0 },
         ke: { unit: '棵', value: 0 },
         zu: { unit: '组', value: 0 },
-        zonge: { unit: '总额', value: 0},
+        zonge: { unit: '总额', value: 0 },
         xitong: { unit: '系统', value: 0 },
         other: { value: 3 },
     },
@@ -90,12 +90,12 @@ const defaultInfo = {
     // 显示设置
     display: {
         ledger: {
-            dgnQty : false,
-        }
-    }
+            dgnQty: false,
+        },
+    },
 };
 
 module.exports = {
     parseInfo,
     defaultInfo,
-};
+};

+ 97 - 77
app/controller/change_controller.js

@@ -9,6 +9,7 @@
  */
 
 const moment = require('moment');
+const sendToWormhole = require('stream-wormhole');
 const fs = require('fs');
 const path = require('path');
 const audit = require('../const/audit');
@@ -42,8 +43,9 @@ module.exports = app => {
             const total = await ctx.service.change.getCountByStatus(tender.id, status);
             if (changes !== null) {
                 let i = 0;
-                for(let c of changes) {
-                    const changeAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times);
+                for (const c of changes) {
+                    const status = c.status === audit.flow.status.uncheck ? 0 : 1;
+                    const changeAudit = await ctx.service.changeAudit.getLastUser(c.cid, c.times, status);
                     changes[i].changeAudit = changeAudit;
                     i++;
                 }
@@ -62,7 +64,7 @@ module.exports = app => {
             filter.count[filter.status.uncheck] = await ctx.service.change.getCountByStatus(tender.id, filter.status.uncheck);// await ctx.service.change.checkingDatas(tender.id, ctx.session.sessionUser.accountId);
             filter.count[filter.status.checking] = await ctx.service.change.getCountByStatus(tender.id, filter.status.checking);// await ctx.service.change.checkedDatas(tender.id, ctx.session.sessionUser.accountId);
             filter.count[filter.status.checked] = await ctx.service.change.getCountByStatus(tender.id, filter.status.checked);// await ctx.service.change.pendingDatas(tender.id, ctx.session.sessionUser.accountId);
-            filter.count[filter.status.checkNo] = await ctx.service.change.getCountByStatus(tender.id, filter.status.checkNo);//await ctx.service.change.pendingDatas(tender.id, ctx.session.sessionUser.accountId);
+            filter.count[filter.status.checkNo] = await ctx.service.change.getCountByStatus(tender.id, filter.status.checkNo);// await ctx.service.change.pendingDatas(tender.id, ctx.session.sessionUser.accountId);
 
             const codeRule = tender.c_rule ? JSON.parse(tender.c_rule) : [];
             for (const rule of codeRule) {
@@ -80,6 +82,7 @@ module.exports = app => {
                         const s = '0000000000';
                         rule.preview = s.substr(s.length - rule.format);
                         break;
+                    default: break;
                 }
             }
 
@@ -91,9 +94,10 @@ module.exports = app => {
                 pageInfo,
                 changes,
                 filter,
-                status: status,
+                status,
                 codeRule,
                 auditConst: audit.flow,
+                changeConst,
                 ruleType: codeRuleConst.ruleType.change,
                 ruleConst: codeRuleConst.measure,
                 tenderMenu: this.menu.tenderMenu,
@@ -107,7 +111,7 @@ module.exports = app => {
          * 变更管理 页面 (Get)
          *
          * @param {Object} ctx - egg全局变量
-         * @returns {Promise<void>}
+         * @return {void}
          */
         async index(ctx) {
             try {
@@ -121,8 +125,8 @@ module.exports = app => {
 
         /**
          *
-         * @param ctx
-         * @returns {Promise<void>}
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
          */
         async newCode(ctx) {
             const responseData = {
@@ -152,10 +156,11 @@ module.exports = app => {
                             break;
                         case codeRuleConst.measure.ruleType.addNo:
                             let s = '0000000000';
-                            const count = rule.start + await ctx.service.change.count({tid: tenderId});
+                            const count = rule.start + await ctx.service.change.count({ tid: tenderId });
                             s = s + count;
                             code.push(s.substr(s.length - rule.format));
                             break;
+                        default: break;
                     }
                 }
                 responseData.data = code.join('');
@@ -171,7 +176,7 @@ module.exports = app => {
          * 新增变更 (Post)
          *
          * @param {Object} ctx - egg全局变量
-         * @returns {Promise<void>}
+         * @return {void}
          */
         async add(ctx) {
             try {
@@ -195,8 +200,8 @@ module.exports = app => {
 
         /**
          * 变更管理 状态筛选 页面 (Get)
-         * @param ctx
-         * @returns {Promise<void>}
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
          */
         async status(ctx) {
             try {
@@ -204,7 +209,7 @@ module.exports = app => {
                 await this._filterChanges(ctx, status);
             } catch (err) {
                 this.logger.error(err);
-                ctx.redirect('/tender/'+ ctx.params.id +'/change');
+                ctx.redirect('/tender/' + ctx.params.id + '/change');
             }
         }
 
@@ -212,23 +217,27 @@ module.exports = app => {
          * 变更信息 页面 (Get)
          *
          * @param {Object} ctx - egg全局变量
-         * @returns {Promise<void>}
+         * @return {void}
          */
         async info(ctx) {
             try {
                 const whiteList = this.ctx.app.config.multipart.whitelist;
-                const tid = ctx.session.sessionUser.tenderId !== undefined ? ctx.session.sessionUser.tenderId : ctx.params.id;
-                const tender = await this.service.tender.getDataById(tid);
-                const change = await ctx.service.change.getDataByCondition({cid: ctx.params.cid});
+                const tenderid = ctx.session.sessionUser.tenderId !== undefined ? ctx.session.sessionUser.tenderId : ctx.params.id;
+                const tender = await this.service.tender.getDataById(tenderid);
+                const change = await ctx.service.change.getDataByCondition({ cid: ctx.params.cid });
 
                 // 后台判断当前人查看info状态
                 const auditStatus = await ctx.service.changeAudit.getStatusByChange(change);
 
-                // 获取公司列表
-                const companyList = await ctx.service.changeCompany.getAllDataByCondition({ tid: tid });
-
                 // 获取附件列表
-                const attList = await ctx.service.changeAtt.getAllDataByCondition({ cid: ctx.params.cid });
+                const attList = await ctx.service.changeAtt.getAllDataByCondition({ where: { cid: ctx.params.cid } });
+
+                // 根据auditStatus获取审批人列表
+                // const auditList = await ctx.service.changeAudit.getListByStatus(change, auditStatus);
+                const auditList = [];
+
+                // 获取已选清单
+                const changeList = await ctx.service.changeAuditList.getAllDataByCondition({ where: { cid: ctx.params.cid } });
 
                 const renderData = {
                     uid: ctx.session.sessionUser.accountId,
@@ -237,71 +246,82 @@ module.exports = app => {
                     changeConst,
                     auditStatus,
                     auditConst: audit.flow,
-                    companyList,
                     attList,
                     whiteList,
+                    auditList,
+                    changeList,
                 };
-                await this.layout('change/info.ejs', renderData, 'change/info_modal.ejs');
-            } catch (err) {
-                this.log(err);
-                ctx.redirect('/tender/'+ ctx.params.id +'/change');
-            }
-        }
-
-        /**
-         * 变更清单 页面 (Get)
-         *
-         * @param {Object} ctx - egg全局变量
-         * @returns {Promise<void>}
-         */
-        async bills(ctx) {
-            try {
-                const tender = ctx.tenderData;
-                const tenderList = ctx.tenderList;
-                const change = await ctx.service.change.getDataByCondition({cid: ctx.params.cid});
-
-                const renderData = {
-                    tender,
-                    tenderList,
-                    change,
-                };
-                await this.layout('change/bills.ejs', renderData, 'change/info_modal.ejs');
+                // 根据auditStatus状态获取的不同的数据
+                if (auditStatus === 1 || auditStatus === 2) {
+                    // 获取标准清单列表
+                    const dealBillList = await ctx.service.dealBills.getAllDataByCondition({ where: { tender_id: tenderid } });
+                    renderData.dealBillList = dealBillList;
+                    renderData.changeUnits = ctx.tender.info.precision;
+                    renderData.tpUnit = ctx.tender.info.decimal.tp;
+                    // 根据清单获取提交数据和计算总金额
+                    const changeListData = [];
+                    const changeWhiteListData = [];
+                    let ototalCost = 0;
+                    let ctotalCost = 0;
+                    for (const cl of changeList) {
+                        const cLArray = [
+                            cl.code,
+                            cl.name,
+                            cl.unit,
+                            cl.unit_price,
+                            cl.oamount,
+                            cl.camount,
+                            cl.detail,
+                            cl.lid,
+                        ];
+                        ototalCost += ctx.helper.accMul(cl.unit_price, cl.oamount);
+                        ctotalCost += ctx.helper.accMul(cl.unit_price, cl.camount);
+                        if (cl.lid !== 0) {
+                            changeListData.push(cLArray.join(';'));
+                        } else {
+                            changeWhiteListData.push(cLArray.join(';'));
+                        }
+                    }
+                    renderData.changeListData = changeListData.join('^_^');
+                    renderData.changeWhiteListData = changeWhiteListData.join('^_^');
+                    renderData.ototalCost = ototalCost;
+                    renderData.ctotalCost = ctotalCost;
+
+                    // 获取公司列表
+                    const companyList = await ctx.service.changeCompany.getAllDataByCondition({ where: { tid: tenderid } });
+                    renderData.companyList = companyList;
+                }
 
+                await this.layout('change/info.ejs', renderData, 'change/info_modal.ejs');
             } catch (err) {
                 this.log(err);
-                ctx.redirect('/change');
+                ctx.redirect('/tender/' + ctx.params.id + '/change');
             }
         }
 
         /**
-         * 附件 页面 (Get)
-         *
+         * 变更令上报和保存
          * @param {Object} ctx - egg全局变量
-         * @returns {Promise<void>}
+         * @return {void}
          */
-        async file(ctx) {
+        async save(ctx) {
             try {
-                const tender = ctx.tenderData;
-                const tenderList = ctx.tenderList;
-                const change = await ctx.service.change.getDataByCondition({cid: ctx.params.cid});
-
-                const renderData = {
-                    tender,
-                    tenderList,
-                    change,
-                };
-                await this.layout('change/file.ejs', renderData, 'change/file_modal.ejs');
-
+                // console.log(ctx.request.body);
+                const result = await ctx.service.change.save(ctx.request.body, ctx.session.sessionUser.tenderId);
+                if (!result) {
+                    throw '上报失败';
+                }
+                ctx.redirect('/tender/' + ctx.session.sessionUser.tenderId + '/change');
             } catch (err) {
                 this.log(err);
-                ctx.redirect('/change');
+                ctx.redirect('/tender/' + ctx.session.sessionUser.tenderId + '/change/' + ctx.request.body.cid + '/info');
             }
         }
 
         /**
          * 变更公司管理
-         * @param ctx
-         * @return {Promise.<void>}
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
          */
         async updateCompany(ctx) {
             const responseData = {
@@ -326,8 +346,8 @@ module.exports = app => {
 
         /**
          * 上传附件
-         * @param ctx
-         * @return {Promise<void>}
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
          */
         async uploadFile(ctx) {
             const responseData = {
@@ -350,15 +370,15 @@ module.exports = app => {
                 // 保存文件
                 await ctx.helper.saveStreamFile(stream, path.join(this.app.baseDir, dirName, fileName));
                 // 保存数据到att表
-                let fileData = {
-                    in_time : create_time,
+                const fileData = {
+                    in_time: create_time,
                     filename: fileInfo.name,
                     fileext: fileInfo.ext,
                     filesize: stream.fields.size,
                     filepath: path.join(dirName, fileName),
                 };
                 const result = await ctx.service.changeAtt.save(stream.fields, fileData, ctx.session.sessionUser.accountId);
-                if (!(result.effectRows = 1)) {
+                if (result.effectRows !== 1) {
                     throw '导入数据库保存失败';
                 }
                 fileData.in_time = moment(create_time * 1000).format('YYYY-MM-DD');
@@ -378,8 +398,8 @@ module.exports = app => {
 
         /**
          * 下载附件
-         * @param ctx
-         * @return {Promise<void>}
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
          */
         async downloadFile(ctx) {
             const id = ctx.params.id;
@@ -390,8 +410,8 @@ module.exports = app => {
                         const fileName = path.join(this.app.baseDir, fileInfo.filepath);
                         ctx.response.set({
                             'Content-Type': 'application/octet-stream',
-                            'Content-Disposition': `attachment; filename=` + fileInfo.filename + fileInfo.fileext,
-                            'Content-Length': fileInfo.filesize
+                            'Content-Disposition': 'attachment; filename=' + fileInfo.filename + fileInfo.fileext,
+                            'Content-Length': fileInfo.filesize,
                         });
                         ctx.body = await fs.createReadStream(fileName);
                     } else {
@@ -406,8 +426,8 @@ module.exports = app => {
 
         /**
          * 删除附件
-         * @param ctx
-         * @return {Promise<void>}
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
          */
         async deleteFile(ctx) {
             const responseData = {
@@ -444,4 +464,4 @@ module.exports = app => {
     }
 
     return ChangeController;
-};
+};

+ 10 - 5
app/controller/project_controller.js

@@ -117,10 +117,10 @@ module.exports = app => {
         }
 
         /**
-         * 查询项目的参与人
+         * 查询项目或企业(暂无)的参与人
          *
-         * @param ctx
-         * @returns {Promise<void>}
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
          */
         async searchAccount(ctx) {
             const projectId = ctx.session.sessionProject.id;
@@ -138,8 +138,13 @@ module.exports = app => {
                 if (!name || name === '') {
                     throw '请输入姓名进行检索';
                 }
-
-                responseData.data = await ctx.service.projectAccount.getAccountInfoByName(projectId, name);
+                // 查询方式,默认为只查询一个
+                const type = data.type;
+                if (type === undefined) {
+                    responseData.data = await ctx.service.projectAccount.getAccountInfoByName(projectId, name);
+                } else if (type === 'more') {
+                    responseData.data = await ctx.service.projectAccount.getAccountInfoByName(projectId, name, 1);
+                }
             } catch (err) {
                 responseData.err = 1;
                 responseData.msg = err.toString();

+ 94 - 6
app/extend/helper.js

@@ -57,19 +57,107 @@ module.exports = {
 
     /**
      * 字节转换
-     * @param bytes 字节
-     * @return {string} 大小
+     * @param {number} bytes - 字节
+     * @return {string} - 大小
      */
     bytesToSize(bytes) {
         if (bytes === 0) return '0 B';
-        let k = 1024;
-        const sizes = ['B','KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
-        let i = Math.floor(Math.log(bytes) / Math.log(k));
-        //return (bytes / Math.pow(k, i)) + ' ' + sizes[i];
+        const k = 1024;
+        const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
+        const i = Math.floor(Math.log(bytes) / Math.log(k));
+        // return (bytes / Math.pow(k, i)) + ' ' + sizes[i];
         return (bytes / Math.pow(k, i)).toPrecision(3) + ' ' + sizes[i];
     },
 
     /**
+     * 浮点乘法计算
+     * @param {number} arg1 - 乘数
+     * @param {number} arg2 - 被乘数
+     * @return {string} - 结果
+     */
+    accMul(arg1, arg2) {
+        let m = 0;
+        const s1 = arg1.toString();
+        const s2 = arg2.toString();
+        try {
+            m += s1.split('.')[1] !== undefined ? s1.split('.')[1].length : 0;
+        } catch (e) {
+            throw e;
+        }
+        try {
+            m += s2.split('.')[1] !== undefined ? s2.split('.')[1].length : 0;
+        } catch (e) {
+            throw e;
+        }
+        return Number(s1.replace('.', '')) * Number(s2.replace('.', '')) / Math.pow(10, m);
+    },
+
+    // 四舍五入或末尾加零,实现类似php的 sprintf("%.".decimal."f", val);
+    roundNum(val, decimals) {
+        if (val !== '') {
+            val = parseFloat(val);
+            if (decimals < 1) {
+                val = (Math.round(val)).toString();
+            } else {
+                let num = val.toString();
+                if (num.lastIndexOf('.') === -1) {
+                    num += '.';
+                    num += this.makezero(decimals);
+                    val = num;
+                } else {
+                    const valdecimals = num.split('.')[1].length;
+                    if (parseInt(valdecimals) < parseInt(decimals)) {
+                        num += this.makezero(parseInt(decimals) - parseInt(valdecimals));
+                        val = num;
+                    } else if (parseInt(valdecimals) > parseInt(decimals)) {
+                        val = parseFloat(val) !== 0 ? Math.round(this.accMul(val, this.makemultiple(decimals))) / this.makemultiple(decimals) : this.makedecimalzero(decimals);
+                        let num = val.toString();
+                        if (num.lastIndexOf('.') === -1) {
+                            num += '.';
+                            num += this.makezero(decimals);
+                            val = num;
+                        } else {
+                            const valdecimals = num.split('.')[1].length;
+                            if (parseInt(valdecimals) < parseInt(decimals)) {
+                                num += this.makezero(parseInt(decimals) - parseInt(valdecimals));
+                                val = num;
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        return val;
+    },
+
+    // 生成num位的0
+    makezero(num) {
+        const arr = new Array(num);
+        for (let i = 0; i < num; i++) {
+            arr[i] = 0;
+        }
+        return arr.join('');
+    },
+
+    // 生成num位的10倍数
+    makemultiple(num) {
+        return Math.pow(10, parseInt(num));
+    },
+
+    // 根据单位获取小数位数
+    findDecimal(unit) {
+        let value = 2;
+        const changeUnits = this.ctx.tender.info.precision;
+        for (const d in changeUnits) {
+            if (changeUnits[d].unit !== undefined && changeUnits[d].unit === unit) {
+                value = changeUnits[d].value;
+                break;
+            }
+        }
+        return value;
+    },
+
+    /**
      * 显示排序符号
      *
      * @param {String} field - 字段名称

+ 187 - 0
app/public/css/datatable/dataTables.bootstrap.css

@@ -0,0 +1,187 @@
+table.dataTable {
+  clear: both;
+  margin-top: 6px !important;
+  margin-bottom: 6px !important;
+  max-width: none !important;
+  border-collapse: separate !important;
+}
+table.dataTable td,
+table.dataTable th {
+  -webkit-box-sizing: content-box;
+  box-sizing: content-box;
+}
+table.dataTable td.dataTables_empty,
+table.dataTable th.dataTables_empty {
+  text-align: center;
+}
+table.dataTable.nowrap th,
+table.dataTable.nowrap td {
+  white-space: nowrap;
+}
+
+div.dataTables_wrapper div.dataTables_length label {
+  font-weight: normal;
+  text-align: left;
+  white-space: nowrap;
+}
+div.dataTables_wrapper div.dataTables_length select {
+  width: 75px;
+  display: inline-block;
+}
+div.dataTables_wrapper div.dataTables_filter {
+  text-align: right;
+}
+div.dataTables_wrapper div.dataTables_filter label {
+  font-weight: normal;
+  white-space: nowrap;
+  text-align: left;
+}
+div.dataTables_wrapper div.dataTables_filter input {
+  margin-left: 0.5em;
+  display: inline-block;
+  width: auto;
+}
+div.dataTables_wrapper div.dataTables_info {
+  padding-top: 8px;
+  white-space: nowrap;
+}
+div.dataTables_wrapper div.dataTables_paginate {
+  margin: 0;
+  white-space: nowrap;
+  text-align: right;
+}
+div.dataTables_wrapper div.dataTables_paginate ul.pagination {
+  margin: 2px 0;
+  white-space: nowrap;
+}
+div.dataTables_wrapper div.dataTables_processing {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 200px;
+  margin-left: -100px;
+  margin-top: -26px;
+  text-align: center;
+  padding: 1em 0;
+}
+
+table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting,
+table.dataTable thead > tr > td.sorting_asc,
+table.dataTable thead > tr > td.sorting_desc,
+table.dataTable thead > tr > td.sorting {
+  padding-right: 30px;
+}
+table.dataTable thead > tr > th:active,
+table.dataTable thead > tr > td:active {
+  outline: none;
+}
+table.dataTable thead .sorting,
+table.dataTable thead .sorting_asc,
+table.dataTable thead .sorting_desc,
+table.dataTable thead .sorting_asc_disabled,
+table.dataTable thead .sorting_desc_disabled {
+  cursor: pointer;
+  position: relative;
+}
+table.dataTable thead .sorting:after,
+table.dataTable thead .sorting_asc:after,
+table.dataTable thead .sorting_desc:after,
+table.dataTable thead .sorting_asc_disabled:after,
+table.dataTable thead .sorting_desc_disabled:after {
+  position: absolute;
+  bottom: 8px;
+  right: 8px;
+  display: block;
+  font-family: 'Glyphicons Halflings';
+  opacity: 0.5;
+}
+table.dataTable thead .sorting:after {
+  opacity: 0.2;
+  content: "\e150";
+  /* sort */
+}
+table.dataTable thead .sorting_asc:after {
+  content: "\e155";
+  /* sort-by-attributes */
+}
+table.dataTable thead .sorting_desc:after {
+  content: "\e156";
+  /* sort-by-attributes-alt */
+}
+table.dataTable thead .sorting_asc_disabled:after,
+table.dataTable thead .sorting_desc_disabled:after {
+  color: #eee;
+}
+
+div.dataTables_scrollHead table.dataTable {
+  margin-bottom: 0 !important;
+}
+
+div.dataTables_scrollBody > table {
+  border-top: none;
+  margin-top: 0 !important;
+  margin-bottom: 0 !important;
+}
+div.dataTables_scrollBody > table > thead .sorting:after,
+div.dataTables_scrollBody > table > thead .sorting_asc:after,
+div.dataTables_scrollBody > table > thead .sorting_desc:after {
+  display: none;
+}
+div.dataTables_scrollBody > table > tbody > tr:first-child > th,
+div.dataTables_scrollBody > table > tbody > tr:first-child > td {
+  border-top: none;
+}
+
+div.dataTables_scrollFoot > .dataTables_scrollFootInner {
+  box-sizing: content-box;
+}
+div.dataTables_scrollFoot > .dataTables_scrollFootInner > table {
+  margin-top: 0 !important;
+  border-top: none;
+}
+
+@media screen and (max-width: 767px) {
+  div.dataTables_wrapper div.dataTables_length,
+  div.dataTables_wrapper div.dataTables_filter,
+  div.dataTables_wrapper div.dataTables_info,
+  div.dataTables_wrapper div.dataTables_paginate {
+    text-align: center;
+  }
+}
+table.dataTable.table-condensed > thead > tr > th {
+  padding-right: 20px;
+}
+table.dataTable.table-condensed .sorting:after,
+table.dataTable.table-condensed .sorting_asc:after,
+table.dataTable.table-condensed .sorting_desc:after {
+  top: 6px;
+  right: 6px;
+}
+
+table.table-bordered.dataTable th,
+table.table-bordered.dataTable td {
+  border-left-width: 0;
+}
+table.table-bordered.dataTable th:last-child, table.table-bordered.dataTable th:last-child,
+table.table-bordered.dataTable td:last-child,
+table.table-bordered.dataTable td:last-child {
+  border-right-width: 0;
+}
+table.table-bordered.dataTable tbody th,
+table.table-bordered.dataTable tbody td {
+  border-bottom-width: 0;
+}
+
+div.dataTables_scrollHead table.table-bordered {
+  border-bottom-width: 0;
+}
+
+div.table-responsive > div.dataTables_wrapper > div.row {
+  margin: 0;
+}
+div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:first-child {
+  padding-left: 0;
+}
+div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:last-child {
+  padding-right: 0;
+}

Plik diff jest za duży
+ 1 - 0
app/public/css/datatable/dataTables.bootstrap.min.css


+ 206 - 0
app/public/css/datatable/dataTables.bootstrap4.css

@@ -0,0 +1,206 @@
+table.dataTable {
+  clear: both;
+  margin-top: 6px !important;
+  margin-bottom: 6px !important;
+  max-width: none !important;
+  border-collapse: separate !important;
+  border-spacing: 0;
+}
+table.dataTable td,
+table.dataTable th {
+  -webkit-box-sizing: content-box;
+  box-sizing: content-box;
+}
+table.dataTable td.dataTables_empty,
+table.dataTable th.dataTables_empty {
+  text-align: center;
+}
+table.dataTable.nowrap th,
+table.dataTable.nowrap td {
+  white-space: nowrap;
+}
+
+div.dataTables_wrapper div.dataTables_length label {
+  font-weight: normal;
+  text-align: left;
+  white-space: nowrap;
+}
+div.dataTables_wrapper div.dataTables_length select {
+  width: auto;
+  display: inline-block;
+}
+div.dataTables_wrapper div.dataTables_filter {
+  text-align: right;
+}
+div.dataTables_wrapper div.dataTables_filter label {
+  font-weight: normal;
+  white-space: nowrap;
+  text-align: left;
+}
+div.dataTables_wrapper div.dataTables_filter input {
+  margin-left: 0.5em;
+  display: inline-block;
+  width: auto;
+}
+div.dataTables_wrapper div.dataTables_info {
+  padding-top: 0.85em;
+  white-space: nowrap;
+}
+div.dataTables_wrapper div.dataTables_paginate {
+  margin: 0;
+  white-space: nowrap;
+  text-align: right;
+}
+div.dataTables_wrapper div.dataTables_paginate ul.pagination {
+  margin: 2px 0;
+  white-space: nowrap;
+  justify-content: flex-end;
+}
+div.dataTables_wrapper div.dataTables_processing {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 200px;
+  margin-left: -100px;
+  margin-top: -26px;
+  text-align: center;
+  padding: 1em 0;
+}
+
+table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting,
+table.dataTable thead > tr > td.sorting_asc,
+table.dataTable thead > tr > td.sorting_desc,
+table.dataTable thead > tr > td.sorting {
+  padding-right: 30px;
+}
+table.dataTable thead > tr > th:active,
+table.dataTable thead > tr > td:active {
+  outline: none;
+}
+table.dataTable thead .sorting,
+table.dataTable thead .sorting_asc,
+table.dataTable thead .sorting_desc,
+table.dataTable thead .sorting_asc_disabled,
+table.dataTable thead .sorting_desc_disabled {
+  cursor: pointer;
+  position: relative;
+}
+table.dataTable thead .sorting:before, table.dataTable thead .sorting:after,
+table.dataTable thead .sorting_asc:before,
+table.dataTable thead .sorting_asc:after,
+table.dataTable thead .sorting_desc:before,
+table.dataTable thead .sorting_desc:after,
+table.dataTable thead .sorting_asc_disabled:before,
+table.dataTable thead .sorting_asc_disabled:after,
+table.dataTable thead .sorting_desc_disabled:before,
+table.dataTable thead .sorting_desc_disabled:after {
+  position: absolute;
+  bottom: 0.9em;
+  display: block;
+  opacity: 0.3;
+}
+table.dataTable thead .sorting:before,
+table.dataTable thead .sorting_asc:before,
+table.dataTable thead .sorting_desc:before,
+table.dataTable thead .sorting_asc_disabled:before,
+table.dataTable thead .sorting_desc_disabled:before {
+  right: 1em;
+  content: "\2191";
+}
+table.dataTable thead .sorting:after,
+table.dataTable thead .sorting_asc:after,
+table.dataTable thead .sorting_desc:after,
+table.dataTable thead .sorting_asc_disabled:after,
+table.dataTable thead .sorting_desc_disabled:after {
+  right: 0.5em;
+  content: "\2193";
+}
+table.dataTable thead .sorting_asc:before,
+table.dataTable thead .sorting_desc:after {
+  opacity: 1;
+}
+table.dataTable thead .sorting_asc_disabled:before,
+table.dataTable thead .sorting_desc_disabled:after {
+  opacity: 0;
+}
+
+div.dataTables_scrollHead table.dataTable {
+  margin-bottom: 0 !important;
+}
+
+div.dataTables_scrollBody table {
+  border-top: none;
+  margin-top: 0 !important;
+  margin-bottom: 0 !important;
+}
+div.dataTables_scrollBody table thead .sorting:before,
+div.dataTables_scrollBody table thead .sorting_asc:before,
+div.dataTables_scrollBody table thead .sorting_desc:before,
+div.dataTables_scrollBody table thead .sorting:after,
+div.dataTables_scrollBody table thead .sorting_asc:after,
+div.dataTables_scrollBody table thead .sorting_desc:after {
+  display: none;
+}
+div.dataTables_scrollBody table tbody tr:first-child th,
+div.dataTables_scrollBody table tbody tr:first-child td {
+  border-top: none;
+}
+
+div.dataTables_scrollFoot > .dataTables_scrollFootInner {
+  box-sizing: content-box;
+}
+div.dataTables_scrollFoot > .dataTables_scrollFootInner > table {
+  margin-top: 0 !important;
+  border-top: none;
+}
+
+@media screen and (max-width: 767px) {
+  div.dataTables_wrapper div.dataTables_length,
+  div.dataTables_wrapper div.dataTables_filter,
+  div.dataTables_wrapper div.dataTables_info,
+  div.dataTables_wrapper div.dataTables_paginate {
+    text-align: center;
+  }
+}
+table.dataTable.table-sm > thead > tr > th {
+  padding-right: 20px;
+}
+table.dataTable.table-sm .sorting:before,
+table.dataTable.table-sm .sorting_asc:before,
+table.dataTable.table-sm .sorting_desc:before {
+  top: 5px;
+  right: 0.85em;
+}
+table.dataTable.table-sm .sorting:after,
+table.dataTable.table-sm .sorting_asc:after,
+table.dataTable.table-sm .sorting_desc:after {
+  top: 5px;
+}
+
+table.table-bordered.dataTable th,
+table.table-bordered.dataTable td {
+  border-left-width: 0;
+}
+table.table-bordered.dataTable th:last-child, table.table-bordered.dataTable th:last-child,
+table.table-bordered.dataTable td:last-child,
+table.table-bordered.dataTable td:last-child {
+  border-right-width: 0;
+}
+table.table-bordered.dataTable tbody th,
+table.table-bordered.dataTable tbody td {
+  border-bottom-width: 0;
+}
+
+div.dataTables_scrollHead table.table-bordered {
+  border-bottom-width: 0;
+}
+
+div.table-responsive > div.dataTables_wrapper > div.row {
+  margin: 0;
+}
+div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:first-child {
+  padding-left: 0;
+}
+div.table-responsive > div.dataTables_wrapper > div.row > div[class^="col-"]:last-child {
+  padding-right: 0;
+}

Plik diff jest za duży
+ 1 - 0
app/public/css/datatable/dataTables.bootstrap4.min.css


+ 118 - 0
app/public/css/datatable/dataTables.foundation.css

@@ -0,0 +1,118 @@
+table.dataTable {
+  clear: both;
+  margin: 0.5em 0 !important;
+  max-width: none !important;
+  width: 100%;
+}
+table.dataTable td,
+table.dataTable th {
+  -webkit-box-sizing: content-box;
+  box-sizing: content-box;
+}
+table.dataTable td.dataTables_empty,
+table.dataTable th.dataTables_empty {
+  text-align: center;
+}
+table.dataTable.nowrap th, table.dataTable.nowrap td {
+  white-space: nowrap;
+}
+
+div.dataTables_wrapper {
+  position: relative;
+}
+div.dataTables_wrapper div.dataTables_length label {
+  float: left;
+  text-align: left;
+  margin-bottom: 0;
+}
+div.dataTables_wrapper div.dataTables_length select {
+  width: 75px;
+  margin-bottom: 0;
+}
+div.dataTables_wrapper div.dataTables_filter label {
+  float: right;
+  margin-bottom: 0;
+}
+div.dataTables_wrapper div.dataTables_filter input {
+  display: inline-block !important;
+  width: auto !important;
+  margin-bottom: 0;
+  margin-left: 0.5em;
+}
+div.dataTables_wrapper div.dataTables_info {
+  padding-top: 2px;
+}
+div.dataTables_wrapper div.dataTables_paginate {
+  float: right;
+  margin: 0;
+}
+div.dataTables_wrapper div.dataTables_processing {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 200px;
+  margin-left: -100px;
+  margin-top: -26px;
+  text-align: center;
+  padding: 1rem 0;
+}
+
+table.dataTable thead > tr > th.sorting_asc, table.dataTable thead > tr > th.sorting_desc, table.dataTable thead > tr > th.sorting,
+table.dataTable thead > tr > td.sorting_asc,
+table.dataTable thead > tr > td.sorting_desc,
+table.dataTable thead > tr > td.sorting {
+  padding-right: 1.5rem;
+}
+table.dataTable thead > tr > th:active,
+table.dataTable thead > tr > td:active {
+  outline: none;
+}
+table.dataTable thead .sorting,
+table.dataTable thead .sorting_asc,
+table.dataTable thead .sorting_desc,
+table.dataTable thead .sorting_asc_disabled,
+table.dataTable thead .sorting_desc_disabled {
+  cursor: pointer;
+}
+table.dataTable thead .sorting,
+table.dataTable thead .sorting_asc,
+table.dataTable thead .sorting_desc,
+table.dataTable thead .sorting_asc_disabled,
+table.dataTable thead .sorting_desc_disabled {
+  background-repeat: no-repeat;
+  background-position: center right;
+}
+table.dataTable thead .sorting {
+  background-image: url("../images/sort_both.png");
+}
+table.dataTable thead .sorting_asc {
+  background-image: url("../images/sort_asc.png");
+}
+table.dataTable thead .sorting_desc {
+  background-image: url("../images/sort_desc.png");
+}
+table.dataTable thead .sorting_asc_disabled {
+  background-image: url("../images/sort_asc_disabled.png");
+}
+table.dataTable thead .sorting_desc_disabled {
+  background-image: url("../images/sort_desc_disabled.png");
+}
+
+div.dataTables_scrollHead table {
+  margin-bottom: 0 !important;
+}
+
+div.dataTables_scrollBody table {
+  border-top: none;
+  margin-top: 0 !important;
+  margin-bottom: 0 !important;
+}
+div.dataTables_scrollBody table tbody tr:first-child th,
+div.dataTables_scrollBody table tbody tr:first-child td {
+  border-top: none;
+}
+
+div.dataTables_scrollFoot table {
+  margin-top: 0 !important;
+  border-top: none;
+}

Plik diff jest za duży
+ 1 - 0
app/public/css/datatable/dataTables.foundation.min.css


+ 481 - 0
app/public/css/datatable/dataTables.jqueryui.css

@@ -0,0 +1,481 @@
+/*
+ * Table styles
+ */
+table.dataTable {
+  width: 100%;
+  margin: 0 auto;
+  clear: both;
+  border-collapse: separate;
+  border-spacing: 0;
+  /*
+   * Header and footer styles
+   */
+  /*
+   * Body styles
+   */
+}
+table.dataTable thead th,
+table.dataTable tfoot th {
+  font-weight: bold;
+}
+table.dataTable thead th,
+table.dataTable thead td {
+  padding: 10px 18px;
+}
+table.dataTable thead th:active,
+table.dataTable thead td:active {
+  outline: none;
+}
+table.dataTable tfoot th,
+table.dataTable tfoot td {
+  padding: 10px 18px 6px 18px;
+}
+table.dataTable tbody tr {
+  background-color: #ffffff;
+}
+table.dataTable tbody tr.selected {
+  background-color: #B0BED9;
+}
+table.dataTable tbody th,
+table.dataTable tbody td {
+  padding: 8px 10px;
+}
+table.dataTable.row-border tbody th, table.dataTable.row-border tbody td, table.dataTable.display tbody th, table.dataTable.display tbody td {
+  border-top: 1px solid #ddd;
+}
+table.dataTable.row-border tbody tr:first-child th,
+table.dataTable.row-border tbody tr:first-child td, table.dataTable.display tbody tr:first-child th,
+table.dataTable.display tbody tr:first-child td {
+  border-top: none;
+}
+table.dataTable.cell-border tbody th, table.dataTable.cell-border tbody td {
+  border-top: 1px solid #ddd;
+  border-right: 1px solid #ddd;
+}
+table.dataTable.cell-border tbody tr th:first-child,
+table.dataTable.cell-border tbody tr td:first-child {
+  border-left: 1px solid #ddd;
+}
+table.dataTable.cell-border tbody tr:first-child th,
+table.dataTable.cell-border tbody tr:first-child td {
+  border-top: none;
+}
+table.dataTable.stripe tbody tr.odd, table.dataTable.display tbody tr.odd {
+  background-color: #f9f9f9;
+}
+table.dataTable.stripe tbody tr.odd.selected, table.dataTable.display tbody tr.odd.selected {
+  background-color: #acbad4;
+}
+table.dataTable.hover tbody tr:hover, table.dataTable.display tbody tr:hover {
+  background-color: #f6f6f6;
+}
+table.dataTable.hover tbody tr:hover.selected, table.dataTable.display tbody tr:hover.selected {
+  background-color: #aab7d1;
+}
+table.dataTable.order-column tbody tr > .sorting_1,
+table.dataTable.order-column tbody tr > .sorting_2,
+table.dataTable.order-column tbody tr > .sorting_3, table.dataTable.display tbody tr > .sorting_1,
+table.dataTable.display tbody tr > .sorting_2,
+table.dataTable.display tbody tr > .sorting_3 {
+  background-color: #fafafa;
+}
+table.dataTable.order-column tbody tr.selected > .sorting_1,
+table.dataTable.order-column tbody tr.selected > .sorting_2,
+table.dataTable.order-column tbody tr.selected > .sorting_3, table.dataTable.display tbody tr.selected > .sorting_1,
+table.dataTable.display tbody tr.selected > .sorting_2,
+table.dataTable.display tbody tr.selected > .sorting_3 {
+  background-color: #acbad5;
+}
+table.dataTable.display tbody tr.odd > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd > .sorting_1 {
+  background-color: #f1f1f1;
+}
+table.dataTable.display tbody tr.odd > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd > .sorting_2 {
+  background-color: #f3f3f3;
+}
+table.dataTable.display tbody tr.odd > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd > .sorting_3 {
+  background-color: whitesmoke;
+}
+table.dataTable.display tbody tr.odd.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_1 {
+  background-color: #a6b4cd;
+}
+table.dataTable.display tbody tr.odd.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_2 {
+  background-color: #a8b5cf;
+}
+table.dataTable.display tbody tr.odd.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_3 {
+  background-color: #a9b7d1;
+}
+table.dataTable.display tbody tr.even > .sorting_1, table.dataTable.order-column.stripe tbody tr.even > .sorting_1 {
+  background-color: #fafafa;
+}
+table.dataTable.display tbody tr.even > .sorting_2, table.dataTable.order-column.stripe tbody tr.even > .sorting_2 {
+  background-color: #fcfcfc;
+}
+table.dataTable.display tbody tr.even > .sorting_3, table.dataTable.order-column.stripe tbody tr.even > .sorting_3 {
+  background-color: #fefefe;
+}
+table.dataTable.display tbody tr.even.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_1 {
+  background-color: #acbad5;
+}
+table.dataTable.display tbody tr.even.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_2 {
+  background-color: #aebcd6;
+}
+table.dataTable.display tbody tr.even.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_3 {
+  background-color: #afbdd8;
+}
+table.dataTable.display tbody tr:hover > .sorting_1, table.dataTable.order-column.hover tbody tr:hover > .sorting_1 {
+  background-color: #eaeaea;
+}
+table.dataTable.display tbody tr:hover > .sorting_2, table.dataTable.order-column.hover tbody tr:hover > .sorting_2 {
+  background-color: #ececec;
+}
+table.dataTable.display tbody tr:hover > .sorting_3, table.dataTable.order-column.hover tbody tr:hover > .sorting_3 {
+  background-color: #efefef;
+}
+table.dataTable.display tbody tr:hover.selected > .sorting_1, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_1 {
+  background-color: #a2aec7;
+}
+table.dataTable.display tbody tr:hover.selected > .sorting_2, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_2 {
+  background-color: #a3b0c9;
+}
+table.dataTable.display tbody tr:hover.selected > .sorting_3, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_3 {
+  background-color: #a5b2cb;
+}
+table.dataTable.no-footer {
+  border-bottom: 1px solid #111;
+}
+table.dataTable.nowrap th, table.dataTable.nowrap td {
+  white-space: nowrap;
+}
+table.dataTable.compact thead th,
+table.dataTable.compact thead td {
+  padding: 4px 17px 4px 4px;
+}
+table.dataTable.compact tfoot th,
+table.dataTable.compact tfoot td {
+  padding: 4px;
+}
+table.dataTable.compact tbody th,
+table.dataTable.compact tbody td {
+  padding: 4px;
+}
+table.dataTable th.dt-left,
+table.dataTable td.dt-left {
+  text-align: left;
+}
+table.dataTable th.dt-center,
+table.dataTable td.dt-center,
+table.dataTable td.dataTables_empty {
+  text-align: center;
+}
+table.dataTable th.dt-right,
+table.dataTable td.dt-right {
+  text-align: right;
+}
+table.dataTable th.dt-justify,
+table.dataTable td.dt-justify {
+  text-align: justify;
+}
+table.dataTable th.dt-nowrap,
+table.dataTable td.dt-nowrap {
+  white-space: nowrap;
+}
+table.dataTable thead th.dt-head-left,
+table.dataTable thead td.dt-head-left,
+table.dataTable tfoot th.dt-head-left,
+table.dataTable tfoot td.dt-head-left {
+  text-align: left;
+}
+table.dataTable thead th.dt-head-center,
+table.dataTable thead td.dt-head-center,
+table.dataTable tfoot th.dt-head-center,
+table.dataTable tfoot td.dt-head-center {
+  text-align: center;
+}
+table.dataTable thead th.dt-head-right,
+table.dataTable thead td.dt-head-right,
+table.dataTable tfoot th.dt-head-right,
+table.dataTable tfoot td.dt-head-right {
+  text-align: right;
+}
+table.dataTable thead th.dt-head-justify,
+table.dataTable thead td.dt-head-justify,
+table.dataTable tfoot th.dt-head-justify,
+table.dataTable tfoot td.dt-head-justify {
+  text-align: justify;
+}
+table.dataTable thead th.dt-head-nowrap,
+table.dataTable thead td.dt-head-nowrap,
+table.dataTable tfoot th.dt-head-nowrap,
+table.dataTable tfoot td.dt-head-nowrap {
+  white-space: nowrap;
+}
+table.dataTable tbody th.dt-body-left,
+table.dataTable tbody td.dt-body-left {
+  text-align: left;
+}
+table.dataTable tbody th.dt-body-center,
+table.dataTable tbody td.dt-body-center {
+  text-align: center;
+}
+table.dataTable tbody th.dt-body-right,
+table.dataTable tbody td.dt-body-right {
+  text-align: right;
+}
+table.dataTable tbody th.dt-body-justify,
+table.dataTable tbody td.dt-body-justify {
+  text-align: justify;
+}
+table.dataTable tbody th.dt-body-nowrap,
+table.dataTable tbody td.dt-body-nowrap {
+  white-space: nowrap;
+}
+
+table.dataTable,
+table.dataTable th,
+table.dataTable td {
+  box-sizing: content-box;
+}
+
+/*
+ * Control feature layout
+ */
+.dataTables_wrapper {
+  position: relative;
+  clear: both;
+  *zoom: 1;
+  zoom: 1;
+}
+.dataTables_wrapper .dataTables_length {
+  float: left;
+}
+.dataTables_wrapper .dataTables_filter {
+  float: right;
+  text-align: right;
+}
+.dataTables_wrapper .dataTables_filter input {
+  margin-left: 0.5em;
+}
+.dataTables_wrapper .dataTables_info {
+  clear: both;
+  float: left;
+  padding-top: 0.755em;
+}
+.dataTables_wrapper .dataTables_paginate {
+  float: right;
+  text-align: right;
+  padding-top: 0.25em;
+}
+.dataTables_wrapper .dataTables_paginate .paginate_button {
+  box-sizing: border-box;
+  display: inline-block;
+  min-width: 1.5em;
+  padding: 0.5em 1em;
+  margin-left: 2px;
+  text-align: center;
+  text-decoration: none !important;
+  cursor: pointer;
+  *cursor: hand;
+  color: #333 !important;
+  border: 1px solid transparent;
+  border-radius: 2px;
+}
+.dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
+  color: #333 !important;
+  border: 1px solid #979797;
+  background-color: white;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(100%, #dcdcdc));
+  /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, white 0%, #dcdcdc 100%);
+  /* Chrome10+,Safari5.1+ */
+  background: -moz-linear-gradient(top, white 0%, #dcdcdc 100%);
+  /* FF3.6+ */
+  background: -ms-linear-gradient(top, white 0%, #dcdcdc 100%);
+  /* IE10+ */
+  background: -o-linear-gradient(top, white 0%, #dcdcdc 100%);
+  /* Opera 11.10+ */
+  background: linear-gradient(to bottom, white 0%, #dcdcdc 100%);
+  /* W3C */
+}
+.dataTables_wrapper .dataTables_paginate .paginate_button.disabled, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active {
+  cursor: default;
+  color: #666 !important;
+  border: 1px solid transparent;
+  background: transparent;
+  box-shadow: none;
+}
+.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
+  color: white !important;
+  border: 1px solid #111;
+  background-color: #585858;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));
+  /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, #585858 0%, #111 100%);
+  /* Chrome10+,Safari5.1+ */
+  background: -moz-linear-gradient(top, #585858 0%, #111 100%);
+  /* FF3.6+ */
+  background: -ms-linear-gradient(top, #585858 0%, #111 100%);
+  /* IE10+ */
+  background: -o-linear-gradient(top, #585858 0%, #111 100%);
+  /* Opera 11.10+ */
+  background: linear-gradient(to bottom, #585858 0%, #111 100%);
+  /* W3C */
+}
+.dataTables_wrapper .dataTables_paginate .paginate_button:active {
+  outline: none;
+  background-color: #2b2b2b;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));
+  /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
+  /* Chrome10+,Safari5.1+ */
+  background: -moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
+  /* FF3.6+ */
+  background: -ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
+  /* IE10+ */
+  background: -o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
+  /* Opera 11.10+ */
+  background: linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);
+  /* W3C */
+  box-shadow: inset 0 0 3px #111;
+}
+.dataTables_wrapper .dataTables_paginate .ellipsis {
+  padding: 0 1em;
+}
+.dataTables_wrapper .dataTables_processing {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 100%;
+  height: 40px;
+  margin-left: -50%;
+  margin-top: -25px;
+  padding-top: 20px;
+  text-align: center;
+  font-size: 1.2em;
+  background-color: white;
+  background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(25%, rgba(255, 255, 255, 0.9)), color-stop(75%, rgba(255, 255, 255, 0.9)), color-stop(100%, rgba(255, 255, 255, 0)));
+  background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+  background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+  background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+  background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+  background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+}
+.dataTables_wrapper .dataTables_length,
+.dataTables_wrapper .dataTables_filter,
+.dataTables_wrapper .dataTables_info,
+.dataTables_wrapper .dataTables_processing,
+.dataTables_wrapper .dataTables_paginate {
+  color: #333;
+}
+.dataTables_wrapper .dataTables_scroll {
+  clear: both;
+}
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody {
+  *margin-top: -1px;
+  -webkit-overflow-scrolling: touch;
+}
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > th, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > td, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > th, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > td {
+  vertical-align: middle;
+}
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > th > div.dataTables_sizing,
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > td > div.dataTables_sizing, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > th > div.dataTables_sizing,
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > td > div.dataTables_sizing {
+  height: 0;
+  overflow: hidden;
+  margin: 0 !important;
+  padding: 0 !important;
+}
+.dataTables_wrapper.no-footer .dataTables_scrollBody {
+  border-bottom: 1px solid #111;
+}
+.dataTables_wrapper.no-footer div.dataTables_scrollHead table.dataTable,
+.dataTables_wrapper.no-footer div.dataTables_scrollBody > table {
+  border-bottom: none;
+}
+.dataTables_wrapper:after {
+  visibility: hidden;
+  display: block;
+  content: "";
+  clear: both;
+  height: 0;
+}
+
+@media screen and (max-width: 767px) {
+  .dataTables_wrapper .dataTables_info,
+  .dataTables_wrapper .dataTables_paginate {
+    float: none;
+    text-align: center;
+  }
+  .dataTables_wrapper .dataTables_paginate {
+    margin-top: 0.5em;
+  }
+}
+@media screen and (max-width: 640px) {
+  .dataTables_wrapper .dataTables_length,
+  .dataTables_wrapper .dataTables_filter {
+    float: none;
+    text-align: center;
+  }
+  .dataTables_wrapper .dataTables_filter {
+    margin-top: 0.5em;
+  }
+}
+table.dataTable thead th div.DataTables_sort_wrapper {
+  position: relative;
+}
+table.dataTable thead th div.DataTables_sort_wrapper span {
+  position: absolute;
+  top: 50%;
+  margin-top: -8px;
+  right: -18px;
+}
+table.dataTable thead th.ui-state-default,
+table.dataTable tfoot th.ui-state-default {
+  border-left-width: 0;
+}
+table.dataTable thead th.ui-state-default:first-child,
+table.dataTable tfoot th.ui-state-default:first-child {
+  border-left-width: 1px;
+}
+
+/*
+ * Control feature layout
+ */
+.dataTables_wrapper .dataTables_paginate .fg-button {
+  box-sizing: border-box;
+  display: inline-block;
+  min-width: 1.5em;
+  padding: 0.5em;
+  margin-left: 2px;
+  text-align: center;
+  text-decoration: none !important;
+  cursor: pointer;
+  *cursor: hand;
+  border: 1px solid transparent;
+}
+.dataTables_wrapper .dataTables_paginate .fg-button:active {
+  outline: none;
+}
+.dataTables_wrapper .dataTables_paginate .fg-button:first-child {
+  border-top-left-radius: 3px;
+  border-bottom-left-radius: 3px;
+}
+.dataTables_wrapper .dataTables_paginate .fg-button:last-child {
+  border-top-right-radius: 3px;
+  border-bottom-right-radius: 3px;
+}
+.dataTables_wrapper .ui-widget-header {
+  font-weight: normal;
+}
+.dataTables_wrapper .ui-toolbar {
+  padding: 8px;
+}
+.dataTables_wrapper.no-footer .dataTables_scrollBody {
+  border-bottom: none;
+}
+.dataTables_wrapper .dataTables_length,
+.dataTables_wrapper .dataTables_filter,
+.dataTables_wrapper .dataTables_info,
+.dataTables_wrapper .dataTables_processing,
+.dataTables_wrapper .dataTables_paginate {
+  color: inherit;
+}

Plik diff jest za duży
+ 1 - 0
app/public/css/datatable/dataTables.jqueryui.min.css


+ 102 - 0
app/public/css/datatable/dataTables.semanticui.css

@@ -0,0 +1,102 @@
+/*
+ * Styling for DataTables with Semantic UI
+ */
+table.dataTable.table {
+  margin: 0;
+}
+table.dataTable.table thead th,
+table.dataTable.table thead td {
+  position: relative;
+}
+table.dataTable.table thead th.sorting, table.dataTable.table thead th.sorting_asc, table.dataTable.table thead th.sorting_desc,
+table.dataTable.table thead td.sorting,
+table.dataTable.table thead td.sorting_asc,
+table.dataTable.table thead td.sorting_desc {
+  padding-right: 20px;
+}
+table.dataTable.table thead th.sorting:after, table.dataTable.table thead th.sorting_asc:after, table.dataTable.table thead th.sorting_desc:after,
+table.dataTable.table thead td.sorting:after,
+table.dataTable.table thead td.sorting_asc:after,
+table.dataTable.table thead td.sorting_desc:after {
+  position: absolute;
+  top: 12px;
+  right: 8px;
+  display: block;
+  font-family: Icons;
+}
+table.dataTable.table thead th.sorting:after,
+table.dataTable.table thead td.sorting:after {
+  content: "\f0dc";
+  color: #ddd;
+  font-size: 0.8em;
+}
+table.dataTable.table thead th.sorting_asc:after,
+table.dataTable.table thead td.sorting_asc:after {
+  content: "\f0de";
+}
+table.dataTable.table thead th.sorting_desc:after,
+table.dataTable.table thead td.sorting_desc:after {
+  content: "\f0dd";
+}
+table.dataTable.table td,
+table.dataTable.table th {
+  -webkit-box-sizing: content-box;
+  box-sizing: content-box;
+}
+table.dataTable.table td.dataTables_empty,
+table.dataTable.table th.dataTables_empty {
+  text-align: center;
+}
+table.dataTable.table.nowrap th,
+table.dataTable.table.nowrap td {
+  white-space: nowrap;
+}
+
+div.dataTables_wrapper div.dataTables_length select {
+  vertical-align: middle;
+  min-height: 2.7142em;
+}
+div.dataTables_wrapper div.dataTables_length .ui.selection.dropdown {
+  min-width: 0;
+}
+div.dataTables_wrapper div.dataTables_filter span.input {
+  margin-left: 0.5em;
+}
+div.dataTables_wrapper div.dataTables_info {
+  padding-top: 13px;
+  white-space: nowrap;
+}
+div.dataTables_wrapper div.dataTables_processing {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 200px;
+  margin-left: -100px;
+  text-align: center;
+}
+div.dataTables_wrapper div.row.dt-table {
+  padding: 0;
+}
+div.dataTables_wrapper div.dataTables_scrollHead table.dataTable {
+  border-bottom-right-radius: 0;
+  border-bottom-left-radius: 0;
+  border-bottom: none;
+}
+div.dataTables_wrapper div.dataTables_scrollBody thead .sorting:after,
+div.dataTables_wrapper div.dataTables_scrollBody thead .sorting_asc:after,
+div.dataTables_wrapper div.dataTables_scrollBody thead .sorting_desc:after {
+  display: none;
+}
+div.dataTables_wrapper div.dataTables_scrollBody table.dataTable {
+  border-radius: 0;
+  border-top: none;
+  border-bottom-width: 0;
+}
+div.dataTables_wrapper div.dataTables_scrollBody table.dataTable.no-footer {
+  border-bottom-width: 1px;
+}
+div.dataTables_wrapper div.dataTables_scrollFoot table.dataTable {
+  border-top-right-radius: 0;
+  border-top-left-radius: 0;
+  border-top: none;
+}

Plik diff jest za duży
+ 1 - 0
app/public/css/datatable/dataTables.semanticui.min.css


+ 48 - 0
app/public/css/datatable/fixedColumns.bootstrap.css

@@ -0,0 +1,48 @@
+table.DTFC_Cloned tr {
+  background-color: white;
+  margin-bottom: 0;
+}
+
+div.DTFC_LeftHeadWrapper table,
+div.DTFC_RightHeadWrapper table {
+  border-bottom: none !important;
+  margin-bottom: 0 !important;
+  background-color: white;
+}
+
+div.DTFC_LeftBodyWrapper table,
+div.DTFC_RightBodyWrapper table {
+  border-top: none;
+  margin: 0 !important;
+}
+div.DTFC_LeftBodyWrapper table thead .sorting:after,
+div.DTFC_LeftBodyWrapper table thead .sorting_asc:after,
+div.DTFC_LeftBodyWrapper table thead .sorting_desc:after,
+div.DTFC_LeftBodyWrapper table thead .sorting:after,
+div.DTFC_LeftBodyWrapper table thead .sorting_asc:after,
+div.DTFC_LeftBodyWrapper table thead .sorting_desc:after,
+div.DTFC_RightBodyWrapper table thead .sorting:after,
+div.DTFC_RightBodyWrapper table thead .sorting_asc:after,
+div.DTFC_RightBodyWrapper table thead .sorting_desc:after,
+div.DTFC_RightBodyWrapper table thead .sorting:after,
+div.DTFC_RightBodyWrapper table thead .sorting_asc:after,
+div.DTFC_RightBodyWrapper table thead .sorting_desc:after {
+  display: none;
+}
+div.DTFC_LeftBodyWrapper table tbody tr:first-child th,
+div.DTFC_LeftBodyWrapper table tbody tr:first-child td,
+div.DTFC_RightBodyWrapper table tbody tr:first-child th,
+div.DTFC_RightBodyWrapper table tbody tr:first-child td {
+  border-top: none;
+}
+
+div.DTFC_LeftFootWrapper table,
+div.DTFC_RightFootWrapper table {
+  border-top: none;
+  margin-top: 0 !important;
+  background-color: white;
+}
+
+div.DTFC_Blocker {
+  background-color: white;
+}

Plik diff jest za duży
+ 1 - 0
app/public/css/datatable/fixedColumns.bootstrap.min.css


+ 52 - 0
app/public/css/datatable/fixedColumns.bootstrap4.css

@@ -0,0 +1,52 @@
+table.DTFC_Cloned tr {
+  background-color: white;
+  margin-bottom: 0;
+}
+
+div.DTFC_LeftHeadWrapper table,
+div.DTFC_RightHeadWrapper table {
+  border-bottom: none !important;
+  margin-bottom: 0 !important;
+  background-color: white;
+}
+
+div.DTFC_LeftBodyWrapper table,
+div.DTFC_RightBodyWrapper table {
+  border-top: none;
+  margin: 0 !important;
+}
+div.DTFC_LeftBodyWrapper table thead .sorting:after,
+div.DTFC_LeftBodyWrapper table thead .sorting_asc:after,
+div.DTFC_LeftBodyWrapper table thead .sorting_desc:after,
+div.DTFC_LeftBodyWrapper table thead .sorting:after,
+div.DTFC_LeftBodyWrapper table thead .sorting_asc:after,
+div.DTFC_LeftBodyWrapper table thead .sorting_desc:after,
+div.DTFC_RightBodyWrapper table thead .sorting:after,
+div.DTFC_RightBodyWrapper table thead .sorting_asc:after,
+div.DTFC_RightBodyWrapper table thead .sorting_desc:after,
+div.DTFC_RightBodyWrapper table thead .sorting:after,
+div.DTFC_RightBodyWrapper table thead .sorting_asc:after,
+div.DTFC_RightBodyWrapper table thead .sorting_desc:after {
+  display: none;
+}
+div.DTFC_LeftBodyWrapper table tbody tr:first-child th,
+div.DTFC_LeftBodyWrapper table tbody tr:first-child td,
+div.DTFC_RightBodyWrapper table tbody tr:first-child th,
+div.DTFC_RightBodyWrapper table tbody tr:first-child td {
+  border-top: none;
+}
+
+div.DTFC_LeftFootWrapper table,
+div.DTFC_RightFootWrapper table {
+  border-top: none;
+  margin-top: 0 !important;
+  background-color: white;
+}
+
+div.DTFC_Blocker {
+  background-color: white;
+}
+
+table.dataTable.table-striped.DTFC_Cloned tbody {
+  background-color: white;
+}

Plik diff jest za duży
+ 1 - 0
app/public/css/datatable/fixedColumns.bootstrap4.min.css


+ 18 - 0
app/public/css/datatable/fixedColumns.dataTables.css

@@ -0,0 +1,18 @@
+table.DTFC_Cloned thead,
+table.DTFC_Cloned tfoot {
+  background-color: white;
+}
+
+div.DTFC_Blocker {
+  background-color: white;
+}
+
+div.DTFC_LeftWrapper table.dataTable,
+div.DTFC_RightWrapper table.dataTable {
+  margin-bottom: 0;
+  z-index: 2;
+}
+div.DTFC_LeftWrapper table.dataTable.no-footer,
+div.DTFC_RightWrapper table.dataTable.no-footer {
+  border-bottom: none;
+}

+ 1 - 0
app/public/css/datatable/fixedColumns.dataTables.min.css

@@ -0,0 +1 @@
+table.DTFC_Cloned thead,table.DTFC_Cloned tfoot{background-color:white}div.DTFC_Blocker{background-color:white}div.DTFC_LeftWrapper table.dataTable,div.DTFC_RightWrapper table.dataTable{margin-bottom:0;z-index:2}div.DTFC_LeftWrapper table.dataTable.no-footer,div.DTFC_RightWrapper table.dataTable.no-footer{border-bottom:none}

+ 31 - 0
app/public/css/datatable/fixedColumns.foundation.css

@@ -0,0 +1,31 @@
+div.DTFC_LeftHeadWrapper table,
+div.DTFC_LeftBodyWrapper table,
+div.DTFC_LeftFootWrapper table {
+  border-right-width: 0;
+}
+
+div.DTFC_RightHeadWrapper table,
+div.DTFC_RightBodyWrapper table,
+div.DTFC_RightFootWrapper table {
+  border-left-width: 0;
+}
+
+div.DTFC_LeftHeadWrapper table,
+div.DTFC_RightHeadWrapper table {
+  margin-bottom: 0 !important;
+}
+
+div.DTFC_LeftBodyWrapper table,
+div.DTFC_RightBodyWrapper table {
+  border-top: none;
+  margin: 0 !important;
+}
+
+div.DTFC_LeftFootWrapper table,
+div.DTFC_RightFootWrapper table {
+  margin-top: 0 !important;
+}
+
+div.DTFC_Blocker {
+  background-color: white;
+}

Plik diff jest za duży
+ 1 - 0
app/public/css/datatable/fixedColumns.foundation.min.css


+ 12 - 0
app/public/css/datatable/fixedColumns.jqueryui.css

@@ -0,0 +1,12 @@
+div.DTFC_LeftWrapper table.dataTable,
+div.DTFC_RightWrapper table.dataTable {
+  z-index: 2;
+}
+div.DTFC_LeftWrapper table.dataTable.no-footer,
+div.DTFC_RightWrapper table.dataTable.no-footer {
+  border-bottom: none;
+}
+
+div.DTFC_Blocker {
+  background-color: white;
+}

+ 1 - 0
app/public/css/datatable/fixedColumns.jqueryui.min.css

@@ -0,0 +1 @@
+div.DTFC_LeftWrapper table.dataTable,div.DTFC_RightWrapper table.dataTable{z-index:2}div.DTFC_LeftWrapper table.dataTable.no-footer,div.DTFC_RightWrapper table.dataTable.no-footer{border-bottom:none}div.DTFC_Blocker{background-color:white}

+ 40 - 0
app/public/css/datatable/fixedColumns.semanticui.css

@@ -0,0 +1,40 @@
+div.DTFC_LeftWrapper table.ui.table.dataTable {
+  border-right: none;
+}
+
+div.DTFC_RightWrapper table.ui.table.dataTable {
+  border-left: none;
+}
+
+div.DTFC_Blocker {
+  background-color: white;
+}
+
+div.DTFC_LeftWrapper table.dataTable,
+div.DTFC_RightWrapper table.dataTable {
+  z-index: 2;
+}
+
+div.DTFC_LeftHeadWrapper table.ui.table.dataTable,
+div.DTFC_RightHeadWrapper table.ui.table.dataTable {
+  border-bottom: none;
+}
+
+div.DTFC_LeftBodyWrapper table.ui.table.dataTable,
+div.DTFC_RightBodyWrapper table.ui.table.dataTable {
+  border-top: none;
+}
+div.DTFC_LeftBodyWrapper table.ui.table.dataTable thead .sorting:after,
+div.DTFC_LeftBodyWrapper table.ui.table.dataTable thead .sorting_asc:after,
+div.DTFC_LeftBodyWrapper table.ui.table.dataTable thead .sorting_desc:after,
+div.DTFC_LeftBodyWrapper table.ui.table.dataTable thead .sorting:after,
+div.DTFC_LeftBodyWrapper table.ui.table.dataTable thead .sorting_asc:after,
+div.DTFC_LeftBodyWrapper table.ui.table.dataTable thead .sorting_desc:after,
+div.DTFC_RightBodyWrapper table.ui.table.dataTable thead .sorting:after,
+div.DTFC_RightBodyWrapper table.ui.table.dataTable thead .sorting_asc:after,
+div.DTFC_RightBodyWrapper table.ui.table.dataTable thead .sorting_desc:after,
+div.DTFC_RightBodyWrapper table.ui.table.dataTable thead .sorting:after,
+div.DTFC_RightBodyWrapper table.ui.table.dataTable thead .sorting_asc:after,
+div.DTFC_RightBodyWrapper table.ui.table.dataTable thead .sorting_desc:after {
+  display: none;
+}

Plik diff jest za duży
+ 1 - 0
app/public/css/datatable/fixedColumns.semanticui.min.css


+ 99 - 0
app/public/css/datatable/fixedheadertable.css

@@ -0,0 +1,99 @@
+/*!
+* jquery.fixedHeaderTable. The jQuery fixedHeaderTable plugin
+*
+* Copyright (c) 2011 Mark Malek
+* http://fixedheadertable.com
+*
+* Licensed under MIT
+* http://www.opensource.org/licenses/mit-license.php
+* 
+* http://docs.jquery.com/Plugins/Authoring
+* jQuery authoring guidelines
+*
+* Launch  : October 2009
+* Version : 1.3
+* Released: May 9th, 2011
+*
+* 
+* all CSS sizing (width,height) is done in pixels (px)
+*/
+
+/* @group Reset */
+
+.fht-table,
+.fht-table thead,
+.fht-table tfoot,
+.fht-table tbody,
+.fht-table tr,
+.fht-table th,
+.fht-table td {
+  margin: 0;
+	padding: 0;
+	vertical-align:middle;
+	}
+.fht-table {
+	}
+.fht-table-wrapper,
+.fht-table-wrapper .fht-thead,
+.fht-table-wrapper .fht-tfoot,
+.fht-table-wrapper .fht-fixed-column .fht-tbody,
+.fht-table-wrapper .fht-fixed-body .fht-tbody,
+.fht-table-wrapper .fht-tbody {
+	overflow: hidden;
+
+	position: relative;
+	}
+
+	.fht-table-wrapper .fht-fixed-body .fht-tbody,
+	.fht-table-wrapper .fht-tbody {
+
+	    overflow: auto;
+		}
+
+		.fht-table-wrapper .fht-table .fht-cell {
+
+			overflow: hidden;
+		    height: 1px;
+			}
+	
+	.fht-table-wrapper .fht-fixed-column,
+	.fht-table-wrapper .fht-fixed-body {
+	    top: 0;
+	    left: 0;
+	    position: absolute;
+	    }
+	    
+	.fht-table-wrapper .fht-fixed-column {
+	    z-index: 1;
+	    }
+
+.fancyTable td, .fancyTable th {
+	border: 1px solid #d4d4d4;
+	padding:3px;
+	white-space:nowrap;
+	}
+	.fancyTable td{
+	min-width:60px
+
+	}
+.fancyTable tbody tr th {
+	background-color: #fff;
+	}
+.fancyTable tbody tr td {
+	background-color: #fff;
+	}
+.fancyTable tbody tr.odd td{
+	background: #fff
+	}
+.fancyTable tbody tr th{
+	font-weight: 600;
+	background: #fff
+	}
+.fancyTable thead tr th,
+.fancyTable thead tr td,
+.fancyTable tfoot tr th, 
+.fancyTable tfoot tr td {
+	background: #fff;
+	font-weight: bold;
+	color:#444;
+	}

+ 448 - 0
app/public/css/datatable/jquery.dataTables.css

@@ -0,0 +1,448 @@
+/*
+ * Table styles
+ */
+table.dataTable {
+  width: 100%;
+  margin: 0 auto;
+  clear: both;
+  border-collapse: separate;
+  border-spacing: 0;
+  /*
+   * Header and footer styles
+   */
+  /*
+   * Body styles
+   */
+}
+table.dataTable thead th,
+table.dataTable tfoot th {
+  font-weight: bold;
+}
+table.dataTable thead th,
+table.dataTable thead td {
+  padding: 10px 18px;
+  border-bottom: 1px solid #111;
+}
+table.dataTable thead th:active,
+table.dataTable thead td:active {
+  outline: none;
+}
+table.dataTable tfoot th,
+table.dataTable tfoot td {
+  padding: 10px 18px 6px 18px;
+  border-top: 1px solid #111;
+}
+table.dataTable thead .sorting,
+table.dataTable thead .sorting_asc,
+table.dataTable thead .sorting_desc,
+table.dataTable thead .sorting_asc_disabled,
+table.dataTable thead .sorting_desc_disabled {
+  cursor: pointer;
+  *cursor: hand;
+  background-repeat: no-repeat;
+  background-position: center right;
+}
+table.dataTable thead .sorting {
+  background-image: url("../images/sort_both.png");
+}
+table.dataTable thead .sorting_asc {
+  background-image: url("../images/sort_asc.png");
+}
+table.dataTable thead .sorting_desc {
+  background-image: url("../images/sort_desc.png");
+}
+table.dataTable thead .sorting_asc_disabled {
+  background-image: url("../images/sort_asc_disabled.png");
+}
+table.dataTable thead .sorting_desc_disabled {
+  background-image: url("../images/sort_desc_disabled.png");
+}
+table.dataTable tbody tr {
+  background-color: #ffffff;
+}
+table.dataTable tbody tr.selected {
+  background-color: #B0BED9;
+}
+table.dataTable tbody th,
+table.dataTable tbody td {
+  padding: 8px 10px;
+}
+table.dataTable.row-border tbody th, table.dataTable.row-border tbody td, table.dataTable.display tbody th, table.dataTable.display tbody td {
+  border-top: 1px solid #ddd;
+}
+table.dataTable.row-border tbody tr:first-child th,
+table.dataTable.row-border tbody tr:first-child td, table.dataTable.display tbody tr:first-child th,
+table.dataTable.display tbody tr:first-child td {
+  border-top: none;
+}
+table.dataTable.cell-border tbody th, table.dataTable.cell-border tbody td {
+  border-top: 1px solid #ddd;
+  border-right: 1px solid #ddd;
+}
+table.dataTable.cell-border tbody tr th:first-child,
+table.dataTable.cell-border tbody tr td:first-child {
+  border-left: 1px solid #ddd;
+}
+table.dataTable.cell-border tbody tr:first-child th,
+table.dataTable.cell-border tbody tr:first-child td {
+  border-top: none;
+}
+table.dataTable.stripe tbody tr.odd, table.dataTable.display tbody tr.odd {
+  background-color: #f9f9f9;
+}
+table.dataTable.stripe tbody tr.odd.selected, table.dataTable.display tbody tr.odd.selected {
+  background-color: #acbad4;
+}
+table.dataTable.hover tbody tr:hover, table.dataTable.display tbody tr:hover {
+  background-color: #f6f6f6;
+}
+table.dataTable.hover tbody tr:hover.selected, table.dataTable.display tbody tr:hover.selected {
+  background-color: #aab7d1;
+}
+table.dataTable.order-column tbody tr > .sorting_1,
+table.dataTable.order-column tbody tr > .sorting_2,
+table.dataTable.order-column tbody tr > .sorting_3, table.dataTable.display tbody tr > .sorting_1,
+table.dataTable.display tbody tr > .sorting_2,
+table.dataTable.display tbody tr > .sorting_3 {
+  background-color: #fafafa;
+}
+table.dataTable.order-column tbody tr.selected > .sorting_1,
+table.dataTable.order-column tbody tr.selected > .sorting_2,
+table.dataTable.order-column tbody tr.selected > .sorting_3, table.dataTable.display tbody tr.selected > .sorting_1,
+table.dataTable.display tbody tr.selected > .sorting_2,
+table.dataTable.display tbody tr.selected > .sorting_3 {
+  background-color: #acbad5;
+}
+table.dataTable.display tbody tr.odd > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd > .sorting_1 {
+  background-color: #f1f1f1;
+}
+table.dataTable.display tbody tr.odd > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd > .sorting_2 {
+  background-color: #f3f3f3;
+}
+table.dataTable.display tbody tr.odd > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd > .sorting_3 {
+  background-color: whitesmoke;
+}
+table.dataTable.display tbody tr.odd.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_1 {
+  background-color: #a6b4cd;
+}
+table.dataTable.display tbody tr.odd.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_2 {
+  background-color: #a8b5cf;
+}
+table.dataTable.display tbody tr.odd.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.odd.selected > .sorting_3 {
+  background-color: #a9b7d1;
+}
+table.dataTable.display tbody tr.even > .sorting_1, table.dataTable.order-column.stripe tbody tr.even > .sorting_1 {
+  background-color: #fafafa;
+}
+table.dataTable.display tbody tr.even > .sorting_2, table.dataTable.order-column.stripe tbody tr.even > .sorting_2 {
+  background-color: #fcfcfc;
+}
+table.dataTable.display tbody tr.even > .sorting_3, table.dataTable.order-column.stripe tbody tr.even > .sorting_3 {
+  background-color: #fefefe;
+}
+table.dataTable.display tbody tr.even.selected > .sorting_1, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_1 {
+  background-color: #acbad5;
+}
+table.dataTable.display tbody tr.even.selected > .sorting_2, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_2 {
+  background-color: #aebcd6;
+}
+table.dataTable.display tbody tr.even.selected > .sorting_3, table.dataTable.order-column.stripe tbody tr.even.selected > .sorting_3 {
+  background-color: #afbdd8;
+}
+table.dataTable.display tbody tr:hover > .sorting_1, table.dataTable.order-column.hover tbody tr:hover > .sorting_1 {
+  background-color: #eaeaea;
+}
+table.dataTable.display tbody tr:hover > .sorting_2, table.dataTable.order-column.hover tbody tr:hover > .sorting_2 {
+  background-color: #ececec;
+}
+table.dataTable.display tbody tr:hover > .sorting_3, table.dataTable.order-column.hover tbody tr:hover > .sorting_3 {
+  background-color: #efefef;
+}
+table.dataTable.display tbody tr:hover.selected > .sorting_1, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_1 {
+  background-color: #a2aec7;
+}
+table.dataTable.display tbody tr:hover.selected > .sorting_2, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_2 {
+  background-color: #a3b0c9;
+}
+table.dataTable.display tbody tr:hover.selected > .sorting_3, table.dataTable.order-column.hover tbody tr:hover.selected > .sorting_3 {
+  background-color: #a5b2cb;
+}
+table.dataTable.no-footer {
+  border-bottom: 1px solid #111;
+}
+table.dataTable.nowrap th, table.dataTable.nowrap td {
+  white-space: nowrap;
+}
+table.dataTable.compact thead th,
+table.dataTable.compact thead td {
+  padding: 4px 17px 4px 4px;
+}
+table.dataTable.compact tfoot th,
+table.dataTable.compact tfoot td {
+  padding: 4px;
+}
+table.dataTable.compact tbody th,
+table.dataTable.compact tbody td {
+  padding: 4px;
+}
+table.dataTable th.dt-left,
+table.dataTable td.dt-left {
+  text-align: left;
+}
+table.dataTable th.dt-center,
+table.dataTable td.dt-center,
+table.dataTable td.dataTables_empty {
+  text-align: center;
+}
+table.dataTable th.dt-right,
+table.dataTable td.dt-right {
+  text-align: right;
+}
+table.dataTable th.dt-justify,
+table.dataTable td.dt-justify {
+  text-align: justify;
+}
+table.dataTable th.dt-nowrap,
+table.dataTable td.dt-nowrap {
+  white-space: nowrap;
+}
+table.dataTable thead th.dt-head-left,
+table.dataTable thead td.dt-head-left,
+table.dataTable tfoot th.dt-head-left,
+table.dataTable tfoot td.dt-head-left {
+  text-align: left;
+}
+table.dataTable thead th.dt-head-center,
+table.dataTable thead td.dt-head-center,
+table.dataTable tfoot th.dt-head-center,
+table.dataTable tfoot td.dt-head-center {
+  text-align: center;
+}
+table.dataTable thead th.dt-head-right,
+table.dataTable thead td.dt-head-right,
+table.dataTable tfoot th.dt-head-right,
+table.dataTable tfoot td.dt-head-right {
+  text-align: right;
+}
+table.dataTable thead th.dt-head-justify,
+table.dataTable thead td.dt-head-justify,
+table.dataTable tfoot th.dt-head-justify,
+table.dataTable tfoot td.dt-head-justify {
+  text-align: justify;
+}
+table.dataTable thead th.dt-head-nowrap,
+table.dataTable thead td.dt-head-nowrap,
+table.dataTable tfoot th.dt-head-nowrap,
+table.dataTable tfoot td.dt-head-nowrap {
+  white-space: nowrap;
+}
+table.dataTable tbody th.dt-body-left,
+table.dataTable tbody td.dt-body-left {
+  text-align: left;
+}
+table.dataTable tbody th.dt-body-center,
+table.dataTable tbody td.dt-body-center {
+  text-align: center;
+}
+table.dataTable tbody th.dt-body-right,
+table.dataTable tbody td.dt-body-right {
+  text-align: right;
+}
+table.dataTable tbody th.dt-body-justify,
+table.dataTable tbody td.dt-body-justify {
+  text-align: justify;
+}
+table.dataTable tbody th.dt-body-nowrap,
+table.dataTable tbody td.dt-body-nowrap {
+  white-space: nowrap;
+}
+
+table.dataTable,
+table.dataTable th,
+table.dataTable td {
+  box-sizing: content-box;
+}
+
+/*
+ * Control feature layout
+ */
+.dataTables_wrapper {
+  position: relative;
+  clear: both;
+  *zoom: 1;
+  zoom: 1;
+}
+.dataTables_wrapper .dataTables_length {
+  float: left;
+}
+.dataTables_wrapper .dataTables_filter {
+  float: right;
+  text-align: right;
+}
+.dataTables_wrapper .dataTables_filter input {
+  margin-left: 0.5em;
+}
+.dataTables_wrapper .dataTables_info {
+  clear: both;
+  float: left;
+  padding-top: 0.755em;
+}
+.dataTables_wrapper .dataTables_paginate {
+  float: right;
+  text-align: right;
+  padding-top: 0.25em;
+}
+.dataTables_wrapper .dataTables_paginate .paginate_button {
+  box-sizing: border-box;
+  display: inline-block;
+  min-width: 1.5em;
+  padding: 0.5em 1em;
+  margin-left: 2px;
+  text-align: center;
+  text-decoration: none !important;
+  cursor: pointer;
+  *cursor: hand;
+  color: #333 !important;
+  border: 1px solid transparent;
+  border-radius: 2px;
+}
+.dataTables_wrapper .dataTables_paginate .paginate_button.current, .dataTables_wrapper .dataTables_paginate .paginate_button.current:hover {
+  color: #333 !important;
+  border: 1px solid #979797;
+  background-color: white;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, white), color-stop(100%, #dcdcdc));
+  /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, white 0%, #dcdcdc 100%);
+  /* Chrome10+,Safari5.1+ */
+  background: -moz-linear-gradient(top, white 0%, #dcdcdc 100%);
+  /* FF3.6+ */
+  background: -ms-linear-gradient(top, white 0%, #dcdcdc 100%);
+  /* IE10+ */
+  background: -o-linear-gradient(top, white 0%, #dcdcdc 100%);
+  /* Opera 11.10+ */
+  background: linear-gradient(to bottom, white 0%, #dcdcdc 100%);
+  /* W3C */
+}
+.dataTables_wrapper .dataTables_paginate .paginate_button.disabled, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:hover, .dataTables_wrapper .dataTables_paginate .paginate_button.disabled:active {
+  cursor: default;
+  color: #666 !important;
+  border: 1px solid transparent;
+  background: transparent;
+  box-shadow: none;
+}
+.dataTables_wrapper .dataTables_paginate .paginate_button:hover {
+  color: white !important;
+  border: 1px solid #111;
+  background-color: #585858;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #585858), color-stop(100%, #111));
+  /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, #585858 0%, #111 100%);
+  /* Chrome10+,Safari5.1+ */
+  background: -moz-linear-gradient(top, #585858 0%, #111 100%);
+  /* FF3.6+ */
+  background: -ms-linear-gradient(top, #585858 0%, #111 100%);
+  /* IE10+ */
+  background: -o-linear-gradient(top, #585858 0%, #111 100%);
+  /* Opera 11.10+ */
+  background: linear-gradient(to bottom, #585858 0%, #111 100%);
+  /* W3C */
+}
+.dataTables_wrapper .dataTables_paginate .paginate_button:active {
+  outline: none;
+  background-color: #2b2b2b;
+  background: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #2b2b2b), color-stop(100%, #0c0c0c));
+  /* Chrome,Safari4+ */
+  background: -webkit-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
+  /* Chrome10+,Safari5.1+ */
+  background: -moz-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
+  /* FF3.6+ */
+  background: -ms-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
+  /* IE10+ */
+  background: -o-linear-gradient(top, #2b2b2b 0%, #0c0c0c 100%);
+  /* Opera 11.10+ */
+  background: linear-gradient(to bottom, #2b2b2b 0%, #0c0c0c 100%);
+  /* W3C */
+  box-shadow: inset 0 0 3px #111;
+}
+.dataTables_wrapper .dataTables_paginate .ellipsis {
+  padding: 0 1em;
+}
+.dataTables_wrapper .dataTables_processing {
+  position: absolute;
+  top: 50%;
+  left: 50%;
+  width: 100%;
+  height: 40px;
+  margin-left: -50%;
+  margin-top: -25px;
+  padding-top: 20px;
+  text-align: center;
+  font-size: 1.2em;
+  background-color: white;
+  background: -webkit-gradient(linear, left top, right top, color-stop(0%, rgba(255, 255, 255, 0)), color-stop(25%, rgba(255, 255, 255, 0.9)), color-stop(75%, rgba(255, 255, 255, 0.9)), color-stop(100%, rgba(255, 255, 255, 0)));
+  background: -webkit-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+  background: -moz-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+  background: -ms-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+  background: -o-linear-gradient(left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+  background: linear-gradient(to right, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 0.9) 25%, rgba(255, 255, 255, 0.9) 75%, rgba(255, 255, 255, 0) 100%);
+}
+.dataTables_wrapper .dataTables_length,
+.dataTables_wrapper .dataTables_filter,
+.dataTables_wrapper .dataTables_info,
+.dataTables_wrapper .dataTables_processing,
+.dataTables_wrapper .dataTables_paginate {
+  color: #333;
+}
+.dataTables_wrapper .dataTables_scroll {
+  clear: both;
+}
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody {
+  *margin-top: -1px;
+  -webkit-overflow-scrolling: touch;
+}
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > th, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > td, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > th, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > td {
+  vertical-align: middle;
+}
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > th > div.dataTables_sizing,
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > thead > tr > td > div.dataTables_sizing, .dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > th > div.dataTables_sizing,
+.dataTables_wrapper .dataTables_scroll div.dataTables_scrollBody > table > tbody > tr > td > div.dataTables_sizing {
+  height: 0;
+  overflow: hidden;
+  margin: 0 !important;
+  padding: 0 !important;
+}
+.dataTables_wrapper.no-footer .dataTables_scrollBody {
+  border-bottom: 1px solid #111;
+}
+.dataTables_wrapper.no-footer div.dataTables_scrollHead table.dataTable,
+.dataTables_wrapper.no-footer div.dataTables_scrollBody > table {
+  border-bottom: none;
+}
+.dataTables_wrapper:after {
+  visibility: hidden;
+  display: block;
+  content: "";
+  clear: both;
+  height: 0;
+}
+
+@media screen and (max-width: 767px) {
+  .dataTables_wrapper .dataTables_info,
+  .dataTables_wrapper .dataTables_paginate {
+    float: none;
+    text-align: center;
+  }
+  .dataTables_wrapper .dataTables_paginate {
+    margin-top: 0.5em;
+  }
+}
+@media screen and (max-width: 640px) {
+  .dataTables_wrapper .dataTables_length,
+  .dataTables_wrapper .dataTables_filter {
+    float: none;
+    text-align: center;
+  }
+  .dataTables_wrapper .dataTables_filter {
+    margin-top: 0.5em;
+  }
+}

Plik diff jest za duży
+ 1 - 0
app/public/css/datatable/jquery.dataTables.min.css


+ 18 - 0
app/public/css/datatable/tablecloth.css

@@ -0,0 +1,18 @@
+/* 
+
+	TableCloth	
+	by Alen Grakalic, brought to you by cssglobe.com
+	
+*/
+
+/* general styles */
+
+table{width:100%;border-collapse:collapse;}
+th, td{text-align:left;padding:3px;border:1px solid #ddd;font-size:12px}
+th {border-bottom:1px solid #aaa;border-right:1px solid #aaa}
+th{background:#f5f5f5;color:#333;font-weight:normal}
+td{background:#fff;}
+thead th{text-align:center;padding:0 5px}
+tr:hover td{background:#fffaf2}
+tr:hover th{background:#ffe7bd}
+tr td:hover{background:#ffeed1}

+ 81 - 0
app/public/js/change_calculation.js

@@ -0,0 +1,81 @@
+//本js引入是为了浮点小数运算结果不精确bug的办法,来源: http://blog.csdn.net/yao_jing/article/details/50778011
+
+//除法函数,用来得到精确的除法结果
+//说明:javascript的除法结果会有误差,在两个浮点数相除的时候会比较明显。这个函数返回较为精确的除法结果。
+//调用:accDiv(arg1,arg2)
+//返回值:arg1除以arg2的精确结果
+function accDiv(arg1,arg2){
+    var t1=0,t2=0,r1,r2;
+    try{t1=arg1.toString().split(".")[1].length}catch(e){}
+    try{t2=arg2.toString().split(".")[1].length}catch(e){}
+    with(Math){
+        r1=Number(arg1.toString().replace(".",""));
+        r2=Number(arg2.toString().replace(".",""));
+        return (r1/r2)*pow(10,t2-t1);
+    }
+}
+//给Number类型增加一个div方法,调用起来更加方便。
+Number.prototype.div = function (arg){
+    return accDiv(this, arg);
+};
+//乘法函数,用来得到精确的乘法结果
+//说明:javascript的乘法结果会有误差,在两个浮点数相乘的时候会比较明显。这个函数返回较为精确的乘法结果。
+//调用:accMul(arg1,arg2)
+//返回值:arg1乘以arg2的精确结果
+function accMul(arg1,arg2)
+{
+    var m=0,s1=arg1.toString(),s2=arg2.toString();
+    try{m+=s1.split(".")[1].length}catch(e){}
+    try{m+=s2.split(".")[1].length}catch(e){}
+    return Number(s1.replace(".",""))*Number(s2.replace(".",""))/Math.pow(10,m);
+}
+//给Number类型增加一个mul方法,调用起来更加方便。
+Number.prototype.mul = function (arg){
+    return accMul(arg, this);
+};
+//加法函数,用来得到精确的加法结果
+//说明:javascript的加法结果会有误差,在两个浮点数相加的时候会比较明显。这个函数返回较为精确的加法结果。
+//调用:accAdd(arg1,arg2)
+//返回值:arg1加上arg2的精确结果
+function accAdd(arg1,arg2){
+    var r1,r2,m,c;
+    try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}
+    try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}
+    c=Math.abs(r1-r2);
+    m=Math.pow(10,Math.max(r1,r2));
+    if(c>0){
+        var cm=Math.pow(10,c);
+        if(r1>r2){
+            arg1=Number(arg1.toString().replace(".",""));
+            arg2=Number(arg2.toString().replace(".",""))*cm;
+        }else{
+            arg1=Number(arg1.toString().replace(".",""))*cm;
+            arg2=Number(arg2.toString().replace(".",""));
+        }
+    } else {
+        arg1=Number(arg1.toString().replace(".",""));
+        arg2=Number(arg2.toString().replace(".",""));
+    }
+    return (arg1+arg2)/m;
+    //return (arg1*m+arg2*m)/m;
+}
+//给Number类型增加一个add方法,调用起来更加方便。
+Number.prototype.add = function (arg){
+    return accAdd(arg,this);
+};
+//减法函数
+function accSub(arg1,arg2){
+    var r1,r2,m,n;
+    try{r1=arg1.toString().split(".")[1].length}catch(e){r1=0}
+    try{r2=arg2.toString().split(".")[1].length}catch(e){r2=0}
+    m=Math.pow(10,Math.max(r1,r2));
+    //last modify by deeka
+    //动态控制精度长度
+    n=(r1>=r2)?r1:r2;
+    return ((arg2*m-arg1*m)/m).toFixed(n);
+}
+///给number类增加一个sub方法,调用起来更加方便
+Number.prototype.sub = function (arg){
+    return accSub(arg,this);
+
+};

+ 49 - 1
app/public/js/change_detail.js

@@ -8,12 +8,50 @@
  * @version
  */
 
+$.event.special.valuechange = {
+    teardown: function (namespaces) {
+        $(this).unbind('.valuechange');
+    },
+
+    handler: function (e) {
+        $.event.special.valuechange.triggerChanged($(this));
+    },
+
+    add: function (obj) {
+        $(this).on('keyup.valuechange cut.valuechange paste.valuechange input.valuechange', obj.selector, $.event.special.valuechange.handler)
+    },
+
+    triggerChanged: function (element) {
+        var current = element[0].contentEditable === 'true' ? element.html() : element.val()
+            , previous = typeof element.data('previous') === 'undefined' ? element[0].defaultValue : element.data('previous');
+        if (current !== previous) {
+            element.trigger('valuechange', [element.data('previous')]);
+            element.data('previous', current);
+        }
+    }
+};
+
 $(document).ready(() => {
     // tab切换
     $('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
         const tab = $(this).attr('aria-controls');
         $('.show_title').hide();
         $('#'+ tab +'_title').show();
+        if (tab === 'bills' && $('#bills').hasClass('first-bill-pane')) {
+            table = $('#tablelist').removeAttr('width').DataTable({
+                columnDefs: [
+                    { className: 'allwidth1', width: 100, targets: 0 },
+                    { className: 'allwidth2', width: 150, targets: [1,2] },
+                    { className: 'allwidth4', width: 40, targets: 9 },
+                    { className: 'allwidth5', width: 60, targets: 3 },
+                    { className: 'allwidth3',width: 80, targets: '_all' }
+                ],
+                fixedColumns: {
+                    leftColumns: 5
+                }
+            });
+            $('#bills').removeClass('first-bill-pane');
+        }
     });
 
     // 上传附件
@@ -58,6 +96,7 @@ $(document).ready(() => {
 
     });
 
+    // 删除附件
     $('body').on('click', '.delete-file', function () {
         let attid = $(this).data('attid');
         console.log(attid);
@@ -72,5 +111,14 @@ $(document).ready(() => {
                 newsort++;
             });
         });
+    });
+
+    // 变更详情展示和隐藏
+    $('.change-detail-checkbox').on('click', function (e) {
+        if($(e.target).is('label')){
+            return;
+        }
+        let column = table.column(2);
+        column.visible(!column.visible());
     })
-});
+});

+ 517 - 11
app/public/js/change_set.js

@@ -1,7 +1,7 @@
 'use strict';
 
 /**
- * 变更令详细页js
+ * 变更令上报和重新上报功能js
  *
  * @author EllisRan.
  * @date 2018/11/22
@@ -20,23 +20,529 @@ $(document).ready(() => {
             // 上报审批modal
             $('.up-change').show();
             $('.save-change').hide();
-            // 判断清单列表和变更信息是否填写完整
         }
-    })
+    });
 
     // 提交表单
     // 上报时按钮点击
-    $('button[data-sumbit^="_change"]').on('click', function () {
+    $('button[data-sumbit="sumbit_change"]').on('click', function () {
         let category = $(this).data('category');
         if (category === 'save_change') {
             // 保存修改modal
-            $('.up-change').hide();
-            $('.save-change').show();
+            $('#changeStatus').val(2);
+            // 获取auditlist并填入input中
+            getAuditList();
+            if ($('input[name="code"]').val() === '') {
+                toastr.error('申请编号不能为空!');
+                return;
+            }
+            if ($('input[name="name"]').val() === '') {
+                toastr.error('工程名称不能为空!');
+                return;
+            }
+            $('#change_form').submit();
         } else {
             // 上报审批modal
-            $('.up-change').show();
-            $('.save-change').hide();
-            // 判断清单列表和变更信息是否填写完整
+            $('#changeStatus').val(1);
+            getAuditList();
+            let returnFlag = false;
+            // 表单判断
+            if ($('input[name="code"]').val() === '') {
+                toastr.error('申请编号不能为空!');
+                returnFlag = true;
+            }
+            if ($('input[name="name"]').val() === '') {
+                toastr.error('工程名称不能为空!');
+                returnFlag = true;
+            }
+            if ($('textarea[name="content"]').val() === '') {
+                toastr.error('工程变更理由及内容不能为空!');
+                returnFlag = true;
+            }
+            if ($('#change-list').val() === '' && $('#change-whitelist').val() === '') {
+                toastr.error('请添加变更清单!');
+                returnFlag = true;
+            } else {
+                let changeList = [];
+                if ($('#change-list').val() !== '') {
+                    changeList = $('#change-list').val().split('^_^');
+                }
+                let changeWhiteList = [];
+                if ($('#change-whitelist').val() !== '') {
+                    changeWhiteList = $('#change-whitelist').val().split('^_^');
+                }
+                changeList.push.apply(changeList, changeWhiteList);
+                for (const [index, cl] of changeList.entries()) {
+                    const clInfo = cl.split(';');
+                    if (clInfo[0] === '' || clInfo[1] === '' || clInfo[3] === '' || clInfo[4] === '' || clInfo[5] === '') {
+                        toastr.error('变更清单第' + (index+1) + '行未完整填写数据(变更详情可空)');
+                        returnFlag = true;
+                    }
+                }
+            }
+            if ($('#changeaudit').val() === '') {
+                toastr.error('请添加审批流程!');
+                returnFlag = true;
+            }
+            if (returnFlag) {
+                return;
+            }
+            $('#change_form').submit();
+            $(this).attr('disabled', true);
+        }
+    });
+
+    // 搜索用户
+    $('#search_audit_btn').click(function () {
+        const keyword = $('#search_audit_input').val();
+        if (keyword === '') {
+            toastr.error('请输入姓名进行检索!');
+        } else {
+            $('#search_audit_list').html('');
+            const data = { keyword: keyword, type: 'more' };
+            postData('/search/user', data, function (result) {
+                const searchList = result;
+                $('#search_audit_list').html('');
+                if (searchList.length === 0) {
+                    toastr.error('不存在该用户姓名!');
+                } else {
+                    let search_audit_html = '';
+                    for (const s of searchList) {
+                        search_audit_html += '<div class="card border-primary" style="margin-bottom: 5px;">' +
+                            '<div class="card-body">' +
+                            '<h5 class="card-title">' +
+                            '<a class="btn btn-primary btn-sm pull-right add_audit_btn" ' +
+                            'href="javascript:void(0);" data-user="' + s.id + '/%/' + s.name + '/%/' + s.role + '/%/' + s.company + '">添加</a>' + s.name +
+                            '</h5>' +
+                            '<h6 class="card-subtitle mb-2 text-muted">' + s.role + '</h6>' +
+                            '<p class="card-text">' + s.company + '</p>' +
+                            '</div>' +
+                            '</div>';
+                    }
+                    $('#search_audit_list').html(search_audit_html);
+                }
+            });
+        }
+    });
+
+    // 添加到审批流程中
+    $('body').on('click', '.add_audit_btn', function () {
+        const userData = $(this).data('user').split('/%/');
+        // 先判断是否已存在该审批流程的审批人,再添加(不包括上报)
+        let auditListIdData = [];
+        $('#auditList li').each(function () {
+           let aid = $(this).data('auditid');
+           auditListIdData.push(aid);
+        });
+        if (!in_array(auditListIdData, userData[0])) {
+            // 令其它的审批人流程图标转换
+            $('#auditList li i').removeClass('fa-stop-circle').addClass('fa-chevron-circle-down');
+            // 添加新审批人
+            const addhtml = '<li class="list-group-item" data-auditmsg="' + $(this).data('user') + '"' +
+                'data-auditid="' + userData[0] + '" >' +
+                '<a href="javascript:void(0);" class="text-danger pull-right remove_audit_btn">移除</a>' +
+                '<i class="fa fa-stop-circle"></i>' +
+                userData[1] + '<small class="text-muted">' + userData[2] + '</small>' +
+                '</li>';
+            $('#auditList').append(addhtml);
+        } else {
+            toastr.error('审批流程中已存在该用户!');
+        }
+    });
+
+    // 移除审批流程的审批人
+    $('body').on('click', '.remove_audit_btn', function () {
+        $(this).parents('li').remove();
+        // 令最后一个图标转换
+        if ($('#auditList li').length !== 0 && !$('#auditList li i').hasClass('fa-stop-circle')) {
+            $('#auditList li').eq($('#auditList li').length-1).children('i')
+                .removeClass('fa-chevron-circle-down').addClass('fa-stop-circle');
+        }
+    });
+
+    // 打开签约清单modal并删除之前的操作
+    $('#open-list-modal').click(function () {
+       $('#table-list-select tr').removeClass('table-success');
+    });
+
+    // 清单选中和移除
+    $('#table-list-select tr').on('click', function () {
+       if ($(this).hasClass('table-success')) {
+           $(this).removeClass('table-success');
+           // 选中
+       } else {
+           $(this).addClass('table-success');
+           // 移除
+       }
+    });
+
+    // 添加空白清单or签约清单
+    $('.add-list-btn').on('click', function () {
+        //生成table清单
+        if($(this).hasClass('btn-outline-primary')){
+            maketablelist('addwhite');
+        }else{
+            maketablelist();
+        }
+        $('#addlist').modal('hide');
+    });
+
+    // 选中input所有值
+    $('body').on('focus', ".clist input", function() {
+        $(this).select();
+    });
+
+    // 移除已选清单并重新编号
+    $('body').on('click', '#list td a', function () {
+        const index = $(this).parents('tr').data('index');
+        const lid = $(this).parents('tr').data('lid');
+        // 判断属于空白还是普通清单,并删除对应的index值
+        const changelist = isNaN(lid) ? $('#change-list').val().split('^_^') : $('#change-whitelist').val().split('^_^');
+        if($.trim(changelist) != ''){
+            changelist.splice(index, 1);
+            if (isNaN(lid)) {
+                $('#change-list').val(changelist.join('^_^'));
+            } else {
+                $('#change-whitelist').val(changelist.join('^_^'));
+            }
+        }
+
+        // 重新绘制table
+        maketablelist();
+    });
+
+    // 清单输入监控并更新
+    $('body').on('valuechange', '.clist input', function (e, previous) {
+        const index = $(this).parents('tr').data('index');
+        const lid = $(this).parents('tr').data('lid');
+        const isWhite = !isNaN(lid) ? true : false;
+        const tr = $('#list tr[data-lid="' + lid + '"]').eq(0);
+        const site = parseInt($(this).parents('td').data('site'));
+        switch (site) {
+            case 0:
+            case 1:
+            case 2:
+            case 4:
+                tr.children('td[data-site="' + site + '"]').children('input').val($(this).val());
+                break;
+            case 5:
+            case 7:
+            default:
+                break;
+        }
+        const code = $.trim(tr.children('td[data-site="0"]').children('input').val()) || $.trim(tr.children('td[data-site="0"]').text());
+        const name = $.trim(tr.children('td[data-site="1"]').children('input').val()) || $.trim(tr.children('td[data-site="1"]').text());
+        const unit = $.trim(tr.children('td[data-site="3"]').children('select').val()) || $.trim(tr.children('td[data-site="3"]').text());
+        const price = (tr.children('td[data-site="4"]').children('input').val() != '-' ? tr.children('td[data-site="4"]').children('input').val() : '') || tr.children('td[data-site="4"]').text();
+        const oamount = (tr.children('td[data-site="5"]').children('input').val() != '-' ? tr.children('td[data-site="5"]').children('input').val() : '') || tr.children('td[data-site="5"]').text();
+        const scnum = tr.children('td[data-site="7"]').children('input').val() != '-' ? tr.children('td[data-site="7"]').children('input').val() : '';
+        const detail = $.trim(tr.children('td[data-site="2"]').children('input').val());
+        const trlist = [code,name,unit,price,oamount,scnum,detail];
+        console.log(code);
+        if (isWhite) {
+            let changelist = $('#change-whitelist').val().split('^_^');
+            trlist.push(0);
+            changelist.splice(index, 1, trlist.join(';'));
+            $('#change-whitelist').val(changelist.join('^_^'));
+        } else {
+            let changelist = $('#change-list').val().split('^_^');
+            trlist.push(lid.split('_')[0]);
+            changelist.splice(index, 1, trlist.join(';'));
+            $('#change-list').val(changelist.join('^_^'));
+        }
+        tr.children('td[data-site="6"]').text(price != '' && oamount != '' ? roundnum(parseFloat(price).mul(parseFloat(oamount)),totalPriceUnit) : '');
+        tr.children('td[data-site="8"]').text(price != '' && scnum != '' ? roundnum(parseFloat(price).mul(parseFloat(scnum)),totalPriceUnit) : '');
+        totalamount(totalPriceUnit);
+    });
+
+    // 空白清单单位选择监控并更新小数位数
+    $('body').on("change", '.clist select', function () {
+        const index = $(this).parents('tr').data('index');
+        const tr = $('#list tr[data-lid="' + index + '"]');
+        const code = $.trim(tr.children('td[data-site="0"]').children('input').val());
+        const name = $.trim(tr.children('td[data-site="1"]').children('input').val());
+        const unit = $(this).val();
+        const price = tr.children('td[data-site="4"]').children('input').val() != '-' ? tr.children('td[data-site="4"]').children('input').val() : '';
+        let oamount = tr.children('td[data-site="5"]').children('input').val() != '-' ? tr.children('td[data-site="5"]').children('input').val() : '';
+        let scnum = tr.children('td[data-site="7"]').children('input').val() != '-' ? tr.children('td[data-site="7"]').children('input').val() : '';
+        const detail = $.trim(tr.children('td[data-site="2"]').children('input').val());
+
+        // 根据单位更新数量位数和合计
+        const numdecimal = findDecimal(unit);
+        oamount = roundnum(oamount, numdecimal);
+        scnum = roundnum(scnum, numdecimal);
+        tr.children('td[data-site="5"]').children('input').val(oamount);
+        tr.children('td[data-site="5"]').children('input').attr('onkeyup','RegNum(this,event,'+ numdecimal +')');
+        tr.children('td[data-site="7"]').children('input').val(scnum);
+        tr.children('td[data-site="7"]').children('input').attr('onkeyup','RegNum(this,event,'+ numdecimal +')');
+        const trlist = [code,name,unit,price,oamount,scnum,detail,0];
+        let changelist = $('#change-whitelist').val().split('^_^');
+        changelist.splice(index, 1, trlist.join(';'));
+        $('#change-whitelist').val(changelist.join('^_^'));
+        tr.children('td[data-site="6"]').text(price != '' && oamount != '' ? roundnum(parseFloat(price).mul(parseFloat(oamount)),totalPriceUnit) : '');
+        tr.children('td[data-site="8"]').text(price != '' && scnum != '' ? roundnum(parseFloat(price).mul(parseFloat(scnum)),totalPriceUnit) : '');
+        totalamount(totalPriceUnit);
+    });
+
+    // 自动编号
+    $('.reduction-code').click(function () {
+       const code = $(this).data('code');
+       $('input[name="code"]').val(code);
+    });
+
+});
+
+//判断元素是否在数组中,相当于php的in_array();
+function in_array(arr, obj) {
+    let i = arr.length;
+    while (i--) {
+        if (arr[i] == obj) {
+            return true;
+        }
+    }
+    return false;
+}
+
+// 获取审批流程中审批人列表数据
+function getAuditList() {
+    if ($('#auditList li').length === 0) {
+        $('#changeaudit').val('');
+    } else {
+        let auditInfoArray = [];
+        $('#auditList li').each(function () {
+            const aMsg = $(this).data('auditmsg');
+            auditInfoArray.push(aMsg);
+        });
+        $('#changeaudit').val(auditInfoArray.join(','));
+    }
+}
+
+// 重新生成清单
+function maketablelist(status){
+    // 金额位数
+    const decimal = totalPriceUnit;
+
+    let html = '';
+
+    // 原有清单(不含空白清单)
+    let radionList = $('#change-list').val() !== '' ? $('#change-list').val().split('^_^') : [];
+    // 获取选中的签约清单并插入到原有清单中
+    $('#table-list-select .table-success').each(function(){
+        let code = $(this).children('td').eq(1).text();
+        let name = $(this).children('td').eq(2).text();
+        let unit = $(this).children('td').eq(3).text();
+        let price = $(this).children('td').eq(4).text();
+        let oamount = $(this).children('td').eq(5).text();
+
+        // 根据单位获取数量的位数,并得出
+        let numdecimal = findDecimal(unit);
+
+        let scnum = makedecimalzero(numdecimal);
+        let detail = '';
+        let lid = $(this).data('lid');
+        let trlist = [code, name, unit, price, oamount, scnum, detail, lid];
+        radionList.push(trlist.join(';'));
+    });
+    // 排序
+    radionList.sort();
+    let index = 0;
+    let whiteIndex = 0;
+    let deteletr = '<td><a class="text-danger">移除</a></td>';
+    for (const radion of radionList) {
+        const radionArray = radion.split(';');
+        let code = radionArray[0];
+        let name = radionArray[1];
+        let unit = radionArray[2];
+        let price = radionArray[3];
+        let oamount = radionArray[4];
+        let scnum = radionArray[5];
+        let detail = radionArray[6];
+        let lid = radionArray[7];
+        let sctotal = scnum !== '' && scnum !== '-' ? roundnum(parseFloat(price).mul(parseFloat(scnum)),decimal) : '';
+
+        // 根据单位获取数量的位数,并得出
+        let numdecimal = findDecimal(unit);
+
+        html += '<tr class="clist clid" data-lid="' + lid + '_' + index + '" data-index="' + index + '">' +
+            '<td data-site="0">'+ code +'</td>' +
+            '<td data-site="1">'+ name +'</td>' +
+            '<td data-site="2"><input class="form-control input-sm" type="text" placeholder="变更详情" value="' + detail + '"></td>' +
+            '<td data-site="3">'+ unit +'</td>' +
+            '<td data-site="4">'+ roundnum(price, decimal) +'</td>' +
+            '<td data-site="5">'+ roundnum(oamount, numdecimal) +'</td>' +
+            '<td data-site="6">'+ roundnum(parseFloat(price).mul(parseFloat(oamount)),decimal) +'</td>' +
+            '<td data-site="7"><input class="form-control input-sm" type="text" onkeyup="RegNum(this,event,'+ numdecimal +')" placeholder="请输入变更数量" value="'+ (scnum != '-' ? roundnum(scnum, numdecimal) : '') +'"></td>' +
+            '<td data-site="8">'+ sctotal +'</td>'+
+            deteletr +'</tr>';
+        index ++;
+    }
+    $('#change-list').val(radionList.join('^_^'));
+
+
+    let radionWhiteList = $('#change-whitelist').val() !== '' ? $('#change-whitelist').val().split('^_^') : [];
+    //判断是否添加空白清单
+    if(status == 'addwhite'){
+        let trlist = ['','',changeUnits.t.unit,makedecimalzero(decimal),makedecimalzero(changeUnits.t.value),makedecimalzero(changeUnits.t.value),'',0];
+        radionWhiteList.push(trlist.join(';'));
+    }
+
+    for (const rw of radionWhiteList) {
+        const radionArray = rw.split(';');
+        let code = radionArray[0];
+        let name = radionArray[1];
+        let unit = radionArray[2];
+        let price = radionArray[3];
+        let oamount = radionArray[4];
+        let scnum = radionArray[5];
+        let detail = radionArray[6];
+        let ototal = price != '' && oamount != '' ? roundnum(parseFloat(price).mul(parseFloat(oamount)),decimal) : '';
+        let sctotal = price != '' && scnum != '' ? roundnum(parseFloat(price).mul(parseFloat(scnum)),decimal) : '';
+
+        let optionlist = '';
+        for (const j in changeUnits) {
+            if (changeUnits[j].unit !== undefined && changeUnits[j].unit === unit) {
+                optionlist += '<option selected="selected">'+ changeUnits[j].unit +'</option>';
+            } else if(changeUnits[j].unit !== undefined) {
+                optionlist += '<option>'+ changeUnits[j].unit +'</option>';
+            }
+        }
+
+        // 根据单位获取数量的位数,并得出
+        let numdecimal = findDecimal(unit);
+
+        html += '<tr class="clist" data-lid="' + whiteIndex + '" data-index="' + whiteIndex + '">' +
+            '<td data-site="0"><input class="form-control input-sm" type="text" value="'+ code +'" placeholder="请输入清单编号"></td>' +
+            '<td data-site="1"><input class="form-control input-sm" type="text" value="'+ name +'" placeholder="请输入名称"></td>' +
+            '<td data-site="2"><input class="form-control input-sm" type="text" value="'+ detail +'" placeholder="变更详情"></td>' +
+            '<td data-site="3"><select class="form-control input-sm">'+ optionlist +'</select></td>' +
+            '<td data-site="4"><input class="form-control input-sm" type="text" onkeyup="RegNum(this,event,'+ decimal +')" value="'+ roundnum(price, decimal) +'" placeholder="请输入单价"></td>' +
+            '<td data-site="5"><input class="form-control input-sm" type="text" onkeyup="RegNum(this,event,'+ numdecimal +')" value="'+ roundnum(oamount, numdecimal) +'" placeholder="请输入数量"></td>' +
+            '<td data-site="6">'+ ototal +'</td>' +
+            '<td data-site="7"><input class="form-control input-sm" type="text" onkeyup="RegNum(this,event,'+ numdecimal +')" value="'+ roundnum(scnum, numdecimal) +'" placeholder="请输入变更数量"></td>' +
+            '<td data-site="8">'+ sctotal +'</td>'+
+            deteletr +'</tr>';
+        whiteIndex ++;
+    }
+
+    $('#change-whitelist').val(radionWhiteList.join('^_^'));
+
+    table.destroy();
+    $('#list').html(html);
+    table = $('#tablelist').removeAttr('width').DataTable({
+        columnDefs: [
+            { className: 'allwidth1', width: 100, targets: 0 },
+            { className: 'allwidth2', width: 150, targets: [1,2] },
+            { className: 'allwidth4', width: 40, targets: 9 },
+            { className: 'allwidth5', width: 60, targets: 3 },
+            { className: 'allwidth3',width: 80, targets: '_all' }
+        ],
+        fixedColumns: {
+            leftColumns: 5
+        }
+    });
+    // 判断是否显示变更详情
+    if (!$('.change-detail-checkbox').is(':checked')) {
+        const column = table.column(2);
+        column.visible(!column.visible());
+    }
+    totalamount(decimal);
+    $('#table-list-select tr').removeClass('table-success');
+}
+
+//统计合计金额
+function totalamount(decimal){
+    let zero = makedecimalzero(decimal);
+    let ctotalnum = 0;
+    let ototalnum = 0;
+    $('.clist').each(function(){
+        let ctotal = $(this).children('td[data-site="8"]').text();
+        ctotalnum = ctotal != '' ? parseFloat(ctotalnum).add(parseFloat(ctotal)) : parseFloat(ctotalnum);
+        let ototal = $(this).children('td[data-site="6"]').text();
+        ototalnum = ototal != '' ? parseFloat(ototalnum).add(parseFloat(ototal)) : parseFloat(ototalnum);
+    });
+    $('.ctatalamount').eq(1).text(ctotalnum != 0 ? roundnum(ctotalnum,decimal) : zero);
+    $('.otatalamount').eq(1).text(ototalnum != 0 ? roundnum(ototalnum,decimal) : zero);
+}
+
+//四舍五入或末尾加零,实现类似php的 sprintf("%.".decimal."f", val);
+function roundnum(val,decimals){
+    if(val !== ''){
+        val = parseFloat(val);
+        if(decimals < 1){
+            val = (Math.round(val)).toString();
+        }else{
+            let num = val.toString();
+            if(num.lastIndexOf('.') == -1){
+                num += '.';
+                num += makezero(decimals);
+                val = num;
+            }else{
+                let valdecimals = num.split('.')[1].length;
+                if(parseInt(valdecimals) < parseInt(decimals)){
+                    num += makezero(parseInt(decimals)-parseInt(valdecimals));
+                    val = num;
+                }else if(parseInt(valdecimals) > parseInt(decimals)){
+                    val = parseFloat(val) != 0 ? Math.round(val.mul(makemultiple(decimals))).div(makemultiple(decimals)) : makedecimalzero(decimals);
+                    let num = val.toString();
+                    if(num.lastIndexOf('.') == -1){
+                        num += '.';
+                        num += makezero(decimals);
+                        val = num;
+                    }else {
+                        let valdecimals = num.split('.')[1].length;
+                        if (parseInt(valdecimals) < parseInt(decimals)) {
+                            num += makezero(parseInt(decimals) - parseInt(valdecimals));
+                            val = num;
+                        }
+                    }
+                }
+            }
+        }
+    }
+    return val;
+}
+
+//根据位数生成编号,3位-》001 ,5位-》00001
+function makenum(num){
+    let arr = new Array(num);
+    for(let i=0;i< num;i++){
+        if(i != num-1){
+            arr[i] = 0;
+        }else{
+            arr[i] = 1;
+        }
+    }
+    return arr.join('');
+}
+//生成num位的0
+function makezero(num){
+    let arr = new Array(num);
+    for(let i=0;i< num;i++){
+        arr[i] = 0;
+    }
+    return arr.join('');
+}
+//生成num小数位数的0.
+function makedecimalzero(num){
+    if(num < 1){
+        return '0';
+    }else{
+        return '0.'+makezero(num);
+    }
+}
+//生成num位的10倍数
+function makemultiple(num){
+    return Math.pow(10,parseInt(num));
+}
+
+// 找出单位对应的小数位数值
+function findDecimal(unit) {
+    let value = 2;
+    for (const d in changeUnits) {
+        if (changeUnits[d].unit !== undefined && changeUnits[d].unit === unit) {
+            value = changeUnits[d].value;
+            break;
         }
-    })
-});
+    }
+    return value;
+}

+ 182 - 0
app/public/js/datatable/dataTables.bootstrap.js

@@ -0,0 +1,182 @@
+/*! DataTables Bootstrap 3 integration
+ * ©2011-2015 SpryMedia Ltd - datatables.net/license
+ */
+
+/**
+ * DataTables integration for Bootstrap 3. This requires Bootstrap 3 and
+ * DataTables 1.10 or newer.
+ *
+ * This file sets the defaults and adds options to DataTables to style its
+ * controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
+ * for further information.
+ */
+(function( factory ){
+	if ( typeof define === 'function' && define.amd ) {
+		// AMD
+		define( ['jquery', 'datatables.net'], function ( $ ) {
+			return factory( $, window, document );
+		} );
+	}
+	else if ( typeof exports === 'object' ) {
+		// CommonJS
+		module.exports = function (root, $) {
+			if ( ! root ) {
+				root = window;
+			}
+
+			if ( ! $ || ! $.fn.dataTable ) {
+				// Require DataTables, which attaches to jQuery, including
+				// jQuery if needed and have a $ property so we can access the
+				// jQuery object that is used
+				$ = require('datatables.net')(root, $).$;
+			}
+
+			return factory( $, root, root.document );
+		};
+	}
+	else {
+		// Browser
+		factory( jQuery, window, document );
+	}
+}(function( $, window, document, undefined ) {
+'use strict';
+var DataTable = $.fn.dataTable;
+
+
+/* Set the defaults for DataTables initialisation */
+$.extend( true, DataTable.defaults, {
+	dom:
+		"<'row'<'col-sm-6'l><'col-sm-6'f>>" +
+		"<'row'<'col-sm-12'tr>>" +
+		"<'row'<'col-sm-5'i><'col-sm-7'p>>",
+	renderer: 'bootstrap'
+} );
+
+
+/* Default class modification */
+$.extend( DataTable.ext.classes, {
+	sWrapper:      "dataTables_wrapper form-inline dt-bootstrap",
+	sFilterInput:  "form-control input-sm",
+	sLengthSelect: "form-control input-sm",
+	sProcessing:   "dataTables_processing panel panel-default"
+} );
+
+
+/* Bootstrap paging button renderer */
+DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
+	var api     = new DataTable.Api( settings );
+	var classes = settings.oClasses;
+	var lang    = settings.oLanguage.oPaginate;
+	var aria = settings.oLanguage.oAria.paginate || {};
+	var btnDisplay, btnClass, counter=0;
+
+	var attach = function( container, buttons ) {
+		var i, ien, node, button;
+		var clickHandler = function ( e ) {
+			e.preventDefault();
+			if ( !$(e.currentTarget).hasClass('disabled') && api.page() != e.data.action ) {
+				api.page( e.data.action ).draw( 'page' );
+			}
+		};
+
+		for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
+			button = buttons[i];
+
+			if ( $.isArray( button ) ) {
+				attach( container, button );
+			}
+			else {
+				btnDisplay = '';
+				btnClass = '';
+
+				switch ( button ) {
+					case 'ellipsis':
+						btnDisplay = '&#x2026;';
+						btnClass = 'disabled';
+						break;
+
+					case 'first':
+						btnDisplay = lang.sFirst;
+						btnClass = button + (page > 0 ?
+							'' : ' disabled');
+						break;
+
+					case 'previous':
+						btnDisplay = lang.sPrevious;
+						btnClass = button + (page > 0 ?
+							'' : ' disabled');
+						break;
+
+					case 'next':
+						btnDisplay = lang.sNext;
+						btnClass = button + (page < pages-1 ?
+							'' : ' disabled');
+						break;
+
+					case 'last':
+						btnDisplay = lang.sLast;
+						btnClass = button + (page < pages-1 ?
+							'' : ' disabled');
+						break;
+
+					default:
+						btnDisplay = button + 1;
+						btnClass = page === button ?
+							'active' : '';
+						break;
+				}
+
+				if ( btnDisplay ) {
+					node = $('<li>', {
+							'class': classes.sPageButton+' '+btnClass,
+							'id': idx === 0 && typeof button === 'string' ?
+								settings.sTableId +'_'+ button :
+								null
+						} )
+						.append( $('<a>', {
+								'href': '#',
+								'aria-controls': settings.sTableId,
+								'aria-label': aria[ button ],
+								'data-dt-idx': counter,
+								'tabindex': settings.iTabIndex
+							} )
+							.html( btnDisplay )
+						)
+						.appendTo( container );
+
+					settings.oApi._fnBindAction(
+						node, {action: button}, clickHandler
+					);
+
+					counter++;
+				}
+			}
+		}
+	};
+
+	// IE9 throws an 'unknown error' if document.activeElement is used
+	// inside an iframe or frame. 
+	var activeEl;
+
+	try {
+		// Because this approach is destroying and recreating the paging
+		// elements, focus is lost on the select button which is bad for
+		// accessibility. So we want to restore focus once the draw has
+		// completed
+		activeEl = $(host).find(document.activeElement).data('dt-idx');
+	}
+	catch (e) {}
+
+	attach(
+		$(host).empty().html('<ul class="pagination"/>').children('ul'),
+		buttons
+	);
+
+	if ( activeEl !== undefined ) {
+		$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
+	}
+};
+
+
+return DataTable;
+}));

Plik diff jest za duży
+ 8 - 0
app/public/js/datatable/dataTables.bootstrap.min.js


+ 184 - 0
app/public/js/datatable/dataTables.bootstrap4.js

@@ -0,0 +1,184 @@
+/*! DataTables Bootstrap 4 integration
+ * ©2011-2017 SpryMedia Ltd - datatables.net/license
+ */
+
+/**
+ * DataTables integration for Bootstrap 4. This requires Bootstrap 4 and
+ * DataTables 1.10 or newer.
+ *
+ * This file sets the defaults and adds options to DataTables to style its
+ * controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
+ * for further information.
+ */
+(function( factory ){
+	if ( typeof define === 'function' && define.amd ) {
+		// AMD
+		define( ['jquery', 'datatables.net'], function ( $ ) {
+			return factory( $, window, document );
+		} );
+	}
+	else if ( typeof exports === 'object' ) {
+		// CommonJS
+		module.exports = function (root, $) {
+			if ( ! root ) {
+				root = window;
+			}
+
+			if ( ! $ || ! $.fn.dataTable ) {
+				// Require DataTables, which attaches to jQuery, including
+				// jQuery if needed and have a $ property so we can access the
+				// jQuery object that is used
+				$ = require('datatables.net')(root, $).$;
+			}
+
+			return factory( $, root, root.document );
+		};
+	}
+	else {
+		// Browser
+		factory( jQuery, window, document );
+	}
+}(function( $, window, document, undefined ) {
+'use strict';
+var DataTable = $.fn.dataTable;
+
+
+/* Set the defaults for DataTables initialisation */
+$.extend( true, DataTable.defaults, {
+	dom:
+		"<'row'<'col-sm-12 col-md-6'l><'col-sm-12 col-md-6'f>>" +
+		"<'row'<'col-sm-12'tr>>" +
+		"<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>",
+	renderer: 'bootstrap'
+} );
+
+
+/* Default class modification */
+$.extend( DataTable.ext.classes, {
+	sWrapper:      "dataTables_wrapper dt-bootstrap4",
+	sFilterInput:  "form-control form-control-sm",
+	sLengthSelect: "custom-select custom-select-sm form-control form-control-sm",
+	sProcessing:   "dataTables_processing card",
+	sPageButton:   "paginate_button page-item"
+} );
+
+
+/* Bootstrap paging button renderer */
+DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, buttons, page, pages ) {
+	var api     = new DataTable.Api( settings );
+	var classes = settings.oClasses;
+	var lang    = settings.oLanguage.oPaginate;
+	var aria = settings.oLanguage.oAria.paginate || {};
+	var btnDisplay, btnClass, counter=0;
+
+	var attach = function( container, buttons ) {
+		var i, ien, node, button;
+		var clickHandler = function ( e ) {
+			e.preventDefault();
+			if ( !$(e.currentTarget).hasClass('disabled') && api.page() != e.data.action ) {
+				api.page( e.data.action ).draw( 'page' );
+			}
+		};
+
+		for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
+			button = buttons[i];
+
+			if ( $.isArray( button ) ) {
+				attach( container, button );
+			}
+			else {
+				btnDisplay = '';
+				btnClass = '';
+
+				switch ( button ) {
+					case 'ellipsis':
+						btnDisplay = '&#x2026;';
+						btnClass = 'disabled';
+						break;
+
+					case 'first':
+						btnDisplay = lang.sFirst;
+						btnClass = button + (page > 0 ?
+							'' : ' disabled');
+						break;
+
+					case 'previous':
+						btnDisplay = lang.sPrevious;
+						btnClass = button + (page > 0 ?
+							'' : ' disabled');
+						break;
+
+					case 'next':
+						btnDisplay = lang.sNext;
+						btnClass = button + (page < pages-1 ?
+							'' : ' disabled');
+						break;
+
+					case 'last':
+						btnDisplay = lang.sLast;
+						btnClass = button + (page < pages-1 ?
+							'' : ' disabled');
+						break;
+
+					default:
+						btnDisplay = button + 1;
+						btnClass = page === button ?
+							'active' : '';
+						break;
+				}
+
+				if ( btnDisplay ) {
+					node = $('<li>', {
+							'class': classes.sPageButton+' '+btnClass,
+							'id': idx === 0 && typeof button === 'string' ?
+								settings.sTableId +'_'+ button :
+								null
+						} )
+						.append( $('<a>', {
+								'href': '#',
+								'aria-controls': settings.sTableId,
+								'aria-label': aria[ button ],
+								'data-dt-idx': counter,
+								'tabindex': settings.iTabIndex,
+								'class': 'page-link'
+							} )
+							.html( btnDisplay )
+						)
+						.appendTo( container );
+
+					settings.oApi._fnBindAction(
+						node, {action: button}, clickHandler
+					);
+
+					counter++;
+				}
+			}
+		}
+	};
+
+	// IE9 throws an 'unknown error' if document.activeElement is used
+	// inside an iframe or frame. 
+	var activeEl;
+
+	try {
+		// Because this approach is destroying and recreating the paging
+		// elements, focus is lost on the select button which is bad for
+		// accessibility. So we want to restore focus once the draw has
+		// completed
+		activeEl = $(host).find(document.activeElement).data('dt-idx');
+	}
+	catch (e) {}
+
+	attach(
+		$(host).empty().html('<ul class="pagination"/>').children('ul'),
+		buttons
+	);
+
+	if ( activeEl !== undefined ) {
+		$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
+	}
+};
+
+
+return DataTable;
+}));

Plik diff jest za duży
+ 8 - 0
app/public/js/datatable/dataTables.bootstrap4.min.js


Plik diff jest za duży
+ 1632 - 0
app/public/js/datatable/dataTables.fixedColumns.js


Plik diff jest za duży
+ 35 - 0
app/public/js/datatable/dataTables.fixedColumns.min.js


+ 174 - 0
app/public/js/datatable/dataTables.foundation.js

@@ -0,0 +1,174 @@
+/*! DataTables Foundation integration
+ * ©2011-2015 SpryMedia Ltd - datatables.net/license
+ */
+
+/**
+ * DataTables integration for Foundation. This requires Foundation 5 and
+ * DataTables 1.10 or newer.
+ *
+ * This file sets the defaults and adds options to DataTables to style its
+ * controls using Foundation. See http://datatables.net/manual/styling/foundation
+ * for further information.
+ */
+(function( factory ){
+	if ( typeof define === 'function' && define.amd ) {
+		// AMD
+		define( ['jquery', 'datatables.net'], function ( $ ) {
+			return factory( $, window, document );
+		} );
+	}
+	else if ( typeof exports === 'object' ) {
+		// CommonJS
+		module.exports = function (root, $) {
+			if ( ! root ) {
+				root = window;
+			}
+
+			if ( ! $ || ! $.fn.dataTable ) {
+				$ = require('datatables.net')(root, $).$;
+			}
+
+			return factory( $, root, root.document );
+		};
+	}
+	else {
+		// Browser
+		factory( jQuery, window, document );
+	}
+}(function( $, window, document, undefined ) {
+'use strict';
+var DataTable = $.fn.dataTable;
+
+// Detect Foundation 5 / 6 as they have different element and class requirements
+var meta = $('<meta class="foundation-mq"/>').appendTo('head');
+DataTable.ext.foundationVersion = meta.css('font-family').match(/small|medium|large/) ? 6 : 5;
+meta.remove();
+
+
+$.extend( DataTable.ext.classes, {
+	sWrapper:    "dataTables_wrapper dt-foundation",
+	sProcessing: "dataTables_processing panel callout"
+} );
+
+
+/* Set the defaults for DataTables initialisation */
+$.extend( true, DataTable.defaults, {
+	dom:
+		"<'row grid-x'<'small-6 columns cell'l><'small-6 columns cell'f>r>"+
+		"t"+
+		"<'row grid-x'<'small-6 columns cell'i><'small-6 columns cell'p>>",
+	renderer: 'foundation'
+} );
+
+
+/* Page button renderer */
+DataTable.ext.renderer.pageButton.foundation = function ( settings, host, idx, buttons, page, pages ) {
+	var api = new DataTable.Api( settings );
+	var classes = settings.oClasses;
+	var lang = settings.oLanguage.oPaginate;
+	var aria = settings.oLanguage.oAria.paginate || {};
+	var btnDisplay, btnClass;
+	var tag;
+	var v5 = DataTable.ext.foundationVersion === 5;
+
+	var attach = function( container, buttons ) {
+		var i, ien, node, button;
+		var clickHandler = function ( e ) {
+			e.preventDefault();
+			if ( !$(e.currentTarget).hasClass('unavailable') && api.page() != e.data.action ) {
+				api.page( e.data.action ).draw( 'page' );
+			}
+		};
+
+		for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
+			button = buttons[i];
+
+			if ( $.isArray( button ) ) {
+				attach( container, button );
+			}
+			else {
+				btnDisplay = '';
+				btnClass = '';
+				tag = null;
+
+				switch ( button ) {
+					case 'ellipsis':
+						btnDisplay = '&#x2026;';
+						btnClass = 'unavailable disabled';
+						tag = null;
+						break;
+
+					case 'first':
+						btnDisplay = lang.sFirst;
+						btnClass = button + (page > 0 ?
+							'' : ' unavailable disabled');
+						tag = page > 0 ? 'a' : null;
+						break;
+
+					case 'previous':
+						btnDisplay = lang.sPrevious;
+						btnClass = button + (page > 0 ?
+							'' : ' unavailable disabled');
+						tag = page > 0 ? 'a' : null;
+						break;
+
+					case 'next':
+						btnDisplay = lang.sNext;
+						btnClass = button + (page < pages-1 ?
+							'' : ' unavailable disabled');
+						tag = page < pages-1 ? 'a' : null;
+						break;
+
+					case 'last':
+						btnDisplay = lang.sLast;
+						btnClass = button + (page < pages-1 ?
+							'' : ' unavailable disabled');
+						tag = page < pages-1 ? 'a' : null;
+						break;
+
+					default:
+						btnDisplay = button + 1;
+						btnClass = page === button ?
+							'current' : '';
+						tag = page === button ?
+							null : 'a';
+						break;
+				}
+
+				if ( v5 ) {
+					tag = 'a';
+				}
+
+				if ( btnDisplay ) {
+					node = $('<li>', {
+							'class': classes.sPageButton+' '+btnClass,
+							'aria-controls': settings.sTableId,
+							'aria-label': aria[ button ],
+							'tabindex': settings.iTabIndex,
+							'id': idx === 0 && typeof button === 'string' ?
+								settings.sTableId +'_'+ button :
+								null
+						} )
+						.append( tag ?
+							$('<'+tag+'/>', {'href': '#'} ).html( btnDisplay ) :
+							btnDisplay
+						)
+						.appendTo( container );
+
+					settings.oApi._fnBindAction(
+						node, {action: button}, clickHandler
+					);
+				}
+			}
+		}
+	};
+
+	attach(
+		$(host).empty().html('<ul class="pagination"/>').children('ul'),
+		buttons
+	);
+};
+
+
+return DataTable;
+}));

Plik diff jest za duży
+ 8 - 0
app/public/js/datatable/dataTables.foundation.min.js


+ 164 - 0
app/public/js/datatable/dataTables.jqueryui.js

@@ -0,0 +1,164 @@
+/*! DataTables jQuery UI integration
+ * ©2011-2014 SpryMedia Ltd - datatables.net/license
+ */
+
+/**
+ * DataTables integration for jQuery UI. This requires jQuery UI and
+ * DataTables 1.10 or newer.
+ *
+ * This file sets the defaults and adds options to DataTables to style its
+ * controls using jQuery UI. See http://datatables.net/manual/styling/jqueryui
+ * for further information.
+ */
+(function( factory ){
+	if ( typeof define === 'function' && define.amd ) {
+		// AMD
+		define( ['jquery', 'datatables.net'], function ( $ ) {
+			return factory( $, window, document );
+		} );
+	}
+	else if ( typeof exports === 'object' ) {
+		// CommonJS
+		module.exports = function (root, $) {
+			if ( ! root ) {
+				root = window;
+			}
+
+			if ( ! $ || ! $.fn.dataTable ) {
+				$ = require('datatables.net')(root, $).$;
+			}
+
+			return factory( $, root, root.document );
+		};
+	}
+	else {
+		// Browser
+		factory( jQuery, window, document );
+	}
+}(function( $, window, document, undefined ) {
+'use strict';
+var DataTable = $.fn.dataTable;
+
+
+var sort_prefix = 'css_right ui-icon ui-icon-';
+var toolbar_prefix = 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix ui-corner-';
+
+/* Set the defaults for DataTables initialisation */
+$.extend( true, DataTable.defaults, {
+	dom:
+		'<"'+toolbar_prefix+'tl ui-corner-tr"lfr>'+
+		't'+
+		'<"'+toolbar_prefix+'bl ui-corner-br"ip>',
+	renderer: 'jqueryui'
+} );
+
+
+$.extend( DataTable.ext.classes, {
+	"sWrapper":            "dataTables_wrapper dt-jqueryui",
+
+	/* Full numbers paging buttons */
+	"sPageButton":         "fg-button ui-button ui-state-default",
+	"sPageButtonActive":   "ui-state-disabled",
+	"sPageButtonDisabled": "ui-state-disabled",
+
+	/* Features */
+	"sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
+		"ui-buttonset-multi paging_", /* Note that the type is postfixed */
+
+	/* Sorting */
+	"sSortAsc":            "ui-state-default sorting_asc",
+	"sSortDesc":           "ui-state-default sorting_desc",
+	"sSortable":           "ui-state-default sorting",
+	"sSortableAsc":        "ui-state-default sorting_asc_disabled",
+	"sSortableDesc":       "ui-state-default sorting_desc_disabled",
+	"sSortableNone":       "ui-state-default sorting_disabled",
+	"sSortIcon":           "DataTables_sort_icon",
+
+	/* Scrolling */
+	"sScrollHead": "dataTables_scrollHead "+"ui-state-default",
+	"sScrollFoot": "dataTables_scrollFoot "+"ui-state-default",
+
+	/* Misc */
+	"sHeaderTH":  "ui-state-default",
+	"sFooterTH":  "ui-state-default"
+} );
+
+
+DataTable.ext.renderer.header.jqueryui = function ( settings, cell, column, classes ) {
+	// Calculate what the unsorted class should be
+	var noSortAppliedClass = sort_prefix+'caret-2-n-s';
+	var asc = $.inArray('asc', column.asSorting) !== -1;
+	var desc = $.inArray('desc', column.asSorting) !== -1;
+
+	if ( !column.bSortable || (!asc && !desc) ) {
+		noSortAppliedClass = '';
+	}
+	else if ( asc && !desc ) {
+		noSortAppliedClass = sort_prefix+'caret-1-n';
+	}
+	else if ( !asc && desc ) {
+		noSortAppliedClass = sort_prefix+'caret-1-s';
+	}
+
+	// Setup the DOM structure
+	$('<div/>')
+		.addClass( 'DataTables_sort_wrapper' )
+		.append( cell.contents() )
+		.append( $('<span/>')
+			.addClass( classes.sSortIcon+' '+noSortAppliedClass )
+		)
+		.appendTo( cell );
+
+	// Attach a sort listener to update on sort
+	$(settings.nTable).on( 'order.dt', function ( e, ctx, sorting, columns ) {
+		if ( settings !== ctx ) {
+			return;
+		}
+
+		var colIdx = column.idx;
+
+		cell
+			.removeClass( classes.sSortAsc +" "+classes.sSortDesc )
+			.addClass( columns[ colIdx ] == 'asc' ?
+				classes.sSortAsc : columns[ colIdx ] == 'desc' ?
+					classes.sSortDesc :
+					column.sSortingClass
+			);
+
+		cell
+			.find( 'span.'+classes.sSortIcon )
+			.removeClass(
+				sort_prefix+'triangle-1-n' +" "+
+				sort_prefix+'triangle-1-s' +" "+
+				sort_prefix+'caret-2-n-s' +" "+
+				sort_prefix+'caret-1-n' +" "+
+				sort_prefix+'caret-1-s'
+			)
+			.addClass( columns[ colIdx ] == 'asc' ?
+				sort_prefix+'triangle-1-n' : columns[ colIdx ] == 'desc' ?
+					sort_prefix+'triangle-1-s' :
+					noSortAppliedClass
+			);
+	} );
+};
+
+
+/*
+ * TableTools jQuery UI compatibility
+ * Required TableTools 2.1+
+ */
+if ( DataTable.TableTools ) {
+	$.extend( true, DataTable.TableTools.classes, {
+		"container": "DTTT_container ui-buttonset ui-buttonset-multi",
+		"buttons": {
+			"normal": "DTTT_button ui-button ui-state-default"
+		},
+		"collection": {
+			"container": "DTTT_collection ui-buttonset ui-buttonset-multi"
+		}
+	} );
+}
+
+
+return DataTable;
+}));

Plik diff jest za duży
+ 9 - 0
app/public/js/datatable/dataTables.jqueryui.min.js


+ 212 - 0
app/public/js/datatable/dataTables.semanticui.js

@@ -0,0 +1,212 @@
+/*! DataTables Bootstrap 3 integration
+ * ©2011-2015 SpryMedia Ltd - datatables.net/license
+ */
+
+/**
+ * DataTables integration for Bootstrap 3. This requires Bootstrap 3 and
+ * DataTables 1.10 or newer.
+ *
+ * This file sets the defaults and adds options to DataTables to style its
+ * controls using Bootstrap. See http://datatables.net/manual/styling/bootstrap
+ * for further information.
+ */
+(function( factory ){
+	if ( typeof define === 'function' && define.amd ) {
+		// AMD
+		define( ['jquery', 'datatables.net'], function ( $ ) {
+			return factory( $, window, document );
+		} );
+	}
+	else if ( typeof exports === 'object' ) {
+		// CommonJS
+		module.exports = function (root, $) {
+			if ( ! root ) {
+				root = window;
+			}
+
+			if ( ! $ || ! $.fn.dataTable ) {
+				// Require DataTables, which attaches to jQuery, including
+				// jQuery if needed and have a $ property so we can access the
+				// jQuery object that is used
+				$ = require('datatables.net')(root, $).$;
+			}
+
+			return factory( $, root, root.document );
+		};
+	}
+	else {
+		// Browser
+		factory( jQuery, window, document );
+	}
+}(function( $, window, document, undefined ) {
+'use strict';
+var DataTable = $.fn.dataTable;
+
+
+/* Set the defaults for DataTables initialisation */
+$.extend( true, DataTable.defaults, {
+	dom:
+		"<'ui stackable grid'"+
+			"<'row'"+
+				"<'eight wide column'l>"+
+				"<'right aligned eight wide column'f>"+
+			">"+
+			"<'row dt-table'"+
+				"<'sixteen wide column'tr>"+
+			">"+
+			"<'row'"+
+				"<'seven wide column'i>"+
+				"<'right aligned nine wide column'p>"+
+			">"+
+		">",
+	renderer: 'semanticUI'
+} );
+
+
+/* Default class modification */
+$.extend( DataTable.ext.classes, {
+	sWrapper:      "dataTables_wrapper dt-semanticUI",
+	sFilter:       "dataTables_filter ui input",
+	sProcessing:   "dataTables_processing ui segment",
+	sPageButton:   "paginate_button item"
+} );
+
+
+/* Bootstrap paging button renderer */
+DataTable.ext.renderer.pageButton.semanticUI = function ( settings, host, idx, buttons, page, pages ) {
+	var api     = new DataTable.Api( settings );
+	var classes = settings.oClasses;
+	var lang    = settings.oLanguage.oPaginate;
+	var aria = settings.oLanguage.oAria.paginate || {};
+	var btnDisplay, btnClass, counter=0;
+
+	var attach = function( container, buttons ) {
+		var i, ien, node, button;
+		var clickHandler = function ( e ) {
+			e.preventDefault();
+			if ( !$(e.currentTarget).hasClass('disabled') && api.page() != e.data.action ) {
+				api.page( e.data.action ).draw( 'page' );
+			}
+		};
+
+		for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
+			button = buttons[i];
+
+			if ( $.isArray( button ) ) {
+				attach( container, button );
+			}
+			else {
+				btnDisplay = '';
+				btnClass = '';
+
+				switch ( button ) {
+					case 'ellipsis':
+						btnDisplay = '&#x2026;';
+						btnClass = 'disabled';
+						break;
+
+					case 'first':
+						btnDisplay = lang.sFirst;
+						btnClass = button + (page > 0 ?
+							'' : ' disabled');
+						break;
+
+					case 'previous':
+						btnDisplay = lang.sPrevious;
+						btnClass = button + (page > 0 ?
+							'' : ' disabled');
+						break;
+
+					case 'next':
+						btnDisplay = lang.sNext;
+						btnClass = button + (page < pages-1 ?
+							'' : ' disabled');
+						break;
+
+					case 'last':
+						btnDisplay = lang.sLast;
+						btnClass = button + (page < pages-1 ?
+							'' : ' disabled');
+						break;
+
+					default:
+						btnDisplay = button + 1;
+						btnClass = page === button ?
+							'active' : '';
+						break;
+				}
+
+				var tag = btnClass.indexOf( 'disabled' ) === -1 ?
+					'a' :
+					'div';
+
+				if ( btnDisplay ) {
+					node = $('<'+tag+'>', {
+							'class': classes.sPageButton+' '+btnClass,
+							'id': idx === 0 && typeof button === 'string' ?
+								settings.sTableId +'_'+ button :
+								null,
+							'href': '#',
+							'aria-controls': settings.sTableId,
+							'aria-label': aria[ button ],
+							'data-dt-idx': counter,
+							'tabindex': settings.iTabIndex
+						} )
+						.html( btnDisplay )
+						.appendTo( container );
+
+					settings.oApi._fnBindAction(
+						node, {action: button}, clickHandler
+					);
+
+					counter++;
+				}
+			}
+		}
+	};
+
+	// IE9 throws an 'unknown error' if document.activeElement is used
+	// inside an iframe or frame. 
+	var activeEl;
+
+	try {
+		// Because this approach is destroying and recreating the paging
+		// elements, focus is lost on the select button which is bad for
+		// accessibility. So we want to restore focus once the draw has
+		// completed
+		activeEl = $(host).find(document.activeElement).data('dt-idx');
+	}
+	catch (e) {}
+
+	attach(
+		$(host).empty().html('<div class="ui stackable pagination menu"/>').children(),
+		buttons
+	);
+
+	if ( activeEl !== undefined ) {
+		$(host).find( '[data-dt-idx='+activeEl+']' ).focus();
+	}
+};
+
+
+// Javascript enhancements on table initialisation
+$(document).on( 'init.dt', function (e, ctx) {
+	if ( e.namespace !== 'dt' ) {
+		return;
+	}
+
+	var api = new $.fn.dataTable.Api( ctx );
+
+	// Length menu drop down
+	if ( $.fn.dropdown ) {
+		$( 'div.dataTables_length select', api.table().container() ).dropdown();
+	}
+
+	// Filtering input
+	$( 'div.dataTables_filter.ui.input', api.table().container() ).removeClass('input').addClass('form');
+	$( 'div.dataTables_filter input', api.table().container() ).wrap( '<span class="ui input" />' );
+} );
+
+
+return DataTable;
+}));

Plik diff jest za duży
+ 9 - 0
app/public/js/datatable/dataTables.semanticui.min.js


+ 38 - 0
app/public/js/datatable/fixedColumns.bootstrap.js

@@ -0,0 +1,38 @@
+/*! Bootstrap 3 styling wrapper for FixedColumns
+ * ©2018 SpryMedia Ltd - datatables.net/license
+ */
+
+(function( factory ){
+	if ( typeof define === 'function' && define.amd ) {
+		// AMD
+		define( ['jquery', 'datatables.net-bs', 'datatables.net-fixedcolumns'], function ( $ ) {
+			return factory( $, window, document );
+		} );
+	}
+	else if ( typeof exports === 'object' ) {
+		// CommonJS
+		module.exports = function (root, $) {
+			if ( ! root ) {
+				root = window;
+			}
+
+			if ( ! $ || ! $.fn.dataTable ) {
+				$ = require('datatables.net-bs')(root, $).$;
+			}
+
+			if ( ! $.fn.dataTable.FixedColumns ) {
+				require('datatables.net-fixedcolumns')(root, $);
+			}
+
+			return factory( $, root, root.document );
+		};
+	}
+	else {
+		// Browser
+		factory( jQuery, window, document );
+	}
+}(function( $, window, document, undefined ) {
+
+return $.fn.dataTable;
+
+}));

+ 5 - 0
app/public/js/datatable/fixedColumns.bootstrap.min.js

@@ -0,0 +1,5 @@
+/*!
+ Bootstrap 3 styling wrapper for FixedColumns
+ ©2018 SpryMedia Ltd - datatables.net/license
+*/
+(function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net-bs","datatables.net-fixedcolumns"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);if(!b||!b.fn.dataTable)b=require("datatables.net-bs")(a,b).$;b.fn.dataTable.FixedColumns||require("datatables.net-fixedcolumns")(a,b);return c(b,a,a.document)}:c(jQuery,window,document)})(function(c){return c.fn.dataTable});

+ 38 - 0
app/public/js/datatable/fixedColumns.bootstrap4.js

@@ -0,0 +1,38 @@
+/*! Bootstrap 4 styling wrapper for FixedColumns
+ * ©2018 SpryMedia Ltd - datatables.net/license
+ */
+
+(function( factory ){
+	if ( typeof define === 'function' && define.amd ) {
+		// AMD
+		define( ['jquery', 'datatables.net-bs4', 'datatables.net-fixedcolumns'], function ( $ ) {
+			return factory( $, window, document );
+		} );
+	}
+	else if ( typeof exports === 'object' ) {
+		// CommonJS
+		module.exports = function (root, $) {
+			if ( ! root ) {
+				root = window;
+			}
+
+			if ( ! $ || ! $.fn.dataTable ) {
+				$ = require('datatables.net-bs4')(root, $).$;
+			}
+
+			if ( ! $.fn.dataTable.FixedColumns ) {
+				require('datatables.net-fixedcolumns')(root, $);
+			}
+
+			return factory( $, root, root.document );
+		};
+	}
+	else {
+		// Browser
+		factory( jQuery, window, document );
+	}
+}(function( $, window, document, undefined ) {
+
+return $.fn.dataTable;
+
+}));

+ 5 - 0
app/public/js/datatable/fixedColumns.bootstrap4.min.js

@@ -0,0 +1,5 @@
+/*!
+ Bootstrap 4 styling wrapper for FixedColumns
+ ©2018 SpryMedia Ltd - datatables.net/license
+*/
+(function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net-bs4","datatables.net-fixedcolumns"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);if(!b||!b.fn.dataTable)b=require("datatables.net-bs4")(a,b).$;b.fn.dataTable.FixedColumns||require("datatables.net-fixedcolumns")(a,b);return c(b,a,a.document)}:c(jQuery,window,document)})(function(c){return c.fn.dataTable});

+ 38 - 0
app/public/js/datatable/fixedColumns.dataTables.js

@@ -0,0 +1,38 @@
+/*! DataTables styling wrapper for FixedColumns
+ * ©2018 SpryMedia Ltd - datatables.net/license
+ */
+
+(function( factory ){
+	if ( typeof define === 'function' && define.amd ) {
+		// AMD
+		define( ['jquery', 'datatables.net-dt', 'datatables.net-fixedcolumns'], function ( $ ) {
+			return factory( $, window, document );
+		} );
+	}
+	else if ( typeof exports === 'object' ) {
+		// CommonJS
+		module.exports = function (root, $) {
+			if ( ! root ) {
+				root = window;
+			}
+
+			if ( ! $ || ! $.fn.dataTable ) {
+				$ = require('datatables.net-dt')(root, $).$;
+			}
+
+			if ( ! $.fn.dataTable.FixedColumns ) {
+				require('datatables.net-fixedcolumns')(root, $);
+			}
+
+			return factory( $, root, root.document );
+		};
+	}
+	else {
+		// Browser
+		factory( jQuery, window, document );
+	}
+}(function( $, window, document, undefined ) {
+
+return $.fn.dataTable;
+
+}));

+ 38 - 0
app/public/js/datatable/fixedColumns.foundation.js

@@ -0,0 +1,38 @@
+/*! Bootstrap 4 styling wrapper for FixedColumns
+ * ©2018 SpryMedia Ltd - datatables.net/license
+ */
+
+(function( factory ){
+	if ( typeof define === 'function' && define.amd ) {
+		// AMD
+		define( ['jquery', 'datatables.net-zf', 'datatables.net-fixedcolumns'], function ( $ ) {
+			return factory( $, window, document );
+		} );
+	}
+	else if ( typeof exports === 'object' ) {
+		// CommonJS
+		module.exports = function (root, $) {
+			if ( ! root ) {
+				root = window;
+			}
+
+			if ( ! $ || ! $.fn.dataTable ) {
+				$ = require('datatables.net-zf')(root, $).$;
+			}
+
+			if ( ! $.fn.dataTable.FixedColumns ) {
+				require('datatables.net-fixedcolumns')(root, $);
+			}
+
+			return factory( $, root, root.document );
+		};
+	}
+	else {
+		// Browser
+		factory( jQuery, window, document );
+	}
+}(function( $, window, document, undefined ) {
+
+return $.fn.dataTable;
+
+}));

+ 5 - 0
app/public/js/datatable/fixedColumns.foundation.min.js

@@ -0,0 +1,5 @@
+/*!
+ Bootstrap 4 styling wrapper for FixedColumns
+ ©2018 SpryMedia Ltd - datatables.net/license
+*/
+(function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net-zf","datatables.net-fixedcolumns"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);if(!b||!b.fn.dataTable)b=require("datatables.net-zf")(a,b).$;b.fn.dataTable.FixedColumns||require("datatables.net-fixedcolumns")(a,b);return c(b,a,a.document)}:c(jQuery,window,document)})(function(c){return c.fn.dataTable});

+ 38 - 0
app/public/js/datatable/fixedColumns.jqueryui.js

@@ -0,0 +1,38 @@
+/*! jQuery UI styling wrapper for FixedColumns
+ * ©2018 SpryMedia Ltd - datatables.net/license
+ */
+
+(function( factory ){
+	if ( typeof define === 'function' && define.amd ) {
+		// AMD
+		define( ['jquery', 'datatables.net-jqui', 'datatables.net-fixedcolumns'], function ( $ ) {
+			return factory( $, window, document );
+		} );
+	}
+	else if ( typeof exports === 'object' ) {
+		// CommonJS
+		module.exports = function (root, $) {
+			if ( ! root ) {
+				root = window;
+			}
+
+			if ( ! $ || ! $.fn.dataTable ) {
+				$ = require('datatables.net-jqui')(root, $).$;
+			}
+
+			if ( ! $.fn.dataTable.FixedColumns ) {
+				require('datatables.net-fixedcolumns')(root, $);
+			}
+
+			return factory( $, root, root.document );
+		};
+	}
+	else {
+		// Browser
+		factory( jQuery, window, document );
+	}
+}(function( $, window, document, undefined ) {
+
+return $.fn.dataTable;
+
+}));

+ 5 - 0
app/public/js/datatable/fixedColumns.jqueryui.min.js

@@ -0,0 +1,5 @@
+/*!
+ jQuery UI styling wrapper for FixedColumns
+ ©2018 SpryMedia Ltd - datatables.net/license
+*/
+(function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net-jqui","datatables.net-fixedcolumns"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);if(!b||!b.fn.dataTable)b=require("datatables.net-jqui")(a,b).$;b.fn.dataTable.FixedColumns||require("datatables.net-fixedcolumns")(a,b);return c(b,a,a.document)}:c(jQuery,window,document)})(function(c){return c.fn.dataTable});

+ 38 - 0
app/public/js/datatable/fixedColumns.semanicui.js

@@ -0,0 +1,38 @@
+/*! Semanic UI styling wrapper for FixedColumns
+ * ©2018 SpryMedia Ltd - datatables.net/license
+ */
+
+(function( factory ){
+	if ( typeof define === 'function' && define.amd ) {
+		// AMD
+		define( ['jquery', 'datatables.net-se', 'datatables.net-fixedcolumns'], function ( $ ) {
+			return factory( $, window, document );
+		} );
+	}
+	else if ( typeof exports === 'object' ) {
+		// CommonJS
+		module.exports = function (root, $) {
+			if ( ! root ) {
+				root = window;
+			}
+
+			if ( ! $ || ! $.fn.dataTable ) {
+				$ = require('datatables.net-se')(root, $).$;
+			}
+
+			if ( ! $.fn.dataTable.FixedColumns ) {
+				require('datatables.net-fixedcolumns')(root, $);
+			}
+
+			return factory( $, root, root.document );
+		};
+	}
+	else {
+		// Browser
+		factory( jQuery, window, document );
+	}
+}(function( $, window, document, undefined ) {
+
+return $.fn.dataTable;
+
+}));

+ 38 - 0
app/public/js/datatable/fixedColumns.semanticui.js

@@ -0,0 +1,38 @@
+/*! Semanic UI styling wrapper for FixedColumns
+ * ©2018 SpryMedia Ltd - datatables.net/license
+ */
+
+(function( factory ){
+	if ( typeof define === 'function' && define.amd ) {
+		// AMD
+		define( ['jquery', 'datatables.net-se', 'datatables.net-fixedcolumns'], function ( $ ) {
+			return factory( $, window, document );
+		} );
+	}
+	else if ( typeof exports === 'object' ) {
+		// CommonJS
+		module.exports = function (root, $) {
+			if ( ! root ) {
+				root = window;
+			}
+
+			if ( ! $ || ! $.fn.dataTable ) {
+				$ = require('datatables.net-se')(root, $).$;
+			}
+
+			if ( ! $.fn.dataTable.FixedColumns ) {
+				require('datatables.net-fixedcolumns')(root, $);
+			}
+
+			return factory( $, root, root.document );
+		};
+	}
+	else {
+		// Browser
+		factory( jQuery, window, document );
+	}
+}(function( $, window, document, undefined ) {
+
+return $.fn.dataTable;
+
+}));

+ 5 - 0
app/public/js/datatable/fixedColumns.semanticui.min.js

@@ -0,0 +1,5 @@
+/*!
+ Semanic UI styling wrapper for FixedColumns
+ ©2018 SpryMedia Ltd - datatables.net/license
+*/
+(function(c){"function"===typeof define&&define.amd?define(["jquery","datatables.net-se","datatables.net-fixedcolumns"],function(a){return c(a,window,document)}):"object"===typeof exports?module.exports=function(a,b){a||(a=window);if(!b||!b.fn.dataTable)b=require("datatables.net-se")(a,b).$;b.fn.dataTable.FixedColumns||require("datatables.net-fixedcolumns")(a,b);return c(b,a,a.document)}:c(jQuery,window,document)})(function(c){return c.fn.dataTable});

+ 53 - 0
app/public/js/datatable/jlzf-change-table.js

@@ -0,0 +1,53 @@
+$(function(){
+    //datatables基本设置
+    $.extend( $.fn.dataTable.defaults, {
+        paging: false,
+        ordering: false,
+        searching: false,
+        info: false,
+        scrollX: true,
+        scrollY: '500px',
+        scrollCollapse: true,
+        language: {
+            emptyTable: "&nbsp;",
+            zeroRecords:"&nbsp;"
+        }
+    } );
+});
+function RegNum(obj,e,decimal)
+{
+    var pos = obj.selectionEnd;
+    var event = e || window.event;
+    var keyCode = event.keyCode ? event.keyCode : event.which ? event.which : event.charCode;
+    if(keyCode != 37 && keyCode != 39){
+        if (decimal != 0) {
+            //先把非数字的都替换掉,除了数字和.
+            obj.value = obj.value.replace(/[^\d.-]/g,"");
+            //保证第一个数字为0后,第二个数字不能为0
+            obj.value = obj.value !== '0' ? obj.value.replace(/^0+/,'').replace(/^\./,"0.") : obj.value;
+            //保证-0后不能再接0
+            obj.value = obj.value.replace(/^\-0+/g,"-0");
+            //保证只有出现一个.而没有多个.
+            obj.value = obj.value.replace(/\.{2,}/g,".");
+            //必须保证第一个为数字而不是.
+            obj.value = obj.value.replace(/^\./g,"");
+            //保证.只出现一次,而不能出现两次以上
+            obj.value = obj.value.replace(".","$#$").replace(/\./g,"").replace("$#$",".");
+            //保证-只能出现一次,且必须在第一位
+            obj.value = parseFloat(obj.value) > 0 ? obj.value.replace(/\-/g,"") : obj.value.replace("-","$#$").replace(/\-/g,"").replace("$#$","-");
+            //只能输入deciaml 位小数
+            var reg = new RegExp("^(\\-)*(\\d+)\\.(\\d{1,"+decimal+"}).*$");
+            obj.value = obj.value.replace(reg,'$1$2.$3');
+        } else {
+            //先把非数字的都替换掉,除了数字和.
+            obj.value = obj.value.replace(/[^\d-]/g,"");
+            //保证第一个数字为0后,第二个数字不能为0
+            obj.value = obj.value !== '0' ? obj.value.replace(/^0+/,'') : obj.value;
+            //保证-0后不能再接0
+            obj.value = obj.value.replace(/^\-0+/g,"-0");
+            //保证-只能出现一次,且必须在第一位
+            obj.value = parseFloat(obj.value) > 0 ? obj.value.replace(/\-/g,"") : obj.value.replace("-","$#$").replace(/\-/g,"").replace("$#$","-");
+        }
+    }
+    obj.setSelectionRange(pos,pos);
+}

Plik diff jest za duży
+ 15296 - 0
app/public/js/datatable/jquery.dataTables.js


Plik diff jest za duży
+ 166 - 0
app/public/js/datatable/jquery.dataTables.min.js


+ 706 - 0
app/public/js/datatable/jquery.fixedheadertable.js

@@ -0,0 +1,706 @@
+/*!
+ * jquery.fixedHeaderTable. The jQuery fixedHeaderTable plugin
+ *
+ * Copyright (c) 2013 Mark Malek
+ * http://fixedheadertable.com
+ *
+ * Licensed under MIT
+ * http://www.opensource.org/licenses/mit-license.php
+ *
+ * http://docs.jquery.com/Plugins/Authoring
+ * jQuery authoring guidelines
+ *
+ * Launch  : October 2009
+ * Version : 1.3
+ * Released: May 9th, 2011
+ *
+ *
+ * all CSS sizing (width,height) is done in pixels (px)
+ */
+
+(function ($) {
+
+  $.fn.fixedHeaderTable = function (method) {
+
+    // plugin's default options
+    var defaults = {
+      width:          '100%',
+      height:         '100%',
+      themeClass:     'fht-default',
+      borderCollapse:  true,
+      fixedColumns:    0, // fixed first columns
+      fixedColumn:     false, // For backward-compatibility
+      sortable:        false,
+      autoShow:        true, // hide table after its created
+      footer:          false, // show footer
+      cloneHeadToFoot: false, // clone head and use as footer
+      autoResize:      false, // resize table if its parent wrapper changes size
+      create:          null // callback after plugin completes
+    };
+
+    var settings = {};
+
+    // public methods
+    var methods = {
+      init: function (options) {
+        settings = $.extend({}, defaults, options);
+
+        // iterate through all the DOM elements we are attaching the plugin to
+        return this.each(function () {
+          var $self = $(this); // reference the jQuery version of the current DOM element
+
+          if (helpers._isTable($self)) {
+            methods.setup.apply(this, Array.prototype.slice.call(arguments, 1));
+            $.isFunction(settings.create) && settings.create.call(this);
+          } else {
+            $.error('Invalid table mark-up');
+          }
+        });
+      },
+
+      /*
+       * Setup table structure for fixed headers and optional footer
+       */
+      setup: function () {
+        var $self       = $(this),
+            self        = this,
+            $thead      = $self.find('thead'),
+            $tfoot      = $self.find('tfoot'),
+            tfootHeight = 0,
+            $wrapper,
+            $divHead,
+            $divBody,
+            $fixedBody,
+            widthMinusScrollbar;
+
+        settings.originalTable = $(this).clone();
+        settings.includePadding = helpers._isPaddingIncludedWithWidth();
+        settings.scrollbarOffset = helpers._getScrollbarWidth();
+        settings.themeClassName = settings.themeClass;
+
+        if (settings.width.search('%') > -1) {
+            widthMinusScrollbar = $self.parent().width() - settings.scrollbarOffset;
+        } else {
+            widthMinusScrollbar = settings.width - settings.scrollbarOffset;
+        }
+
+        $self.css({
+          width: widthMinusScrollbar
+        });
+
+
+        if (!$self.closest('.fht-table-wrapper').length) {
+          $self.addClass('fht-table');
+          $self.wrap('<div class="fht-table-wrapper"></div>');
+        }
+
+        $wrapper = $self.closest('.fht-table-wrapper');
+
+        if(settings.fixedColumn == true && settings.fixedColumns <= 0) {
+          settings.fixedColumns = 1;
+        }
+
+        if (settings.fixedColumns > 0 && $wrapper.find('.fht-fixed-column').length == 0) {
+          $self.wrap('<div class="fht-fixed-body"></div>');
+
+          $('<div class="fht-fixed-column"></div>').prependTo($wrapper);
+
+          $fixedBody    = $wrapper.find('.fht-fixed-body');
+        }
+
+        $wrapper.css({
+          width: settings.width,
+          height: settings.height
+        })
+          .addClass(settings.themeClassName);
+
+        if (!$self.hasClass('fht-table-init')) {
+          $self.wrap('<div class="fht-tbody"></div>');
+        }
+
+        $divBody = $self.closest('.fht-tbody');
+
+        var tableProps = helpers._getTableProps($self);
+
+        helpers._setupClone($divBody, tableProps.tbody);
+
+        if (!$self.hasClass('fht-table-init')) {
+          if (settings.fixedColumns > 0) {
+            $divHead = $('<div class="fht-thead"><table class="fht-table"></table></div>').prependTo($fixedBody);
+          } else {
+            $divHead = $('<div class="fht-thead"><table class="fht-table"></table></div>').prependTo($wrapper);
+          }
+
+          $divHead.find('table.fht-table')
+            .addClass(settings.originalTable.attr('class'))
+            .attr('style', settings.originalTable.attr('style'));
+
+          $thead.clone().appendTo($divHead.find('table'));
+        } else {
+          $divHead = $wrapper.find('div.fht-thead');
+        }
+
+        helpers._setupClone($divHead, tableProps.thead);
+
+        $self.css({
+          'margin-top': -$divHead.outerHeight(true)
+        });
+
+        /*
+         * Check for footer
+         * Setup footer if present
+         */
+        if (settings.footer == true) {
+          helpers._setupTableFooter($self, self, tableProps);
+
+          if (!$tfoot.length) {
+            $tfoot = $wrapper.find('div.fht-tfoot table');
+          }
+
+          tfootHeight = $tfoot.outerHeight(true);
+        }
+
+        var tbodyHeight = $wrapper.height() - $thead.outerHeight(true) - tfootHeight - tableProps.border;
+
+        $divBody.css({
+          'height': tbodyHeight
+        });
+
+        $self.addClass('fht-table-init');
+
+        if (typeof(settings.altClass) !== 'undefined') {
+          methods.altRows.apply(self);
+        }
+
+        if (settings.fixedColumns > 0) {
+          helpers._setupFixedColumn($self, self, tableProps);
+        }
+
+        if (!settings.autoShow) {
+          $wrapper.hide();
+        }
+
+        helpers._bindScroll($divBody, tableProps);
+
+        return self;
+      },
+
+      /*
+       * Resize the table
+       * Incomplete - not implemented yet
+       */
+      resize: function() {
+        var self  = this;
+        return self;
+      },
+
+      /*
+       * Add CSS class to alternating rows
+       */
+      altRows: function(arg1) {
+        var $self = $(this),
+        altClass  = (typeof(arg1) !== 'undefined') ? arg1 : settings.altClass;
+
+        $self.closest('.fht-table-wrapper')
+          .find('tbody tr:odd:not(:hidden)')
+          .addClass(altClass);
+      },
+
+      /*
+       * Show a hidden fixedHeaderTable table
+       */
+      show: function(arg1, arg2, arg3) {
+        var $self   = $(this),
+            self      = this,
+            $wrapper  = $self.closest('.fht-table-wrapper');
+
+        // User provided show duration without a specific effect
+        if (typeof(arg1) !== 'undefined' && typeof(arg1) === 'number') {
+          $wrapper.show(arg1, function() {
+            $.isFunction(arg2) && arg2.call(this);
+          });
+
+          return self;
+
+        } else if (typeof(arg1) !== 'undefined' && typeof(arg1) === 'string' &&
+          typeof(arg2) !== 'undefined' && typeof(arg2) === 'number') {
+          // User provided show duration with an effect
+
+          $wrapper.show(arg1, arg2, function() {
+            $.isFunction(arg3) && arg3.call(this);
+          });
+
+          return self;
+
+        }
+
+        $self.closest('.fht-table-wrapper')
+          .show();
+        $.isFunction(arg1) && arg1.call(this);
+
+        return self;
+      },
+
+      /*
+       * Hide a fixedHeaderTable table
+       */
+      hide: function(arg1, arg2, arg3) {
+        var $self     = $(this),
+            self    = this,
+            $wrapper  = $self.closest('.fht-table-wrapper');
+
+        // User provided show duration without a specific effect
+        if (typeof(arg1) !== 'undefined' && typeof(arg1) === 'number') {
+          $wrapper.hide(arg1, function() {
+            $.isFunction(arg3) && arg3.call(this);
+          });
+
+          return self;
+        } else if (typeof(arg1) !== 'undefined' && typeof(arg1) === 'string' &&
+          typeof(arg2) !== 'undefined' && typeof(arg2) === 'number') {
+
+          $wrapper.hide(arg1, arg2, function() {
+            $.isFunction(arg3) && arg3.call(this);
+          });
+
+          return self;
+        }
+
+        $self.closest('.fht-table-wrapper')
+          .hide();
+
+        $.isFunction(arg3) && arg3.call(this);
+
+
+
+        return self;
+      },
+
+      /*
+       * Destory fixedHeaderTable and return table to original state
+       */
+      destroy: function() {
+        var $self    = $(this),
+            self     = this,
+            $wrapper = $self.closest('.fht-table-wrapper');
+
+        $self.insertBefore($wrapper)
+          .removeAttr('style')
+          .append($wrapper.find('tfoot'))
+          .removeClass('fht-table fht-table-init')
+          .find('.fht-cell')
+          .remove();
+
+        $wrapper.remove();
+
+        return self;
+      }
+
+    };
+
+    // private methods
+    var helpers = {
+
+      /*
+       * return boolean
+       * True if a thead and tbody exist.
+       */
+      _isTable: function($obj) {
+        var $self = $obj,
+            hasTable = $self.is('table'),
+            hasThead = $self.find('thead').length > 0,
+            hasTbody = $self.find('tbody').length > 0;
+
+        if (hasTable && hasThead && hasTbody) {
+          return true;
+        }
+
+        return false;
+
+      },
+
+      /*
+       * return void
+       * bind scroll event
+       */
+      _bindScroll: function($obj) {
+        var $self = $obj,
+            $wrapper = $self.closest('.fht-table-wrapper'),
+            $thead = $self.siblings('.fht-thead'),
+            $tfoot = $self.siblings('.fht-tfoot');
+
+        $self.bind('scroll', function() {
+          if (settings.fixedColumns > 0) {
+            var $fixedColumns = $wrapper.find('.fht-fixed-column');
+
+            $fixedColumns.find('.fht-tbody table')
+              .css({
+                  'margin-top': -$self.scrollTop()
+              });
+          }
+
+          $thead.find('table')
+            .css({
+              'margin-left': -this.scrollLeft
+            });
+
+          if (settings.footer || settings.cloneHeadToFoot) {
+            $tfoot.find('table')
+              .css({
+                'margin-left': -this.scrollLeft
+              });
+          }
+        });
+      },
+
+      /*
+       * return void
+       */
+      _fixHeightWithCss: function ($obj, tableProps) {
+        if (settings.includePadding) {
+          $obj.css({
+            'height': $obj.height() + tableProps.border
+          });
+        } else {
+          $obj.css({
+            'height': $obj.parent().height() + tableProps.border
+          });
+        }
+      },
+
+      /*
+       * return void
+       */
+      _fixWidthWithCss: function($obj, tableProps, width) {
+        if (settings.includePadding) {
+          $obj.each(function() {
+            $(this).css({
+              'width': width == undefined ? $(this).width() + tableProps.border : width + tableProps.border
+            });
+          });
+        } else {
+          $obj.each(function() {
+            $(this).css({
+              'width': width == undefined ? $(this).parent().width() + tableProps.border : width + tableProps.border
+            });
+          });
+        }
+
+      },
+
+      /*
+       * return void
+       */
+      _setupFixedColumn: function ($obj, obj, tableProps) {
+        var $self             = $obj,
+            $wrapper          = $self.closest('.fht-table-wrapper'),
+            $fixedBody        = $wrapper.find('.fht-fixed-body'),
+            $fixedColumn      = $wrapper.find('.fht-fixed-column'),
+            $thead            = $('<div class="fht-thead"><table class="fht-table"><thead><tr></tr></thead></table></div>'),
+            $tbody            = $('<div class="fht-tbody"><table class="fht-table"><tbody></tbody></table></div>'),
+            $tfoot            = $('<div class="fht-tfoot"><table class="fht-table"><tfoot><tr></tr></tfoot></table></div>'),
+            fixedBodyWidth    = $wrapper.width(),
+            fixedBodyHeight   = $fixedBody.find('.fht-tbody').height() - settings.scrollbarOffset,
+            $firstThChildren,
+            $firstTdChildren,
+            fixedColumnWidth,
+            $newRow,
+            firstTdChildrenSelector;
+
+        $thead.find('table.fht-table').addClass(settings.originalTable.attr('class'));
+        $tbody.find('table.fht-table').addClass(settings.originalTable.attr('class'));
+        $tfoot.find('table.fht-table').addClass(settings.originalTable.attr('class'));
+
+        $firstThChildren = $fixedBody.find('.fht-thead thead tr > *:lt(' + settings.fixedColumns + ')');
+        fixedColumnWidth = settings.fixedColumns * tableProps.border;
+        $firstThChildren.each(function() {
+          fixedColumnWidth += $(this).outerWidth(true);
+        });
+
+        // Fix cell heights
+        helpers._fixHeightWithCss($firstThChildren, tableProps);
+        helpers._fixWidthWithCss($firstThChildren, tableProps);
+
+        var tdWidths = [];
+        $firstThChildren.each(function() {
+          tdWidths.push($(this).width());
+        });
+
+        firstTdChildrenSelector = 'tbody tr > *:not(:nth-child(n+' + (settings.fixedColumns + 1) + '))';
+        $firstTdChildren = $fixedBody.find(firstTdChildrenSelector)
+          .each(function(index) {
+            helpers._fixHeightWithCss($(this), tableProps);
+            helpers._fixWidthWithCss($(this), tableProps, tdWidths[index % settings.fixedColumns] );
+          });
+
+        // clone header
+        $thead.appendTo($fixedColumn)
+          .find('tr')
+          .append($firstThChildren.clone());
+
+        $tbody.appendTo($fixedColumn)
+          .css({
+            'margin-top': -1,
+            'height': fixedBodyHeight + tableProps.border
+          });
+
+        $firstTdChildren.each(function(index) {
+          if (index % settings.fixedColumns == 0) {
+            $newRow = $('<tr></tr>').appendTo($tbody.find('tbody'));
+
+            if (settings.altClass && $(this).parent().hasClass(settings.altClass)) {
+              $newRow.addClass(settings.altClass);
+            }
+          }
+
+          $(this).clone()
+            .appendTo($newRow);
+        });
+
+        // set width of fixed column wrapper
+        $fixedColumn.css({
+          'height': 0,
+          'width': fixedColumnWidth
+        });
+
+
+        // bind mousewheel events
+        var maxTop = $fixedColumn.find('.fht-tbody .fht-table').height() - $fixedColumn.find('.fht-tbody').height();
+        $fixedColumn.find('.fht-tbody .fht-table').bind('mousewheel', function(event, delta, deltaX, deltaY) {
+          if (deltaY == 0) {
+            return;
+          }
+          var top = parseInt($(this).css('marginTop'), 10) + (deltaY > 0 ? 120 : -120);
+          if (top > 0) {
+            top = 0;
+          }
+          if (top < -maxTop) {
+            top = -maxTop;
+          }
+          $(this).css('marginTop', top);
+          $fixedBody.find('.fht-tbody').scrollTop(-top).scroll();
+          return false;
+        });
+
+
+        // set width of body table wrapper
+        $fixedBody.css({
+          'width': fixedBodyWidth
+        });
+
+        // setup clone footer with fixed column
+        if (settings.footer == true || settings.cloneHeadToFoot == true) {
+          var $firstTdFootChild = $fixedBody.find('.fht-tfoot tr > *:lt(' + settings.fixedColumns + ')'),
+              footwidth;
+
+          helpers._fixHeightWithCss($firstTdFootChild, tableProps);
+          $tfoot.appendTo($fixedColumn)
+            .find('tr')
+            .append($firstTdFootChild.clone());
+          // Set (view width) of $tfoot div to width of table (this accounts for footers with a colspan)
+          footwidth = $tfoot.find('table').innerWidth();
+          $tfoot.css({
+            'top': settings.scrollbarOffset,
+            'width': footwidth
+          });
+        }
+      },
+
+      /*
+       * return void
+       */
+      _setupTableFooter: function ($obj, obj, tableProps) {
+        var $self     = $obj,
+            $wrapper  = $self.closest('.fht-table-wrapper'),
+            $tfoot    = $self.find('tfoot'),
+            $divFoot  = $wrapper.find('div.fht-tfoot');
+
+        if (!$divFoot.length) {
+          if (settings.fixedColumns > 0) {
+            $divFoot = $('<div class="fht-tfoot"><table class="fht-table"></table></div>').appendTo($wrapper.find('.fht-fixed-body'));
+          } else {
+            $divFoot = $('<div class="fht-tfoot"><table class="fht-table"></table></div>').appendTo($wrapper);
+          }
+        }
+        $divFoot.find('table.fht-table').addClass(settings.originalTable.attr('class'));
+
+        switch (true) {
+          case !$tfoot.length && settings.cloneHeadToFoot == true && settings.footer == true:
+
+            var $divHead = $wrapper.find('div.fht-thead');
+
+            $divFoot.empty();
+            $divHead.find('table')
+              .clone()
+              .appendTo($divFoot);
+
+            break;
+          case $tfoot.length && settings.cloneHeadToFoot == false && settings.footer == true:
+
+            $divFoot.find('table')
+              .append($tfoot)
+              .css({
+                'margin-top': -tableProps.border
+              });
+
+            helpers._setupClone($divFoot, tableProps.tfoot);
+
+            break;
+        }
+
+      },
+
+      /*
+       * return object
+       * Widths of each thead cell and tbody cell for the first rows.
+       * Used in fixing widths for the fixed header and optional footer.
+       */
+      _getTableProps: function($obj) {
+        var tableProp = {
+              thead: {},
+              tbody: {},
+              tfoot: {},
+              border: 0
+            },
+            borderCollapse = 1;
+
+        if (settings.borderCollapse == true) {
+          borderCollapse = 2;
+        }
+
+        tableProp.border = ($obj.find('th:first-child').outerWidth() - $obj.find('th:first-child').innerWidth()) / borderCollapse;
+
+        $obj.find('thead tr:first-child > *').each(function(index) {
+          tableProp.thead[index] = $(this).width() + tableProp.border;
+        });
+
+        $obj.find('tfoot tr:first-child > *').each(function(index) {
+          tableProp.tfoot[index] = $(this).width() + tableProp.border;
+        });
+
+        $obj.find('tbody tr:first-child > *').each(function(index) {
+          tableProp.tbody[index] = $(this).width() + tableProp.border;
+        });
+
+        return tableProp;
+      },
+
+      /*
+       * return void
+       * Fix widths of each cell in the first row of obj.
+       */
+      _setupClone: function($obj, cellArray) {
+        var $self    = $obj,
+            selector = ($self.find('thead').length) ?
+              'thead tr:first-child > *' :
+              ($self.find('tfoot').length) ?
+              'tfoot tr:first-child > *' :
+              'tbody tr:first-child > *',
+            $cell;
+
+        $self.find(selector).each(function(index) {
+          $cell = ($(this).find('div.fht-cell').length) ? $(this).find('div.fht-cell') : $('<div class="fht-cell"></div>').appendTo($(this));
+
+          $cell.css({
+            'width': parseInt(cellArray[index], 10)
+          });
+
+          /*
+           * Fixed Header and Footer should extend the full width
+           * to align with the scrollbar of the body
+           */
+          if (!$(this).closest('.fht-tbody').length && $(this).is(':last-child') && !$(this).closest('.fht-fixed-column').length) {
+            var padding = Math.max((($(this).innerWidth() - $(this).width()) / 2), settings.scrollbarOffset);
+            $(this).css({
+              'padding-right': parseInt($(this).css('padding-right')) + padding + 'px'
+            });
+          }
+        });
+      },
+
+      /*
+       * return boolean
+       * Determine how the browser calculates fixed widths with padding for tables
+       * true if width = padding + width
+       * false if width = width
+       */
+      _isPaddingIncludedWithWidth: function() {
+        var $obj = $('<table class="fht-table"><tr><td style="padding: 10px; font-size: 10px;">test</td></tr></table>'),
+            defaultHeight,
+            newHeight;
+
+        $obj.addClass(settings.originalTable.attr('class'));
+        $obj.appendTo('body');
+
+        defaultHeight = $obj.find('td').height();
+
+        $obj.find('td')
+          .css('height', $obj.find('tr').height());
+
+        newHeight = $obj.find('td').height();
+        $obj.remove();
+
+        if (defaultHeight != newHeight) {
+          return true;
+        } else {
+          return false;
+        }
+
+      },
+
+      /*
+       * return int
+       * get the width of the browsers scroll bar
+       */
+      _getScrollbarWidth: function() {
+        var scrollbarWidth = 0;
+
+        if (!scrollbarWidth) {
+          if (/msie/.test(navigator.userAgent.toLowerCase())) {
+            var $textarea1 = $('<textarea cols="10" rows="2"></textarea>')
+                  .css({ position: 'absolute', top: -1000, left: -1000 }).appendTo('body'),
+                $textarea2 = $('<textarea cols="10" rows="2" style="overflow: hidden;"></textarea>')
+                  .css({ position: 'absolute', top: -1000, left: -1000 }).appendTo('body');
+
+            scrollbarWidth = $textarea1.width() - $textarea2.width() + 2; // + 2 for border offset
+            $textarea1.add($textarea2).remove();
+          } else {
+            var $div = $('<div />')
+                  .css({ width: 100, height: 100, overflow: 'auto', position: 'absolute', top: -1000, left: -1000 })
+                  .prependTo('body').append('<div />').find('div')
+                  .css({ width: '100%', height: 200 });
+
+            scrollbarWidth = 100 - $div.width();
+            $div.parent().remove();
+          }
+        }
+
+        return scrollbarWidth;
+      }
+
+    };
+
+
+    // if a method as the given argument exists
+    if (methods[method]) {
+
+      // call the respective method
+      return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
+
+      // if an object is given as method OR nothing is given as argument
+    } else if (typeof method === 'object' || !method) {
+
+      // call the initialization method
+      return methods.init.apply(this, arguments);
+
+      // otherwise
+    } else {
+
+      // trigger an error
+      $.error('Method "' +  method + '" does not exist in fixedHeaderTable plugin!');
+
+    }
+
+  };
+
+})(jQuery);

Plik diff jest za duży
+ 20 - 0
app/public/js/datatable/jquery.fixedheadertable.min.js


+ 808 - 0
app/public/js/datatable/jquery.tablesorter.js

@@ -0,0 +1,808 @@
+/*
+ * 
+ * TableSorter 2.0 - Client-side table sorting with ease!
+ * Version 2.0
+ * @requires jQuery v1.1.3
+ * 
+ * Copyright (c) 2007 Christian Bach
+ * Examples and docs at: http://tablesorter.com
+ * Dual licensed under the MIT and GPL licenses:
+ * http://www.opensource.org/licenses/mit-license.php
+ * http://www.gnu.org/licenses/gpl.html
+ * 
+ */
+/**
+ *
+ * @description Create a sortable table with multi-column sorting capabilitys
+ * 
+ * @example $('#table').tablesorter();
+ * @desc Create a simple tablesorter interface.
+ *
+ * @example $('#table').tablesorter({ sortList:[[0,0],[1,0]] });
+ * @desc Create a tablesorter interface and sort on the first and secound column in ascending order.
+ * 
+ * @example $('#table').tablesorter({ headers: { 0: { sorter: false}, 1: {sorter: false} } });
+ * @desc Create a tablesorter interface and disableing the first and secound column headers.
+ * 
+ * @example $('#table').tablesorter({ 0: {sorter:"integer"}, 1: {sorter:"currency"} });
+ * @desc Create a tablesorter interface and set a column parser for the first and secound column.
+ * 
+ * 
+ * @param Object settings An object literal containing key/value pairs to provide optional settings.
+ * 
+ * @option String cssHeader (optional) 			A string of the class name to be appended to sortable tr elements in the thead of the table. 
+ * 												Default value: "header"
+ * 
+ * @option String cssAsc (optional) 			A string of the class name to be appended to sortable tr elements in the thead on a ascending sort. 
+ * 												Default value: "headerSortUp"
+ * 
+ * @option String cssDesc (optional) 			A string of the class name to be appended to sortable tr elements in the thead on a descending sort. 
+ * 												Default value: "headerSortDown"
+ * 
+ * @option String sortInitialOrder (optional) 	A string of the inital sorting order can be asc or desc. 
+ * 												Default value: "asc"
+ * 
+ * @option String sortMultisortKey (optional) 	A string of the multi-column sort key. 
+ * 												Default value: "shiftKey"
+ * 
+ * @option String textExtraction (optional) 	A string of the text-extraction method to use. 
+ * 												For complex html structures inside td cell set this option to "complex", 
+ * 												on large tables the complex option can be slow. 
+ * 												Default value: "simple"
+ * 
+ * @option Object headers (optional) 			An array containing the forces sorting rules. 
+ * 												This option let's you specify a default sorting rule. 
+ * 												Default value: null
+ * 
+ * @option Array sortList (optional) 			An array containing the forces sorting rules. 
+ * 												This option let's you specify a default sorting rule. 
+ * 												Default value: null
+ * 
+ * @option Array sortForce (optional) 			An array containing the forces sorting rules. 
+ * 												This option let's you specify a default sorting rule. 
+ * 												Default value: null
+ *  
+ * 
+ * @option Boolean widthFixed (optional) 		Boolean flag indicating if tablesorter should apply fixed widths to the table columns.
+ * 												This is usefull when using the pager companion plugin.
+ * 												This options requires the dimension jquery plugin.
+ * 												Default value: false
+ *
+ * @option Boolean cancelSelection (optional) 	Boolean flag indicating if tablesorter should cancel selection of the table headers text.
+ * 												Default value: true
+ * 
+ * @type jQuery
+ *
+ * @name tablesorter
+ * 
+ * @cat Plugins/Tablesorter
+ * 
+ * @author Christian Bach/christian.bach@polyester.se
+ */
+
+(function($) {
+	$.extend({
+		tablesorter: new function() {
+			
+			var parsers = [], widgets = [];
+			
+			this.defaults = {
+				cssHeader: "header",
+				cssAsc: "headerSortUp",
+				cssDesc: "headerSortDown",
+				sortInitialOrder: "asc",
+				sortMultiSortKey: "shiftKey",
+				sortForce: null,
+				textExtraction: "simple",
+				parsers: {}, 
+				widgets: [],		
+				widgetZebra: {css: ["even","odd"]},
+				headers: {},
+				widthFixed: false,
+				cancelSelection: true,
+				sortList: [],
+				headerList: [],
+				dateFormat: "us",
+				debug: false
+			};
+			
+			/* debuging utils */
+			function benchmark(label,stamp) {
+				log(label + "," + (new Date().getTime() - stamp.getTime()) + "ms");
+			}
+			
+			function log(s) {
+				if (typeof console != "undefined" && typeof console.debug != "undefined") {
+					console.log(s);
+				} else {
+					alert(s);
+				}
+			}
+						
+			/* parsers utils */
+			function buildParserCache(table,$headers) {
+				
+				if(table.config.debug) { var parsersDebug = ""; }
+				
+				var list = [], cells = table.tBodies[0].rows[0].cells, l = cells.length;
+				
+				for (var i=0;i < l; i++) {
+					var p = false;
+					
+					if($.meta && ($($headers[i]).data() && $($headers[i]).data().sorter)  ) {
+					
+						p = getParserById($($headers[i]).data().sorter);	
+					
+					} else if((table.config.headers[i] && table.config.headers[i].sorter)) {
+
+						p = getParserById(table.config.headers[i].sorter);
+					}
+					if(!p) {
+						p = detectParserForColumn(table.config,cells[i]);
+					}
+
+					if(table.config.debug) { parsersDebug += "column:" + i + " parser:" +p.id + "\n"; }
+
+					list.push(p);
+				}
+
+				if(table.config.debug) { log(parsersDebug); }
+
+				return list;
+			};
+			
+			function detectParserForColumn(config,node) {
+				var l = parsers.length;
+				for(var i=1; i < l; i++) {
+					if(parsers[i].is($.trim(getElementText(config,node)))) {
+						return parsers[i];
+					}
+				}
+				
+				// 0 is always the generic parser (text)
+				return parsers[0];
+			}
+			
+			function getParserById(name) {
+				var l = parsers.length;
+				for(var i=0; i < l; i++) {
+					if(parsers[i].id.toLowerCase() == name.toLowerCase()) {	
+						return parsers[i];
+					}
+				}
+				return false;
+			}
+			
+			/* utils */
+			function buildCache(table) {
+				
+				if(table.config.debug) { var cacheTime = new Date(); }
+				
+				var totalRows = (table.tBodies[0] && table.tBodies[0].rows.length) || 0,
+					totalCells = table.tBodies[0].rows[0].cells.length,
+					parsers = table.config.parsers, 
+					cache = {row: [], normalized: []};
+				
+					for (var i=0;i < totalRows; ++i) {
+					
+						/** Add the table data to main data array */
+						var c = table.tBodies[0].rows[i], cols = [];
+					
+						cache.row.push($(c));
+						
+						for(var j=0; j < totalCells; ++j) {
+							cols.push(parsers[j].format(getElementText(table.config,c.cells[j]),table,c.cells[j]));	
+						}
+												
+						cols.push(i); // add position for rowCache
+						cache.normalized.push(cols);
+						cols = null;
+					};
+				
+				if(table.config.debug) { benchmark("Building cache for " + totalRows + " rows:", cacheTime); }
+				
+				return cache;
+			};
+			
+			function getElementText(config,node) {
+				
+				if(!node) return "";
+								
+				var t = "";
+				
+				
+				if(typeof(config.textExtraction) == "function") {
+					t = config.textExtraction(node);
+				} else if(config.textExtraction == "complex") { 
+					t = $(node).text();
+				} else {
+					if(node.childNodes[0] && node.childNodes[0].hasChildNodes()) {
+						t = node.childNodes[0].innerHTML;
+					} else {
+						t = node.innerHTML;
+					}
+				}
+				return t;
+			}
+			
+			function appendToTable(table,cache) {
+				
+				if(table.config.debug) {var appendTime = new Date()}
+				
+				var c = cache, 
+					r = c.row, 
+					n= c.normalized, 
+					totalRows = n.length, 
+					checkCell = (n[0].length-1), 
+					tableBody = $("tbody:first",table).empty();
+					rows = [];
+				
+				for (var i=0;i < totalRows; i++) {
+					 	rows.push(r[n[i][checkCell]]);
+						if(table.config.appender == null) {
+							tableBody.append(r[n[i][checkCell]]);
+						}
+				}	
+
+				if(table.config.appender != null) {
+					table.config.appender(table,rows);	
+				}
+				
+				rows = null;
+				
+				//apply table widgets
+				applyWidget(table);
+				
+				if(table.config.debug) { benchmark("Rebuilt table:", appendTime); }
+			
+			};
+			
+			function buildHeaders(table) {
+				
+				if(table.config.debug) { var time = new Date(); }
+				
+				var meta = ($.meta) ? true : false, tableHeadersRows = [];
+			
+				for(var i = 0; i < table.tHead.rows.length; i++) { tableHeadersRows[i]=0; };
+				
+				$tableHeaders = $(checkCellColSpan(table, tableHeadersRows, 0,table.tHead.rows[0].cells.length));
+		
+				$tableHeaders.each(function(index) {
+							
+					this.count = 0;
+					this.column = index;
+					this.order = formatSortingOrder(table.config.sortInitialOrder);
+					
+					if(checkHeaderMetadata(this) || checkHeaderOptions(table,index)) this.sortDisabled = true;
+					
+					if(!this.sortDisabled) {
+						$(this).addClass(table.config.cssHeader);
+					}
+					
+					// add cell to headerList
+					table.config.headerList[index]= this;
+				});
+				
+				if(table.config.debug) { benchmark("Built headers:", time); log($tableHeaders); }
+				
+				return $tableHeaders;
+				
+			};
+						
+		   	function checkCellColSpan(table, headerArr, row) {
+                var arr = [], r = table.tHead.rows, c = r[row].cells;
+				
+				for(var i=headerArr[row]; i < c.length; i++) {
+					var cell = c[i];
+					
+					if ( cell.colSpan > 1) { 
+						arr = arr.concat(checkCellColSpan(table, headerArr,row+cell.rowSpan));
+					} else  {
+						if(table.tHead.length == 1 || (cell.rowSpan > 1 || !r[row+1])) {
+							arr.push(cell);
+						}
+						headerArr[row] = (i+row);
+					}
+				}
+				return arr;
+			};
+			
+			function checkHeaderMetadata(cell) {
+				if(($.meta) && ($(cell).data().sorter === false)) { return true; };
+				return false;
+			}
+			
+			function checkHeaderOptions(table,i) {	
+				if((table.config.headers[i]) && (table.config.headers[i].sorter === false)) { return true; };
+				return false;
+			}
+			
+			function applyWidget(table) {
+				var c = table.config.widgets;
+				var l = c.length;
+				for(var i=0; i < l; i++) {
+					
+					getWidgetById(c[i]).format(table);
+				}
+				
+			}
+			
+			function getWidgetById(name) {
+				var l = widgets.length;
+				for(var i=0; i < l; i++) {
+					if(widgets[i].id.toLowerCase() == name.toLowerCase() ) {
+						return widgets[i]; 
+					}
+				}
+			};
+			
+			function formatSortingOrder(v) {
+				
+				if(typeof(v) != "Number") {
+					i = (v.toLowerCase() == "desc") ? 1 : 0;
+				} else {
+					i = (v == (0 || 1)) ? v : 0;
+				}
+				return i;
+			}
+			
+			function isValueInArray(v, a) {
+				var l = a.length;
+				for(var i=0; i < l; i++) {
+					if(a[i][0] == v) {
+						return true;	
+					}
+				}
+				return false;
+			}
+				
+			function setHeadersCss(table,$headers, list, css) {
+				// remove all header information
+				$headers.removeClass(css[0]).removeClass(css[1]);
+				
+				var h = [];
+				$headers.each(function(offset) {
+						if(!this.sortDisabled) {
+							h[this.column] = $(this);					
+						}
+				});
+
+				var l = list.length; 
+				for(var i=0; i < l; i++) {
+					h[list[i][0]].addClass(css[list[i][1]]);
+				}
+			}
+			
+			function fixColumnWidth(table,$headers) {
+				var c = table.config;
+				if(c.widthFixed) {
+					var colgroup = $('<colgroup>');
+					$("tbody:first tr:first td",table).each(function() {
+						
+						colgroup.append($('<col>').css('width',$(this).width()));
+					
+					});
+					$(table).prepend(colgroup);
+				};
+			}
+			
+			function updateHeaderSortCount(table,sortList) {
+				var c = table.config, l = sortList.length;
+				for(var i=0; i < l; i++) {
+					var s = sortList[i], o = c.headerList[s[0]];
+					o.count = s[1];
+					o.count++;
+				}
+			}
+			
+			/* sorting methods */
+			function multisort(table,sortList,cache) {
+				
+				if(table.config.debug) { var sortTime = new Date(); }
+				
+				var dynamicExp = "var sortWrapper = function(a,b) {", l = sortList.length;
+					
+				for(var i=0; i < l; i++) {
+					
+					var c = sortList[i][0];
+					var order = sortList[i][1];
+					var s = (getCachedSortType(table.config.parsers,c) == "text") ? ((order == 0) ? "sortText" : "sortTextDesc") : ((order == 0) ? "sortNumeric" : "sortNumericDesc");
+					
+					var e = "e" + i;
+					
+					dynamicExp += "var " + e + " = " + s + "(a[" + c + "],b[" + c + "]); ";
+					dynamicExp += "if(" + e + ") { return " + e + "; } ";
+					dynamicExp += "else { ";
+				}
+					
+				for(var i=0; i < l; i++) {
+					dynamicExp += "}; ";
+				}
+				
+				dynamicExp += "return 0; ";	
+				dynamicExp += "}; ";	
+				
+				eval(dynamicExp);
+				
+				cache.normalized.sort(sortWrapper);
+				
+				if(table.config.debug) { benchmark("Sorting on " + sortList.toString() + " and dir " + order+ " time:", sortTime); }
+				
+				return cache;
+			};
+			
+			function sortText(a,b) {
+				return ((a < b) ? -1 : ((a > b) ? 1 : 0));
+			};
+			
+			function sortTextDesc(a,b) {
+				return ((b < a) ? -1 : ((b > a) ? 1 : 0));
+			};	
+			
+	 		function sortNumeric(a,b) {
+				return a-b;
+			};
+			
+			function sortNumericDesc(a,b) {
+				return b-a;
+			};
+			
+			function getCachedSortType(parsers,i) {
+				return parsers[i].type;
+			};
+			
+			/* public methods */
+			this.construct = function(settings) {
+
+				return this.each(function() {
+					
+					
+					
+					
+					var $this, $document,$headers, cache, config, shiftDown = 0, sortOrder;
+					
+					this.config = {};
+					
+					config = $.extend(this.config, $.tablesorter.defaults, settings);
+					
+					if(!this.tHead || !this.tBodies) return true;
+					
+					// store common expression for speed					
+					$this = $(this);
+					
+					// build headers
+					$headers = buildHeaders(this);
+					
+					// try to auto detect column type, and store in tables config
+					this.config.parsers = buildParserCache(this,$headers);
+					
+					
+					// build the cache for the tbody cells
+					cache = buildCache(this);
+					
+					// get the css class names, could be done else where.
+					var sortCSS = [config.cssDesc,config.cssAsc];
+					
+					// fixate columns if the users supplies the fixedWidth option
+					fixColumnWidth(this);
+					
+					// apply event handling to headers
+					// this is to big, perhaps break it out?
+					$headers.click(function(e) {
+						if(!this.sortDisabled) {
+							// store exp, for speed
+							var $cell = $(this);
+	
+							// get current column index
+							var i = this.column;
+							
+							// get current column sort order
+							this.order = this.count++ % 2;
+							
+							
+							
+							// user only whants to sort on one column
+							if(!e[config.sortMultiSortKey]) {
+								
+								// flush the sort list
+								config.sortList = [];
+								
+								if(config.sortForce != null) {
+									var a = config.sortForce; 
+									for(var j=0; j < a.length; j++) { 	
+										config.sortList.push(a[j]);	
+									}
+								}
+								
+								// add column to sort list
+								config.sortList.push([i,this.order]);
+							
+							// multi column sorting	
+							} else {
+								// the user has clicked on an all ready sortet column.
+								if(isValueInArray(i,config.sortList)) {	 
+									
+									// revers the sorting direction for all tables.
+									for(var j=0; j < config.sortList.length; j++) {
+										var s = config.sortList[j], o = config.headerList[s[0]];
+										if(s[0] == i) {
+											o.count = s[1];
+											o.count++;
+											s[1] = o.count % 2;
+										}
+									}	
+								} else {
+									// add column to sort list array
+									config.sortList.push([i,this.order]);
+								}
+							};
+							
+							//set css for headers
+							setHeadersCss($this[0],$headers,config.sortList,sortCSS);
+							
+							// sort the table and append it to the dom
+							appendToTable($this[0],multisort($this[0],config.sortList,cache));
+							
+							// stop normal event by returning false
+							return false;
+						}
+					// cancel selection	
+					}).mousedown(function() {
+						if(config.cancelSelection) {
+							this.onselectstart = function() {return false};
+							//alert(this.onselectstart);
+							return false;
+						}
+					});
+					
+					// apply easy methods that trigger binded events
+					$this.bind("update",function() {
+						
+						// rebuild the cache map
+						cache = buildCache(this);
+						
+					}).bind("sorton",function(e,list) {
+						
+						// update and store the sortlist
+						var sortList = config.sortList = list;
+						
+						// update header count index
+						updateHeaderSortCount(this,sortList);
+						
+						//set css for headers
+						setHeadersCss(this,$headers,sortList,sortCSS);
+						
+						// sort the table and append it to the dom
+						appendToTable(this,multisort(this,sortList,cache));
+						
+					}).bind("appendCache",function() {
+						
+						appendToTable(this,cache);
+					
+					}).bind("applyWidgetId",function(e,id) {
+						
+						getWidgetById(id).format(this);
+						
+					});
+					
+					if($.meta && ($(this).data() && $(this).data().sortlist)) {
+						config.sortList = $(this).data().sortlist;
+					}
+					// if user has supplied a sort list to constructor.
+					if(config.sortList.length > 0) {
+						$this.trigger("sorton",[config.sortList]);	
+					}
+					
+					// apply widgets
+					applyWidget(this);
+				});
+			};
+			
+			this.addParser = function(parser) {
+				var l = parsers.length, a = true;
+				for(var i=0; i < l; i++) {
+					if(parsers[i].id.toLowerCase() == parser.id.toLowerCase()) {
+						a = false;
+					}
+				}
+				if(a) { parsers.push(parser); };
+			};
+			
+			this.addWidget = function(widget) {
+				widgets.push(widget);
+			};
+			
+			this.formatFloat = function(s) {
+
+				var i = parseFloat(s);
+				return (isNaN(i)) ? 0 : i;
+			};
+			this.formatInt = function(s) {
+				var i = parseInt(s);
+				return (isNaN(i)) ? 0 : i;
+			};
+			
+		}
+	});
+	
+	// extend plugin scope
+	$.fn.extend({
+        tablesorter: $.tablesorter.construct
+	});
+	
+	// add default parsers
+	$.tablesorter.addParser({
+		id: "text",
+		is: function(s) {
+			return true;
+		},
+		format: function(s) {
+			return $.trim(s.toLowerCase());
+		},
+		type: "text"
+	});
+	
+	$.tablesorter.addParser({
+		id: "integer",
+		is: function(s) {
+			return s.match(new RegExp(/^\d+$/));
+		},
+		format: function(s) {
+			return $.tablesorter.formatInt(s);
+		},
+		type: "numeric"
+	});
+	
+	$.tablesorter.addParser({
+		id: "currency",
+		is: function(s) {
+			return /^[£$€?.]/.test(s);
+		},
+		format: function(s) {
+			return $.tablesorter.formatFloat(s.replace(new RegExp(/[^0-9.]/g),""));
+		},
+		type: "numeric"
+	});
+	
+	$.tablesorter.addParser({
+		id: "integer",
+		is: function(s) {
+			return /^\d+$/.test(s);
+		},
+		format: function(s) {
+			return $.tablesorter.formatFloat(s);
+		},
+		type: "numeric"
+	});
+	
+	$.tablesorter.addParser({
+		id: "floating",
+		is: function(s) {
+			return s.match(new RegExp(/^(\+|-)?[0-9]+\.[0-9]+((E|e)(\+|-)?[0-9]+)?$/));
+		},
+		format: function(s) {
+			return $.tablesorter.formatFloat(s.replace(new RegExp(/,/),""));
+		},
+		type: "numeric"
+	});
+	
+	$.tablesorter.addParser({
+		id: "ipAddress",
+		is: function(s) {
+			return /^\d{2,3}[\.]\d{2,3}[\.]\d{2,3}[\.]\d{2,3}$/.test(s);
+		},
+		format: function(s) {
+			var a = s.split(".");
+			var r = "";
+			for (var i = 0, item; item = a[i]; i++) {
+			   if(item.length == 2) {
+					r += "0" + item;
+			   } else {
+					r += item;
+			   }
+			}
+			return $.tablesorter.formatFloat(s);
+		},
+		type: "numeric"
+	});
+	
+	$.tablesorter.addParser({
+		id: "url",
+		is: function(s) {
+			return /^(https?|ftp|file):\/\/$/.test(s);
+		},
+		format: function(s) {
+			return jQuery.trim(s.replace(new RegExp(/(https?|ftp|file):\/\//),''));
+		},
+		type: "text"
+	});
+	
+	$.tablesorter.addParser({
+		id: "isoDate",
+		is: function(s) {
+			return /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(s);
+		},
+		format: function(s) {
+			return $.tablesorter.formatFloat((s != "") ? new Date(s.replace(new RegExp(/-/g),"/")).getTime() : "0");
+		},
+		type: "numeric"
+	});
+	
+	$.tablesorter.addParser({
+		id: "percent",
+		is: function(s) {
+			return /^\d{1,3}%$/.test(s);
+		},
+		format: function(s) {
+			return $.tablesorter.formatFloat(s.replace(new RegExp(/%/g),""));
+		},
+		type: "numeric"
+	});
+	
+	$.tablesorter.addParser({
+		id: "usLongDate",
+		is: function(s) {
+			return /^[A-Za-z]{3,10}\.? [0-9]{1,2}, ([0-9]{4}|\'?[0-9]{2}) (([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(AM|PM)))$/.test(s);
+		},
+		format: function(s) {
+			return $.tablesorter.formatFloat(new Date(s).getTime());
+		},
+		type: "numeric"
+	});
+	
+	$.tablesorter.addParser({
+		id: "shortDate",
+		is: function(s) {
+			return /\d{1,2}[\/-]\d{1,2}[\/-]\d{2,4}/.test(s);
+		},
+		format: function(s,table) {
+			var c = table.config;
+			s = s.replace(new RegExp(/-/g),"/");
+			if(c.dateFormat == "us") {
+				/** reformat the string in ISO format */
+				s = s.replace(new RegExp(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{4})/), "$3/$1/$2");
+			} else if(c.dateFormat == "uk") {
+				/** reformat the string in ISO format */
+				s = s.replace(new RegExp(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{4})/), "$3/$2/$1");
+			} else if(c.dateFormat == "dd/mm/yy" || c.dateFormat == "dd-mm-yy") {
+				s = s.replace(new RegExp(/(\d{1,2})[\/-](\d{1,2})[\/-](\d{2})/), "$1/$2/$3");	
+			}
+			return $.tablesorter.formatFloat(new Date(s).getTime());
+		},
+		type: "numeric"
+	});
+	
+	$.tablesorter.addParser({
+	    id: "time",
+	    is: function(s) {
+	        return /^(([0-2]?[0-9]:[0-5][0-9])|([0-1]?[0-9]:[0-5][0-9]\s(am|pm)))$/.test(s);
+	    },
+	    format: function(s) {
+	        return $.tablesorter.formatFloat(new Date("2000/01/01 " + s).getTime());
+	    },
+	  type: "numeric"
+	});
+	
+	
+	$.tablesorter.addParser({
+	    id: "metadata",
+	    is: function(s) {
+	        return false;
+	    },
+	    format: function(s,table,cell) {
+			var c = table.config, p = (!c.parserMetadataName) ? 'sortValue' : c.parserMetadataName;
+	        return $(cell).data()[p];
+	    },
+	  type: "numeric"
+	});
+	
+	// add default widgets
+	$.tablesorter.addWidget({
+		id: "zebra",
+		format: function(table) {
+			$("> tbody:first/tr:visible:even",table).removeClass(table.config.widgetZebra.css[1]).addClass(table.config.widgetZebra.css[0]);
+			$("> tbody:first/tr:visible:odd",table).removeClass(table.config.widgetZebra.css[0]).addClass(table.config.widgetZebra.css[1]);
+		}
+	});
+	
+})(jQuery);

+ 184 - 0
app/public/js/datatable/tablecloth.js

@@ -0,0 +1,184 @@
+/* 
+
+	Tablecloth 
+	written by Alen Grakalic, provided by Css Globe (cssglobe.com)
+	please visit http://cssglobe.com/lab/tablecloth/
+	
+*/
+
+this.tablecloth = function(){
+	
+	// CONFIG 
+	
+	// if set to true then mouseover a table cell will highlight entire column (except sibling headings)
+	var highlightCols = true;
+	
+	// if set to true then mouseover a table cell will highlight entire row	(except sibling headings)
+	var highlightRows = true;	
+	
+	// if set to true then click on a table sell will select row or column based on config
+	var selectable = true;
+	
+	// this function is called when 
+	// add your own code if you want to add action 
+	// function receives object that has been clicked 
+	this.clickAction = function(obj){
+		//alert(obj.innerHTML);
+		
+	};
+
+
+	
+	// END CONFIG (do not edit below this line)
+	
+	
+	var tableover = false;
+	this.start = function(){
+		var tables = document.getElementsByTagName("table");
+		for (var i=0;i<tables.length;i++){
+			tables[i].onmouseover = function(){tableover = true};
+			tables[i].onmouseout = function(){tableover = false};			
+			rows(tables[i]);
+		};
+	};
+	
+	this.rows = function(table){
+		var css = "";
+		var tr = table.getElementsByTagName("tr");
+		for (var i=0;i<tr.length;i++){
+			css = (css == "odd") ? "even" : "odd";
+			tr[i].className = css;
+			var arr = new Array();
+			for(var j=0;j<tr[i].childNodes.length;j++){				
+				if(tr[i].childNodes[j].nodeType == 1) arr.push(tr[i].childNodes[j]);
+			};		
+			for (var j=0;j<arr.length;j++){				
+				arr[j].row = i;
+				arr[j].col = j;
+				if(arr[j].innerHTML == "&nbsp;" || arr[j].innerHTML == "") arr[j].className += " empty";					
+				arr[j].css = arr[j].className;
+				arr[j].onmouseover = function(){
+					over(table,this,this.row,this.col);
+				};
+				arr[j].onmouseout = function(){
+					out(table,this,this.row,this.col);
+				};
+				arr[j].onmousedown = function(){
+					down(table,this,this.row,this.col);
+				};
+				arr[j].onmouseup = function(){
+					up(table,this,this.row,this.col);
+				};				
+				arr[j].onclick = function(){
+					click(table,this,this.row,this.col);
+				};								
+			};
+		};
+	};
+	
+	// appyling mouseover state for objects (th or td)
+	this.over = function(table,obj,row,col){
+		if (!highlightCols && !highlightRows) obj.className = obj.css + " over";  
+		if(check1(obj,col)){
+			if(highlightCols) highlightCol(table,obj,col);
+			if(highlightRows) highlightRow(table,obj,row);		
+		};
+	};
+	// appyling mouseout state for objects (th or td)	
+	this.out = function(table,obj,row,col){
+		if (!highlightCols && !highlightRows) obj.className = obj.css; 
+		unhighlightCol(table,col);
+		unhighlightRow(table,row);
+	};
+	// appyling mousedown state for objects (th or td)	
+	this.down = function(table,obj,row,col){
+		obj.className = obj.css + " down";  
+	};
+	// appyling mouseup state for objects (th or td)	
+	this.up = function(table,obj,row,col){
+		obj.className = obj.css + " over";  
+	};	
+	// onclick event for objects (th or td)	
+	this.click = function(table,obj,row,col){
+		if(check1){
+			if(selectable) {
+				unselect(table);	
+				if(highlightCols) highlightCol(table,obj,col,true);
+				if(highlightRows) highlightRow(table,obj,row,true);
+				document.onclick = unselectAll;
+			}
+		};
+		clickAction(obj); 		
+	};		
+	
+	this.highlightCol = function(table,active,col,sel){
+		var css = (typeof(sel) != "undefined") ? "selected" : "over";
+		var tr = table.getElementsByTagName("tr");
+		for (var i=0;i<tr.length;i++){	
+			var arr = new Array();
+			for(j=0;j<tr[i].childNodes.length;j++){				
+				if(tr[i].childNodes[j].nodeType == 1) arr.push(tr[i].childNodes[j]);
+			};							
+			var obj = arr[col];
+			if (check2(active,obj) && check3(obj)) obj.className = obj.css + " " + css; 		
+		};
+	};
+	this.unhighlightCol = function(table,col){
+		var tr = table.getElementsByTagName("tr");
+		for (var i=0;i<tr.length;i++){
+			var arr = new Array();
+			for(j=0;j<tr[i].childNodes.length;j++){				
+				if(tr[i].childNodes[j].nodeType == 1) arr.push(tr[i].childNodes[j])
+			};				
+			var obj = arr[col];
+			if(check3(obj)) obj.className = obj.css; 
+		};
+	};	
+	this.highlightRow = function(table,active,row,sel){
+		var css = (typeof(sel) != "undefined") ? "selected" : "over";
+		var tr = table.getElementsByTagName("tr")[row];		
+		for (var i=0;i<tr.childNodes.length;i++){		
+			var obj = tr.childNodes[i];
+			if (check2(active,obj) && check3(obj)) obj.className = obj.css + " " + css; 		
+		};
+	};
+	this.unhighlightRow = function(table,row){
+		var tr = table.getElementsByTagName("tr")[row];		
+		for (var i=0;i<tr.childNodes.length;i++){
+			var obj = tr.childNodes[i];			
+			if(check3(obj)) obj.className = obj.css; 			
+		};
+	};
+	this.unselect = function(table){
+		tr = table.getElementsByTagName("tr")
+		for (var i=0;i<tr.length;i++){
+			for (var j=0;j<tr[i].childNodes.length;j++){
+				var obj = tr[i].childNodes[j];	
+				if(obj.className) obj.className = obj.className.replace("selected","");
+			};
+		};
+	};
+	this.unselectAll = function(){
+		if(!tableover){
+			tables = document.getElementsByTagName("table");
+			for (var i=0;i<tables.length;i++){
+				unselect(tables[i])
+			};		
+		};
+	};	
+	this.check1 = function(obj,col){
+		return (!(col == 0 && obj.className.indexOf("empty") != -1));
+	}
+	this.check2 = function(active,obj){
+		return (!(active.tagName == "TH" && obj.tagName == "TH")); 
+	};
+	this.check3 = function(obj){
+		return (obj.className) ? (obj.className.indexOf("selected") == -1) : true; 
+	};	
+	
+	start();
+	
+};
+
+/* script initiates on page load. */
+window.onload = tablecloth;

+ 2 - 0
app/router.js

@@ -142,6 +142,8 @@ module.exports = app => {
     app.get('/change/download/file/:id', sessionAuth, 'changeController.downloadFile');
     app.post('/change/delete/file', sessionAuth, 'changeController.deleteFile');
 
+    app.post('/change/save', sessionAuth, 'changeController.save');
+
     // 变更单位管理
     app.post('/change/update/company', sessionAuth, 'changeController.updateCompany');
 

+ 158 - 62
app/service/change.js

@@ -73,7 +73,7 @@ module.exports = app => {
         }
 
         async add(tenderId, userId, code, name) {
-            const count = await this.count({tid: tenderId, code: code});
+            const count = await this.count({ tid: tenderId, code });
             if (count > 0) {
                 throw '变更令号重复';
             }
@@ -82,17 +82,17 @@ module.exports = app => {
             this.transaction = await this.db.beginTransaction();
             let result = false;
             try {
-                let cid = this.uuid.v4();
+                const cid = this.uuid.v4();
                 const change = {
-                    cid: cid,
+                    cid,
                     tid: tenderId,
                     uid: userId,
                     status: audit.flow.status.uncheck,
                     times: 1,
                     valid: true,
                     in_time: new Date(),
-                    code: code,
-                    name: name,
+                    code,
+                    name,
                 };
                 const operate = await this.transaction.insert(this.tableName, change);
 
@@ -101,11 +101,10 @@ module.exports = app => {
                 }
 
                 // 把提交人信息添加到zh_change_audit
-                this.ctx.service.changeAudit.transaction = this.transaction;
                 const userInfo = await this.ctx.service.projectAccount.getDataById(userId);
                 const changeaudit = {
                     tid: tenderId,
-                    cid: cid,
+                    cid,
                     uid: userId,
                     name: userInfo.name,
                     jobs: userInfo.role,
@@ -113,7 +112,7 @@ module.exports = app => {
                     times: 1,
                     usite: 0,
                     usort: 0,
-                    status: 2
+                    status: 2,
                 };
 
                 await this.transaction.insert(this.ctx.service.changeAudit.tableName, changeaudit);
@@ -180,44 +179,37 @@ module.exports = app => {
 
         /**
          * 获取变更令列表
-         * @param tenderId 标段id
-         * @param userId  创建者id
-         * @param status  状态
-         * @return {Promise.<void>}
+         * @param {int} tenderId - 标段id
+         * @param {int} status - 状态
+         * @return {object} list - 列表
          */
         async getListByStatus(tenderId, status = 0) {
             let sql = '';
             let sqlParam = '';
             switch (status) {
-                case 0:
-                    // 包含你的所有变更令
+                case 0:// 包含你的所有变更令
                     sql = 'SELECT a.* FROM ?? AS a WHERE a.tid = ? AND ' +
-                        '(a.uid = ? OR (a.status != 1 AND a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? GROUP BY b.cid)))';
+                        '(a.uid = ? OR (a.status != 1 AND a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? GROUP BY b.cid))) ORDER BY a.in_time DESC';
                     sqlParam = [this.tableName, tenderId, this.ctx.session.sessionUser.accountId,
                         this.ctx.service.changeAudit.tableName, this.ctx.session.sessionUser.accountId];
                     break;
-                case 1:
-                    // 待处理(你的)
-                    sql = 'SELECT * FROM ?? WHERE tid = ? AND uid = ? AND status = ?';
+                case 1:// 待处理(你的)
+                    sql = 'SELECT * FROM ?? WHERE tid = ? AND uid = ? AND status = ? ORDER BY in_time DESC';
                     sqlParam = [this.tableName, tenderId, this.ctx.session.sessionUser.accountId, status];
                     break;
-                case 2:
-                    // 待上报(所有的)PS:取未上报和退回的变更令
+                case 2:// 待上报(所有的)PS:取未上报和退回的变更令
                     sql = 'SELECT a.* FROM ?? AS a WHERE ' +
                         'a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? GROUP BY b.cid) AND ' +
-                        '(a.status = 1 OR a.status = 5) AND a.tid = ?';
+                        '(a.status = 1 OR a.status = 5) AND a.tid = ? ORDER BY a.in_time DESC';
                     sqlParam = [this.tableName, this.ctx.service.changeAudit.tableName,
                         this.ctx.session.sessionUser.accountId, tenderId];
                     break;
-                case 3:
-                // 进行中(所有的)
-                case 4:
-                // 已完成(所有的)
-                case 5:
-                    // 终止(所有的)
+                case 3:// 进行中(所有的)
+                case 4:// 已完成(所有的)
+                case 5:// 终止(所有的)
                     sql = 'SELECT a.* FROM ?? AS a WHERE ' +
                         'a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? GROUP BY b.cid) AND ' +
-                        'a.status = ? AND a.tid = ?';
+                        'a.status = ? AND a.tid = ? ORDER BY a.in_time DESC';
                     sqlParam = [this.tableName, this.ctx.service.changeAudit.tableName,
                         this.ctx.session.sessionUser.accountId, status, tenderId];
                     break;
@@ -235,53 +227,157 @@ module.exports = app => {
 
         /**
          * 获取变更令个数
-         * @param tenderId 标段id
-         * @param userId  创建者id
-         * @param status  状态
-         * @return {Promise.<*>}
+         * @param {int} tenderId - 标段id
+         * @param {int} status - 状态
+         * @return {void}
          */
         async getCountByStatus(tenderId, status) {
             switch (status) {
-                case 0:
-                    // 包含你的所有变更令
-                    let sql = 'SELECT count(*) AS count FROM ?? AS a WHERE a.tid = ? AND ' +
+                case 0:// 包含你的所有变更令
+                    const sql = 'SELECT count(*) AS count FROM ?? AS a WHERE a.tid = ? AND ' +
                         '(a.uid = ? OR a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? GROUP BY b.cid))';
-                    let sqlParam = [this.tableName, tenderId, this.ctx.session.sessionUser.accountId,
+                    const sqlParam = [this.tableName, tenderId, this.ctx.session.sessionUser.accountId,
                         this.ctx.service.changeAudit.tableName, this.ctx.session.sessionUser.accountId];
-                    let result = await this.db.query(sql, sqlParam);
-                    return result[0]['count'];
-                    break;
-                case 1:
-                    // 待处理(你的)
+                    const result = await this.db.query(sql, sqlParam);
+                    return result[0].count;
+                case 1:// 待处理(你的)
                     return await this.count({
                         tid: tenderId,
                         uid: this.ctx.session.sessionUser.accountId,
-                        status: status,
+                        status,
                     });
-                    break;
-                case 2:
-                    // 待上报(所有的)PS:取未上报和退回的变更令
-                    let sql2 = 'SELECT count(*) AS count FROM ?? AS a WHERE a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? GROUP BY b.cid) AND (a.status = 1 OR a.status = 5) AND a.tid = ?';
-                    let sqlParam2 = [this.tableName, this.ctx.service.changeAudit.tableName, this.ctx.session.sessionUser.accountId, tenderId];
-                    let result2 = await this.db.query(sql2, sqlParam2);
-                    return result2[0]['count'];
-                    break;
-                case 3:
-                    // 进行中(所有的)
-                case 4:
-                    // 已完成(所有的)
-                case 5:
-                    // 终止(所有的)
-                    let sql3 = 'SELECT count(*) AS count FROM ?? AS a WHERE a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? GROUP BY b.cid) AND a.status = ? AND a.tid = ?';
-                    let sqlParam3 = [this.tableName, this.ctx.service.changeAudit.tableName, this.ctx.session.sessionUser.accountId, status, tenderId];
-                    let result3 = await this.db.query(sql3, sqlParam3);
-                    return result3[0]['count'];
-                    break;
+                case 2:// 待上报(所有的)PS:取未上报和退回的变更令
+                    const sql2 = 'SELECT count(*) AS count FROM ?? AS a WHERE a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? GROUP BY b.cid) AND (a.status = 1 OR a.status = 5) AND a.tid = ?';
+                    const sqlParam2 = [this.tableName, this.ctx.service.changeAudit.tableName, this.ctx.session.sessionUser.accountId, tenderId];
+                    const result2 = await this.db.query(sql2, sqlParam2);
+                    return result2[0].count;
+                case 3:// 进行中(所有的)
+                case 4:// 已完成(所有的)
+                case 5:// 终止(所有的)
+                    const sql3 = 'SELECT count(*) AS count FROM ?? AS a WHERE a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? GROUP BY b.cid) AND a.status = ? AND a.tid = ?';
+                    const sqlParam3 = [this.tableName, this.ctx.service.changeAudit.tableName, this.ctx.session.sessionUser.accountId, status, tenderId];
+                    const result3 = await this.db.query(sql3, sqlParam3);
+                    return result3[0].count;
                 default:
                     break;
             }
         }
+
+        /**
+         * 上报或重新上报或保存修改功能
+         * @param {int} postData - 表单提交的数据
+         * @param {int} tenderId - 标段id
+         * @return {void}
+         */
+        async save(postData, tenderId) {
+            // 初始化事务
+            this.transaction = await this.db.beginTransaction();
+            let result = false;
+            try {
+                const changeInfo = await this.getDataByCondition({ cid: postData.cid });
+                // 先删除本次原有的变更审批人和清单
+                await this.ctx.service.changeAudit.deleteAuditData(this.transaction, changeInfo.cid, changeInfo.times);
+                await this.transaction.delete(this.ctx.service.changeAuditList.tableName, { cid: changeInfo.cid });
+                // 再插入postData里的变更审批人和清单
+                if (postData.changeaudit !== undefined && postData.changeaudit !== '') {
+                    const lastUser = await this.ctx.service.changeAudit.getLastUser(changeInfo.cid, changeInfo.times, 0);
+                    const changeAudit = postData.changeaudit.split(',');
+                    const insertCA = [];
+                    let uSite = 1;
+                    let uSort = parseInt(lastUser.usort) + 1;
+                    for (const ca of changeAudit) {
+                        const auditInfo = ca.split('/%/');
+                        const caArray = {
+                            tid: tenderId,
+                            cid: changeInfo.cid,
+                            uid: auditInfo[0],
+                            name: auditInfo[1],
+                            jobs: auditInfo[2],
+                            company: auditInfo[3],
+                            times: changeInfo.times,
+                            usite: uSite,
+                            usort: uSort,
+                            status: 2,
+                            sdesc: '',
+                            sin_time: new Date(),
+                        };
+                        uSite++;
+                        uSort++;
+                        insertCA.push(caArray);
+                    }
+                    await this.transaction.insert(this.ctx.service.changeAudit.tableName, insertCA);
+                }
+                let changeList = [];
+                if (postData.changelist !== undefined && postData.changelist !== '') {
+                    changeList = postData.changelist.split('^_^');
+                }
+                let changeWhiteList = [];
+                if (postData.changewhitelist !== undefined && postData.changewhitelist !== '') {
+                    changeWhiteList = postData.changewhitelist.split('^_^');
+                }
+                changeList.push.apply(changeList, changeWhiteList);
+                const insertCL = [];
+                let total_price = 0;
+                for (const cl of changeList) {
+                    const clInfo = cl.split(';');
+                    const clArray = {
+                        tid: tenderId,
+                        cid: changeInfo.cid,
+                        lid: clInfo[7],
+                        code: clInfo[0],
+                        name: clInfo[1],
+                        unit: clInfo[2],
+                        unit_price: clInfo[3],
+                        oamount: clInfo[4],
+                        camount: clInfo[5],
+                        samount: '',
+                        detail: clInfo[6],
+                    };
+                    insertCL.push(clArray);
+                    total_price += this.ctx.helper.accMul(clArray.unit_price, clArray.camount);
+                }
+                await this.transaction.insert(this.ctx.service.changeAuditList.tableName, insertCL);
+
+                // 修改变更令基本数据
+                const cArray = {
+                    code: postData.code,
+                    name: postData.name,
+                    peg: postData.peg,
+                    org_name: postData.org_name,
+                    org_code: postData.org_code,
+                    new_name: postData.new_name,
+                    new_code: postData.new_code,
+                    content: postData.content,
+                    basis: postData.basis,
+                    memo: postData.memo,
+                    type: postData.type.join(','),
+                    class: postData.class,
+                    quality: postData.quality,
+                    company: postData.company,
+                    charge: postData.charge,
+                    total_price,
+                };
+                const options = {
+                    where: {
+                        cid: changeInfo.cid,
+                    },
+                };
+
+                // 根据上报状态修改变更令状态和审批状态
+                if (postData.changestatus !== undefined && parseInt(postData.changestatus) === 1) {
+                    cArray.status = 2;
+                    cArray.cin_time = Date.parse(new Date()) / 1000;
+                }
+                await this.transaction.update(this.tableName, cArray, options);
+                await this.transaction.commit();
+                result = true;
+            } catch (error) {
+                await this.transaction.rollback();
+                result = false;
+            }
+            return result;
+        }
     }
 
     return Change;
-};
+};

+ 6 - 4
app/service/change_att.js

@@ -23,14 +23,16 @@ module.exports = app => {
 
         /**
          * 添加附件
-         * @param data
-         * @param fileData
+         * @param {Object} postData - 表单信息
+         * @param {Object} fileData - 文件信息
+         * @param {int} uid - 上传者id
+         * @return {void}
          */
         async save(postData, fileData, uid) {
             const data = {
                 tid: postData.tid,
                 cid: postData.cid,
-                uid: uid,
+                uid,
             };
             Object.assign(data, fileData);
             const result = await this.db.insert(this.tableName, data);
@@ -39,4 +41,4 @@ module.exports = app => {
     }
 
     return ChangeAtt;
-};
+};

+ 74 - 12
app/service/change_audit.js

@@ -23,11 +23,12 @@ module.exports = app => {
             this.tableName = 'change_audit';
         }
 
-
         /**
          * 获取最后一位审批人
-         * @param cid
-         * @return {Promise.<void>}
+         * @param {int} cid - 变更令id
+         * @param {int} times - 次数
+         * @param {int} site - 位置
+         * @return {void}
          */
         async getLastUser(cid, times, site = 1) {
             this.initSqlBuilder();
@@ -58,16 +59,14 @@ module.exports = app => {
 
         /**
          * 获取当前审批人查看info时的状态
-         * @param cid
-         * @param times
-         * @param status
-         * @return {Promise.<void>}
+         * @param {Object} change - 变更令数据
+         * @return {void}
          */
         async getStatusByChange(change) {
             const statusConst = audit.flow.status;
             const auditStatusConst = audit.flow.auditStatus;
             const uid = this.ctx.session.sessionUser.accountId;
-            const changeAuditInfo = (await this.getAllDataByCondition({where: { cid: change.cid, times: change.times, uid: uid}, order: ['id', 'DESC']}));
+            const changeAuditInfo = await this.getAllDataByCondition({ where: { cid: change.cid, times: change.times, uid }, order: ['id', 'DESC'] });
 
             if (changeAuditInfo === null) {
                 // 无权限查看此变更令
@@ -95,12 +94,75 @@ module.exports = app => {
             } else if (change.status === statusConst.checking && changeAuditInfo.status !== auditStatusConst.checking) {
                 // 审批中但你未到你审批或你已审批
                 return 7;
-            } else {
-                // 无权限查看此变更令
-                return 0;
             }
+            // 无权限查看此变更令
+            return 0;
+        }
+
+        /**
+         * 根据用户查看此变更状态获取审批人列表
+         * @param {Object} change - 变更令
+         * @param {int} status - 状态
+         * @return {object} list - 列表
+         */
+        async getListByStatus(change, status) {
+            let sql = '';
+            let sqlParam = '';
+            switch (status) {
+                case 1:// 待上报
+                case 2:// 待重新上报
+                    sql = 'SELECT * FROM ?? WHERE ' +
+                        'cid = ? AND times = ? GROUP BY usite';
+                    sqlParam = [this.tableName, change.cid,
+                        change.times];
+                    break;
+                case 3: // 被退回但你不是原报人
+                case 4:// 已完成
+                case 5:// 已终止
+                    // 获取完整的审批顺序
+                    sql = 'SELECT a.* FROM ?? AS a WHERE ' +
+                        'a.cid IN (SELECT b.cid FROM ?? AS b WHERE b.uid = ? GROUP BY b.cid) AND ' +
+                        'a.status = ? AND a.tid = ?';
+                    sqlParam = [this.tableName, this.ctx.service.changeAudit.tableName,
+                        this.ctx.session.sessionUser.accountId, status, ''];
+                    break;
+                case 7:// 审批中但你未到你审批或你已审批
+                    break;
+                case 6:// 待你审批
+                default:// 无权限查看此变更令
+                    break;
+            }
+            const list = await this.db.query(sql, sqlParam);
+            return list;
+        }
+
+        /**
+         * 删除变更令审批人列表
+         * @param {Object} transaction - 事务
+         * @param {Object} cid - 变更令id
+         * @param {int} times - 次数
+         * @return {object} 返回结果
+         */
+        async deleteAuditData(transaction, cid, times) {
+            this.initSqlBuilder();
+            this.sqlBuilder.setAndWhere('cid', {
+                value: this.db.escape(cid),
+                operate: '=',
+            });
+            this.sqlBuilder.setAndWhere('times', {
+                value: times,
+                operate: '=',
+            });
+            this.sqlBuilder.setAndWhere('usite', {
+                value: 0,
+                operate: '!=',
+            });
+            const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'delete');
+            const result = await transaction.query(sql, sqlParam);
+
+            return result;
         }
     }
 
     return ChangeAudit;
-};
+};

+ 28 - 0
app/service/change_audit_list.js

@@ -0,0 +1,28 @@
+'use strict';
+
+/**
+ *
+ *
+ * @author Mai
+ * @date 2018/8/14
+ * @version
+ */
+
+const audit = require('../const/audit');
+
+module.exports = app => {
+    class ChangeAuditList extends app.BaseService {
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'change_audit_list';
+        }
+    }
+
+    return ChangeAuditList;
+};

+ 10 - 15
app/service/change_company.js

@@ -8,8 +8,6 @@
  * @version
  */
 
-const audit = require('../const/audit');
-
 module.exports = app => {
     class ChangeCompany extends app.BaseService {
         /**
@@ -25,25 +23,22 @@ module.exports = app => {
 
         /**
          * 队列修改和添加公司信息
-         * @param tenderId   标段id
-         * @param updateIdArray  更新的公司id
-         * @param updateArray   更新的公司名称
-         * @param addArray      添加的公司名称
-         * @return {Promise.<[*,*]>}  返回新增的公司列表,和替换下拉选择公司列表
+         * @param {Object} data - 公司信息集合
+         * @return {Object} - 返回新增的公司列表,和替换下拉选择公司列表
          */
         async setCompanyList(data) {
             const tenderId = parseInt(data.tid);
             const updateIdArray = data.uci;
             const updateArray = data.uc;
             const addArray = data.ac;
-            let addCompany = new Array();
-            let selectCompany = new Array();
+            const addCompany = [];
+            const selectCompany = [];
             // 初始化事务
             this.transaction = await this.db.beginTransaction();
             try {
                 // 更新公司信息
                 if (updateIdArray.length !== 0) {
-                    for (let index in updateIdArray) {
+                    for (const index in updateIdArray) {
                         const updateData = {
                             id: updateIdArray[index],
                             name: updateArray[index],
@@ -54,17 +49,17 @@ module.exports = app => {
                 }
 
                 if (addArray.length !== 0) {
-                    for (let name of addArray) {
+                    for (const name of addArray) {
                         const addData = {
                             tid: tenderId,
-                            name: name,
+                            name,
                         };
                         const operate = await this.transaction.insert(this.tableName, addData);
                         if (operate.affectedRows !== 1) {
                             throw '提交数据失败';
                         } else {
-                            selectCompany.push({id: operate.insertId, name: name});
-                            addCompany.push({id: operate.insertId, name: name});
+                            selectCompany.push({ id: operate.insertId, name });
+                            addCompany.push({ id: operate.insertId, name });
                         }
                     }
                 }
@@ -79,4 +74,4 @@ module.exports = app => {
     }
 
     return ChangeCompany;
-};
+};

+ 3 - 3
app/service/deal_bills.js

@@ -15,7 +15,7 @@ module.exports = app => {
          * 构造函数
          * @param ctx
          */
-        constructor (ctx) {
+        constructor(ctx) {
             super(ctx);
             this.tableName = 'deal_bills';
         }
@@ -56,7 +56,7 @@ module.exports = app => {
                 }
                 await transaction.commit();
                 result = true;
-            } catch(err) {
+            } catch (err) {
                 await transaction.rollback();
                 throw err;
             }
@@ -65,4 +65,4 @@ module.exports = app => {
     }
 
     return DealBills;
-}
+}

+ 6 - 5
app/service/project_account.js

@@ -235,11 +235,12 @@ module.exports = app => {
 
         /**
          * 根据项目Id,用户名查找用户数据
-         * @param projectId
-         * @param name
-         * @returns {Promise<*>}
+         * @param {int} projectId - 项目id
+         * @param {Object} name - 关键字
+         * @param {int} type - 查询方式
+         * @return {Object} 列表或单条数据
          */
-        async getAccountInfoByName(projectId, name) {
+        async getAccountInfoByName(projectId, name, type = 0) {
             this.initSqlBuilder();
             this.sqlBuilder.columns = ['id', 'name', 'company', 'role'];
             this.sqlBuilder.setAndWhere('project_id', {
@@ -252,7 +253,7 @@ module.exports = app => {
             });
 
             const [sql, sqlParam] = this.sqlBuilder.build(this.tableName, 'select');
-            const info = await this.db.queryOne(sql, sqlParam);
+            const info = type === 1 ? await this.db.query(sql, sqlParam) : await this.db.queryOne(sql, sqlParam);
 
             return info;
         }

+ 7 - 2
app/view/change/index.ejs

@@ -32,11 +32,16 @@
                 </tr>
                 </thead>
                 <tbody id="changeList">
+                <% const classArray = []; %>
+                <% for (const t in changeConst.class) { %>
+                    <% const cClass = changeConst.class[t] %>
+                    <% classArray[cClass.value] = cClass.name %>
+                <% } %>
                 <% for (const c of changes) { %>
                 <tr>
                     <td><a href="change/<%- c.cid %>/info"><%- c.code %></a></td>
                     <td><%- c.name %></td>
-                    <td><%- c.class %></td>
+                    <td><%- classArray[c.class] %><% c.class %></td>
                     <td><%- c.total_price %></td>
                     <% if (uid === c.changeAudit.uid && c.status === auditConst.status.uncheck) { %>
                     <td>
@@ -75,4 +80,4 @@
         </div>
     </div>
 </div>
-<script src="/public/js/change.js"></script>
+<script src="/public/js/change.js"></script>

Plik diff jest za duży
+ 229 - 58
app/view/change/info.ejs


+ 70 - 187
app/view/change/info_modal.ejs

@@ -42,42 +42,54 @@
             <form method="post" action="/tender/<%- tender.id %>/change/<%- change.cid %>/save">
                 <div class="modal-body">
                     <!--如未创建清单-->
-                    <h5>还没添加任何变更清单,无法提交。</h5>
+                    <!--<h5>还没添加任何变更清单,无法提交。</h5>-->
                     <!--可以提交审批 但需要设置审批流程-->
                     <div class="form-group">
                         <label>搜索审批人</label>
                         <div class="input-group">
-                            <input class="form-control" placeholder="请输入姓名进行检索" type="text">
+                            <input class="form-control" placeholder="请输入姓名进行检索" type="text" id="search_audit_input">
                             <div class="input-group-append">
-                                <button class="btn btn-outline-secondary" type="button"><i class="fa fa-search"></i></button>
+                                <button class="btn btn-outline-secondary" type="button" id="search_audit_btn"><i class="fa fa-search"></i></button>
                             </div>
                         </div>
                     </div>
-                    <div class="card border-primary">
-                        <div class="card-body">
-                            <h5 class="card-title">
-                                <a href="#" class="btn btn-primary btn-sm pull-right">添加</a>张三
-                            </h5>
-                            <h6 class="card-subtitle mb-2 text-muted">监理</h6>
-                            <p class="card-text">XXXXX公司</p>
-                        </div>
+                    <div id="search_audit_list">
                     </div>
                     <div class="card mt-3">
                         <div class="card-header">
                             审批流程
                         </div>
                         <ul class="list-group list-group-flush">
-                            <li class="list-group-item"><i class="fa fa fa-play-circle fa-rotate-90"></i> 布尔  <small class="text-muted">施工</small></li>
-                            <li class="list-group-item"><a href="" class="text-danger pull-right">移除</a><i class="fa fa-chevron-circle-down"></i> 张三  <small class="text-muted">监理</small></li>
-                            <li class="list-group-item"><a href="" class="text-danger pull-right">移除</a><i class="fa fa-chevron-circle-down"></i> 王五 <small class="text-muted">监理</small></li>
-                            <li class="list-group-item"><a href="" class="text-danger pull-right">移除</a><i class="fa fa fa-stop-circle"></i> 李四 <small class="text-muted">监理</small></li>
+                            <% for (const audit of auditList) { %>
+                                <% if (audit.usite === 0) { %>
+                                <li class="list-group-item">
+                                    <i class="fa fa-play-circle fa-rotate-90"></i>
+                                    <%= audit.name %><small class="text-muted"><%= audit.jobs %></small>
+                                </li>
+                                <% } %>
+                            <% } %>
+                        </ul>
+                        <ul class="list-group list-group-flush" id="auditList">
+                            <% for (const audit of auditList) { %>
+                                <% if (audit.usite !== 0) { %>
+                                <li class="list-group-item" data-auditmsg="<%= audit.uid + '/%/' + audit.name + '/%/' + audit.jobs + '/%/' + audit.company %>"
+                                    data-auditid="<%= audit.uid %>">
+                                    <a href="javascript:void(0)" class="text-danger pull-right remove_audit_btn">移除</a>
+                                    <% if (audit.usite === auditList.length-1) { %><i class="fa fa-stop-circle"></i>
+                                    <% } else { %><i class="fa fa-chevron-circle-down"></i>
+                                    <% } %>
+                                    <%= audit.name %><small class="text-muted"><%= audit.jobs %></small>
+                                </li>
+                                <% } %>
+                            <% } %>
                         </ul>
+                        <input type="hidden" id="auditIdList" value="">
                     </div>
                 </div>
                 <div class="modal-footer">
                     <button type="button" class="btn btn-secondary" data-dismiss="modal">关闭</button>
-                    <button type="button" data-sumbit="up_change" class="btn btn-primary up-change">确认上报</button>
-                    <button type="button" data-sumbit="save_change" class="btn btn-success save-change">保存修改</button>
+                    <button type="button" data-sumbit="sumbit_change" data-category="up_change" class="btn btn-primary up-change">确认上报</button>
+                    <button type="button" data-sumbit="sumbit_change" data-category="save_change" class="btn btn-success save-change">保存修改</button>
                 </div>
             </form>
         </div>
@@ -85,11 +97,10 @@
 </div>
 
 <script src="/public/js/change_company.js"></script>
-<% } %>
 
 <!--添加清单-->
 <div class="modal fade " tabindex="-1" role="dialog" aria-hidden="true" id="addlist">
-    <div class="modal-dialog modal-lg">
+    <div class="modal-dialog modal-xl">
         <div class="modal-content">
             <div class="modal-header">
                 <h5 class="modal-title" id="mySmallModalLabel">从清单中选择</h5>
@@ -98,180 +109,52 @@
                 </button>
             </div>
             <div class="modal-body">
-                <div style="height:400px;overflow-y:auto">
-                    <table class="table table-striped table-bordered table-condensed">
-                        <thead><tr><th>序号</th><th>清单编号</th><th>名称</th><th>单位</th><th>单价</th><th>选择</th></tr></thead>
-                        <tbody>
-                        <tr>
-                            <td>1</td>
-                            <td>202-1-1</td>
-                            <td>清理现场</td>
-                            <td>m2</td>
-                            <td>3.88</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr class="table-success">
-                            <td>2</td>
-                            <td>204-1</td>
-                            <td>干处挖土方</td>
-                            <td>m3</td>
-                            <td>435</td>
-                            <td><input type="checkbox" checked></td>
-                        </tr>
-                        <tr class="table-success">
-                            <td>3</td>
-                            <td>202-1-1</td>
-                            <td>清理现场</td>
-                            <td>m2</td>
-                            <td>3.88</td>
-                            <td><input type="checkbox" checked></td>
-                        </tr>
-                        <tr>
-                            <td>4</td>
-                            <td>204-1</td>
-                            <td>干处挖土方</td>
-                            <td>m3</td>
-                            <td>435</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>5</td>
-                            <td>202-1-1</td>
-                            <td>清理现场</td>
-                            <td>m2</td>
-                            <td>3.88</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>6</td>
-                            <td>204-1</td>
-                            <td>干处挖土方</td>
-                            <td>m3</td>
-                            <td>435</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>7</td>
-                            <td>202-1-1</td>
-                            <td>清理现场</td>
-                            <td>m2</td>
-                            <td>3.88</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>8</td>
-                            <td>204-1</td>
-                            <td>干处挖土方</td>
-                            <td>m3</td>
-                            <td>435</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>9</td>
-                            <td>202-1-1</td>
-                            <td>清理现场</td>
-                            <td>m2</td>
-                            <td>3.88</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>10</td>
-                            <td>204-1</td>
-                            <td>干处挖土方</td>
-                            <td>m3</td>
-                            <td>435</td>
-                            <td><input type="checkbox"></td>
-                        </tr><tr>
-                            <td>11</td>
-                            <td>202-1-1</td>
-                            <td>清理现场</td>
-                            <td>m2</td>
-                            <td>3.88</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>12</td>
-                            <td>204-1</td>
-                            <td>干处挖土方</td>
-                            <td>m3</td>
-                            <td>435</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>13</td>
-                            <td>202-1-1</td>
-                            <td>清理现场</td>
-                            <td>m2</td>
-                            <td>3.88</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>14</td>
-                            <td>204-1</td>
-                            <td>干处挖土方</td>
-                            <td>m3</td>
-                            <td>435</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>15</td>
-                            <td>202-1-1</td>
-                            <td>清理现场</td>
-                            <td>m2</td>
-                            <td>3.88</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>16</td>
-                            <td>204-1</td>
-                            <td>干处挖土方</td>
-                            <td>m3</td>
-                            <td>435</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>17</td>
-                            <td>202-1-1</td>
-                            <td>清理现场</td>
-                            <td>m2</td>
-                            <td>3.88</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>18</td>
-                            <td>204-1</td>
-                            <td>干处挖土方</td>
-                            <td>m3</td>
-                            <td>435</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>19</td>
-                            <td>202-1-1</td>
-                            <td>清理现场</td>
-                            <td>m2</td>
-                            <td>3.88</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        <tr>
-                            <td>20</td>
-                            <td>204-1</td>
-                            <td>干处挖土方</td>
-                            <td>m3</td>
-                            <td>435</td>
-                            <td><input type="checkbox"></td>
-                        </tr>
-                        </tbody>
-                    </table>
+                <div class="row">
+                    <div class="col-7">
+                        <div style="height:400px;overflow-y:auto">
+                            <table class="table table-striped table-bordered table-condensed">
+                                <thead><tr><th>序号</th><th>清单编号</th><th>名称</th><th>单位</th><th>单价</th><th>数量</th><th>金额</th></tr></thead>
+                                <tbody id="table-list-select">
+                                <% if (dealBillList !== undefined) { %>
+                                    <% for (const [index, db] of dealBillList.entries()) { %>
+                                        <tr data-lid="<%= db.id %>">
+                                            <td><%= index+1 %></td>
+                                            <td><%= db.code %></td>
+                                            <td><%= db.name %></td>
+                                            <td><%= db.unit %></td>
+                                            <td><%= ctx.helper.roundNum(db.unit_price, tpUnit) %></td>
+                                            <td><%= ctx.helper.roundNum(db.quantity,ctx.helper.findDecimal(db.unit)) %></td>
+                                            <td><%= ctx.helper.roundNum(ctx.helper.accMul(db.quantity, db.unit_price), tpUnit) %></td>
+                                        </tr>
+                                    <% } %>
+                                <% } %>
+                                </tbody>
+                            </table>
+                        </div>
+                    </div>
+                    <div class="col-5">
+                        <div style="height:400px;overflow-y:auto">
+                            <table class="table table-sm table-bordered">
+                                <tr><th>项目节编号</th><th>名称</th><th>部位明细</th><th>选择</th></tr>
+                                <tr><td colspan="3">自行编辑变更详情</td><td><input type="checkbox"></td></tr>
+                                <tr><td>1-4-5-1-1-1-1</td><td>桥台桩基础</td><td>0#桥台1#桩</td><td><input type="checkbox"></td></tr>
+                                <tr><td>1-4-5-1-1-1-1</td><td>桥台桩基础</td><td>0#桥台2#桩</td><td><input type="checkbox"></td></tr>
+                                <tr><td>1-4-5-1-1-1-1</td><td>桥台桩基础</td><td>0#桥台3#桩</td><td><input type="checkbox"></td></tr>
+                                <tr><td>1-4-5-1-1-1-1</td><td>桥台桩基础</td><td>0#桥台4#桩</td><td><input type="checkbox"></td></tr>
+                            </table>
+                        </div>
+                    </div>
                 </div>
             </div>
             <div class="modal-footer">
-                <button type="button" class="btn btn-secondary" data-dismiss="modal">取消</button>
-                <button type="button" class="btn btn-primary">添加</button>
+                <button type="button" class="add-list-btn btn btn-outline-primary">添加空白清单</button>
+                <button type="button" class="btn btn-secondary" data-dismiss="modal" id="cancel-list-btn">取消</button>
+                <button type="button" class="add-list-btn btn btn-primary">添加</button>
             </div>
         </div>
     </div>
 </div>
+<% } %>
 
 <!--添加附件-->
 <div class="modal fade" tabindex="-1" role="dialog" aria-hidden="true" id="addfujian">
@@ -293,4 +176,4 @@
             </div>
         </div>
     </div>
-</div>
+</div>

Plik diff jest za duży
+ 7413 - 3248
package-lock.json


+ 2 - 1
package.json

@@ -23,6 +23,7 @@
     "node-uuid": "^1.4.8",
     "node-xlsx": "^0.12.0",
     "stream-to-array": "^2.3.0",
+    "stream-wormhole": "^1.1.0",
     "ueditor": "^1.2.3",
     "uglify-es": "^3.3.9",
     "uglify-js": "^3.3.27",
@@ -32,7 +33,7 @@
   "devDependencies": {
     "autod": "^2.9.0",
     "autod-egg": "^1.1.0",
-    "egg-bin": "^4.3.7",
+    "egg-bin": "^4.10.0",
     "egg-ci": "^1.8.0",
     "egg-mock": "^3.14.0",
     "eslint": "^4.17.0",