瀏覽代碼

1. 台账修订,总分包更新相关
2. 资料模板库,分享模板相关

MaiXinRong 5 月之前
父節點
當前提交
7a5a7d5cad

+ 5 - 6
app/controller/file_controller.js

@@ -397,13 +397,13 @@ module.exports = app => {
             const defaultTemplate = await ctx.service.filingTemplateList.getOriginTemplate();
             ctx.redirect('/file/template/' + defaultTemplate.id);
         }
-
         async templateDetail(ctx) {
             try {
                 const renderData = {
                     jsFiles: this.app.jsFiles.common.concat(this.app.jsFiles.file.template),
                 };
                 renderData.templateList = await ctx.service.filingTemplateList.getAllTemplate(ctx.session.sessionProject.id);
+                renderData.shareTemplate = await ctx.service.filingTemplateList.getShareTemplate(ctx.session.sessionProject.id);
                 renderData.FtType = ctx.service.filingTemplateList.FtType;
                 renderData.template = renderData.templateList.find(x => { return x.id === ctx.params.id });
                 if (!renderData.template) throw '查看的资料模板不存在';
@@ -416,12 +416,13 @@ module.exports = app => {
                 ctx.redirect(this.menu.menu.dashboard.url);
             }
         }
-
         async saveTemplate(ctx) {
             try {
                 const id = ctx.query.id;
                 const name = ctx.request.body.name;
-                const [save, templateId] = await ctx.service.filingTemplateList.save(name, id);
+                const is_share = ctx.request.body.is_share ? parseInt(ctx.request.body.is_share) : undefined;
+                const share_id = ctx.request.body.share_id;
+                const [save, templateId] = share_id ? await ctx.service.filingTemplateList.copy(share_id) : await ctx.service.filingTemplateList.save(name, is_share, id);
                 if (!save) throw '保存数据失败';
                 ctx.redirect('/file/template/' + templateId);
             } catch(err) {
@@ -430,7 +431,6 @@ module.exports = app => {
                 ctx.redirect('/file/template');
             }
         }
-
         async resetTemplate(ctx) {
             try {
                 const id = ctx.query.id;
@@ -442,7 +442,6 @@ module.exports = app => {
                 ctx.redirect('/file/template');
             }
         }
-
         async delTemplate(ctx) {
             try {
                 const id = ctx.query.id;
@@ -459,7 +458,6 @@ module.exports = app => {
                 ctx.redirect('/file/template');
             }
         }
-
         async updateTemplate(ctx) {
             try {
                 const data = JSON.parse(ctx.request.body.data);
@@ -528,6 +526,7 @@ module.exports = app => {
         }
         async manageUpdate(ctx) {
             try {
+                this.checkLock(ctx);
                 const data = JSON.parse(ctx.request.body.data);
                 if (!data.updateType) throw '数据错误';
                 let result;

+ 5 - 4
app/lib/sum_load.js

@@ -104,6 +104,7 @@ class loadGclBaseTree {
                 quantity: 0,
                 is_leaf: source.is_leaf,
                 hasPos: false,
+                sub_up: source.unit_price || 0,
             };
             this.keyNodeId += 1;
             parent.children.push(node);
@@ -278,7 +279,7 @@ class updateReviseGclTree extends loadGclBaseTree {
         }
     }
     gather(source, parent) {
-        const node =  this.ignoreParent ? this.addNodeWithoutParent(source) : this.addNode(source, parent);
+        const node = this.ignoreParent ? this.addNodeWithoutParent(source) : this.addNode(source, parent);
         node.deal_qty = this.ctx.helper.add(node.deal_qty, source.deal_qty);
         node.sgfh_qty = this.ctx.helper.add(node.sgfh_qty, source.sgfh_qty);
         node.qtcl_qty = this.ctx.helper.add(node.qtcl_qty, source.qtcl_qty);
@@ -489,7 +490,7 @@ class sumLoad {
 
     async loadGatherGcl(select, maxId, tenders, defaultData, subUp) {
         this.loadTree = new loadLedgerGclTree(this.ctx, {
-            parent: select, maxId, type: 'ledger', defaultData, subUp,
+            parent: select, maxId, type: 'ledger', defaultData, useSubUp: subUp,
         });
         for (const tender of tenders) {
             const billsData = await this.ctx.service.ledger.getData(tender.tid);
@@ -517,10 +518,10 @@ class sumLoad {
         return this.loadTree;
     }
 
-    async updateGatherGcl(select, maxId, tenders, defaultData) {
+    async updateGatherGcl(select, maxId, tenders, defaultData, subUp) {
         const ignoreParent = this.ctx.tender.info.fun_rela.sum_load.ignoreParent;
         this.loadTree = new updateReviseGclTree(this.ctx, {
-            parent: select, maxId, type: 'ledger', defaultData, ignoreParent,
+            parent: select, maxId, type: 'ledger', defaultData, ignoreParent, useSubUp: subUp,
         });
         const posterity = await this.ctx.service.reviseBills.getPosterityByParentId(this.ctx.tender.id, select.ledger_id);
         const pos = await this.ctx.service.revisePos.getData(this.ctx.tender.id);

+ 32 - 0
app/public/js/filing_template.js

@@ -269,6 +269,16 @@ $(document).ready(function() {
             '</div>');
         $(`.table-file[tempId=${tempId}]`).html(html.join(''));
     });
+    $('body').on('click', 'a[name=shareTemplate]', function(e){
+        e.stopPropagation();
+        const tempId = $(this).parents('.table-file').attr('tempId');
+        hiddenSubmit('/file/template/save?id='+tempId, 'is_share', 1);
+    });
+    $('body').on('click', 'a[name=shareOffTemplate]', function(e){
+        e.stopPropagation();
+        const tempId = $(this).parents('.table-file').attr('tempId');
+        hiddenSubmit('/file/template/save?id='+tempId, 'is_share', 0);
+    });
 
     class MultiObj {
         constructor(setting) {
@@ -462,4 +472,26 @@ $(document).ready(function() {
             }
         });
     });
+    $('#import-share-template').click(() => {
+        const check = $('[name=sst-check]');
+        for (const c of check) {
+            c.checked = false;
+        }
+        $('#select-share-template').modal('show');
+    });
+    $('[name=sst-check]').change(function() {
+        const check = $('[name=sst-check]');
+        for (const c of check) {
+            if (c.value !== this.value) c.checked = false;
+        }
+        // if (val.length > 1) val.shift();
+    });
+    $('#sst-ok').click(function() {
+        const tempId = $('[name=sst-check]:checked').val();
+        if (!tempId) {
+            toastr.warning('请选择要导入的模板');
+            return;
+        }
+        hiddenSubmit('/file/template/save', 'share_id', tempId);
+    });
 });

+ 27 - 4
app/service/filing_template.js

@@ -40,15 +40,38 @@ module.exports = app => {
             this.tableName = 'filing_template';
         }
 
-        async initTemplate(transaction, template) {
-            const insertData = [];
+        getDefaultTemplateData(templateId) {
+            const result = [];
             for (const [i, f] of filingType.entries()) {
-                insertData.push({
-                    id: this.uuid.v4(), temp_id: template.id, tree_pid: -1, tree_level: 1, tree_order: i + 1,
+                result.push({
+                    id: this.uuid.v4(), temp_id: templateId, tree_pid: -1, tree_level: 1, tree_order: i + 1,
                     add_user_id: this.ctx.session.sessionUser.accountId, is_fixed: true,
                     name: f.name, filing_type: f.value,
                 });
             }
+            return result;
+        }
+
+        getCopyTemplateData(templateId, templateData) {
+            templateData.sort((x, y) => { return x.tree_level - y.tree_level; });
+            const insertData = [];
+            for (const d of templateData) {
+                if (d.id === undefined || d.tree_pid === undefined || d.tree_order === undefined || d.tree_level === undefined || d.name === undefined || d.is_fixed === undefined || d.filing_type === undefined) {
+                    throw '数据格式有误';
+                }
+                const parent = insertData.find(x => { return x.org_id === d.tree_pid });
+                insertData.push({
+                    id: this.uuid.v4(), temp_id: templateId, add_user_id: this.ctx.session.sessionUser.accountId,
+                    tree_pid: parent ? parent.id : rootId, tree_level: parent ? parent.tree_level + 1 : 1, tree_order: d.tree_order,
+                    name: d.name, tips: d.tips, filing_type: d.filing_type, is_fixed: parent ? d.is_fixed : 1, org_id: d.id,
+                });
+            }
+            insertData.forEach(x => { delete x.org_id; });
+            return insertData;
+        }
+
+        async initTemplate(transaction, template, templateData) {
+            const insertData = templateData ? this.getCopyTemplateData(template.id, templateData) : this.getDefaultTemplateData(template.id);
             if (transaction) {
                 await transaction.insert(this.tableName, insertData);
             } else {

+ 42 - 2
app/service/filing_template_list.js

@@ -38,6 +38,14 @@ module.exports = app => {
             return await this.db.query(sql, [pid]);
         }
 
+        async getShareTemplate(pid) {
+            const sql = `SELECT ftl.*, p.name as project_name, pa.name as user_name FROM ${this.tableName} ftl 
+                            LEFT JOIN ${this.ctx.service.projectAccount.tableName} pa ON ftl.user_id = pa.id
+                            LEFT JOIN ${this.ctx.service.project.tableName} p ON ftl.project_id = p.id  
+                            WHERE ftl.is_share = 1 and ftl.project_id <> ?`;
+            return await this.db.query(sql, [pid]);
+        }
+
         /**
          * 保存/新增数据
          *
@@ -45,9 +53,12 @@ module.exports = app => {
          * @param {String} id - 存在则为保存,反之新增
          * @return {boolean} - 操作结果
          */
-        async save(name, id = '') {
+        async save(name, is_share, id = '') {
             if (id) {
-                const result = await this.defaultUpdate({ id, name });
+                const updateData = { id };
+                if (name !== undefined) updateData.name = name;
+                if (is_share !== undefined) updateData.is_share = is_share;
+                const result = await this.defaultUpdate(updateData);
                 return [result.affectedRows > 0, id];
             } else {
                 const conn = await this.db.beginTransaction();
@@ -70,6 +81,35 @@ module.exports = app => {
         }
 
         /**
+         * 拷贝模板
+         *
+         * @param {string} shareId - 拷贝模板的id
+         * @return {Boolean} - 操作结果
+         */
+        async copy(shareId) {
+            const shareTemplate = await this.getDataById(shareId);
+            if (!shareTemplate.is_share) throw '模板已取消共享';
+            const shareTemplateData = await this.ctx.service.filingTemplate.getData(shareId);
+
+            const conn = await this.db.beginTransaction();
+            try {
+                const newTemplate = {
+                    id: this.uuid.v4(), project_id: this.ctx.session.sessionProject.id,
+                    user_id: this.ctx.session.sessionUser.accountId,
+                    name: shareTemplate.name || '拷贝XXX模板库', ft_type: FtType.add,
+                };
+                await conn.insert(this.tableName, newTemplate);
+                await this.ctx.service.filingTemplate.initTemplate(conn, newTemplate, shareTemplateData);
+                await conn.commit();
+                return [true, newTemplate.id];
+            } catch (err) {
+                this.ctx.log(err);
+                await conn.rollback();
+                return [false, err.stack ? '拷贝模板数据错误' : ''];
+            }
+        }
+
+        /**
          * 删除模板
          *
          * @param {string} id - 删除的id

+ 11 - 1
app/view/file/template.ejs

@@ -19,9 +19,18 @@
                             <% for (const temp of templateList) { %>
                             <dd class="list-group-item <%- (temp.id === template.id ? 'bg-warning' : '')%>">
                                 <div class="d-flex justify-content-between align-items-center table-file" tempId="<%- temp.id %>">
-                                    <div><%if (temp.ft_type === FtType.org) { %><span class="text-success mr-1" style="border: 1px solid">默认</span><% } %><%- temp.name %>%></div>
+                                    <div>
+                                        <% if (temp.ft_type === FtType.org) { %><span class="text-success mr-1" style="border: 1px solid">默认</span><% } %>
+                                        <% if (temp.is_share) { %><span class="text-primary mr-1" style="border: 1px solid">分享</span><% } %>
+                                        <%- temp.name %>%>
+                                    </div>
                                     <% if (temp.ft_type) { %>
                                     <div class="btn-group-table" style="display: none;">
+                                        <% if (temp.is_share) { %>
+                                        <a href="javascript: void(0);" class="mr-1" data-toggle="tooltip" data-placement="bottom" data-original-title="取消分享" name="shareOffTemplate"><i class="fa fa-chain-broken fa-fw"></i></a>
+                                        <% } else { %>
+                                        <a href="javascript: void(0);" class="mr-1" data-toggle="tooltip" data-placement="bottom" data-original-title="分享" name="shareTemplate"><i class="fa fa-chain fa-fw"></i></a>
+                                        <% } %>
                                         <a href="javascript: void(0);" class="mr-1" data-toggle="tooltip" data-placement="bottom" data-original-title="编辑" name="renameTemplate"><i class="fa fa-pencil fa-fw"></i></a>
                                         <a href="javascript: void(0);" class="mr-1" data-toggle="tooltip" data-placement="bottom" data-original-title="删除" name="delTemplate"><i class="fa fa-trash-o fa-fw text-danger"></i></a>
                                     </div>
@@ -46,6 +55,7 @@
                         </form>
                         <div class="ml-auto p-2">
                             <a href="javascript: void(0);" class="btn btn-sm btn-primary" id="import-template">导入</a>
+                            <a href="javascript: void(0);" class="btn btn-sm btn-primary" id="import-share-template">拷贝分享模板库</a>
                             <a href="javascript: void(0);" class="btn btn-sm btn-primary" id="export-template">导出</a>
                             <a href="javascript: void(0);" class="btn btn-sm btn-primary" id="multi-setting">附加配置</a>
                         </div>

+ 23 - 1
app/view/file/template_modal.ejs

@@ -1,4 +1,3 @@
-<% include ../shares/select_file_modal.ejs %>
 <div class="modal fade" id="multi-set" data-backdrop="static">
     <div class="modal-dialog modal-lg" role="document">
         <div class="modal-content">
@@ -18,4 +17,27 @@
             </div>
         </div>
     </div>
+</div>
+<div class="modal fade" id="select-share-template" data-backdrop="static">
+    <div class="modal-dialog modal-lg" role="document">
+        <div class="modal-content">
+            <div class="modal-header">
+                <h5 class="modal-title">选择分享模板库</h5>
+            </div>
+            <div class="modal-body">
+                <div class="form-group modal-height-300 scroll-y">
+                    <table class="table table-sm table-bordered table-hover">
+                        <tr class="text-center"><th>模板库名称</th><th>所属项目</th><th>分享人</th><th>选择</th></tr>
+                        <% for (const st of shareTemplate) { %>
+                        <tr><td><%- st.name %></td><td><%- st.project_name %></td><td class="text-center"><%- st.user_name %></td><td class="text-center"><input type="checkbox" name="sst-check" value="<%- st.id %>"></td></tr>
+                        <% } %>
+                    </table>
+                </div>
+            </div>
+            <div class="modal-footer">
+                <button type="button" class="btn btn-secondary btn-sm" data-dismiss="modal">关闭</button>
+                <button type="button" class="btn btn-primary btn-sm" id="sst-ok">确认</button>
+            </div>
+        </div>
+    </div>
 </div>

+ 4 - 1
sql/update.sql

@@ -13,9 +13,12 @@ ADD COLUMN `c_mode` tinyint(1) NULL DEFAULT 0 COMMENT '变更清单模式' AFTER
 ALTER TABLE `zh_change_ledger`
 ADD COLUMN `features` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NULL DEFAULT '' COMMENT '项目特征' AFTER `memo`;
 
-ALTER TABLE `calculation`.`zh_sub_project`
+ALTER TABLE `zh_sub_project`
 ADD COLUMN `lock_file` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '资料归集,是否锁定' AFTER `filing_template_name`;
 
+ALTER TABLE `zh_filing_template_list`
+ADD COLUMN `is_share` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否分享' AFTER `memo`;
+
 ------------------------------------
 -- 表数据
 ------------------------------------