m0_70156489 20 hodín pred
rodič
commit
5b208428a0

+ 44 - 9
application/admin/controller/Procuremen.php

@@ -552,23 +552,51 @@ class Procuremen extends Backend
 
     /**
      * 左侧菜单(协助初选)
-     * 禁止扫整包/重 SQL。有月份小键则用;否则只展示当月,等列表第一次暖缓存后再补全
+     * 优先 Redis 月份小键;为空时用轻量 DISTINCT 查库补齐(避免只显示空当月、漏掉有数据的月份)
      */
     protected function GetIndexYearMonths()
     {
-        $ymList = $this->loadProcuremenSidebarYmList();
+        $ymList = $this->ensureProcuremenPickSidebarYmList();
         if ($ymList === []) {
-            $def = $this->resolveProcuremenDefaultYm('pick');
+            $def = date('Y-m');
             $ymList = [preg_match('/^\d{4}-\d{2}$/', $def) ? $def : date('Y-m')];
         }
-        $def = $this->resolveProcuremenDefaultYm('pick');
-        if (preg_match('/^\d{4}-\d{2}$/', $def) && !in_array($def, $ymList, true)) {
-            $ymList[] = $def;
-        }
 
         return $this->buildYearMonthSidebar($ymList);
     }
 
+    /**
+     * 初选侧栏月份:以轻量 DISTINCT 查库为准(有数据才显示),并写回 Redis 小键。
+     *
+     * @return string[]
+     */
+    protected function ensureProcuremenPickSidebarYmList(bool $forceRefresh = false): array
+    {
+        static $memo = null;
+        if (!$forceRefresh && is_array($memo)) {
+            return $memo;
+        }
+
+        $fromDb = $this->queryProcuremenPickSidebarYmListLight();
+        if ($fromDb !== []) {
+            $this->saveProcuremenSidebarYmList($fromDb);
+            $memo = $fromDb;
+
+            return $memo;
+        }
+
+        // 库侧暂无初选数据时,再回退 Redis / 当月,避免侧栏空白
+        $cached = $this->loadProcuremenSidebarYmList();
+        if ($cached !== []) {
+            $memo = $cached;
+
+            return $memo;
+        }
+        $memo = [date('Y-m')];
+
+        return $memo;
+    }
+
     /**
      * @return string[] 形如 2026-07
      */
@@ -995,11 +1023,18 @@ class Procuremen extends Backend
     }
 
     /**
-     * 列表默认月份:已下发类取最近有数据的月份,初选仍用当月
+     * 列表默认月份:已下发类取最近有数据的月份;初选也取最近有数据月份(避免跨月后落到空当月)
      */
     protected function resolveProcuremenDefaultYm(string $stage): string
     {
         if ($stage === 'pick') {
+            $yms = $this->ensureProcuremenPickSidebarYmList();
+            if ($yms !== []) {
+                rsort($yms, SORT_STRING);
+
+                return $yms[0];
+            }
+
             return date('Y-m');
         }
         try {
@@ -1897,7 +1932,7 @@ class Procuremen extends Backend
                 'activeYm'      => $ym,
                 // 初选:把有数据的月份带回,替换「空月份日历」侧栏
                 'sidebarYms'    => ($wffTab === 'pick' && (int)$offset === 0)
-                    ? $this->loadProcuremenSidebarYmList()
+                    ? $this->ensureProcuremenPickSidebarYmList()
                     : [],
                 // 仅无筛选的首页带回选项;从当月过滤后结果抽 distinct,避免扫近一年整池
                 'filterOptions' => (

+ 19 - 0
public/assets/js/backend/procuremen.js

@@ -1860,6 +1860,25 @@ define(['jquery', 'bootstrap', 'backend', 'table', 'form'], function ($, undefin
                     }
                     if (res && $.isArray(res.sidebarYms) && res.sidebarYms.length && Controller.wffTab === 'pick') {
                         procuremenRenderSidebarFromYms(res.sidebarYms);
+                        var pickYm = (res.activeYm || '').toString();
+                        if (!/^\d{4}-\d{2}$/.test(pickYm) || res.sidebarYms.indexOf(pickYm) < 0) {
+                            pickYm = String(res.sidebarYms[0] || '');
+                        }
+                        if (/^\d{4}-\d{2}$/.test(pickYm) && pickYm !== Controller.currYm) {
+                            Controller.currYm = pickYm;
+                            $('.procuremen-ym-item').removeClass('active');
+                            $('.procuremen-ym-item[data-ym="' + pickYm + '"]').addClass('active');
+                            // 当前选中的空月份切到有数据月份后,再刷一次列表
+                            setTimeout(function () {
+                                try {
+                                    table.bootstrapTable('refresh', {pageNumber: 1});
+                                } catch (ignore) {
+                                }
+                            }, 0);
+                        } else {
+                            $('.procuremen-ym-item').removeClass('active');
+                            $('.procuremen-ym-item[data-ym="' + Controller.currYm + '"]').addClass('active');
+                        }
                     }
                     if (res && res.activeYm && (Controller.wffTab === 'audit' || Controller.wffTab === 'confirm')) {
                         procuremenApplyActiveYm(res.activeYm);