浏览代码

Merge branch 'dev' of http://192.168.1.41:3000/maixinrong/Calculation into dev

# Conflicts:
#	sql/update.sql
TonyKang 4 年之前
父节点
当前提交
6a7931e1db

+ 102 - 0
app/controller/login_controller.js

@@ -9,6 +9,7 @@
  */
 const URL = require('url');
 const maintainConst = require('../const/maintain');
+const OAuth = require('co-wechat-oauth');
 
 module.exports = app => {
 
@@ -39,9 +40,110 @@ module.exports = app => {
                 maintainData,
                 maintainConst,
                 errorMessage,
+                hostUrl: ctx.protocol + '://' + ctx.host,
             };
             await ctx.render('login/login.ejs', renderData);
         }
+        /**
+         * 微信扫码认证并返回
+         *
+         * @param {Object} ctx - egg全局页面
+         * @return {void}
+         */
+        async wxAuth(ctx) {
+            const code = ctx.query.code;
+            try {
+                const client = new OAuth('wx5320cd30cecdbd68', 'ca7c0dbd9e94dc3b1c3b0e73865743f4');
+                const token = await client.getAccessToken(code);
+                // const user = await client.getUser(token.data.openid);
+                // console.log(user);
+                if (!token) {
+                    throw '微信扫码获取信息失败';
+                }
+                // 判断扫码者项目是否只有一个,是则直接跳到登录页,否则显示项目选择页
+                const paList = await ctx.service.projectAccount.getAllDataByCondition({ where: { wx_unionid: token.data.unionid } });
+                if (paList && paList.length === 1) {
+                    const pro = await ctx.service.project.getDataById(paList[0].project_id);
+                    let redirect_url = ctx.protocol + '://' + ctx.host;
+                    redirect_url += ctx.query.state ? ctx.query.state : '/dashboard';
+                    ctx.redirect('/wx/url2web?project=' + pro.code + '&url=' + redirect_url + '&unionid=' + token.data.unionid);
+                } else {
+                    ctx.session.wechatLogin = token.data.unionid;
+                    ctx.redirect('/wxproject');
+                }
+            } catch (error) {
+                this.log(error);
+                ctx.session.loginError = error;
+                ctx.redirect('/login');
+            }
+        }
+
+        async wxProject(ctx) {
+            try {
+                const unionid = ctx.session.wechatLogin;
+                if (!unionid) {
+                    throw '扫码信息已失效,请重新登录';
+                }
+                ctx.session.wechatLogin = null;
+                const paList = await ctx.service.projectAccount.getAllDataByCondition({ where: { wx_unionid: unionid } });
+                const pidList = ctx.app._.uniq(ctx.app._.map(paList, 'project_id'));
+                const pList = [];
+                const redirect_url = ctx.protocol + '://' + ctx.host + '/dashboard';
+                for (const p of pidList) {
+                    const pro = await ctx.service.project.getDataById(p);
+                    pro.userMsg = ctx.app._.find(paList, { project_id: p });
+                    pList.push(pro);
+                }
+                // 获取系统维护信息
+                const maintainData = await ctx.service.maintain.getDataById(1);
+                const renderData = {
+                    maintainData,
+                    maintainConst,
+                    unionid,
+                    pList,
+                    redirect_url,
+                };
+                await ctx.render('login/wxproject.ejs', renderData);
+            } catch (error) {
+                this.log(error);
+                ctx.session.loginError = error;
+                ctx.redirect('/login');
+            }
+        }
+
+        // 设置用户微信登录项目,跳转到对应wap页面
+        async url2web(ctx) {
+            try {
+                if (!ctx.query.project || !ctx.query.url || !ctx.query.unionid) {
+                    throw '参数有误';
+                }
+                const code = ctx.query.project;
+                // 查找项目数据
+                const projectData = await ctx.service.project.getProjectByCode(code.toString().trim());
+                if (projectData === null) {
+                    throw '不存在项目数据';
+                }
+                const pa = await ctx.service.projectAccount.getDataByCondition({ project_id: projectData.id, wx_unionid: ctx.query.unionid });
+                if (!pa) {
+                    throw '该微信号未绑定此项目';
+                }
+                if (pa.enable !== 1) {
+                    throw '该账号已被停用,请联系销售人员';
+                }
+                // 设置项目和用户session记录
+                const result = await ctx.service.projectAccount.accountLogin({ project: projectData, accountData: pa }, 3);
+                if (!result) {
+                    throw '登录出错';
+                }
+                ctx.redirect(ctx.query.url);
+            } catch (error) {
+                const renderData = {
+                    status: 1,
+                    msg: error,
+                };
+                await ctx.render('wechat/tips.ejs', renderData);
+            }
+        }
 
         /**
          * 登录操作

+ 17 - 1
app/controller/wechat_controller.js

@@ -110,7 +110,7 @@ module.exports = app => {
                     throw '先关注公众号才能绑定项目';
                 }
 
-                const result2 = await ctx.service.projectAccount.bindWx(accountData.id, ctx.session.wechatToken.openid, user.nickname);
+                const result2 = await ctx.service.projectAccount.bindWx(accountData.id, ctx.session.wechatToken.openid, user.nickname, user.unionid);
                 if (!result2) {
                     throw '绑定失败';
                 }
@@ -254,6 +254,22 @@ module.exports = app => {
                 ctx.body = error;
             }
         }
+
+        async batchUpdateUnionid(ctx) {
+            try {
+                const wxList = await ctx.service.projectAccount.getUnionIdList();
+                const updateList = [];
+                for (const wx of wxList) {
+                    const user = await app.wechat.api.getUser(wx.wx_openid);
+                    updateList.push({ id: wx.id, wx_unionid: user.unionid });
+                }
+                await ctx.service.projectAccount.updateRows(updateList);
+                ctx.body = 'success';
+            } catch (error) {
+                console.log(error);
+                ctx.body = error;
+            }
+        }
     }
 
     return WechatController;

二进制
app/public/images/icon-pc.png


二进制
app/public/images/icon-qrcode.png


+ 4 - 0
app/public/js/change_information.js

@@ -236,6 +236,10 @@ $(document).ready(() => {
         headerFont: '12px 微软雅黑',
         font: '12px 微软雅黑',
         readOnly: true,
+        localCache: {
+            key: 'changes-xmj',
+            colWidth: true,
+        }
     };
     SpreadJsObj.initSheet(xmjSpread.getActiveSheet(), xmjSpreadSetting);
 });

+ 4 - 0
app/public/js/change_information_approval.js

@@ -42,6 +42,10 @@ $(document).ready(() => {
                 },
             },
         ],
+        localCache: {
+            key: 'changes-spread',
+            colWidth: true,
+        }
     };
     for (const aid of aidList) {
         const userinfo = _.find(auditList2, { 'uid': aid });

+ 6 - 3
app/public/js/change_information_set.js

@@ -119,6 +119,10 @@ $(document).ready(() => {
                 },
             },
         ],
+        localCache: {
+            key: 'changes-spread',
+            colWidth: true,
+        }
     };
 
     const changeCol = {
@@ -836,9 +840,8 @@ function tableDataRemake(changeListData) {
                     let pushbwmx = '0*;*0';
                     if (listinfo.leafXmjs !== undefined) {
                         const leafInfo = listinfo.leafXmjs.find(function (item) {
-                            return (item.bwmx === undefined || item.bwmx === clinfo.bwmx) && (item.quantity !== null ? item.quantity === parseFloat(clinfo.oamount) : 0 === parseFloat(clinfo.oamount));
+                            return (item.bwmx === undefined || item.bwmx === clinfo.bwmx) && item.code === clinfo.xmj_code && (item.quantity !== null ? item.quantity === parseFloat(clinfo.oamount) : 0 === parseFloat(clinfo.oamount));
                         });
-                        console.log(leafInfo);
                         if (leafInfo) {
                             pushbwmx = leafInfo.code + '!_!' + (leafInfo.jldy !== undefined ? leafInfo.jldy : '') + '!_!' +
                                 (leafInfo.dwgc ? leafInfo.dwgc : '') + '!_!' +
@@ -868,7 +871,7 @@ function tableDataRemake(changeListData) {
                     let pushbwmx = '0*;*0';
                     if (listinfo.leafXmjs !== undefined) {
                         const leafInfo = listinfo.leafXmjs.find(function (item) {
-                            return (item.bwmx === undefined || item.bwmx === clinfo.bwmx || item.jldy === clinfo.bwmx) && (item.quantity !== null ? item.quantity === parseFloat(clinfo.oamount) : 0 === parseFloat(clinfo.oamount));
+                            return (item.bwmx === undefined || item.bwmx === clinfo.bwmx || item.jldy === clinfo.bwmx) && item.code === clinfo.xmj_code && (item.quantity !== null ? item.quantity === parseFloat(clinfo.oamount) : 0 === parseFloat(clinfo.oamount));
                         });
                         if (leafInfo) {
                             pushbwmx = leafInfo.code + '!_!' + (leafInfo.jldy !== undefined ? leafInfo.jldy : '') + '!_!' +

+ 4 - 0
app/public/js/change_information_show.js

@@ -44,6 +44,10 @@ $(document).ready(() => {
                 },
             },
         ],
+        localCache: {
+            key: 'changes-spread',
+            colWidth: true,
+        }
     };
     for (const aid of aidList) {
         const userinfo = _.find(auditList2, { 'uid': aid });

+ 7 - 0
app/router.js

@@ -458,4 +458,11 @@ module.exports = app => {
     // 书签
     app.post('/tender/:id/ledger/tag', sessionAuth, tenderCheck, uncheckTenderCheck, 'tenderController.billsTag');
     app.post('/tender/:id/measure/stage/:order/tag', sessionAuth, tenderCheck, uncheckTenderCheck, stageCheck, 'tenderController.billsTag');
+
+    // 扫码登录
+    app.get('/wxAuth', 'loginController.wxAuth');
+    app.get('/wxproject', 'loginController.wxProject');
+    app.get('/wx/url2web', 'loginController.url2web');
+
+    app.get('/wx/unionid', wechatAuth, 'wechatController.batchUpdateUnionid');
 };

+ 9 - 1
app/service/project_account.js

@@ -764,9 +764,10 @@ module.exports = app => {
          * @param {String} id - 账号id
          * @param {Number} openid - openid
          * @param {Number} nickname - 微信名称
+         * @param {Number} unionid - unionid
          * @return {Boolean} - 返回修改结果
          */
-        async bindWx(id, openid, nickname) {
+        async bindWx(id, openid, nickname, unionid) {
             const wx_type = {};
             for (const key in smsTypeConst) {
                 if (smsTypeConst.hasOwnProperty(key)) {
@@ -779,6 +780,7 @@ module.exports = app => {
                 id,
                 wx_openid: openid,
                 wx_name: nickname,
+                wx_unionid: unionid,
                 wx_type: JSON.stringify(wx_type),
             };
 
@@ -788,6 +790,12 @@ module.exports = app => {
 
             return result;
         }
+
+        async getUnionIdList() {
+            const sql = 'SELECT * FROM ?? WHERE wx_openid != ? and wx_unionid = ?';
+            const sqlParam = [this.tableName, null, null];
+            return await this.db.query(sql, sqlParam);
+        }
     }
 
     return ProjectAccount;

+ 41 - 2
app/view/login/login.ejs

@@ -30,7 +30,9 @@
                 </form>
             <% } else { %>
                 <!--演示版-->
-                <form class="form-signin" method="post" action="/login">
+                <form class="form-signin" method="post" action="/login" id="normal-form" style="min-width: 360px;position: relative">
+                    <!--<div class="change-form" style="position: absolute;right: 0;top: 0px;cursor: pointer;"><i style="padding:5px;font-size: 50px;color: #212529" class="fa fa-qrcode"></i></div>-->
+                    <div class="change-form" data-toggle="tooltip" data-placement="left" title="微信登录" style="position: absolute;right: 0;top: 0px;cursor: pointer;"><img alt="微信扫码登录" style="padding:5px;" width="50px" src="/public/images/icon-qrcode.png"></div>
                     <!-- <h4 class="text-center mb-2">纵横云计量</h4> -->
                     <h5 class="text-center mb-2" id="project_name"></h5>
                     <h5 class="text-center mb-4 text-muted">用户登录</h5>
@@ -73,6 +75,12 @@
                         <a href="#fg-password" data-toggle="modal" data-target="#fg-password"  class="mr-3">忘记密码?</a>
                     </div>
                 </form>
+                <form class="form-signin" id="code-form" style="min-width: 360px;position: relative;display: none">
+                    <!--<div class="change-form" style="position: absolute;right: 0;top: 0px;cursor: pointer;"><i style="padding:5px;font-size: 40px;color: #212529" class="fa fa-laptop"></i></div>-->
+                    <div class="change-form" data-toggle="tooltip" data-placement="left" title="账号登录" style="position: absolute;right: 0;top: 0px;cursor: pointer;"><img alt="账号登录" style="padding:5px;" width="50px" src="/public/images/icon-pc.png"></div>
+                    <div id="wx-code" style="text-align: center">
+                    </div>
+                </form>
             <% } %>
             <!--项目版-->
         </div>
@@ -135,6 +143,37 @@
     const csrf = '<%= ctx.csrf %>'
 </script>
 <script src="/public/js/login.js"></script>
-</body>
+<script src="http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js"></script>
+<script>
+    $(function () {
+        const obj = new WxLogin({
+            self_redirect:false,
+            id:"wx-code",
+            appid: "wx5320cd30cecdbd68",
+            scope: "snsapi_login",
+            redirect_uri: "<%- hostUrl %>/wxAuth",
+            state: getQueryString('referer'),
+            style: "black",
+            href: ""
+        });
 
+        function getQueryString(name) {
+            var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)", "i");
+            var r = window.location.search.substr(1).match(reg); //获取url中"?"符后的字符串并正则匹配
+            var context = "";
+
+            if (r != null)
+                context = r[2];
+            reg = null;
+            r = null;
+            return context == null || context == "" || context == "undefined" ? "" : context;
+        }
+
+        $('.change-form').on('click', function () {
+            $(this).parents('form').hide();
+            $(this).parents('form').siblings('form').show();
+        })
+    })
+</script>
+</body>
 </html>

+ 74 - 0
app/view/login/wxproject.ejs

@@ -0,0 +1,74 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+    <meta charset="utf-8">
+    <meta name="viewport" content="initial-scale=1, maximum-scale=1,user-scalable=no">
+    <meta http-equiv="x-ua-compatible" content="ie=edge">
+    <title>项目列表-计量支付</title>
+    <link rel="stylesheet" href="/public/css/bootstrap/bootstrap.min.css">
+    <link rel="stylesheet" href="/public/css/wap/main.css">
+    <link rel="stylesheet" href="/public/css/toast.css">
+    <link rel="stylesheet" href="/public/css/font-awesome/font-awesome.min.css">
+    <link rel="shortcut icon" href="/public/images/favicon.ico">
+</head>
+<body>
+<div class="container">
+    <!--顶部-->
+    <nav class="fixed-top bg-dark">
+        <div class="my-2 d-flex justify-content-between">
+            <span class="text-white ml-3">项目列表</span>
+            <div class="mr-3"><a class="text-white" href="/login">重新登录</a>
+                <!-- <div class="dropdown">
+                  <button class="btn btn-sm btn-light dropdown-toggle" type="button" data-toggle="dropdown">
+                    张三
+                  </button>
+                  <div class="dropdown-menu" aria-labelledby="dropdownMenuButton">
+                    <a class="dropdown-item" href="#">退出登录</a>
+                  </div>
+                </div> -->
+            </div>
+        </div>
+    </nav>
+    <% if (maintainData.status === maintainConst.status.ongoing) { %>
+        <form class="card m-3 mt-3">
+            <div class="card-body">
+                <h4 class="text-center mb-3"><i class="fa fa-wrench"></i>系统正在维护</h4>
+                <h4>预计恢复时间<%- (maintainData.duration !== maintainConst.duration.forever ? '为 ' + ctx.helper.dateTran(parseFloat(maintainData.maintain_time) + ctx.helper.timeAdd(maintainData.duration)) : ' 暂未确定') %></h4>
+                <h4>造成不便敬请谅解。</h4>
+            </div>
+        </form>
+    <% } else { %>
+    <!--待审批期列表-->
+    <div class="py-6">
+        <% if (pList.length !== 0) { %>
+        <p class="text-muted">您的微信已绑定以下项目:</p>
+        <% for (const p of pList) { %>
+        <div class="card mb-3">
+            <div class="card-header d-flex justify-content-between">
+                <span><%- p.name %></span>
+            </div>
+            <div class="d-flex justify-content-between">
+                <div class="p-2 px-3 row w-75"><div class="col-6">项目编号:<%- p.code %></div><div class="col-6"> 用户账号:<%- p.userMsg.account %><%- p.userMsg.role ? '-'+ p.userMsg.role : '' %></div></div>
+                <div class=""><a href="/wx/url2web?project=<%- p.code %>&url=<%- redirect_url %>&unionid=<%- unionid %>" class="btn btn-block btn-link">进入项目</a></div>
+            </div>
+        </div>
+        <% } %>
+        <% } else { %>
+        <p class="text-muted">当前微信未绑定过任何计量项目,请扫码或搜索 关注“纵横造价”服务号绑定项目</p>
+        <div class="w-50"><img class="w-100" src="/public/images/wechat.png"></div>
+        <% } %>
+    </div>
+    <% } %>
+</div>
+<!-- JS. -->
+<div class="toast" style="text-align: center">
+    <i class="icon fa"></i>
+    <span class="message"></span>
+</div>
+<!-- JS. -->
+<script src="/public/js/jquery/jquery-3.2.1.min.js"></script>
+<script src="/public/js/popper/popper.min.js"></script>
+<script src="/public/js/bootstrap/bootstrap.min.js"></script>
+<script src="/public/js/wap/global.js"></script>
+</body>
+</html>

+ 2 - 2
app/view/tender/shenpi_modal.ejs

@@ -98,7 +98,7 @@
                 <div class="row">
                     <div class="col-6">
                         <% const yb = ctx.helper._.find(accountList, { id: ctx.tender.data.user_id }) %>
-                        <div class="modal-height-300">
+                        <div class="modal-height-500">
                             <table class="table table-hover table-bordered">
                                 <thead>
                                 <tr><th colspan="3" class="text-center" id="stage_audit"><%- yb.name %>(原报)</th></tr>
@@ -120,7 +120,7 @@
                                 <% } %>
                             </select>
                         </div>
-                        <div class="modal-height-300" style="overflow: auto;" id="ledger-spread">
+                        <div class="modal-height-500" style="overflow: auto;" id="ledger-spread">
                         </div>
                     </div>
                 </div>

+ 6 - 0
app/view/tender/tender_sub_mini_menu.ejs

@@ -11,6 +11,12 @@
             </ul>
         </div>
         <div class="nav-box">
+            <ul class="nav-list list-unstyled">
+                <% const curUrl = `/tender/${ctx.tender.id}/advance` %>
+                <li <% if (ctx.url.indexOf(curUrl) !== -1) { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/advance"><i class="fa fa-handshake-o"></i> <span>预付款</span></a></li>
+            </ul>
+        </div>
+        <div class="nav-box">
             <h3><i class="fa fa-list-alt"></i> 0号台账</h3>
             <ul class="nav-list list-unstyled sub-list">
                 <li <% if (ctx.url === '/tender/' + ctx.tender.id + '/ledger') { %>class="active"<% } %>><a href="/tender/<%- ctx.tender.id %>/ledger"><span>台账分解</span></a></li>

+ 1 - 106
sql/update.sql

@@ -1,114 +1 @@
---
---
-
-CREATE TABLE `zh_schedule` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `tid` int(11) NOT NULL,
-  `total_tp` decimal(30,8) DEFAULT NULL COMMENT '已选台账总金额',
-  `plan_gcl` decimal(30,8) DEFAULT NULL COMMENT '计划总工程量',
-  `sj_gcl` decimal(30,8) DEFAULT NULL COMMENT '实际完成工程量',
-  `plan_tp` decimal(30,8) DEFAULT NULL COMMENT '计划总金额',
-  `sj_tp` decimal(30,8) DEFAULT NULL COMMENT '实际完成金额',
-  `stage_sj_tp` decimal(30,8) DEFAULT NULL COMMENT '计量期实际计量总额',
-  `mode` tinyint(1) DEFAULT '2' COMMENT '计划进度计算方式(默认为工程量)',
-  `revising` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否修订后并未更新数据',
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='形象进度表';
-
---
---
-
-CREATE TABLE `zh_schedule_audit` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `tid` int(11) NOT NULL COMMENT '标段id',
-  `audit_id` int(11) NOT NULL COMMENT '用户id',
-  `permission` tinyint(1) NOT NULL DEFAULT '1' COMMENT '权限',
-  `in_time` datetime DEFAULT NULL COMMENT '入库时间',
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='形象进度用户权限表';
-
---
---
-
-CREATE TABLE `zh_schedule_ledger` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `tid` int(11) NOT NULL COMMENT '标段id',
-  `ledger_id` int(11) NOT NULL COMMENT '台账id',
-  `gcl` decimal(30,8) DEFAULT NULL COMMENT '只记录已选最底层树工程量',
-  `tp` decimal(30,8) DEFAULT NULL COMMENT '只记录已选最底层树金额',
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='进度已选台账';
-
---
---
-
-CREATE TABLE `zh_schedule_ledger_history` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `tid` int(11) NOT NULL,
-  `ledger_id` int(11) NOT NULL,
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='旧台账(用于修订后对比新旧台账区别然后调整进度台账)';
-
---
---
-
-CREATE TABLE `zh_schedule_ledger_month` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `tid` int(11) NOT NULL COMMENT '标段id',
-  `lid` int(11) NOT NULL COMMENT '台账id',
-  `yearmonth` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '计划年月',
-  `plan_gcl` decimal(30,8) DEFAULT NULL COMMENT '计划工程量',
-  `sj_gcl` decimal(30,8) DEFAULT NULL COMMENT '实际工程量',
-  `plan_tp` decimal(30,8) DEFAULT NULL COMMENT '计划金额',
-  `sj_tp` decimal(30,8) DEFAULT NULL COMMENT '实际计量金额',
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='台账年月记录进度表';
-
---
---
-
-CREATE TABLE `zh_schedule_month` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `tid` int(11) NOT NULL COMMENT '标段id',
-  `yearmonth` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '计划年月',
-  `plan_gcl` decimal(30,8) DEFAULT NULL COMMENT '计划工程量',
-  `sj_gcl` decimal(30,8) DEFAULT NULL COMMENT '实际工程量',
-  `plan_tp` decimal(30,8) DEFAULT NULL COMMENT '计划金额',
-  `sj_tp` decimal(30,8) DEFAULT NULL COMMENT '实际计量金额',
-  `stage_gcl_used` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已被工程量计量',
-  `stage_tp_used` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已被金额模式计量',
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='进度年月记录汇总台账表';
-
---
---
-
-CREATE TABLE `zh_schedule_stage` (
-  `id` int(11) NOT NULL AUTO_INCREMENT,
-  `tid` int(11) NOT NULL COMMENT '标段id',
-  `yearmonth` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '计划月份',
-  `order` int(11) NOT NULL COMMENT '计量期数',
-  `tp` decimal(30,8) DEFAULT NULL COMMENT '本期计量完成金额',
-  PRIMARY KEY (`id`)
-) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='计量进度-计划月份,计量期选中表';
-
-
---
---
-
-CREATE TABLE `calculation`.`zh_rpt_archive` (
-  `archive_id` INT NOT NULL,
-  `prj_id` INT NULL,
-  `stage_id` INT NULL,
-  `content` VARCHAR(4000) NULL,
-  PRIMARY KEY (`archive_id`),
-  INDEX `PRJ_STG` (`prj_id` ASC, `stage_id` ASC))
-COMMENT = '报表归档表;\n只考虑项目id及期id,其他信息全部归入content';
+ALTER TABLE `zh_project_account` ADD `wx_unionid` VARCHAR(50) NULL COMMENT '微信绑定unionid(同一个开放平台共用)' AFTER `wx_openid`;

+ 100 - 0
sql/update20210312.sql

@@ -0,0 +1,100 @@
+--
+-- 表的结构 `zh_schedule`
+--
+
+CREATE TABLE `zh_schedule` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `tid` int(11) NOT NULL,
+  `total_tp` decimal(30,8) DEFAULT NULL COMMENT '已选台账总金额',
+  `plan_gcl` decimal(30,8) DEFAULT NULL COMMENT '计划总工程量',
+  `sj_gcl` decimal(30,8) DEFAULT NULL COMMENT '实际完成工程量',
+  `plan_tp` decimal(30,8) DEFAULT NULL COMMENT '计划总金额',
+  `sj_tp` decimal(30,8) DEFAULT NULL COMMENT '实际完成金额',
+  `stage_sj_tp` decimal(30,8) DEFAULT NULL COMMENT '计量期实际计量总额',
+  `mode` tinyint(1) DEFAULT '2' COMMENT '计划进度计算方式(默认为工程量)',
+  `revising` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否修订后并未更新数据',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='形象进度表';
+
+--
+-- 表的结构 `zh_schedule_audit`
+--
+
+CREATE TABLE `zh_schedule_audit` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `tid` int(11) NOT NULL COMMENT '标段id',
+  `audit_id` int(11) NOT NULL COMMENT '用户id',
+  `permission` tinyint(1) NOT NULL DEFAULT '1' COMMENT '权限',
+  `in_time` datetime DEFAULT NULL COMMENT '入库时间',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='形象进度用户权限表';
+
+--
+-- 表的结构 `zh_schedule_ledger`
+--
+
+CREATE TABLE `zh_schedule_ledger` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `tid` int(11) NOT NULL COMMENT '标段id',
+  `ledger_id` int(11) NOT NULL COMMENT '台账id',
+  `gcl` decimal(30,8) DEFAULT NULL COMMENT '只记录已选最底层树工程量',
+  `tp` decimal(30,8) DEFAULT NULL COMMENT '只记录已选最底层树金额',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='进度已选台账';
+
+--
+-- 表的结构 `zh_schedule_ledger_history`
+--
+
+CREATE TABLE `zh_schedule_ledger_history` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `tid` int(11) NOT NULL,
+  `ledger_id` int(11) NOT NULL,
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='旧台账(用于修订后对比新旧台账区别然后调整进度台账)';
+
+--
+-- 表的结构 `zh_schedule_ledger_month`
+--
+
+CREATE TABLE `zh_schedule_ledger_month` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `tid` int(11) NOT NULL COMMENT '标段id',
+  `lid` int(11) NOT NULL COMMENT '台账id',
+  `yearmonth` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '计划年月',
+  `plan_gcl` decimal(30,8) DEFAULT NULL COMMENT '计划工程量',
+  `sj_gcl` decimal(30,8) DEFAULT NULL COMMENT '实际工程量',
+  `plan_tp` decimal(30,8) DEFAULT NULL COMMENT '计划金额',
+  `sj_tp` decimal(30,8) DEFAULT NULL COMMENT '实际计量金额',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='台账年月记录进度表';
+
+--
+-- 表的结构 `zh_schedule_month`
+--
+
+CREATE TABLE `zh_schedule_month` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `tid` int(11) NOT NULL COMMENT '标段id',
+  `yearmonth` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '计划年月',
+  `plan_gcl` decimal(30,8) DEFAULT NULL COMMENT '计划工程量',
+  `sj_gcl` decimal(30,8) DEFAULT NULL COMMENT '实际工程量',
+  `plan_tp` decimal(30,8) DEFAULT NULL COMMENT '计划金额',
+  `sj_tp` decimal(30,8) DEFAULT NULL COMMENT '实际计量金额',
+  `stage_gcl_used` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已被工程量计量',
+  `stage_tp_used` tinyint(1) NOT NULL DEFAULT '0' COMMENT '是否已被金额模式计量',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='进度年月记录汇总台账表';
+
+--
+-- 表的结构 `zh_schedule_stage`
+--
+
+CREATE TABLE `zh_schedule_stage` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `tid` int(11) NOT NULL COMMENT '标段id',
+  `yearmonth` varchar(255) COLLATE utf8_unicode_ci NOT NULL COMMENT '计划月份',
+  `order` int(11) NOT NULL COMMENT '计量期数',
+  `tp` decimal(30,8) DEFAULT NULL COMMENT '本期计量完成金额',
+  PRIMARY KEY (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='计量进度-计划月份,计量期选中表';