Browse Source

资料归集模板库相关

MaiXinRong 1 year ago
parent
commit
ab3f8349c5

+ 89 - 0
app/controller/file_controller.js

@@ -353,6 +353,95 @@ module.exports = app => {
                 ctx.body = this.ajaxErrorBody(error, '导入附件失败,请重试');
             }
         }
+
+        async template(ctx) {
+            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.FtType = ctx.service.filingTemplateList.FtType;
+                renderData.template = renderData.templateList.find(x => { return x.id === ctx.params.id });
+                if (!renderData.template) throw '查看的资料模板不存在';
+
+                renderData.templateData = await ctx.service.filingTemplate.getData(renderData.template.id);
+                await this.layout('file/template.ejs', renderData);
+            } catch (err) {
+                ctx.log(err);
+                ctx.session.postError = err.toString();
+                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);
+                if (!save) throw '保存数据失败';
+                ctx.redirect('/file/template/' + templateId);
+            } catch(err) {
+                ctx.log(err);
+                ctx.session.postError = err.toString();
+                ctx.redirect('/file/template');
+            }
+        }
+
+        async resetTemplate(ctx) {
+            try {
+                const id = ctx.query.id;
+                await ctx.service.filingTemplateList.reset(id);
+                ctx.redirect('/file/template/' + id);
+            } catch (err) {
+                ctx.log(err);
+                ctx.postError(err, '重置模板失败');
+                ctx.redirect('/file/template');
+            }
+        }
+
+        async delTemplate(ctx) {
+            try {
+                const id = ctx.query.id;
+                await ctx.service.filingTemplateList.delete(id);
+                console.log(ctx.request.headers.referer, id);
+                if (ctx.request.headers.referer.indexOf(id) > 0) {
+                    ctx.redirect('/file/template');
+                } else {
+                    ctx.redirect(ctx.request.headers.referer);
+                }
+            } catch (err) {
+                ctx.log(err);
+                ctx.postError(err, '删除模板失败');
+                ctx.redirect('/file/template');
+            }
+        }
+
+        async updateTemplate(ctx) {
+            try {
+                const data = JSON.parse(ctx.request.body.data);
+                if (!data.updateType) throw '数据错误';
+                let result;
+                if (data.updateType === 'add') {
+                    result = await ctx.service.filingTemplate.add(ctx.params.id, data);
+                } else if (data.updateType === 'del') {
+                    result = await ctx.service.filingTemplate.del(ctx.params.id, data);
+                } else if (data.updateType === 'save') {
+                    result = await ctx.service.filingTemplate.save(data);
+                } else if (data.updateType === 'move') {
+                    if (!data.id || !(data.tree_order >= 0)) throw '数据错误';
+                    result = await ctx.service.filingTemplate.move(ctx.params.id, data);
+                }
+                ctx.body = { err: 0, msg: '', data: result };
+            } catch (err) {
+                ctx.log(err);
+                ctx.ajaxErrorBody(err, '修改失败');
+            }
+        }
     }
 
     return BudgetController;

+ 2 - 1
app/controller/sub_proj_controller.js

@@ -43,6 +43,7 @@ module.exports = app => {
                 renderData.permissionConst = ctx.service.subProjPermission.PermissionConst;
                 renderData.categoryData = await this.ctx.service.category.getAllCategory(this.ctx.session.sessionProject.id);
                 renderData.companys = await this.ctx.service.constructionUnit.getAllDataByCondition({ where: { pid: ctx.session.sessionProject.id } });
+                renderData.templates = await this.ctx.service.filingTemplateList.getAllTemplate(ctx.session.sessionProject.id);
                 await this.layout('sub_proj/index.ejs', renderData, 'sub_proj/modal.ejs');
             } catch (err) {
                 ctx.log(err);
@@ -124,7 +125,7 @@ module.exports = app => {
                 } else if (data.std_id !== undefined) {
                     result = await ctx.service.subProject.setBudgetStd({ id: data.id, std_id: data.std_id });
                 } else if (data.management !== undefined) {
-                    result = await ctx.service.subProject.setManagement({ id: data.id, management: data.management });
+                    result = await ctx.service.subProject.setManagement({ id: data.id, management: data.management, filingTemplate: data.filingTemplate });
                 }
                 ctx.body = { err: 0, msg: '', data: { update: [result] } };
             } catch(err) {

+ 1 - 1
app/public/js/file_detail.js

@@ -470,7 +470,7 @@ $(document).ready(function() {
                 node.name = node.name + (node.source_node.total_file_count > 0 ? `(${node.source_node.total_file_count})` : '');
                 filingObj.filingTree.updateNode(node);
             },
-            beforeRemove: function(e, key, node, isCancel) {
+            beforeRemove: function(key, node, isCancel) {
                 $('#del-filing').modal('show');
                 return false;
             },

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

@@ -0,0 +1,262 @@
+$(document).ready(function() {
+    autoFlashHeight();
+    $('#filing').height($(".sjs-height-0").height() - $('#add-slibing').parent().parent().height() - 10);
+    class FilingObj {
+        constructor(setting) {
+            // 原始数据整理后的树结构,用来整理zTree显示
+            this.dragTree = createDragTree({
+                id: 'id',
+                pid: 'tree_pid',
+                level: 'tree_level',
+                order: 'tree_order',
+                rootId: '-1'
+            });
+            // 界面显示的zTree
+            this.setting = setting;
+            this.filingTree = null;
+            $('#filing').height($(".sjs-height-0").height()-$('.d-flex',".sjs-height-0").height() - 10);
+        }
+        _loadFilingSourceNode() {
+            const self = this;
+            const loadChildren = function(children) {
+                for (const child of children) {
+                    if (child.children && child.children.length > 0) loadChildren(child.children);
+                    child.source_node = self.dragTree.getItems(child.id);
+                }
+            };
+            const nodes = this.filingTree.getNodes();
+            loadChildren(nodes);
+        }
+        loadFiling() {
+            if (this.filingTree) $.fn.zTree.destroy(this.setting.treeId);
+            const sortNodes = this.dragTree.nodes.map(x => {
+                const result = {
+                    id: x.id,
+                    tree_pid: x.tree_pid,
+                    name: x.name + (x.total_file_count > 0 ? `(${x.total_file_count})` : ''),
+                    spid: x.spid,
+                };
+                return result;
+            });
+            this.filingTree = $.fn.zTree.init($('#filing'), this.setting, sortNodes);
+            this._loadFilingSourceNode();
+            const curCache = getLocalCache(this.curFilingKey);
+            const curNode = curCache ? this.filingTree.getNodeByParam('id', curCache) : null;
+            if (curNode){
+                this.filingTree.selectNode(curNode);
+                filingObj.setCurFiling(curNode);
+            }
+        }
+        analysisFiling(data) {
+            this.dragTree.loadDatas(data);
+            this.loadFiling();
+        }
+        addSiblingFiling(node) {
+            const self = this;
+            postData(`${window.location.pathname}/update`, { updateType: 'add', tree_pid: node.tree_pid, tree_pre_id: node.id }, function(result) {
+                const refreshData = self.dragTree.loadPostData(result);
+                const newNode = refreshData.create[0];
+                const nodes = self.filingTree.addNodes(node.getParentNode(), node.getIndex() + 1, [{ id: newNode.id, tree_pid: newNode.tree_pid, name: newNode.name, spid: newNode.spid }]);
+                nodes[0].source_node = newNode;
+            });
+        }
+        addChildFiling(node) {
+            const self = this;
+            postData(`${window.location.pathname}/update`, { updateType: 'add', tree_pid: node.id }, function(result) {
+                const refreshData = self.dragTree.loadPostData(result);
+                const newNode = refreshData.create[0];
+                const nodes = self.filingTree.addNodes(node, -1, [{ id: newNode.id, tree_pid: newNode.tree_pid, name: newNode.name, spid: newNode.spid}]);
+                nodes[0].source_node = newNode;
+            });
+        }
+        delFiling(node, callback) {
+            const parent = node.getParentNode();
+            const self = this;
+            postData(`${window.location.pathname}/update`, { updateType: 'del', id: node.id }, function(result) {
+                self.dragTree.loadPostData(result);
+                self.filingTree.removeNode(node);
+                if (parent) {
+                    const path = parent.getPath();
+                    for (const p of path) {
+                        p.name = p.source_node.name + (p.source_node.total_file_count > 0 ? `(${p.source_node.total_file_count})` : '');
+                        filingObj.filingTree.updateNode(p);
+                    }
+                }
+                if (callback) callback();
+            });
+        }
+        async renameFiling(node, newName) {
+            const result = await postDataAsync(`${window.location.pathname}/update`, { updateType:'save', id: node.id, name: newName });
+            node.source_node.name = newName;
+            node.name = node.source_node.name + (node.source_node.total_file_count > 0 ? `(${node.source_node.total_file_count})` : '');
+            return result;
+        }
+        async setCurFiling(node) {
+            filingObj.curFiling = node;
+        }
+        moveFiling(node, tree_pid, tree_order) {
+            if (tree_pid === node.source_node.tree_pid && tree_order === node.source_node.tree_order) return;
+
+            const self = this;
+            postData(`${window.location.pathname}/update`, { updateType: 'move', id: node.id, tree_pid, tree_order }, function(result) {
+                const refresh = self.dragTree.loadPostData(result);
+                const updated = [];
+                for (const u of refresh.update) {
+                    if (!u) continue;
+                    const node = self.filingTree.getNodeByParam('id', u.id);
+                    if (node) {
+                        const path = node.getPath();
+                        for (const p of path) {
+                            if (updated.indexOf(p.id) >= 0) continue;
+
+                            p.name = p.source_node.name + (p.source_node.total_file_count > 0 ? `(${p.source_node.total_file_count})` : '');
+                            filingObj.filingTree.updateNode(p);
+                            updated.push(p.id);
+                        }
+                    }
+                }
+            });
+        }
+    }
+    const levelTreeSetting = {
+        treeId: 'filing',
+        view: {
+            selectedMulti: false,
+            showIcon: false,
+        },
+        data: {
+            simpleData: {
+                idKey: 'id',
+                pIdKey: 'tree_pid',
+                rootPId: '-1',
+                enable: true,
+            }
+        },
+        edit: {
+            enable: true,
+            showRemoveBtn: !readOnly,
+            showRenameBtn: !readOnly,
+            renameTitle: '编辑',
+            removeTitle: '删除',
+            drag: {
+                isCopy: false,
+                isMove: true,
+                pre: true,
+                next: true,
+                inner: false,
+            },
+            editNameSelectAll: true,
+        },
+        callback: {
+            onClick: async function (e, key, node) {
+                if (filingObj.curFiling && filingObj.curFiling.id === node.id) return;
+
+                filingObj.setCurFiling(node);
+            },
+            beforeRename: async function(key, node, newName, isCancel) {
+                if (!isCancel) await filingObj.renameFiling(node, newName);
+                return true;
+            },
+            beforeRemove: function(key, node, isCancel) {
+                filingObj.delFiling(node, function() {
+                    $('#del-filing').modal('hide');
+                });
+                return false;
+            },
+            beforeDrop: function(key, nodes, target, moveType, isCopy) {
+                if (readOnly) return false;
+                if (!target) return false;
+
+                const order = nodes[0].getIndex() + 1;
+                const targetOrder = target.getIndex() + 1;
+                const targetParent = target.getParentNode();
+                const targetMax = targetParent ? targetParent.children.length : filingObj.dragTree.children.length;
+                if (moveType === 'prev') {
+                    if (target.tree_pid === nodes[0].tree_pid) {
+                        if (targetOrder > order) {
+                            filingObj.moveFiling(nodes[0], target.tree_pid, targetOrder === 1 ? 1 : targetOrder - 1);
+                        } else {
+                            filingObj.moveFiling(nodes[0], target.tree_pid, targetOrder === 1 ? 1 : targetOrder);
+                        }
+                    } else {
+                        filingObj.moveFiling(nodes[0], target.tree_pid, targetOrder === 1 ? 1 : targetOrder);
+                    }
+                } else if (moveType === 'next') {
+                    if (target.tree_pid === nodes[0].tree_pid) {
+                        if (targetOrder < order) {
+                            filingObj.moveFiling(nodes[0], target.tree_pid, targetOrder === targetMax ? targetMax : targetOrder + 1);
+                        } else {
+                            filingObj.moveFiling(nodes[0], target.tree_pid, targetOrder === targetMax ? targetMax : targetOrder);
+                        }
+                    } else {
+                        filingObj.moveFiling(nodes[0], target.tree_pid, targetOrder + 1);
+                    }
+                } else if (moveType === 'inner') {
+                    filingObj.moveFiling(nodes[0], target.tree_id, targetMax + 1);
+                }
+            }
+        }
+    };
+    const filingObj = new FilingObj(levelTreeSetting);
+    filingObj.analysisFiling(templateData);
+    $('#add-slibing').click(() => {
+        if (!filingObj.curFiling) return;
+        filingObj.addSiblingFiling(filingObj.curFiling);
+    });
+    $('#add-child').click(() => {
+        if (!filingObj.curFiling) return;
+        filingObj.addChildFiling(filingObj.curFiling);
+    });
+
+    const hiddenSubmit = function(action, extraName, extraValue) {
+        $('#hiddenForm').attr('action', action);
+        if (extraName) {
+            $('#extra').attr('name', extraName);
+            $('#extra').val(extraValue);
+        };
+        $('#hiddenForm').submit();
+    };
+    $('body').on('mouseenter', ".table-file", function(){
+        $(this).children(".btn-group-table").css("display","block");
+    });
+    $('body').on('mouseleave', ".table-file", function(){
+        $(this).children(".btn-group-table").css("display","none");
+    });
+    $('body').on('click', 'a[name=renameTemplate]', function(e){
+        $(`#${this.getAttribute('aria-describedby')}`).remove();
+        const tempId = $(this).parents('.table-file').attr('tempId');
+        const template = templateList.find(x => { return x.id === tempId; });
+        if (!template) return;
+
+        const html = [];
+        html.push(`<div><input type="text" class="form-control form-control-sm" style="width: 300px" value="${template.name}"/></div>`);
+        html.push('<div class="btn-group-table" style="display: none;">',
+            `<a href="javascript: void(0)" name="renameOk" class="mr-1"><i class="fa fa-check fa-fw"></i></a>`,
+            `<a href="javascript: void(0)" class="mr-1" name="renameCancel"><i class="fa fa-remove fa-fw text-danger"></i></a>`, '</div>');
+        $(`.table-file[tempId=${tempId}]`).html(html.join(''));
+        e.stopPropagation();
+    });
+    $('body').on('click', 'a[name=renameOk]', function(){
+        const tempId = $(this).parents('.table-file').attr('tempId');
+        const newName = $(this).parents('.table-file').find('input').val();
+        hiddenSubmit('/file/template/save?id='+tempId, 'name', newName);
+    });
+    $('body').on('click', 'a[name=delTemplate]', function(e){
+        e.stopPropagation();
+        const tempId = $(this).parents('.table-file').attr('tempId');
+        hiddenSubmit('/file/template/del?id='+tempId);
+    });
+    $('body').on('click', 'a[name=renameCancel]', function() {
+        const tempId = $(this).parents('.table-file').attr('tempId');
+        const template = templateList.find(x => { return x.id === tempId; });
+        if (!template) return;
+
+        const html = [];
+        html.push(`<div>${template.name}</div>`);
+        html.push('<div class="btn-group-table" style="display: none;">',
+            '<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>');
+        $(`.table-file[tempId=${tempId}]`).html(html.join(''));
+    });
+});

+ 5 - 4
app/public/js/shares/drag_tree.js

@@ -14,6 +14,7 @@ const createDragTree = function (setting) {
             this.children = [];
             // 树设置
             this.setting = setting;
+            if (!this.setting.itemsPre) this.setting.itemsPre = 'id_';
         }
         /**
          * 树结构根据显示排序
@@ -57,7 +58,7 @@ const createDragTree = function (setting) {
                 return a[self.setting.level] - b[self.setting.level];
             });
             for (const data of datas) {
-                const keyName = itemsPre + data[this.setting.id];
+                const keyName = this.setting.itemsPre + data[this.setting.id];
                 if (this.items[keyName]) continue;
 
                 const item = JSON.parse(JSON.stringify(data));
@@ -87,7 +88,7 @@ const createDragTree = function (setting) {
          * @returns {Object}
          */
         getItems(id) {
-            return this.items[itemsPre + id];
+            return this.items[this.setting.itemsPre + id];
         };
         getNodeIndex(node) {
             return this.nodes.indexOf(node);
@@ -353,7 +354,7 @@ const createDragTree = function (setting) {
                     }
                     loadedData.push(node);
                 } else {
-                    const keyName = itemsPre + data[this.setting.id];
+                    const keyName = this.setting.itemsPre + data[this.setting.id];
                     const node = JSON.parse(JSON.stringify(data));
                     this.items[keyName] = node;
                     this.datas.push(node);
@@ -403,7 +404,7 @@ const createDragTree = function (setting) {
                 if (node) {
                     freeDatas.push(node);
                     node.deleteIndex = this.nodes.indexOf(node);
-                    delete this.items[itemsPre + node[this.setting.id]];
+                    delete this.items[this.setting.itemsPre + node[this.setting.id]];
                     if (node[this.setting.pid] !== this.setting.rootId) {
                         const parent = this.getItems(node[this.setting.pid]);
                         if (parent) {

+ 7 - 1
app/public/js/sub_project.js

@@ -233,6 +233,11 @@ $(document).ready(function() {
             const node = ProjectTree.getItems(treeId);
             if (node.is_folder) return;
             $('#sm-management').attr('tree_id', treeId);
+            $('#sm-management').val(node.management);
+            const ft = $(`[value=${node.filing_template_id}]`)[0];
+            if (ft) $('#sm-ft').selectedIndex = Array.prototype.indexOf.call(ft.parentNode.children, ft);
+            //$('#sm-ft').val(node.filing_template_name);
+            $('#sm-ft').attr('disabled', !!node.management);
             $('#set-management').modal('show');
         });
         $('body').on('click', 'a[name=refresh-management]', function(e) {
@@ -382,7 +387,8 @@ $(document).ready(function() {
         const select = $('#sm-management');
         const id = select.attr('tree_id');
         const management = select.val();
-        postData('/subproj/save', { id, management }, function(result) {
+        const filingTemplate =$('#sm-ft').val();
+        postData('/subproj/save', { id, management, filingTemplate }, function(result) {
             projectTreeObj.refreshRow(result);
             $('#set-management').modal('hide');
             $('#sm-management').attr('tree_id', '');

+ 9 - 1
app/router.js

@@ -800,8 +800,16 @@ module.exports = app => {
     app.post('/budget/:id/:btype/update', sessionAuth, budgetCheck, 'budgetController.detailUpdate');
     app.post('/budget/:id/:btype/upload-excel/:ueType', sessionAuth, budgetCheck, 'budgetController.detailUploadExcel');
     app.post('/budget/:id/decimal', sessionAuth, budgetCheck, 'budgetController.decimal');
-    // 电子档案
+    // 资料归集-列表
     app.get('/file', sessionAuth, 'fileController.index');
+    // 资料归集-模板
+    app.get('/file/template', sessionAuth, projectManagerCheck, 'fileController.template');
+    app.post('/file/template/save', sessionAuth, projectManagerCheck, 'fileController.saveTemplate');
+    app.post('/file/template/reset', sessionAuth, projectManagerCheck, 'fileController.resetTemplate');
+    app.post('/file/template/del', sessionAuth, projectManagerCheck, 'fileController.delTemplate');
+    app.get('/file/template/:id', sessionAuth, projectManagerCheck, 'fileController.templateDetail');
+    app.post('/file/template/:id/update', sessionAuth, projectManagerCheck, 'fileController.updateTemplate');
+    // 资料归集-文件
     app.get('/sp/:id/file', sessionAuth, subProjectCheck, 'fileController.file');
     app.post('/sp/:id/permission', sessionAuth, projectManagerCheck, subProjectCheck, 'fileController.getFilingTypePermission');
     app.post('/sp/:id/permission/save', sessionAuth, projectManagerCheck, subProjectCheck, 'fileController.saveFilingTypePermission');

+ 16 - 11
app/service/filing.js

@@ -43,17 +43,24 @@ module.exports = app => {
             return filingType.map(x => { return x.value });
         }
 
-        async initFiling(spid, transaction) {
+        async initFiling(spid, templateId, transaction) {
             const count = await this.count({ spid });
             if (count > 0) return;
 
+            const templateFiling = await this.ctx.service.filingTemplate.getAllDataByCondition({
+                where: { temp_id: templateId },
+                orders: [['tree_level', 'asc']],
+            });
             const insertData = [];
-            for (const [i, f] of filingType.entries()) {
-                insertData.push({
-                    id: this.uuid.v4(), tree_pid: -1, tree_level: 1, tree_order: i + 1,
-                    spid, add_user_id: this.ctx.session.sessionUser.accountId, is_fixed: 1,
-                    filing_type: f.value, name: f.name,
-                });
+            for (const f of templateFiling) {
+                f.newId = this.uuid.v4();
+                const parent = f.tree_pid === rootId ? templateFiling.find(x => { x.id === f.tree_pid; }) : null;
+                const newData = {
+                    id: f.newId, tree_pid : parent ? parent.newId : rootId, tree_level: f.tree_level, tree_order: f.tree_order,
+                    spid, add_user_id: this.ctx.session.sessionUser.accountId, is_fixed: f.tree_level === 1,
+                    filing_type: f.filing_type, name: f.name,
+                };
+                insertData.push(newData);
             }
             if (transaction) {
                 await transaction.insert(this.tableName, insertData);
@@ -103,7 +110,7 @@ module.exports = app => {
             if (parent.file_count > 0) throw `分类【${parent.name}】下存在文件,不可添加子分类`;
 
             const sibling = await this.getAllDataByCondition({ where: { tree_pid: parent.id }, orders: [['tree_order', 'asc']]});
-            const preChild = data.tree_pre_id ? sibling.find(x => { x.id === data.tree_pre_id; }) : null;
+            const preChild = data.tree_pre_id ? sibling.find(x => { return x.id === data.tree_pre_id; }) : null;
 
             const conn = await this.db.beginTransaction();
             try {
@@ -148,7 +155,6 @@ module.exports = app => {
                 throw '更新数据失败';
             }
         }
-
         async del(data) {
             const filing = await this.getDataById(data.id);
             this._checkFixed(filing);
@@ -171,10 +177,9 @@ module.exports = app => {
                 return { delete: delData.map(x => { return x.id }), update: updateData };
             } catch(err) {
                 await conn.rollback();
-                throw error;
+                throw err;
             }
         }
-
         async move(data) {
             const filing = await this.getDataById(data.id);
             if (!filing) throw '移动的分类不存在,请刷新页面后重试';

+ 224 - 0
app/service/filing_template.js

@@ -0,0 +1,224 @@
+'use strict';
+
+/**
+ *
+ * 2024/3/21
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const rootId = '-1';
+const filingType = [
+    { value: 1, name: '立项文件' },
+    { value: 2, name: '招标投标、合同协议文件' },
+    { value: 3, name: '勘察、设计文件' },
+    { value: 4, name: '征地、拆迁、移民文件' },
+    { value: 5, name: '项目管理文件' },
+    { value: 6, name: '施工文件' },
+    { value: 7, name: '信息系统开发文件' },
+    { value: 8, name: '设备文件' },
+    { value: 9, name: '监理文件' },
+    { value: 10, name: '科研项目文件' },
+    { value: 11, name: '生产技术准备、试运行文件' },
+    { value: 12, name: '竣工验收文件' },
+];
+const maxFilingType = 12;
+
+module.exports = app => {
+
+    class FilingTemplate extends app.BaseService {
+
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'filing_template';
+        }
+
+        async initTemplate(transaction, template) {
+            const insertData = [];
+            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,
+                    add_user_id: this.ctx.session.sessionUser.accountId, is_fixed: true,
+                    name: f.name, filing_type: f.value,
+                });
+            }
+            if (transaction) {
+                await transaction.insert(this.tableName, insertData);
+            } else {
+                await this.db.insert(this.tableName, insertData);
+            }
+        }
+
+        async getData(templateId) {
+            return await this.getAllDataByCondition({
+                where: { temp_id: templateId }
+            })
+        }
+
+        async getPosterityData(templateId, id){
+            const result = [];
+            let cur = await this.getAllDataByCondition({ where: { temp_id: templateId, tree_pid: id } });
+            let iLevel = 1;
+            while (cur.length > 0 && iLevel < 6) {
+                result.push(...cur);
+                cur = await this.getAllDataByCondition({ where: { temp_id: templateId, tree_pid: cur.map(x => { return x.id })} });
+                iLevel += 1;
+            }
+            return result;
+        }
+        async getNewName(templateId, name = '新增文件类别') {
+            const data = await this.db.query(`SELECT * FROM ${this.tableName} WHERE temp_id = '${templateId}' AND name LIKE '${name}%'`);
+            if (data.length === 0) return name;
+
+            const _ = this._;
+            const names = data.map(x => { return _.toInteger(x.name.replace(name, '')) });
+            const filterNames = names.filter(x => { return x > 0 });
+            const max = filterNames.reduce((pre, cur) => { return Math.max(pre, cur); }, 0);
+            return max >= 0 ? name + (max + 1) : name;
+        }
+        async getNewFilingType(templateId) {
+            const max = await this.db.queryOne(`SELECT filing_type FROM ${this.tableName} WHERE temp_id = '${templateId}' ORDER BY filing_type DESC`);
+            return max && max.filing_type ? max.filing_type + 1 : maxFilingType + 1;
+        }
+        async add(templateId, data) {
+            const parent = await this.getDataById(data.tree_pid);
+
+            const sibling = await this.getAllDataByCondition({ where: { temp_id: templateId, tree_pid: parent ? parent.id : rootId }, orders: [['tree_order', 'asc']]});
+            const preChild = data.tree_pre_id ? sibling.find(x => { return x.id === data.tree_pre_id; }) : null;
+            const filing_type = parent ? parent.filing_type : await this.getNewFilingType(templateId);
+
+            const conn = await this.db.beginTransaction();
+            try {
+                // 获取当前用户信息
+                const sessionUser = this.ctx.session.sessionUser;
+                // 获取当前项目信息
+                const sessionProject = this.ctx.session.sessionProject;
+
+                const tree_order = preChild ? preChild.tree_order + 1 : (sibling.length > 0 ? sibling[sibling.length - 1].tree_order + 1 : 1);
+                const name = await this.getNewName(templateId);
+                const insertData = {
+                    id: this.uuid.v4(), temp_id: templateId, add_user_id: sessionUser.accountId,
+                    tree_pid: parent ? parent.id : rootId, tree_level: parent ? parent.tree_level + 1 : 1, tree_order,
+                    name, filing_type,
+                };
+                const operate = await conn.insert(this.tableName, insertData);
+                if (operate.affectedRows === 0) throw '新增文件夹失败';
+
+                const updateData = [];
+                if (preChild) {
+                    sibling.forEach(x => {
+                        if (x.tree_order >= tree_order) updateData.push({ id: x.id, tree_order: x.tree_order + 1 });
+                    });
+                }
+                if (updateData.length > 0) await conn.updateRows(this.tableName, updateData);
+
+                await conn.commit();
+                return { create: [insertData], update: updateData };
+            } catch (error) {
+                await conn.rollback();
+                throw error;
+            }
+        }
+        async save(data) {
+            const filing = await this.getDataById(data.id);
+            if (!filing) throw '分类不存在,请刷新页面后重试';
+
+            const result = await this.db.update(this.tableName, { id: data.id, name: data.name });
+            if (result.affectedRows > 0) {
+                return data;
+            } else {
+                throw '更新数据失败';
+            }
+        }
+        async del(templateId, data) {
+            const filing = await this.getDataById(data.id);
+            if (!filing) throw '分类不存在,请刷新页面后重试';
+
+            const posterity = await this.getPosterityData(templateId, data.id);
+            const delData = posterity.map(x => {return x.id; });
+            delData.push(data.id);
+
+            const sibling = await this.getAllDataByCondition({ where: { temp_id: templateId, tree_pid: filing.tree_pid } });
+            const updateData = [];
+            sibling.forEach(x => {
+                if (x.tree_order > filing.tree_order) updateData.push({ id: x.id, tree_order: x.tree_order - 1});
+            });
+            const conn = await this.db.beginTransaction();
+            try {
+                await conn.delete(this.tableName, { id: delData });
+                if (updateData.length > 0) conn.updateRows(this.tableName, updateData);
+
+                await conn.commit();
+                return { delete: delData, update: updateData };
+            } catch(err) {
+                await conn.rollback();
+                throw err;
+            }
+        }
+        async move(templateId, data) {
+            const filing = await this.getDataById(data.id);
+            if (!filing) throw '移动的分类不存在,请刷新页面后重试';
+            const parent = await this.getDataById(data.tree_pid);
+            const sibling = await this.getAllDataByCondition({ where: { temp_id: templateId, tree_pid: data.tree_pid } });
+            const filing_type = parent ? parent.filing_type : await this.getNewFilingType(templateId);
+            const posterity = await this.getPosterityData(templateId, filing.id);
+
+            const result = [];
+            const conn = await this.db.beginTransaction();
+            try {
+                const updateData = { id: filing.id, tree_order: data.tree_order, tree_pid: data.tree_pid, tree_level: parent ? parent.tree_level + 1 : 1, filing_type };
+                conn.update(this.tableName, updateData);
+                result.push(updateData);
+                if (posterity.length > 0) {
+                    const posterityUpdateData = posterity.map(x => { return { id: x.id, filing_type }});
+                    conn.updateRows(this.tableName, posterityUpdateData);
+                    // result.push(...posterity);
+                }
+                const siblingUpdateData = [];
+                if (data.tree_pid === filing.tree_pid) {
+                    if (data.tree_order < filing.tree_order) {
+                        sibling.forEach(x => {
+                            if (x.id === filing.id) return;
+                            if (x.tree_order < data.tree_order) return;
+                            if (x.tree_order > filing.tree_order) return;
+                            siblingUpdateData.push({id: x.id, tree_order: x.tree_order + 1});
+                        });
+                    } else {
+                        sibling.forEach(x => {
+                            if (x.id === filing.id) return;
+                            if (x.tree_order < filing.tree_order) return;
+                            if (x.tree_order > data.tree_order) return;
+                            siblingUpdateData.push({id: x.id, tree_order: x.tree_order - 1});
+                        });
+                    }
+                } else {
+                    const orgSibling = await this.getAllDataByCondition({ where: { temp_id: templateId, tree_pid: filing.tree_pid } });
+                    orgSibling.forEach(x => {
+                        if (x.tree_order < filing.tree_order) return;
+                        siblingUpdateData.push({id: x.id, tree_order: x.tree_order - 1});
+                    });
+                    sibling.forEach(x => {
+                        if (x.tree_order < data.tree_order) return;
+                        siblingUpdateData.push({id: x.id, tree_order: x.tree_order + 1});
+                    })
+                }
+                await conn.updateRows(this.tableName, siblingUpdateData);
+                result.push(...siblingUpdateData);
+                await conn.commit();
+                return { update: result };
+            } catch(err) {
+                await conn.rollback();
+                throw err;
+            }
+        }
+    }
+
+    return FilingTemplate;
+};

+ 108 - 0
app/service/filing_template_list.js

@@ -0,0 +1,108 @@
+'use strict';
+
+/**
+ *
+ * 2024/3/21
+ * @author Mai
+ * @date
+ * @version
+ */
+
+const FtType = {
+    org: 0,
+    add: 1,
+};
+
+module.exports = app => {
+
+    class FilingTemplateList extends app.BaseService {
+
+        /**
+         * 构造函数
+         *
+         * @param {Object} ctx - egg全局变量
+         * @return {void}
+         */
+        constructor(ctx) {
+            super(ctx);
+            this.tableName = 'filing_template_list';
+            this.FtType = FtType;
+        }
+
+        async getOriginTemplate() {
+            return await this.getDataByCondition({ ft_type: FtType.org });
+        }
+
+        async getAllTemplate(pid) {
+            const sql = `SELECT * FROM ${this.tableName} WHERE ft_type = ${FtType.org} OR project_id = ? ORDER BY create_time asc`;
+            return await this.db.query(sql, [pid]);
+        }
+
+        /**
+         * 保存/新增数据
+         *
+         * @param {Object} name - 模板名称
+         * @param {String} id - 存在则为保存,反之新增
+         * @return {boolean} - 操作结果
+         */
+        async save(name, id = '') {
+            if (id) {
+                const result = await this.defaultUpdate({ id, name });
+                return [result.affectedRows > 0, id];
+            } else {
+                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: name || '新增XXX模板库', ft_type: FtType.add,
+                    };
+                    await conn.insert(this.tableName, newTemplate);
+                    await this.ctx.service.filingTemplate.initTemplate(conn, newTemplate);
+                    await conn.commit();
+                    return [true, newTemplate.id];
+                } catch (err) {
+                    this.ctx.log(err);
+                    await conn.rollback();
+                    return [false, ''];
+                }
+            }
+        }
+
+        /**
+         * 删除模板
+         *
+         * @param {string} id - 删除的id
+         * @return {Boolean} - 返回删除的结果
+         */
+        async delete(id) {
+            const conn = await this.db.beginTransaction();
+            try {
+                await conn.delete(this.tableName, { id });
+                await conn.delete(this.ctx.service.filingTemplate.tableName, { temp_id: id });
+                await conn.commit();
+                return true;
+            } catch (error) {
+                this.ctx.log(error);
+                await conn.rollback();
+                return false;
+            }
+        }
+
+        async reset(id) {
+            const template = await this.getDataById(id);
+            const conn = await this.db.beginTransaction();
+            try {
+                await conn.delete(this.ctx.service.filingTemplate.tableName, { temp_id: id });
+                await this.ctx.service.filingTemplate.initTemplate(conn, template);
+                await conn.commit();
+            } catch(err) {
+                await conn.rollback();
+                throw err;
+            }
+        }
+
+    }
+
+    return FilingTemplateList;
+};

+ 1 - 1
app/service/stage_audit.js

@@ -575,7 +575,7 @@ module.exports = app => {
                                 pre_yf_tp: this.ctx.helper.add(this.ctx.stage.pre_yf_tp, stageTp.yf_tp),
                                 pre_sf_tp: this.ctx.helper.add(this.ctx.stage.pre_sf_tp, stageTp.sf_tp),
                             };
-                            await transaction.update(this.ctx.service.stage.tableName, nextStages.map(x => { return { id: x.id, ...preStageTp }; }));
+                            await transaction.updateRows(this.ctx.service.stage.tableName, nextStages.map(x => { return { id: x.id, ...preStageTp }; }));
                         }
 
                         // 添加短信通知-审批通过提醒功能

+ 1 - 1
app/service/stage_pay.js

@@ -522,7 +522,7 @@ module.exports = app => {
                     }
                 }
             }
-            if (updateData.length > 0) await transaction.update(this.tableName, updateData);
+            if (updateData.length > 0) await transaction.updateRows(this.tableName, updateData);
         }
     }
 

+ 5 - 2
app/service/sub_project.js

@@ -378,10 +378,13 @@ module.exports = app => {
                     im.push({ id: this.uuid.v4(), spid: subProject.id, pid: subProject.project_id, uid: u.id, file_permission, filing_type });
                 }
             }
+            const template = await this.ctx.service.filingTemplateList.getDataById(data.filingTemplate);
+            if (!template) throw '选择的文件类别不存在';
+
             const conn = await this.db.beginTransaction();
             try {
-                await conn.update(this.tableName, { id: subProject.id, management: data.management });
-                await this.ctx.service.filing.initFiling(subProject.id, conn);
+                await conn.update(this.tableName, { id: subProject.id, management: data.management, filing_template_id: template.id, filing_template_name: template.name });
+                await this.ctx.service.filing.initFiling(subProject.id, data.filingTemplate, conn);
                 if (dm.length > 0) await conn.delete(this.ctx.service.subProjPermission.tableName, { id: dm });
                 if (um.length > 0) await conn.updateRows(this.ctx.service.subProjPermission.tableName, um);
                 if (im.length > 0) await conn.insert(this.ctx.service.subProjPermission.tableName, im);

+ 68 - 0
app/view/file/template.ejs

@@ -0,0 +1,68 @@
+<div class="panel-content">
+    <div class="panel-title fluid">
+        <div class="title-main  d-flex justify-content-between">
+            <div>资料归集模板库</div>
+        </div>
+    </div>
+    <div class="content-wrap">
+        <div class="c-body">
+            <div class="sjs-height-0 row">
+                <div class="col-3">
+                    <div class="d-flex flex-row">
+                        <form class="ml-2 p-2" method="POST" action="/file/template/save">
+                            <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>" />
+                            <button class="btn btn-sm btn-light text-primary"><i class="fa fa-plus" aria-hidden="true" type="submit"></i> 新增模板库</button>
+                        </form>
+                    </div>
+                    <div>
+                        <dl class="list-group">
+                            <% 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>
+                                    <% if (temp.ft_type) { %>
+                                    <div class="btn-group-table" style="display: none;">
+                                        <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>
+                                    <% } %>
+                                </div>
+                            </dd>
+                            <% } %>
+                        </dl>
+                    </div>
+                </div>
+                <div class="col-9">
+                    <div class="d-flex flex-row">
+                        <div class="p-2">
+                            <a href="javascript: void(0);" class="btn btn-sm btn-light text-primary" id="add-slibing"><i class="fa fa-plus" aria-hidden="true"></i> 同层</a>
+                            <a href="javascript: void(0);" class="btn btn-sm btn-light text-primary" id="add-child"><i class="fa fa-plus" aria-hidden="true"></i> 子项</a>
+                        </div>
+                        <form class="ml-2 p-2" method="POST" action="/file/template/reset?id=<%- template.id %>">
+                            <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>" />
+                            <button class="btn btn-sm btn-primary"><i class="fa fa-refresh" aria-hidden="true"></i> 初始化模板</button>
+                        </form>
+                    </div>
+                    <div>
+                        <ul id="filing" class="ztree" style="overflow: auto"></ul>
+                    </div>
+                </div>
+            </div>
+        </div>
+    </div>
+    <div stype="display: none">
+        <form id="hiddenForm" action="" method="POST">
+            <input type="hidden" name="_csrf_j" value="<%= ctx.csrf %>" />
+            <input type="hidden" id="extra" name="" value="">
+        </form>
+    </div>
+</div>
+<script>
+    const templateList = JSON.parse('<%- JSON.stringify(templateList) %>');
+    const templateData = JSON.parse('<%- JSON.stringify(templateData) %>');
+    $('.table-file').click(function(e) {
+        if (e.target.tagName === 'A' || e.target.tagName === 'I') return;
+        window.location.href = '/file/template/' +  this.getAttribute('tempId');
+    });
+    const readOnly = <%- template.ftType === FtType.org %>;
+</script>

+ 2 - 1
app/view/sub_proj/index.ejs

@@ -6,7 +6,8 @@
             <% if (ctx.session.sessionUser.is_admin) { %>
             <div class="ml-auto">
                 <a href="#add-folder" name="add" data-toggle="modal" data-target="#add-folder" class="btn btn-sm btn-primary">新建文件夹</a>
-                <a href="#add-project" name="add" data-toggle="modal" data-target="#add-project" class="btn btn-sm btn-primary pull-right ml-2">新建项目</a>
+                <a href="#add-project" name="add" data-toggle="modal" data-target="#add-project" class="btn btn-sm btn-primary ml-2">新建项目</a>
+                <a href="/file/template" class="btn btn-sm btn-primary ml-2">资料模板库</a>
             </div>
             <% } %>
         </div>

+ 10 - 0
app/view/sub_proj/modal.ejs

@@ -201,6 +201,16 @@
                             </select>
                         </div>
                     </div>
+                    <div class="form-group row">
+                        <label for="text" class="col-sm-2 col-form-labelcol-form-label-sm">文件类别</label>
+                        <div class="col-sm-10">
+                            <select id="sm-ft" class="form-control form-control-sm">
+                                <% for( const t of templates) { %>
+                                <option value="<%- t.id %>"><%- t.name %></option>
+                                <% } %>
+                            </select>
+                        </div>
+                    </div>
                 </form>
             </div>
             <div class="modal-footer">

+ 8 - 0
config/web.js

@@ -1148,6 +1148,14 @@ const JsFiles = {
                 ],
                 mergeFile: 'file_detail',
             },
+            template: {
+                files: ['/public/js/ztree/jquery.ztree.core.js', '/public/js/ztree/jquery.ztree.exedit.js',],
+                mergeFiles: [
+                    '/public/js/shares/drag_tree.js',
+                    '/public/js/filing_template.js',
+                ],
+                mergeFile: 'filing_template',
+            },
         },
         budget: {
             list: {

+ 50 - 2
sql/update.sql

@@ -1,2 +1,50 @@
-ALTER TABLE `calculation`.`zh_tender_info`
-ADD COLUMN `s_type` varchar(20) NOT NULL DEFAULT '' COMMENT '标段类型(公路gl,房建fj,市政sz)' AFTER `dagl_info`;
+ALTER TABLE `zh_tender_info`
+ADD COLUMN `s_type` varchar(20) NOT NULL DEFAULT '' COMMENT '标段类型(公路gl,房建fj,市政sz)' AFTER `dagl_info`;
+
+ALTER TABLE `zh_sub_project`
+ADD COLUMN `filing_template_id` varchar(36) NOT NULL DEFAULT '' COMMENT '资料归集模板id' AFTER `std_name`,
+ADD COLUMN `filing_template_name` varchar(255) NOT NULL DEFAULT '' COMMENT '资料归集模板名称' AFTER `filing_template_id`;
+
+CREATE TABLE `zh_filing_template_list`  (
+  `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT 'uuid',
+  `project_id` int(11) UNSIGNED NOT NULL DEFAULT 0 COMMENT '项目id',
+  `ft_type` tinyint(4) NOT NULL DEFAULT 0 COMMENT '模板类型(0默认,1新增)',
+  `user_id` int(11) UNSIGNED NOT NULL COMMENT '添加用户',
+  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
+  `memo` varchar(1000) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '备注',
+  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
+
+CREATE TABLE `zh_filing_template`  (
+  `id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT 'uuid',
+  `temp_id` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT 'template_id(zh_filing_template_list)',
+  `tree_pid` varchar(36) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL COMMENT 'uuid',
+  `tree_order` int(11) UNSIGNED NOT NULL COMMENT '树结构-同层排序',
+  `tree_level` int(11) UNSIGNED NOT NULL COMMENT '树结构-层级',
+  `name` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL DEFAULT '' COMMENT '名称',
+  `add_user_id` int(11) NOT NULL DEFAULT 0 COMMENT '添加人',
+  `create_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
+  `update_time` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后更新时间',
+  `is_fixed` tinyint(4) UNSIGNED NOT NULL DEFAULT 0 COMMENT '是否为固定项',
+  `filing_type` int(11) NOT NULL COMMENT '文件类型(跟父项相关,类型为最顶层父项名称)',
+  PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB CHARACTER SET = utf8 COLLATE = utf8_unicode_ci ROW_FORMAT = Dynamic;
+
+INSERT INTO `zh_filing_template_list` (`id`, `project_id`, `ft_type`, `user_id`, `name`, `memo`, `create_time`, `update_time`) VALUES ('698e87d8-e947-4049-98e4-15aae7c5c7fc', 0, 0, 0, '建设项目档案管理规范DA_T 28-2018', '', '2024-03-22 15:04:31', '2024-03-22 15:06:07');
+
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('0395ade6-5fe6-4b36-9b0a-c3696b044aaf', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 1, 1, '立项文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 1);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('5efafc28-fef5-46b3-be92-581a47cc454e', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 2, 1, '招标投标、合同协议文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 2);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('ef7ce0ba-f503-4364-b73f-ed9a1fe8c98d', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 3, 1, '勘察、设计文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 3);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('e2ac9fb4-08f7-4968-b5d1-c2487c2f3f61', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 4, 1, '征地、拆迁、移民文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 4);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('da3b9fb7-646f-49fa-8522-64d1d5ee53b1', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 5, 1, '项目管理文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 5);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('32be53bb-86db-4e4d-ae2d-03d3586e3965', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 6, 1, '施工文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 6);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('4c759d53-50f4-40fe-8f3b-b5b6ba8d3db3', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 7, 1, '信息系统开发文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 7);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('94505d98-f661-4be8-b381-2735476948b9', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 8, 1, '设备文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 8);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('5aca0493-089e-4064-83fd-3ac061cc1b04', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 9, 1, '监理文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 9);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('52f26ad6-bcd3-4bea-b533-283281fe6124', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 10, 1, '科研项目文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 10);
+INSERT INTO `zh_filing_template` (`id`, `temp_id`, `tree_pid`, `tree_order`, `tree_level`, `name`, `add_user_id`, `create_time`, `update_time`, `is_fixed`, `filing_type`) VALUES ('b95ecebd-fbd4-4110-abf4-7c055255d88f', '698e87d8-e947-4049-98e4-15aae7c5c7fc', '-1', 11, 1, '生产技术准备、试运行文件', 13, '2024-03-25 17:16:46', '2024-03-25 17:16:46', 1, 11);
+
+UPDATE zh_sub_project SET filing_template_id = "698e87d8-e947-4049-98e4-15aae7c5c7fc", filing_template_name = '建设项目档案管理规范DA_T 28-2018' WHERE management <> "";
+