m0_70156489 преди 2 дни
родител
ревизия
89c079978e
променени са 2 файла, в които са добавени 182 реда и са изтрити 49 реда
  1. 102 23
      application/index/controller/Index.php
  2. 80 26
      application/index/view/index/rfqadd.html

+ 102 - 23
application/index/controller/Index.php

@@ -5219,21 +5219,26 @@ class Index extends Frontend
         $this->view->assign('defaultCclbmmc', $defaultDept);
         $this->view->assign('adminNickname', trim((string)($profile['contact_name'] ?? '')) ?: '业务员');
         $this->view->assign('rfqDeptOptions', $this->mprocLoadRfqDeptNameOptions());
-        $this->view->assign('rows', $this->mprocLoadRfqAddRows($user, ''));
+        $this->view->assign('rfqStatusTab', 'pending');
+        $this->view->assign('rows', $this->mprocLoadRfqAddRows($user, '', 'pending'));
 
         return $this->view->fetch();
     }
 
     /**
      * 业务员询价列表 JSON(本人发起或被通知)
-     * GET:q
+     * GET:q、status=pending|quoted
      */
     public function rfqaddlist()
     {
         $user = $this->mprocRequireRfqUser();
         $q = trim((string)$this->request->get('q', ''));
-        $rows = $this->mprocLoadRfqAddRows($user, $q);
-        $this->success('ok', null, ['rows' => $rows, 'total' => count($rows)]);
+        $status = trim((string)$this->request->get('status', 'pending'));
+        if ($status !== 'quoted') {
+            $status = 'pending';
+        }
+        $rows = $this->mprocLoadRfqAddRows($user, $q, $status);
+        $this->success('ok', null, ['rows' => $rows, 'total' => count($rows), 'status' => $status]);
     }
 
     /**
@@ -5540,9 +5545,10 @@ class Index extends Frontend
      * 手机端业务员询价列表(本人发起 / 被通知)
      *
      * @param array<string, mixed> $user
+     * @param string               $status pending|quoted|''(空=全部)
      * @return array<int, array<string, mixed>>
      */
-    protected function mprocLoadRfqAddRows(array $user, string $q): array
+    protected function mprocLoadRfqAddRows(array $user, string $q, string $status = ''): array
     {
         $profile = $this->mprocProfileForUser($user);
         $adminName = trim((string)($profile['contact_name'] ?? ''));
@@ -5595,10 +5601,33 @@ class Index extends Frontend
             $rows = [];
         }
         $out = [];
+        $sids = [];
+        foreach ($rows as $r) {
+            if (!is_array($r)) {
+                continue;
+            }
+            $sid = (int)($r['scydgy_id'] ?? 0);
+            if ($sid < 0) {
+                $sids[$sid] = $sid;
+            }
+        }
+        $quotedMap = $this->mprocLoadRfqQuotedSidMap(array_values($sids));
+        $status = trim($status);
+        if ($status !== 'pending' && $status !== 'quoted') {
+            $status = '';
+        }
         foreach ($rows as $r) {
             if (!is_array($r)) {
                 continue;
             }
+            $sid = (int)($r['scydgy_id'] ?? 0);
+            $isQuoted = !empty($quotedMap[$sid]);
+            if ($status === 'pending' && $isQuoted) {
+                continue;
+            }
+            if ($status === 'quoted' && !$isQuoted) {
+                continue;
+            }
             $created = trim((string)($r['createtime'] ?? ''));
             if ($created === '' || stripos($created, '0000-00-00') === 0) {
                 $created = trim((string)($r['dStamp'] ?? ''));
@@ -5606,9 +5635,12 @@ class Index extends Frontend
             if (preg_match('/^\d{10,}$/', $created)) {
                 $created = date('Y-m-d H:i:s', (int)$created);
             }
+            if ($created !== '' && stripos($created, '0000-00-00') === 0) {
+                $created = '';
+            }
             $out[] = [
                 'id'            => (int)($r['id'] ?? 0),
-                'scydgy_id'     => (int)($r['scydgy_id'] ?? 0),
+                'scydgy_id'     => $sid,
                 'CCYDH'         => trim((string)($r['CCYDH'] ?? '')),
                 'CYJMC'         => trim((string)($r['CYJMC'] ?? '')),
                 'CCLBMMC'       => trim((string)($r['CCLBMMC'] ?? '')),
@@ -5619,7 +5651,7 @@ class Index extends Frontend
                 'ceilingPrice'  => trim((string)($r['ceilingPrice'] ?? '')),
                 'cywyxm'        => trim((string)($r['cywyxm'] ?? '')),
                 'MBZ'           => trim((string)($r['MBZ'] ?? '')),
-                'progress_text' => $this->mprocFormatRfqProgressText($r),
+                'progress_text' => $isQuoted ? '已报价' : '待询价',
                 'createtime'    => $created,
             ];
         }
@@ -5628,28 +5660,75 @@ class Index extends Frontend
     }
 
     /**
-     * @param array<string, mixed> $row
+     * 哪些手工询价单已有有效报价(amount 非空且非 0)
+     *
+     * @param array<int, int> $sids
+     * @return array<int, bool>
      */
-    protected function mprocFormatRfqProgressText(array $row): string
+    protected function mprocLoadRfqQuotedSidMap(array $sids): array
     {
-        if (ProcuremenStatus::isPoCompleted($row['status'] ?? '')) {
-            return ProcuremenStatus::PO_COMPLETED;
-        }
-        if ((int)($row['rfq_salesman_notified'] ?? 0) === 1) {
-            return '已通知业务员';
+        $out = [];
+        $sids = array_values(array_unique(array_filter(array_map('intval', $sids), static function ($v) {
+            return $v < 0;
+        })));
+        if ($sids === []) {
+            return $out;
         }
-        $wflow = ProcuremenStatus::normalizeWflowStatus($row['wflow_status'] ?? '');
-        if ($wflow !== ProcuremenStatus::WFLOW_PENDING_ISSUE) {
-            return '待报价';
+        foreach (array_chunk($sids, 200) as $chunk) {
+            try {
+                $rows = Db::table('purchase_order_detail')
+                    ->where('scydgy_id', 'in', $chunk)
+                    ->whereRaw(ProcuremenStatus::sqlPodNotVoid('status'))
+                    ->whereRaw('(status_name IS NULL OR TRIM(status_name) = \'\' OR status_name <> \'' . ProcuremenStatus::POD_VOID . '\')')
+                    ->where('amount', '<>', '')
+                    ->whereNotNull('amount')
+                    ->where('amount', '<>', '0')
+                    ->where('amount', '<>', '0.00')
+                    ->field('scydgy_id')
+                    ->group('scydgy_id')
+                    ->select();
+            } catch (\Throwable $e) {
+                try {
+                    $rows = Db::table('purchase_order_detail')
+                        ->where('scydgy_id', 'in', $chunk)
+                        ->where('amount', '<>', '')
+                        ->whereNotNull('amount')
+                        ->where('amount', '<>', '0')
+                        ->where('amount', '<>', '0.00')
+                        ->field('scydgy_id')
+                        ->group('scydgy_id')
+                        ->select();
+                } catch (\Throwable $e2) {
+                    $rows = [];
+                }
+            }
+            if (!is_array($rows)) {
+                continue;
+            }
+            foreach ($rows as $r) {
+                if (!is_array($r)) {
+                    continue;
+                }
+                $sid = (int)($r['scydgy_id'] ?? 0);
+                if ($sid < 0) {
+                    $out[$sid] = true;
+                }
+            }
         }
+
+        return $out;
+    }
+
+    /**
+     * @param array<string, mixed> $row
+     */
+    protected function mprocFormatRfqProgressText(array $row): string
+    {
         $sid = (int)($row['scydgy_id'] ?? 0);
         if ($sid < 0) {
-            try {
-                $cnt = (int)Db::table('purchase_order_detail')->where('scydgy_id', $sid)->count();
-                if ($cnt > 0) {
-                    return '待报价';
-                }
-            } catch (\Throwable $e) {
+            $map = $this->mprocLoadRfqQuotedSidMap([$sid]);
+            if (!empty($map[$sid])) {
+                return '已报价';
             }
         }
 

+ 80 - 26
application/index/view/index/rfqadd.html

@@ -63,29 +63,47 @@
         }
         .toolbar .btn-search { background: #3c8dbc; color: #fff; }
         .toolbar .btn-add { background: #27ae60; color: #fff; }
+        .order-body {
+            position: relative;
+            display: flex; align-items: stretch;
+            flex: 1 1 0%; min-height: 0; overflow: hidden;
+        }
+        .rfq-side {
+            width: 78px; flex-shrink: 0; align-self: stretch;
+            background: #fff; border-right: 1px solid #e5e5e5;
+            padding: 6px 0 8px; overflow-y: auto; -webkit-overflow-scrolling: touch;
+            z-index: 1;
+        }
+        .rfq-side .rfq-cat {
+            display: block; width: 100%; padding: 12px 4px; border: none;
+            background: transparent; font-size: 13px; color: #666; cursor: pointer;
+            text-align: center; font-family: inherit; line-height: 1.35;
+            -webkit-tap-highlight-color: transparent;
+        }
+        .rfq-side .rfq-cat.active {
+            color: #3c8dbc; font-weight: 600; background: #f0f7fb;
+            box-shadow: inset 3px 0 0 #3c8dbc;
+        }
         .list-wrap {
-            flex: 1 1 0%; min-height: 0; overflow-y: auto; -webkit-overflow-scrolling: touch;
-            padding: 10px 12px 20px;
+            position: absolute; top: 0; right: 0; bottom: 0; left: 78px;
+            overflow-y: auto; -webkit-overflow-scrolling: touch;
+            padding: 10px 12px 20px; background: #f5f5f5;
         }
         .card {
             background: #fff; border-radius: 10px; padding: 12px 14px;
             margin-bottom: 10px; box-shadow: 0 1px 4px rgba(0,0,0,.06);
         }
-        .card .ord { font-size: 15px; font-weight: 700; color: #222; line-height: 1.4; word-break: break-all; }
+        .card .ord {
+            font-size: 15px; font-weight: 700; color: #222; line-height: 1.4; word-break: break-all;
+        }
         .card .meta { margin-top: 8px; font-size: 13px; color: #555; line-height: 1.55; }
         .card .meta b { color: #888; font-weight: 500; }
         .card .tags {
             margin-top: 8px; display: flex; flex-wrap: wrap; gap: 6px 10px;
-            font-size: 12px; color: #666; align-items: center;
+            font-size: 12px; color: #666; align-items: center; justify-content: flex-end;
         }
-        .card .progress {
-            display: inline-block; padding: 2px 8px; border-radius: 10px;
-            background: #eef6fb; color: #3c8dbc; font-weight: 600;
-        }
-        .card .progress.is-done { background: #eaf7ee; color: #27ae60; }
-        .card .time { color: #999; }
         .card .btn-view-quote {
-            margin-left: auto; padding: 4px 10px; border: 1px solid #3c8dbc;
+            padding: 4px 10px; border: 1px solid #3c8dbc;
             border-radius: 6px; background: #fff; color: #3c8dbc;
             font-size: 12px; font-weight: 600; font-family: inherit; cursor: pointer;
         }
@@ -258,7 +276,12 @@
         <button type="button" class="btn-search" id="btnSearch">搜索</button>
         <button type="button" class="btn-add" id="btnOpenAdd">新增询价</button>
     </div>
-    <div class="list-wrap" id="listMain">
+    <div class="order-body">
+        <nav class="rfq-side" id="rfqSide" aria-label="报价状态">
+            <button type="button" class="rfq-cat{if condition="!isset($rfqStatusTab) || $rfqStatusTab neq 'quoted'"} active{/if}" data-status="pending">待询价</button>
+            <button type="button" class="rfq-cat{if condition="isset($rfqStatusTab) && $rfqStatusTab eq 'quoted'"} active{/if}" data-status="quoted">已报价</button>
+        </nav>
+        <div class="list-wrap" id="listMain">
         {if $rows}
         {volist name="rows" id="row"}
         <div class="card">
@@ -266,18 +289,22 @@
             <div class="meta">
                 <div><b>需求部门:</b>{$row.CCLBMMC|default=''|htmlentities}</div>
                 <div><b>工序:</b>{$row.CGYMC|default=''|htmlentities}</div>
-                <div><b>发起人:</b>{$row.cywyxm|default=''|htmlentities}</div>
+                <div><b>本次数量:</b>{$row.This_quantity|default=''|htmlentities}</div>
+                <div><b>最高限价:</b>{$row.ceilingPrice|default=''|htmlentities}</div>
+                <div><b>需求发起人:</b>{$row.cywyxm|default=''|htmlentities}</div>
+                <div><b>需求发起时间:</b>{$row.createtime|default=''|htmlentities}</div>
             </div>
+            {if condition="isset($rfqStatusTab) && $rfqStatusTab eq 'quoted'"}
             <div class="tags">
-                <span class="progress{if condition="$row.progress_text eq '已完结'"} is-done{/if}">{$row.progress_text|default='待询价'|htmlentities}</span>
-                {if $row.createtime}<span class="time">{$row.createtime|htmlentities}</span>{/if}
                 <button type="button" class="btn-view-quote" data-scydgy-id="{$row.scydgy_id}">查看报价</button>
             </div>
+            {/if}
         </div>
         {/volist}
         {else/}
-        <div class="empty" id="emptyTip">暂无询价单,点击右上角「新增询价」</div>
+        <div class="empty" id="emptyTip">暂无询价单</div>
         {/if}
+        </div>
     </div>
 </div>
 
@@ -410,6 +437,8 @@
     var defaultDept = {:json_encode(isset($defaultCclbmmc) ? (string)$defaultCclbmmc : '营销中心', JSON_UNESCAPED_UNICODE)};
     var defaultStarter = {:json_encode(isset($adminNickname) ? (string)$adminNickname : '', JSON_UNESCAPED_UNICODE)};
     var nextCcydh = {:json_encode(isset($nextOrderCcydh) ? (string)$nextOrderCcydh : '', JSON_UNESCAPED_UNICODE)};
+    var currentStatus = {:json_encode(isset($rfqStatusTab) ? (string)$rfqStatusTab : 'pending', JSON_UNESCAPED_UNICODE)};
+    if (currentStatus !== 'quoted') currentStatus = 'pending';
 
     try {
         if (token) {
@@ -444,6 +473,10 @@
             .replace(/"/g, '&quot;');
     }
 
+    function emptyTipText() {
+        return currentStatus === 'quoted' ? '暂无已报价询价单' : '暂无待询价单';
+    }
+
     function postForm(url, data) {
         var body = Object.keys(data).map(function (k) {
             return encodeURIComponent(k) + '=' + encodeURIComponent(data[k] == null ? '' : data[k]);
@@ -505,7 +538,7 @@
         if (!main) return;
         rows = Array.isArray(rows) ? rows : [];
         if (!rows.length) {
-            main.innerHTML = '<div class="empty" id="emptyTip">暂无询价单,点击右上角「新增询价」</div>';
+            main.innerHTML = '<div class="empty" id="emptyTip">' + emptyTipText() + '</div>';
             return;
         }
         var html = '';
@@ -514,26 +547,31 @@
             var name = String(row.CYJMC || '').trim();
             if (title && name) title += ' ' + name;
             else title = title || name || '';
-            var progress = String(row.progress_text || '待询价');
             html += '<div class="card">'
                 + '<div class="ord">' + esc(title) + '</div>'
                 + '<div class="meta">'
                 + '<div><b>需求部门:</b>' + esc(row.CCLBMMC || '') + '</div>'
                 + '<div><b>工序:</b>' + esc(row.CGYMC || '') + '</div>'
-                + '<div><b>发起人:</b>' + esc(row.cywyxm || '') + '</div>'
-                + '</div>'
-                + '<div class="tags">'
-                + '<span class="progress' + (progress === '已完结' ? ' is-done' : '') + '">' + esc(progress) + '</span>'
-                + (row.createtime ? '<span class="time">' + esc(row.createtime) + '</span>' : '')
-                + '<button type="button" class="btn-view-quote" data-scydgy-id="' + esc(row.scydgy_id || '') + '">查看报价</button>'
-                + '</div></div>';
+                + '<div><b>本次数量:</b>' + esc(row.This_quantity || '') + '</div>'
+                + '<div><b>最高限价:</b>' + esc(row.ceilingPrice || '') + '</div>'
+                + '<div><b>需求发起人:</b>' + esc(row.cywyxm || '') + '</div>'
+                + '<div><b>需求发起时间:</b>' + esc(row.createtime || '') + '</div>'
+                + '</div>';
+            if (currentStatus === 'quoted') {
+                html += '<div class="tags">'
+                    + '<button type="button" class="btn-view-quote" data-scydgy-id="' + esc(row.scydgy_id || '') + '">查看报价</button>'
+                    + '</div>';
+            }
+            html += '</div>';
         });
         main.innerHTML = html;
     }
 
     function loadList() {
         var q = (document.getElementById('qInput').value || '').trim();
-        var url = listUrl + (listUrl.indexOf('?') >= 0 ? '&' : '?') + 'q=' + encodeURIComponent(q);
+        var url = listUrl + (listUrl.indexOf('?') >= 0 ? '&' : '?')
+            + 'q=' + encodeURIComponent(q)
+            + '&status=' + encodeURIComponent(currentStatus || 'pending');
         getJson(url).then(function (ret) {
             if (ret && (ret.code === 1 || ret.code === '1')) {
                 var data = ret.data || {};
@@ -549,6 +587,22 @@
         });
     }
 
+    var rfqSide = document.getElementById('rfqSide');
+    if (rfqSide) {
+        rfqSide.addEventListener('click', function (e) {
+            var btn = e.target && e.target.closest ? e.target.closest('.rfq-cat') : null;
+            if (!btn) return;
+            var st = btn.getAttribute('data-status') || 'pending';
+            if (st !== 'quoted') st = 'pending';
+            if (st === currentStatus) return;
+            currentStatus = st;
+            rfqSide.querySelectorAll('.rfq-cat').forEach(function (b) {
+                b.classList.toggle('active', b === btn);
+            });
+            loadList();
+        });
+    }
+
     document.getElementById('btnSearch').addEventListener('click', loadList);
     document.getElementById('qInput').addEventListener('keydown', function (e) {
         if (e.key === 'Enter') {