Просмотр исходного кода

合同支付增加实付明细项填写

ellisran 1 день назад
Родитель
Сommit
14d2715e31
4 измененных файлов с 118 добавлено и 5 удалено
  1. 88 2
      app/public/js/contract_detail.js
  2. 1 0
      app/service/contract_pay.js
  3. 27 2
      app/view/contract/detail_modal.ejs
  4. 2 1
      sql/update.sql

+ 88 - 2
app/public/js/contract_detail.js

@@ -1810,11 +1810,24 @@ $(document).ready(function() {
         $('#cons-addpay input[name="pay_price"]').val(cpInfo ? cpInfo.pay_price : '');
         $('#cons-addpay input[name="debit_price"]').val(cpInfo ? cpInfo.debit_price : '');
         $('#cons-addpay input[name="yf_price"]').val(cpInfo ? cpInfo.yf_price : '');
-        $('#cons-addpay input[name="sf_price"]').val(cpInfo ? cpInfo.sf_price : '');
+        // $('#cons-addpay input[name="sf_price"]').val(cpInfo ? cpInfo.sf_price : '');
         $('#cons-addpay select[name="pay_type"]').val(cpInfo ? cpInfo.pay_type : $('#cons-addpay select[name="pay_type"] option:first').text());
         $('#cons-addpay textarea[name="remark"]').val(cpInfo ? cpInfo.remark : '');
         $('#cons-addpay .yf-tips').text('');
         $('#cons-addpay .sf-tips').text('');
+        let items = null;
+        if (cpInfo) {
+            try { items = cpInfo.sf_json ? JSON.parse(cpInfo.sf_json) : null; } catch (e) {}
+            // 旧数据没有 sf_json 时,用整笔 sf_price 填入首行
+            if (!items || !items.length) items = [{ desc: '', amount: cpInfo.sf_price }];
+        }
+        $('#sf-rows').empty().append(
+            items ? items.map(function (i) { return sfMakeRow(i.desc, i.amount); }) : sfMakeRow()
+        );
+        sfSyncDelBtns();
+        $('#sf-over-warn').hide();
+        $('#sf-sum-display').removeClass('text-danger');
+        sfRecalc();
 
     }
 
@@ -2205,6 +2218,76 @@ $(document).ready(function() {
         });
     }
 
+    function sfMakeRow(desc, amt) {
+        const $r = $(
+            '<div class="sf-row row no-gutters mb-2 align-items-center">' +
+            '<div class="col-6 pr-2">' +
+            '<input type="text" class="form-control form-control-sm sf-desc" placeholder="说明(如:工程款)">' +
+            '</div>' +
+            '<div class="col-5 pr-2">' +
+            '<input type="number" class="form-control form-control-sm sf-amt" placeholder="金额" min="0">' +
+            '</div>' +
+            '<div class="col-1 text-center">' +
+            '<button type="button" class="btn btn-sm btn-outline-secondary sf-del" style="font-size:16px;border: 1px solid #ced4da;" title="删除"><i class="fa fa-trash"></i></button>' +
+            '</div>' +
+            '</div>'
+        );
+        if (desc != null) $r.find('.sf-desc').val(desc);
+        if (amt  != null) $r.find('.sf-amt').val(amt);
+        return $r;
+    }
+
+    function sfSyncDelBtns() {
+        const $rows = $('#sf-rows .sf-row');
+        $rows.find('.sf-del').toggle($rows.length > 1);
+    }
+
+// 汇总明细 → 写入 hidden sf_price / sf_json,校验不超应付
+    function sfRecalc() {
+        let sfSum = 0;
+        const items = [];
+        $('#sf-rows .sf-row').each(function () {
+            const amt  = parseFloat($(this).find('.sf-amt').val()) || 0;
+            const desc = $(this).find('.sf-desc').val();
+            sfSum = ZhCalc.add(sfSum, amt);
+            if ($(this).find('.sf-amt').val() !== '') items.push({ desc: desc, amount: amt });
+        });
+
+        $('[name="sf_price"]').val(sfSum || '');
+        $('[name="sf_json"]').val(JSON.stringify(items));
+        $('#sf-sum-display').text(
+            '¥\u00a0' + sfSum
+        );
+
+        const yfPrice = parseFloat($('#cons-addpay [name="yf_price"]').val()) || 0;
+        if (yfPrice > 0 && sfSum > yfPrice) {
+            $('#sf-over-warn').show();
+            $('#sf-yf-hint').text(
+                '¥\u00a0' + yfPrice
+            );
+            $('#sf-sum-display').addClass('text-danger');
+            $('#cons-addpay .sf-tips').text(' ≤ ' + yfPrice);
+        } else {
+            $('#sf-over-warn').hide();
+            $('#sf-sum-display').removeClass('text-danger');
+            // sf-tips 由原 change 回调管理,这里只在超限时覆盖,不超时不清(让原逻辑自己清)
+        }
+    }
+    // 事件:明细金额变化
+    $('#sf-rows').on('input change', '.sf-amt', sfRecalc);
+    $('#sf-rows').on('input change', '.sf-desc', sfRecalc);
+
+    $('#sf-add-row').on('click', function () {
+        $('#sf-rows').append(sfMakeRow());
+        sfSyncDelBtns();
+        $('#sf-rows .sf-row:last .sf-desc').focus();
+    });
+
+    $('#sf-rows').on('click', '.sf-del', function () {
+        $(this).closest('.sf-row').remove();
+        sfSyncDelBtns();
+        sfRecalc();
+    });
     $('#cons-addpay input[type="number"]').change(function () {
         const name = $(this).attr('name');
         const node = SpreadJsObj.getSelectObject(contractSheet);
@@ -2259,6 +2342,7 @@ $(document).ready(function() {
         }
         if (name === 'pay_price' || name === 'debit_price') {
             $('#cons-addpay input[name="yf_price"]').val(yf_price);
+            setTimeout(sfRecalc, 0); // ← 唯一新增:yf_price 更新后重新校验实付超限
         }
     });
 
@@ -2286,6 +2370,7 @@ $(document).ready(function() {
             debit_price: $('#cons-addpay input[name="debit_price"]').val() || 0,
             yf_price: $('#cons-addpay input[name="yf_price"]').val() || 0,
             sf_price: $('#cons-addpay input[name="sf_price"]').val() || 0,
+            sf_json: $('#cons-addpay input[name="sf_json"]').val() || '',
             pay_type: $('#cons-addpay select[name="pay_type"]').val(),
             remark: $('#cons-addpay textarea[name="remark"]').val(),
         }
@@ -2334,6 +2419,7 @@ $(document).ready(function() {
             debit_price: $('#cons-addpay input[name="debit_price"]').val() || 0,
             yf_price: $('#cons-addpay input[name="yf_price"]').val() || 0,
             sf_price: $('#cons-addpay input[name="sf_price"]').val() || 0,
+            sf_json: $('#cons-addpay input[name="sf_json"]').val() || '',
             pay_type: $('#cons-addpay select[name="pay_type"]').val(),
             remark: $('#cons-addpay textarea[name="remark"]').val(),
         }
@@ -2378,7 +2464,7 @@ $(document).ready(function() {
             return false;
         }
         if (data.sf_price && !/^\d+(\.\d+)?$/.test(data.sf_price)) {
-            toastr.error('实'+ name +'金额只能输入数字');
+            toastr.error('实'+ name +'金额汇总需要大于等于0');
             return false;
         }
         if (cpInfo) {

+ 1 - 0
app/service/contract_pay.js

@@ -74,6 +74,7 @@ module.exports = app => {
                     debit_price: data.debit_price,
                     yf_price: data.yf_price,
                     sf_price: data.sf_price,
+                    sf_json: data.sf_json,
                     pay_type: data.pay_type,
                     remark: data.remark,
                     create_time: new Date(),

Разница между файлами не показана из-за своего большого размера
+ 27 - 2
app/view/contract/detail_modal.ejs


+ 2 - 1
sql/update.sql

@@ -25,7 +25,8 @@ ADD COLUMN `need_shenpi` tinyint(1) NULL COMMENT '是否需要审批' AFTER `fpc
 ADD COLUMN `status` tinyint(2) NULL DEFAULT 1 COMMENT '审批状态' AFTER `need_shenpi`,
 ADD COLUMN `times` tinyint(3) NULL DEFAULT 1 COMMENT '审批次数' AFTER `status`,
 ADD COLUMN `sp_group` int(11) NULL DEFAULT 0 COMMENT '固定审批组id' AFTER `times`,
-ADD COLUMN `final_auditor_str` varchar(50) NOT NULL DEFAULT '' COMMENT '终审人相关(cache)' AFTER `sp_group`;
+ADD COLUMN `final_auditor_str` varchar(50) NOT NULL DEFAULT '' COMMENT '终审人相关(cache)' AFTER `sp_group`,
+ADD COLUMN `sf_json` text NULL COMMENT '实付json数据' AFTER `sf_price`;
 
 ALTER TABLE `zh_contract_tree`
 ADD COLUMN `remark1` varchar(1000) NULL DEFAULT '' COMMENT '备注1' AFTER `remark`;