Explorar el Código

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

MaiXinRong hace 4 días
padre
commit
c836ea3e96

+ 2 - 1
app/controller/sub_proj_setting_controller.js

@@ -560,7 +560,8 @@ module.exports = app => {
                 }).filter(x => { return x.groupList.length > 0; });
 
                 // 获取项目列表
-                const subProjects = await ctx.service.subProject.getAllDataByCondition({ where: { project_id: projectId, is_folder: 0, is_delete: 0 } });
+                // const subProjects = await ctx.service.subProject.getAllDataByCondition({ where: { project_id: projectId, is_folder: 0, is_delete: 0 } });
+                const subProjects = await ctx.service.subProject.getSubProject(projectId, ctx.session.sessionUser.accountId, ctx.session.sessionUser.is_admin);
                 const renderData = {
                     projectData,
                     tenderList,

+ 242 - 0
app/public/js/bootstrap/tree-select.js

@@ -0,0 +1,242 @@
+(() => {
+    // 注入样式
+    const style = document.createElement('style');
+    style.textContent = `
+.tree-select-menu {
+  max-height: 500px;
+  overflow-y: auto;
+  min-width: 250px;
+  font-family: Arial, sans-serif;
+  font-size: 12px;
+  user-select: none;
+  border: 1px solid #dee2e6;
+  padding-left: 4px;
+}
+.tree-node {
+  cursor: default;
+  padding: 4px 8px;
+  display: block;
+  white-space: nowrap;
+  position: relative;
+  text-align: left;
+}
+.tree-node::before {
+  content: '';
+  position: absolute;
+  top: 0;
+  left: 0px;
+  bottom: 0;
+  width: 1px;
+  border-left: 1px dashed #ccc;
+}
+.tree-node:not(.leaf) [data-level="0"] >.tree-label {
+  font-weight: bold;
+}
+.tree-node[data-level="0"]::before,
+.tree-node[data-level="0"]::after {
+  display: none !important;
+}
+.tree-node::after {
+  content: '';
+  position: absolute;
+  top: 14px;
+  left: 0px;
+  width: 10px;
+  height: 1px;
+  background-color: #ccc;
+}
+.tree-node:last-child::before {
+  height: 14px;
+}
+.tree-node.leaf {
+  cursor: pointer;
+  color: #007bff;
+  background-color: #fff;
+}
+.tree-node.leaf:hover {
+  background-color: #e9ecef;
+}
+.tree-label {
+  display: inline-block;
+  vertical-align: middle;
+}
+.tree-toggle {
+  display: inline-block;
+  width: 14px;
+  text-align: center;
+  margin-right: 6px;
+  user-select: none;
+  font-size: 12px;
+  vertical-align: middle;
+}
+.tree-children {
+  display: none;
+  margin-left: 18px;
+  padding-left: 8px;
+}
+.tree-expanded > .tree-children {
+  display: block;
+}
+.tree-select button {
+  color: #495057;
+  border: 1px solid #ced4da;
+  padding: .25rem .5rem;
+}
+.tree-select button:active {
+  color: #6c757d !important;
+  border: 1px solid #ced4da;
+  background-color: #fff !important;
+}
+#tree-container .show>.btn-outline-secondary.dropdown-toggle {
+  color: #6c757d !important;
+  border: 1px solid #80bdff;
+  background-color: #fff !important;
+  box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25);
+}
+#tree-container .show>.btn-outline-secondary.dropdown-toggle:focus {
+  border-color: #80bdff;
+  box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25);
+}
+.tree-select .btn-outline-secondary:hover {
+  color: #6c757d;
+  border: 1px solid #ced4da;
+  background-color: #fff;
+}
+.tree-select .btn-outline-secondary:focus {
+  border-color: #80bdff;
+  box-shadow: 0 0 0 .2rem rgba(0, 123, 255, .25);
+}
+`;
+    document.head.appendChild(style);
+
+    class TreeSelect {
+        constructor({ element, data, selected, onSelect }) {
+            this.container = typeof element === 'string' ? document.querySelector(element) : element;
+            this.onSelect = onSelect;
+            this.selectedId = selected;
+            this.data = this.buildTree(data);
+            this.selectedNode = this.findNodeById(this.data, this.selectedId);
+            this.render();
+        }
+
+        // ✅ flat → tree 转换函数
+        buildTree(data, parentId = '-1') {
+            // 找出所有属于 parentId 的节点
+            const children = data
+                .filter(item => item.tree_pid === parentId)
+                .sort((a, b) => a.tree_order - b.tree_order); // ✅ 按 tree_order 升序排序
+
+            return children.map(item => {
+                const nodeChildren = this.buildTree(data, item.id);
+                return {
+                    id: item.id,
+                    label: item.name,
+                    selected: item.id === this.selectedId,
+                    children: nodeChildren.length ? nodeChildren : undefined
+                };
+            });
+        }
+
+        findNodeById(nodes, id) {
+            for (const node of nodes) {
+                if (node.id === id) return node;
+                if (node.children) {
+                    const found = this.findNodeById(node.children, id);
+                    if (found) return found;
+                }
+            }
+            return null;
+        }
+
+        render() {
+            this.container.innerHTML = `
+        <div class="dropdown tree-select">
+          <button class="btn btn-sm btn-outline-secondary w-100 dropdown-toggle text-left" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
+            ${this.selectedNode ? this.selectedNode.label : '请选择分类'}
+          </button>
+          <div class="dropdown-menu tree-select-menu"></div>
+        </div>
+      `;
+            this.button = this.container.querySelector('button');
+            this.menu = this.container.querySelector('.dropdown-menu');
+            this.button.dataset.selectedId = this.selectedNode?.id || '';
+            this.renderTree(this.data, this.menu, 0);
+        }
+
+        renderTree(nodes, parentEl, level = 0) {
+            nodes.forEach(node => {
+                const wrapper = document.createElement('div');
+                wrapper.className = 'tree-node tree-expanded'; // 默认展开
+                wrapper.dataset.level = level;
+
+                const isLeaf = !node.children || node.children.length === 0;
+                if (isLeaf) wrapper.classList.add('leaf');
+                const toggle = document.createElement('span');
+                toggle.className = 'tree-toggle';
+                toggle.innerHTML = isLeaf ? '' : '<i class="fa fa-minus-square-o"></i>';
+
+                if (!isLeaf) {
+                    wrapper.appendChild(toggle);
+                    const toggle2 = document.createElement('span');
+                    toggle2.className = 'tree-folder';
+                    toggle2.innerHTML = '<i class="fa fa-folder-o"></i> ';
+                    wrapper.appendChild(toggle2);
+                }
+
+                const label = document.createElement('span');
+                label.className = 'tree-label';
+                label.innerHTML = isLeaf ? '&nbsp; ' + node.label : node.label;
+                wrapper.appendChild(label);
+
+                if (!isLeaf) {
+                    const childrenContainer = document.createElement('div');
+                    childrenContainer.className = 'tree-children';
+                    wrapper.appendChild(childrenContainer);
+                    this.renderTree(node.children, childrenContainer, level + 1);
+
+                    if (this.isNodeOrChildSelected(node)) {
+                        wrapper.classList.add('tree-expanded');
+                        toggle.innerHTML = '<i class="fa fa-minus-square-o"></i>';
+                    }
+
+                    // 👇 点击整行展开/收起
+                    wrapper.addEventListener('click', e => {
+                        e.stopPropagation();
+                        const expanded = wrapper.classList.toggle('tree-expanded');
+                        toggle.innerHTML = expanded ? '<i class="fa fa-minus-square-o"></i>' : '<i class="fa fa-plus-square-o"></i>';
+                    });
+                } else {
+                    // 👇 叶子节点可选中
+                    wrapper.addEventListener('click', e => {
+                        e.stopPropagation();
+                        this.selectNode(node);
+                    });
+                }
+
+                parentEl.appendChild(wrapper);
+            });
+        }
+
+        isNodeOrChildSelected(node) {
+            if (node.selected) return true;
+            if (!node.children) return false;
+            return node.children.some(child => this.isNodeOrChildSelected(child));
+        }
+
+        selectNode(node) {
+            this.selectedNode = node;
+            this.button.textContent = node.label;
+            this.button.dataset.selectedId = node.id;
+            $('.tree-select button').dropdown('toggle');
+            if (typeof this.onSelect === 'function') {
+                this.onSelect(node.id, node.label);
+            }
+        }
+
+        getValue() {
+            return this.button.dataset.selectedId || null;
+        }
+    }
+
+    window.TreeSelect = TreeSelect;
+})();

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

@@ -1053,7 +1053,7 @@ $(document).ready(() => {
             {title: '变更详情', colSpan: '1', rowSpan: '2', field: 'detail', hAlign: 0, width: 120, formatter: '@', readOnly: 'readOnly.isEdit'},
             {title: '计量上限(%)', colSpan: '1', rowSpan: '2', field: 'delimit', hAlign: 2, width: 60, type: 'Number', readOnly: 'readOnly.isSettle2', visible: openChangeState},
             {title: '原设计|数量', colSpan: '1|1', rowSpan: '|1', field: 'oamount2', hAlign: 2, width: 120, type: 'Number', readOnly: 'readOnly.isSettle', getValue: 'getValue.oamount2'},
-            {title: '申请变更增(+)减(-)|数量', colSpan: '1|1', rowSpan: '|1', field: 'camount', hAlign: 2, width: 120, readOnly: 'readOnly.isSettle2', getValue: 'getValue.camount'},
+            {title: '申请变更增(+)减(-)|数量', colSpan: '1|1', rowSpan: '|1', field: 'camount', type: 'Number', hAlign: 2, width: 120, readOnly: 'readOnly.isSettle2', getValue: 'getValue.camount'},
             // {title: '数量', colSpan: '1', rowSpan: '2', field: 'oamount', hAlign: 2, width: 80},
         ],
         emptyRows: 0,
@@ -1904,7 +1904,7 @@ $(document).ready(() => {
             }
             select.spamount = ZhCalc.round(validText, findDecimal(select.unit)) || 0;
             select.camount_expr = exprQuantity.expr;
-            select.camount = validText;
+            select.camount = ZhCalc.round(validText, findDecimal(select.unit)) || 0;
             cInfo.spamount = select.spamount;
             cInfo.camount_expr = select.camount_expr;
             cInfo.camount = validText;
@@ -1922,6 +1922,7 @@ $(document).ready(() => {
                         changeSpreadObj.refreshXmjData();
                     }
                 }
+                changeSpreadObj.loadExprToInput(changeSpreadSheet);
             }, function () {
                 select.camount = orgValue;
                 select.camount_expr = orgExprValue;
@@ -2479,10 +2480,10 @@ $(document).ready(() => {
             }
             select.spamount = ZhCalc.round(validText, findDecimal(select.unit)) || 0;
             select.camount_expr = exprQuantity.expr;
-            select.camount = validText;
+            select.camount = ZhCalc.round(validText, findDecimal(select.unit)) || 0;
             cInfo.spamount = select.spamount;
             cInfo.camount_expr = select.camount_expr;
-            cInfo.camount = validText;
+            cInfo.camount = ZhCalc.round(validText, findDecimal(select.unit)) || 0;
             // console.log(select);
             delete cInfo.waitingLoading;
 
@@ -2495,6 +2496,7 @@ $(document).ready(() => {
                 changeSpreadObj.calcOneSum(node);
                 changeSpreadObj.reloadRow(changeSpreadSheet, billIndex);
                 changeSpreadObj.countSum();
+                xmjSpreadObj.loadExprToInput(xmjSheet);
             }, function () {
                 select.camount = orgValue;
                 select.camount_expr = orgExprValue;

+ 8 - 6
app/public/js/change_revise.js

@@ -880,7 +880,7 @@ $(document).ready(() => {
                         SpreadJsObj.reLoadRowData(info.sheet, info.row);
                         return;
                     }
-                    cInfo[col.field] = validText;
+                    cInfo[col.field] = ZhCalc.round(validText, findDecimal(node.unit)) || 0;
                     cInfo.spamount = ZhCalc.round(validText, findDecimal(node.unit)) || 0;
                     cInfo.camount_expr = exprQuantity.expr;
                     node[col.field] = cInfo[col.field];
@@ -1129,7 +1129,7 @@ $(document).ready(() => {
                             continue;
                         }
                         if (bPaste) {
-                            node.camount = validText;
+                            node.camount = ZhCalc.round(validText, findDecimal(node.unit)) || 0;
                             filterNodes.push(node);
                             camountData.push({id: cInfo.id, camount: node.camount, camount_expr: exprQuantity.expr, spamount: ZhCalc.round(validText, findDecimal(node.unit)) || 0 });
                         } else {
@@ -1291,7 +1291,7 @@ $(document).ready(() => {
                                 continue;
                             }
                             if (bPaste) {
-                                node.camount = validText;
+                                node.camount = ZhCalc.round(validText, findDecimal(node.unit)) || 0;
                                 filterNodes.push(node);
                                 camountData.push({id: cInfo.id, camount: node.camount, camount_expr: exprQuantity.expr, spamount: ZhCalc.round(validText, findDecimal(node.unit)) || 0 });
                             } else {
@@ -1801,8 +1801,8 @@ $(document).ready(() => {
                     toastr.error('清单变更数值必须小于等于已调用值 ' + usedInfo.qty);
                     return;
                 }
-                cInfo.camount = camount;
-                select.camount = camount;
+                cInfo.camount = ZhCalc.round(camount, findDecimal(select.unit)) || 0;
+                select.camount = ZhCalc.round(camount, findDecimal(select.unit)) || 0;
                 cInfo.spamount = ZhCalc.round(camount, findDecimal(select.unit)) || 0;
                 cInfo.camount_expr = exprQuantity.expr;
                 delete cInfo.waitingLoading;
@@ -1812,6 +1812,7 @@ $(document).ready(() => {
                     const loadResult = { update: [select] };
                     const refreshNode = billsTree.loadPostData(loadResult);
                     billsTreeSpreadObj.refreshTree(billsSheet, refreshNode);
+                    billsTreeSpreadObj.loadExprToInput(billsSheet);
                 }, function () {
                     cInfo.camount = orgValue;
                     cInfo.spamount = orgValue;
@@ -3109,7 +3110,7 @@ $(document).ready(() => {
                     toastr.error('清单变更数值必须小于等于已调用值 ' + usedInfo.qty);
                     return;
                 }
-                cInfo.camount = camount;
+                cInfo.camount = ZhCalc.round(camount, findDecimal(billsNode.unit)) || 0;
                 cInfo.spamount = ZhCalc.round(camount, findDecimal(billsNode.unit)) || 0;
                 cInfo.camount_expr = exprQuantity.expr;
                 delete cInfo.waitingLoading;
@@ -3119,6 +3120,7 @@ $(document).ready(() => {
                     const loadResult = { update: [billsNode] };
                     const refreshNode = billsTree.loadPostData(loadResult);
                     billsTreeSpreadObj.refreshTree(billsSheet, refreshNode);
+                    posSpreadObj.loadExprToInput(posSheet);
                 }, function () {
                     cInfo.camount = orgValue;
                     cInfo.spamount = orgValue;

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

@@ -1926,6 +1926,10 @@ $(document).ready(() => {
                 yearmonths.push(yearmonth);
             }
             console.log(yearmonths);
+            if (months.length + yearmonths.length > 24) {
+                toastr.error('月信息价不能超过24个月');
+                return false;
+            }
             postData(window.location.pathname + '/month/save', { type: 'adds', updateData: { yearmonths } }, function (data) {
                 months.push(...yearmonths);
                 months.sort();

+ 13 - 1
app/public/js/measure_material.js

@@ -199,8 +199,20 @@ $(function () {
         return `${year}<span>${mon}-${day}</span><span>${hour}:${minute}:${scond}</span>`;
     };
 
+    $('input[name="hz-radio"]').on('change', function () {
+        if ($(this).val() === '1') {
+            $('#hz-input').attr('readonly', 'readonly');
+            $('#hz-btn').attr('disabled', 'disabled');
+        } else {
+            $('#hz-input').removeAttr('readonly');
+            $('#hz-btn').removeAttr('disabled');
+        }
+        $('#hz-btn').trigger('click');
+    });
+
     $('#hz-input').on('keypress', function () {
-        if(window.event.keyCode === 13) {
+        // 还要判断是否是readonly
+        if(window.event.keyCode === 13 && !$(this).prop('readonly') && !$(this).prop('disabled')) {
             $('#hz-btn').trigger('click');
         }
     });

+ 39 - 14
app/public/js/setting_manage.js

@@ -744,20 +744,20 @@ $(document).ready(() => {
         $('#no-project-tenders input').prop('checked', checked);
     });
 
-    $('#change-sp').change(function () {
-        const spid = $(this).val();
-        console.log(spid);
-        postData(`/sp/${spid}/setting/manage/tender/save`, { type: 'get-category', spid }, function (result) {
-            $('#cate-list', '#edit-bd').html(getCategoryHtml(result));
-            const tender = _.find(tenders, { id: cur_tenderid });
-            if (tender && tender.spid === spid) {
-                for (const c of tender.category) {
-                    // $('input[value=' + c.value + ']', '#edit-bd').prop('checked', 'checked');
-                    $('option[value=' + c.value + ']', '#edit-bd').prop('selected', true);
-                }
-            }
-        });
-    })
+    // $('#change-sp').change(function () {
+    //     const spid = $(this).val();
+    //     console.log(spid);
+    //     postData(`/sp/${spid}/setting/manage/tender/save`, { type: 'get-category', spid }, function (result) {
+    //         $('#cate-list', '#edit-bd').html(getCategoryHtml(result));
+    //         const tender = _.find(tenders, { id: cur_tenderid });
+    //         if (tender && tender.spid === spid) {
+    //             for (const c of tender.category) {
+    //                 // $('input[value=' + c.value + ']', '#edit-bd').prop('checked', 'checked');
+    //                 $('option[value=' + c.value + ']', '#edit-bd').prop('selected', true);
+    //             }
+    //         }
+    //     });
+    // })
 
     $('#filter-tender-ok').click(function() {
         const updateData = [];
@@ -774,6 +774,31 @@ $(document).ready(() => {
             window.location.reload();
         });
     });
+
+    $('#edit-bd').on('show.bs.modal', function () {
+
+        const tree = new TreeSelect({
+            element: '#tree-container',
+            data: subProjects,
+            selected: spid,
+            onSelect: (id, label) => {
+                const newSpid = id;
+                console.log(newSpid);
+                $('#change-sp').val(newSpid);
+                postData(`/sp/${newSpid}/setting/manage/tender/save`, { type: 'get-category', spid: newSpid }, function (result) {
+                    $('#cate-list', '#edit-bd').html(getCategoryHtml(result));
+                    const tender = _.find(tenders, { id: cur_tenderid });
+                    if (tender && tender.spid === newSpid) {
+                        for (const c of tender.category) {
+                            // $('input[value=' + c.value + ']', '#edit-bd').prop('checked', 'checked');
+                            $('option[value=' + c.value + ']', '#edit-bd').prop('selected', true);
+                        }
+                    }
+                });
+                // console.log('选中了:', id, label);
+            }
+        });
+    });
 });
 
 const tenderListSpec = (function(){

+ 3 - 0
app/service/material_month.js

@@ -46,6 +46,9 @@ module.exports = app => {
                 const material_month = this.ctx.material.months ? this.ctx.material.months.split(',') : [];
                 material_month.push(...data.yearmonths);
                 material_month.sort();
+                if (material_month.length > 24) {
+                    throw '月信息价不能超过24个月';
+                }
                 if (mbList.length !== 0) {
                     const insertArray = [];
                     const updateArray = [];

+ 2 - 2
app/view/material/modal.ejs

@@ -204,11 +204,11 @@
                     </div>
                     <div class="col">
                         <div class="input-group mb-2">
-                            <input type="text" class="form-control form-control-sm" id="hz-input" placeholder="请输入材差期数(例如汇总第1期,第4至6期则输入:1,4-6)">
+                            <input type="text" class="form-control form-control-sm" id="hz-input" readonly placeholder="请输入材差期数(例如汇总第1期,第4至6期则输入:1,4-6)">
                         </div>
                     </div>
                     <div class="col-auto">
-                        <button id="hz-btn" class="btn btn-sm btn-primary mb-2">汇总</button>
+                        <button id="hz-btn" class="btn btn-sm btn-primary mb-2" disabled>汇总</button>
                     </div>
                 </div>
                 <table class="table table-bordered table-sm">

+ 3 - 0
app/view/sp_setting/manage.ejs

@@ -338,6 +338,7 @@
         </div>
     </div>
 </div>
+<!--<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>-->
 <script>
     const accountGroup = JSON.parse(unescape('<%- escape(JSON.stringify(accountGroup)) %>'));
     const accountList = JSON.parse(unescape('<%- escape(JSON.stringify(accountList)) %>'));
@@ -349,6 +350,8 @@
     const measureType = JSON.parse('<%- JSON.stringify(measureType) %>');
     const auditType = JSON.parse(unescape('<%- escape(JSON.stringify(auditType)) %>'));
     const scPermission = JSON.parse(unescape('<%- escape(JSON.stringify(scPermission)) %>'));
+    const subProjects = JSON.parse(unescape('<%- escape(JSON.stringify(subProjects)) %>'));
+    console.log(subProjects);
     const uid = '<%- uid %>';
     const pid = '<%- pid %>';
     const uphlname = 'user_' + uid + '_pro_' + pid + '_tender_manage_list';

+ 2 - 5
app/view/sp_setting/manage_modal.ejs

@@ -226,11 +226,8 @@
             <div class="modal-body">
                 <div class="form-group">
                     <label>所属项目<b class="text-danger">*</b></label>
-                    <select class="form-control form-control-sm" name="spid" id="change-sp">
-                        <% for (const sp of subProjects) { %>
-                        <option value="<%- sp.id %>"><%- sp.name %></option>
-                        <% } %>
-                    </select>
+                    <div id="tree-container"></div>
+                    <input type="hidden" name="spid" id="change-sp">
                 </div>
                 <div class="form-group">
                     <label>标段名称<b class="text-danger">*</b></label>

+ 2 - 0
config/web.js

@@ -1610,6 +1610,8 @@ const JsFiles = {
                     '/public/js/shares/show_level.js',
                     '/public/js/tender_showhide.js',
                     '/public/js/shenpi.js',
+                    '/public/js/popper/popper.min.js',
+                    '/public/js/bootstrap/tree-select.js',
                     '/public/js/setting_manage.js',
                     '/public/js/tender_list_base.js',
                 ],