liuhairui 2 veckor sedan
förälder
incheckning
5f6cda3035

+ 52 - 7
application/index/controller/Index.php

@@ -401,6 +401,33 @@ class Index extends Frontend
         return $s;
     }
 
+    /**
+     * 从请求中读取短信/邮件直达明细 ID(兼容 query、pathinfo、REQUEST_URI)
+     */
+    protected function mprocReadFocusEidFromRequest(): int
+    {
+        $fe = (int)$this->request->param('focus_eid', 0);
+        if ($fe > 0) {
+            return $fe;
+        }
+        $uri = isset($_SERVER['REQUEST_URI']) ? (string)$_SERVER['REQUEST_URI'] : '';
+        if ($uri !== '' && stripos($uri, 'focus_eid') !== false) {
+            $query = parse_url($uri, PHP_URL_QUERY);
+            if (is_string($query) && $query !== '') {
+                $q = [];
+                parse_str($query, $q);
+                if (is_array($q)) {
+                    $fe = (int)($q['focus_eid'] ?? 0);
+                    if ($fe > 0) {
+                        return $fe;
+                    }
+                }
+            }
+        }
+
+        return 0;
+    }
+
     /**
      * 手机端登录页 URL。注意:勿用 url('...login', ['redirect'=>]),在 url_html_suffix 下会把参数拼进 PATHINFO 导致 404。
      *
@@ -1295,14 +1322,27 @@ class Index extends Frontend
             return $bundle;
         }
         $rows = isset($bundle['rows']) && is_array($bundle['rows']) ? $bundle['rows'] : [];
-        foreach ($rows as $r) {
+        $foundIdx = -1;
+        foreach ($rows as $idx => $r) {
             if (!is_array($r)) {
                 continue;
             }
             if ((int)($r['eid'] ?? $r['id'] ?? $r['ID'] ?? 0) === $focusEid) {
-                return $bundle;
+                $foundIdx = (int)$idx;
+                break;
             }
         }
+        if ($foundIdx > 0) {
+            $hit = $rows[$foundIdx];
+            array_splice($rows, $foundIdx, 1);
+            array_unshift($rows, $hit);
+            $bundle['rows'] = $rows;
+
+            return $bundle;
+        }
+        if ($foundIdx === 0) {
+            return $bundle;
+        }
         $idCol = $this->mprocResolveProcuremenColumn(['id']);
         if ($idCol === null) {
             return $bundle;
@@ -1559,8 +1599,9 @@ class Index extends Frontend
         $q = trim((string)$this->request->get('q', ''));
 
         $mprocFocusEid = 0;
-        $focusEid = (int)$this->request->get('focus_eid', 0);
+        $focusEid = $this->mprocReadFocusEidFromRequest();
         if ($focusEid > 0 && $mainTab === 'orders') {
+            $mprocFocusEid = $focusEid;
             $idCol = $this->mprocResolveProcuremenColumn(['id']);
             if ($idCol) {
                 $qw = $this->mprocListWhereForLoginUser($user);
@@ -1575,7 +1616,6 @@ class Index extends Frontend
                     $dr = null;
                 }
                 if (is_array($dr) && $dr !== []) {
-                    $mprocFocusEid = $focusEid;
                     $q = '';
                     $sid = (int)($dr['scydgy_id'] ?? $dr['SCYDGY_ID'] ?? 0);
                     $po = null;
@@ -1661,10 +1701,15 @@ class Index extends Frontend
 
         $statusNameCol = $this->mprocResolveProcuremenColumn(['status_name', 'status_txt', 'status_text']);
         $bundle = $this->mprocFetchProcuremenList($user, $tab, $q, $statusNameCol);
+        $focusEid = $this->mprocReadFocusEidFromRequest();
+        if ($focusEid > 0) {
+            $bundle = $this->mprocEnsureFocusRowInList($bundle, $focusEid, $user, $statusNameCol);
+        }
         $this->success('ok', '', array_merge([
-            'main_tab' => 'orders',
-            'tab'      => $tab,
-            'is_admin' => !empty($user['is_admin']) ? 1 : 0,
+            'main_tab'  => 'orders',
+            'tab'       => $tab,
+            'is_admin'  => !empty($user['is_admin']) ? 1 : 0,
+            'focus_eid' => $focusEid,
         ], $bundle));
     }
 

+ 67 - 15
application/index/view/index/index.html

@@ -276,6 +276,9 @@
 <form class="search-wrap" id="mproc-search-form" method="get" action="{:url('index/index/index')}">
     <input type="hidden" name="main_tab" value="orders" id="mproc-search-main-tab">
     <input type="hidden" name="tab" id="mproc-search-tab" value="{$mprocTab|default='draft'|htmlentities}">
+    {if $mprocFocusEid}
+    <input type="hidden" name="focus_eid" value="{$mprocFocusEid}">
+    {/if}
     <div class="search-form">
         <input type="search" name="q" id="mproc-input-q" value="{$mprocSearchQ|htmlentities}" placeholder="请输入搜索内容" maxlength="120" enterkeyhint="search">
         <button type="submit">搜索</button>
@@ -494,6 +497,24 @@
     var currentMain = boot.main_tab === 'me' ? 'me' : 'orders';
     var currentListTab = boot.tab && ['draft', 'submitted', 'done'].indexOf(boot.tab) !== -1 ? boot.tab : 'draft';
 
+    /** 短信/邮件链接中的 focus_eid:优先 boot,其次当前 URL */
+    function mprocGetFocusEid() {
+        var fromBoot = parseInt(boot.focus_eid, 10) || 0;
+        if (fromBoot > 0) {
+            return fromBoot;
+        }
+        try {
+            var sp = new URLSearchParams(window.location.search);
+            var fe = parseInt(sp.get('focus_eid'), 10) || 0;
+            if (fe > 0) {
+                boot.focus_eid = fe;
+                return fe;
+            }
+        } catch (ignoreUrl) {
+        }
+        return 0;
+    }
+
     var tabbar = document.getElementById('mproc-tabbar');
     var paneOrders = document.getElementById('mproc-pane-orders');
     var paneMe = document.getElementById('mproc-pane-me');
@@ -667,7 +688,7 @@
             var canEdit = parseInt(r.mproc_can_edit, 10) === 1;
             var ccydh = pick(r, ['CCYDH', 'ccydh']);
             var cname = pick(r, ['company_name', 'Company_name']);
-            var focusEid = parseInt(boot.focus_eid, 10) || 0;
+            var focusEid = mprocGetFocusEid();
             var hl = focusEid > 0 && eid === focusEid ? ' mproc-card-highlight' : '';
             return '<div class="card js-card' + hl + '" data-id="' + eid + '" data-ccydh="' + mprocEscAttr(ccydh) + '" data-amount="' + mprocEscAttr(amtRaw) + '" data-delivery="' + mprocEscAttr(delRaw) + '" data-title="' + mprocEscAttr(tit) + '" data-ceiling-price="' + mprocEscAttr(ceilP) + '" data-this-quantity="' + mprocEscAttr(thisQty) + '">'
                 + '<p class="title">' + mprocEsc(tit) + '</p>'
@@ -718,6 +739,12 @@
         } else {
             u.searchParams.delete('q');
         }
+        var focusEid = mprocGetFocusEid();
+        if (focusEid > 0 && !q) {
+            u.searchParams.set('focus_eid', String(focusEid));
+        } else {
+            u.searchParams.delete('focus_eid');
+        }
         var fetchOpts = {
             method: 'GET',
             credentials: 'same-origin',
@@ -745,8 +772,10 @@
             if (listInner) {
                 listInner.innerHTML = renderListHtml(rows, dns);
             }
-            setTimeout(mprocTryScrollToFocusCard, 80);
-            setTimeout(mprocTryScrollToFocusCard, 400);
+            if (d.focus_eid) {
+                boot.focus_eid = parseInt(d.focus_eid, 10) || boot.focus_eid;
+            }
+            mprocScheduleFocusScroll();
         }).catch(function (e) {
             if (myAbort && mprocListAbort !== myAbort) {
                 return;
@@ -1158,31 +1187,54 @@
 
     /** 邮件/短信直达链接:高亮并滚动到对应明细卡片 */
     function mprocTryScrollToFocusCard() {
-        var eid = parseInt(boot.focus_eid, 10) || 0;
+        var eid = mprocGetFocusEid();
         if (!eid || !listInner) {
-            return;
+            return false;
+        }
+        if (currentMain !== 'orders' && paneOrders) {
+            showMain('orders');
         }
         var card = listInner.querySelector('.js-card[data-id="' + eid + '"]');
         if (!card) {
-            return;
+            return false;
         }
         card.classList.add('mproc-card-highlight');
         var pane = document.querySelector('.mproc-order-main');
         if (!pane) {
-            return;
+            try {
+                card.scrollIntoView({ block: 'center' });
+            } catch (ignoreScroll) {
+            }
+            return true;
         }
+        var top = card.getBoundingClientRect().top - pane.getBoundingClientRect().top + pane.scrollTop - 16;
+        top = Math.max(0, top);
         try {
-            var top = card.getBoundingClientRect().top - pane.getBoundingClientRect().top + pane.scrollTop - 20;
-            pane.scrollTo({ top: Math.max(0, top), behavior: 'smooth' });
-        } catch (e1) {
-            try {
-                card.scrollIntoView({ behavior: 'smooth', block: 'center' });
-            } catch (e2) {}
+            pane.scrollTop = top;
+        } catch (ignoreTop) {
+        }
+        try {
+            pane.scrollTo({ top: top, behavior: 'auto' });
+        } catch (ignoreTo) {
+        }
+        return true;
+    }
+
+    function mprocScheduleFocusScroll() {
+        if (!mprocGetFocusEid()) {
+            return;
         }
+        [0, 120, 350, 700, 1200, 2000].forEach(function (ms) {
+            setTimeout(mprocTryScrollToFocusCard, ms);
+        });
     }
+
     mprocTryRestoreLoginFromStorage();
-    setTimeout(mprocTryScrollToFocusCard, 200);
-    setTimeout(mprocTryScrollToFocusCard, 650);
+    mprocScheduleFocusScroll();
+    window.addEventListener('load', mprocScheduleFocusScroll);
+    window.addEventListener('orientationchange', function () {
+        setTimeout(mprocScheduleFocusScroll, 300);
+    });
 
     if (boot.can_change_pwd) {
         var pwdMask = document.getElementById('pwd-mask');

+ 31 - 5
application/index/view/index/login.html

@@ -260,6 +260,34 @@
         btn.textContent = busy ? (busyText || '请稍候…') : btn.dataset.idleText;
     }
 
+    function mprocExtractFocusEidFromRedirect(redir) {
+        if (!redir) {
+            return 0;
+        }
+        try {
+            var qIdx = String(redir).indexOf('?');
+            if (qIdx < 0) {
+                return 0;
+            }
+            var sp = new URLSearchParams(String(redir).substring(qIdx + 1));
+            return parseInt(sp.get('focus_eid'), 10) || 0;
+        } catch (ignoreParse) {
+            return 0;
+        }
+    }
+
+    function mprocEnsureUrlHasFocusEid(url, redir) {
+        if (!url || /(?:\?|&)focus_eid=\d+/.test(url)) {
+            return url;
+        }
+        var fe = mprocExtractFocusEidFromRedirect(redir);
+        if (fe <= 0) {
+            return url;
+        }
+        var sep = url.indexOf('?') >= 0 ? '&' : '?';
+        return url + sep + 'focus_eid=' + encodeURIComponent(String(fe)) + '&main_tab=orders';
+    }
+
     function goHome(ret) {
         if (ret && (ret.code === 1 || ret.code === '1')) {
             var d = ret.data || {};
@@ -270,11 +298,9 @@
                     localStorage.setItem('mproc_token_exp', String(Date.now() + days * 86400000));
                 } catch (eStore) {}
             }
-            if (ret.url) {
-                location.href = ret.url;
-            } else {
-                location.href = indexUrl;
-            }
+            var jump = ret.url || indexUrl;
+            jump = mprocEnsureUrlHasFocusEid(jump, loginRedirect);
+            location.href = jump;
         } else {
             showToast(ret && ret.msg ? ret.msg : '登录失败', 'err');
         }