Explorar o código

Bark & 企业微信 等显示调整优化

Apply fixes from StyleCI
兔姬桑 %!s(int64=3) %!d(string=hai) anos
pai
achega
12d4365fe4
Modificáronse 31 ficheiros con 287 adicións e 83 borrados
  1. 12 3
      app/Channels/BarkChannel.php
  2. 3 2
      app/Channels/Components/WeChat.php
  3. 1 1
      app/Channels/PushBearChannel.php
  4. 1 1
      app/Channels/PushPlusChannel.php
  5. 1 1
      app/Channels/ServerChanChannel.php
  6. 1 1
      app/Channels/TgChatChannel.php
  7. 29 11
      app/Channels/WeChatChannel.php
  8. 5 3
      app/Components/Helpers.php
  9. 21 0
      app/Http/Controllers/MessageController.php
  10. 12 0
      app/Notifications/Custom.php
  11. 3 2
      app/Notifications/NodeBlocked.php
  12. 1 0
      app/Notifications/NodeDailyReport.php
  13. 3 0
      app/Notifications/NodeOffline.php
  14. 2 3
      app/Notifications/PaymentConfirm.php
  15. 10 13
      app/Notifications/PaymentReceived.php
  16. 11 0
      app/Notifications/TicketClosed.php
  17. 11 0
      app/Notifications/TicketCreated.php
  18. 11 0
      app/Notifications/TicketReplied.php
  19. 32 0
      database/migrations/2022_01_16_160308_add_msgid_notification_log.php
  20. BIN=BIN
      public/assets/images/notification/custom.png
  21. BIN=BIN
      public/assets/images/notification/offline.png
  22. BIN=BIN
      public/assets/images/notification/ticket.png
  23. 1 1
      resources/views/_layout.blade.php
  24. 44 0
      resources/views/components/message.blade.php
  25. 0 1
      resources/views/components/payment/detail.blade.php
  26. 56 20
      resources/views/user/components/payment/manual.blade.php
  27. 12 16
      resources/views/user/help.blade.php
  28. 1 1
      resources/views/user/layouts.blade.php
  29. 2 2
      resources/views/vendor/log-viewer/remark/layouts.blade.php
  30. 0 1
      routes/user.php
  31. 1 0
      routes/web.php

+ 12 - 3
app/Channels/BarkChannel.php

@@ -5,7 +5,9 @@ namespace App\Channels;
 use Helpers;
 use Http;
 use Illuminate\Notifications\Notification;
+use Illuminate\Support\Arr;
 use Log;
+use Str;
 
 class BarkChannel
 {
@@ -17,18 +19,25 @@ class BarkChannel
             $message = $notification->toCustom($notifiable);
         }
 
-        $response = Http::timeout(15)->get('https://api.day.app/'.sysConfig('bark_key').'/'.$message['title'].'/'.$message['content']);
+        if (isset($message['url_type'])) { // 生成对公消息查询URL
+            $msgId = Str::uuid();
+            $message['url'] = route('message.show', ['type' => $message['url_type'], $msgId]);
+            unset($message['url_type']);
+        }
+
+        $response = Http::timeout(15)
+            ->get('https://api.day.app/'.sysConfig('bark_key')."/{$message['title']}/{$message['content']}?".http_build_query(Arr::except($message, ['title', 'content'])));
 
         if ($response->ok()) {
             $ret = $response->json();
             // 发送成功
             if ($ret['code'] === 200) {
-                Helpers::addNotificationLog($message['title'], $message['content'], 3);
+                Helpers::addNotificationLog($message['title'], $message['content'], 3, 1, null, $msgId ?? null);
 
                 return $ret;
             }
             // 发送失败
-            Helpers::addNotificationLog($message['title'], $message['content'], 3, 'admin', -1, $message);
+            Helpers::addNotificationLog($message['title'], $message['content'], 3, -1);
 
             return false;
         }

+ 3 - 2
app/Channels/Components/WeChat.php

@@ -5,6 +5,7 @@ namespace App\Channels\Components;
 use DOMDocument;
 use Exception;
 use Log;
+use Str;
 
 class WeChat
 {
@@ -193,8 +194,8 @@ class PKCS7Encoder
  */
 class Prpcrypt
 {
-    public $key = null;
-    public $iv = null;
+    public $key;
+    public $iv;
 
     public function __construct()
     {

+ 1 - 1
app/Channels/PushBearChannel.php

@@ -26,7 +26,7 @@ class PushBearChannel
                 return $ret;
             }
             // 发送失败
-            Helpers::addMarketing(2, $message['title'], $message['content'], -1, $ret['message']);
+            Helpers::addMarketing(2, $message['title'], $message['content'], -1, '无返回内容');
 
             return false;
         }

+ 1 - 1
app/Channels/PushPlusChannel.php

@@ -30,7 +30,7 @@ class PushPlusChannel
                 return $ret;
             }
             // 发送失败
-            Helpers::addNotificationLog($message['title'], $message['content'], 7, 'admin', -1, $ret ? $ret['msg'] : '未知');
+            Helpers::addNotificationLog($message['title'], $message['content'], 7, -1, $ret ? $ret['msg'] : '未知');
 
             return false;
         }

+ 1 - 1
app/Channels/ServerChanChannel.php

@@ -40,7 +40,7 @@ class ServerChanChannel
                 return $ret;
             }
             // 发送失败
-            Helpers::addNotificationLog($message['title'], $message['content'], 2, 'admin', -1, $ret ? $ret['errmsg'] : '未知');
+            Helpers::addNotificationLog($message['title'], $message['content'], 2, -1, $ret ? $ret['errmsg'] : '未知');
 
             return false;
         }

+ 1 - 1
app/Channels/TgChatChannel.php

@@ -24,7 +24,7 @@ class TgChatChannel
                 return $ret;
             }
             // 发送失败
-            Helpers::addNotificationLog($message['title'], $message['content'], 6, 'admin', -1, $ret ? $ret['message'] : '未知');
+            Helpers::addNotificationLog($message['title'], $message['content'], 6, -1, $ret ? $ret['message'] : '未知');
 
             return false;
         }

+ 29 - 11
app/Channels/WeChatChannel.php

@@ -7,7 +7,6 @@ use Cache;
 use Helpers;
 use Http;
 use Illuminate\Http\Request;
-use Illuminate\Mail\Markdown;
 use Illuminate\Notifications\Notification;
 use Log;
 use Str;
@@ -17,29 +16,39 @@ class WeChatChannel
     private $access_token;
 
     public function __construct()
+    {
+        $this->access_token = $this->getAccessToken();
+    }
+
+    private function getAccessToken()
     {
         if (Cache::has('wechat_access_token')) {
-            $this->access_token = Cache::get('wechat_access_token');
+            $access_token = Cache::get('wechat_access_token');
         } else {
             // https://work.weixin.qq.com/api/doc/90000/90135/91039
             $response = Http::get('https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid='.sysConfig('wechat_cid').'&corpsecret='.sysConfig('wechat_secret'));
             if ($response->ok() && isset($response->json()['access_token'])) {
-                $this->access_token = $response->json()['access_token'];
+                $access_token = $response->json()['access_token'];
                 Cache::put('wechat_access_token', $response->json()['access_token'], 7200); // 2小时
             } else {
                 Log::critical('Wechat消息推送异常:获取access_token失败!'.PHP_EOL.'携带访问参数:'.$response->body());
                 abort(400);
             }
         }
+
+        return $access_token ?? null;
     }
 
     public function send($notifiable, Notification $notification)
-    {
+    { // route('message.show', ['type' => 'markdownMsg', 'msgId' => ''])
         $message = $notification->toCustom($notifiable);
+        if (! $this->access_token) {
+            $this->access_token = $this->getAccessToken();
+        }
 
         $url = 'https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token='.$this->access_token;
 
-        if (isset($message['button'])) {
+        if (isset($message['button'])) { // 按钮交互型
             // https://work.weixin.qq.com/api/doc/90000/90135/90236#%E6%8C%89%E9%92%AE%E4%BA%A4%E4%BA%92%E5%9E%8B
             $body = [
                 'touser'        => '@all',
@@ -66,18 +75,27 @@ class WeChatChannel
                     ],
                 ],
             ];
-        } else {
+        } elseif (isset($message['url_type'])) { // 文本卡片
+            $msgId = Str::uuid(); // 生成对公消息查询URL
             $body = [
                 'touser'   => '@all',
                 'agentid'  => sysConfig('wechat_aid'),
                 'msgtype'  => 'textcard',
                 'textcard' => [
                     'title'       => $message['title'],
-                    'description' => Markdown::parse($message['content'])->toHtml(),
-                    'url'         => route('admin.index'),
-                    'btntxt'      => '',
+                    'description' => '请点击下方按钮【查看详情】',
+                    'url'         => route('message.show', ['type' => $message['url_type'], $msgId]),
+                    'btntxt'      => '查看详情',
                 ],
             ];
+        } else { // 文本消息
+            $body = [
+                'touser'                   => '@all',
+                'agentid'                  => sysConfig('wechat_aid'),
+                'msgtype'                  => 'text',
+                'text'                     => ['content' => $message['content']],
+                'duplicate_check_interval' => 600,
+            ];
         }
 
         $response = Http::timeout(15)->withBody(json_encode($body, JSON_UNESCAPED_UNICODE), 'application/json; charset=utf-8')->post($url);
@@ -86,12 +104,12 @@ class WeChatChannel
         if ($response->ok()) {
             $ret = $response->json();
             if (! $ret['errcode'] && $ret['errmsg'] === 'ok') {
-                Helpers::addNotificationLog($message['title'], $message['content'] ?? var_export($message['body'], true), 5);
+                Helpers::addNotificationLog($message['title'], $message['content'] ?? var_export($message['body'], true), 5, 1, null, $msgId ?? null);
 
                 return $ret;
             }
             // 发送失败
-            Helpers::addNotificationLog($message['title'], $message['content'] ?? var_export($message['body'], true), 5, 'admin', -1, $ret ? $ret['errmsg'] : '未知');
+            Helpers::addNotificationLog($message['title'], $message['content'] ?? var_export($message['body'], true), 5, -1, $ret ? $ret['errmsg'] : '未知');
 
             return false;
         }

+ 5 - 3
app/Components/Helpers.php

@@ -150,15 +150,17 @@ class Helpers
      * @param  string  $title  标题
      * @param  string  $content  内容
      * @param  int  $type  发送类型
-     * @param  string  $address  收信方
      * @param  int  $status  投递状态
-     * @param  string  $error  投递失败时记录的异常信息
+     * @param  string|null  $error  投递失败时记录的异常信息
+     * @param  string|null  $msgId  对公查询ID
+     * @param  string  $address  收信方
      * @return int
      */
-    public static function addNotificationLog(string $title, string $content, int $type, string $address = 'admin', int $status = 1, string $error = ''): int
+    public static function addNotificationLog(string $title, string $content, int $type, int $status = 1, string $error = null, string $msgId = null, string $address = 'admin'): int
     {
         $log = new NotificationLog();
         $log->type = $type;
+        $log->msg_id = $msgId;
         $log->address = $address;
         $log->title = $title;
         $log->content = $content;

+ 21 - 0
app/Http/Controllers/MessageController.php

@@ -0,0 +1,21 @@
+<?php
+
+namespace App\Http\Controllers;
+
+use App\Models\NotificationLog;
+use Illuminate\Http\Request;
+use Illuminate\Mail\Markdown;
+
+class MessageController extends Controller
+{
+    public function index(string $type, string $msgId)
+    {
+        if ($type === 'markdown') {
+            $log = NotificationLog::whereMsgId($msgId)->latest()->firstOrFail();
+            $title = $log->title;
+            $content = Markdown::parse($log->content)->toHtml();
+        }
+
+        return view('components.message', compact('title', 'content'));
+    }
+}

+ 12 - 0
app/Notifications/Custom.php

@@ -49,4 +49,16 @@ class Custom extends Notification implements ShouldQueue
             ->token(sysConfig('telegram_token'))
             ->content($this->content);
     }
+
+    public function toBark($notifiable)
+    {
+        return [
+            'title'    => $this->title,
+            'content'  => $this->content,
+            'group'    => '自定义信息',
+            'icon'     => asset('assets/images/notification/custom.png'),
+            'sound'    => 'newmail',
+            'url_type' => 'markdown',
+        ];
+    }
 }

+ 3 - 2
app/Notifications/NodeBlocked.php

@@ -53,8 +53,9 @@ class NodeBlocked extends Notification implements ShouldQueue
     public function toCustom($notifiable)
     {
         return [
-            'title'   => trans('notification.node_block'),
-            'content' => $this->markdownMessage(),
+            'title'    => trans('notification.node_block'),
+            'content'  => $this->markdownMessage(),
+            'url_type' => 'markdown',
         ];
     }
 

+ 1 - 0
app/Notifications/NodeDailyReport.php

@@ -46,6 +46,7 @@ class NodeDailyReport extends Notification implements ShouldQueue
         return [
             'title'   => __('Nodes Daily Report'),
             'content' => $this->markdownMessage(),
+            'url_type' => 'markdown',
         ];
     }
 

+ 3 - 0
app/Notifications/NodeOffline.php

@@ -46,6 +46,7 @@ class NodeOffline extends Notification implements ShouldQueue
         return [
             'title'   => trans('notification.node_offline'),
             'content' => $this->markdownMessage(),
+            'url_type' => 'markdown',
         ];
     }
 
@@ -54,6 +55,8 @@ class NodeOffline extends Notification implements ShouldQueue
         return [
             'title'   => trans('notification.node_offline'),
             'content' => $this->stringMessage(),
+            'group'   => '节点状态',
+            'icon'    => asset('assets/images/notification/offline.png'),
         ];
     }
 

+ 2 - 3
app/Notifications/PaymentConfirm.php

@@ -6,7 +6,6 @@ use App\Models\Order;
 use App\Models\User;
 use Illuminate\Bus\Queueable;
 use Illuminate\Notifications\Notification;
-use NotificationChannels\Telegram\TelegramChannel;
 use NotificationChannels\Telegram\TelegramMessage;
 
 class PaymentConfirm extends Notification
@@ -31,7 +30,7 @@ class PaymentConfirm extends Notification
     {
         $order = $this->order;
         $goods = $this->order->goods;
-        $message = sprintf("🛒 人工支付\n———————————————\n\t\tℹ️ 账号:%s\n\t\t💰 金额:%s\n\t\t📦 商品:%s\n\t\t", $order->user->username, $order->amount, $goods->name ?? '余额充值');
+        $message = sprintf("🛒 人工支付\n———————————————\n\t\tℹ️ 账号:%s\n\t\t💰 金额:%1.2f\n\t\t📦 商品:%s\n\t\t", $order->user->username, $order->amount, $goods->name ?? '余额充值');
         foreach (User::role('Super Admin')->get() as $admin) {
             if (! $admin->telegram_user_id) {
                 continue;
@@ -62,7 +61,7 @@ class PaymentConfirm extends Notification
                 ],
                 [
                     'keyname' => '💰 金额',
-                    'value'   => $order->amount,
+                    'value'   => sprintf('%1.2f', $order->amount),
                 ],
                 [
                     'keyname' => '📦 商品',

+ 10 - 13
app/Notifications/PaymentReceived.php

@@ -2,7 +2,6 @@
 
 namespace App\Notifications;
 
-use App\Models\User;
 use Illuminate\Bus\Queueable;
 use Illuminate\Contracts\Queue\ShouldQueue;
 use Illuminate\Notifications\Messages\MailMessage;
@@ -46,17 +45,15 @@ class PaymentReceived extends Notification implements ShouldQueue
     // todo: 需要重新审视发送对象
     public function toTelegram($notifiable)
     {
-        foreach (User::role('Super Admin')->get() as $admin) {
-            $message = sprintf(
-                "💰成功收款%s元\n———————————————\n订单号:%s",
-                $this->amount,
-                $this->sn
-            );
-
-            return TelegramMessage::create()
-                ->to($admin->telegram_user_id)
-                ->token(sysConfig('telegram_token'))
-                ->content($message);
-        }
+        $message = sprintf(
+            "💰成功收款%s元\n———————————————\n订单号:%s",
+            $this->amount,
+            $this->sn
+        );
+
+        return TelegramMessage::create()
+            ->to($notifiable->telegram_user_id)
+            ->token(sysConfig('telegram_token'))
+            ->content($message);
     }
 }

+ 11 - 0
app/Notifications/TicketClosed.php

@@ -55,4 +55,15 @@ class TicketClosed extends Notification implements ShouldQueue
             ->token(sysConfig('telegram_token'))
             ->content($this->reason);
     }
+
+    public function toBark($notifiable)
+    {
+        return [
+            'title'   => trans('notification.close_ticket', ['id' => $this->ticketId, 'title' => $this->title]),
+            'content' => $this->reason,
+            'group'   => '工单',
+            'icon'    => asset('assets/images/notification/ticket.png'),
+            'url'     => $this->url,
+        ];
+    }
 }

+ 11 - 0
app/Notifications/TicketCreated.php

@@ -58,4 +58,15 @@ class TicketCreated extends Notification implements ShouldQueue
     {
         return "📮工单提醒 #{$ticket->id}\n———————————————\n主题:\n`{$ticket->title}`\n内容:\n`{$ticket->content}`";
     }
+
+    public function toBark($notifiable)
+    {
+        return [
+            'title'   => trans('notification.new_ticket', ['title' => $this->ticket->title]),
+            'content' => trans('notification.ticket_content').strip_tags($this->ticket->content),
+            'group'   => '工单',
+            'icon'    => asset('assets/images/notification/ticket.png'),
+            'url'     => $this->url,
+        ];
+    }
 }

+ 11 - 0
app/Notifications/TicketReplied.php

@@ -58,4 +58,15 @@ class TicketReplied extends Notification implements ShouldQueue
     {
         return "📮工单回复提醒 #{$reply->ticket->id}\n———————————————\n主题:\n`{$reply->ticket->title}`\n内容:\n`{$reply->content}`";
     }
+
+    public function toBark($notifiable)
+    {
+        return [
+            'title'   => trans('notification.reply_ticket', ['title' => $this->reply->ticket->title]),
+            'content' => trans('notification.ticket_content').strip_tags($this->reply->content),
+            'group'   => '工单',
+            'icon'    => asset('assets/images/notification/ticket.png'),
+            'url'     => $this->url,
+        ];
+    }
 }

+ 32 - 0
database/migrations/2022_01_16_160308_add_msgid_notification_log.php

@@ -0,0 +1,32 @@
+<?php
+
+use Illuminate\Database\Migrations\Migration;
+use Illuminate\Database\Schema\Blueprint;
+use Illuminate\Support\Facades\Schema;
+
+class AddMsgidNotificationLog extends Migration
+{
+    /**
+     * Run the migrations.
+     *
+     * @return void
+     */
+    public function up()
+    {
+        Schema::table('notification_log', static function (Blueprint $table) {
+            $table->uuid('msg_id')->nullable()->comment('消息对公查询号')->after('id');
+        });
+    }
+
+    /**
+     * Reverse the migrations.
+     *
+     * @return void
+     */
+    public function down()
+    {
+        Schema::table('notification_log', static function (Blueprint $table) {
+            $table->dropColumn('msg_id');
+        });
+    }
+}

BIN=BIN
public/assets/images/notification/custom.png


BIN=BIN
public/assets/images/notification/offline.png


BIN=BIN
public/assets/images/notification/ticket.png


+ 1 - 1
resources/views/_layout.blade.php

@@ -14,7 +14,7 @@
           content="An account management Panel based on Laravel7 framework. Include multiple payment, account management, system caching, admin notification, products models, and more.">
     <meta name="keywords" content="ProxyPanel Laravel Shadowsocks ShadowsocksR V2Ray Trojan VNET VPN">
     <meta name="author" content="ZBrettonYe">
-    <meta name="copyright" content="2017-2021©ProxyPanel">
+    <meta name="copyright" content="2017-2022©ProxyPanel">
     <title>@yield('title')</title>
     <link href="{{asset('favicon.ico')}}" rel="shortcut icon apple-touch-icon">
     <!-- 样式表/Stylesheets -->

+ 44 - 0
resources/views/components/message.blade.php

@@ -0,0 +1,44 @@
+@extends('_layout')
+@section('title', sysConfig('website_name'))
+@section('body_class','page-login-v3 layout-full')
+@section('layout_css')
+    <style>
+        .layout-full {
+            margin-right: auto !important;
+            margin-left: auto !important;
+        }
+
+        table {
+            width: 100%
+        }
+
+        @media (min-width: 992px) {
+            .layout-full {
+                max-width: 75vw;
+            }
+        }
+
+        @media (min-width: 1200px) {
+            .layout-full {
+                max-width: 50vw;
+            }
+        }
+    </style>
+
+@endsection
+@section('layout_content')
+    <div class="page vertical-align" data-animsition-in="fade-in" data-animsition-out="fade-out">
+        <div class="page-content container vertical-align-middle">
+            <div class="panel panel-info">
+                <div class="panel-heading">
+                    <h3 class="panel-title">
+                        {{ $title }}
+                    </h3>
+                </div>
+                <div class="panel-body">
+                    {!! $content !!}
+                </div>
+            </div>
+        </div>
+    </div>
+@endsection

+ 0 - 1
resources/views/components/payment/detail.blade.php

@@ -88,7 +88,6 @@
                     </div>
                 </div>
             </div>
-
         </div>
     </div>
 @endsection

+ 56 - 20
resources/views/user/components/payment/manual.blade.php

@@ -10,12 +10,47 @@
             display: none;
         }
 
+        @media (max-width: 768px) {
+            #ad {
+                right: 1vw;
+                bottom: 20vh;
+            }
+
+            #ad img {
+                width: 40vw;
+            }
+        }
+
+        @media (min-width: 768px) {
+            #ad {
+                right: 3vw;
+                bottom: 15vh;
+            }
+
+            #ad img {
+                width: 30vw;
+            }
+        }
+
+        @media (min-width: 1200px) {
+            #ad {
+                right: 10vw;
+                bottom: 15vh;
+            }
+
+            #ad img {
+                width: 20vw;
+            }
+        }
+
         #ad {
             position: fixed;
             z-index: 9999;
-            right: 30px;
-            bottom: 30px;
-            margin-left: 535px;
+            margin-right: auto;
+        }
+
+        #ad img {
+            max-width: 300px;
         }
 
         #ad > button {
@@ -28,10 +63,8 @@
 
 @section('content')
     <div id="ad">
-        <button class="btn btn-icon btn-default" type="button" onclick="document.getElementById('ad').style.display = 'none'">
-            <i class="icon wb-close"></i>
-        </button>
-        <img src="{{asset('assets/images/help/作者要饭求放过.PNG')}}" class="w-lg-250 w-150" alt="">
+        <button class="btn btn-pure btn-outline-light icon wb-close" type="button" onclick="document.getElementById('ad').style.display = 'none'"></button>
+        <img src="{{asset('assets/images/help/作者要饭求放过.PNG')}}" alt="支付宝领红包">
     </div>
     <div class="page-content container">
         <div class="panel panel-bordered">
@@ -40,7 +73,10 @@
                     <i class="icon wb-payment"></i>{{sysConfig('website_name').' '.trans('common.payment.manual')}}
                 </h1>
             </div>
-            <div class="panel-body border-primary">
+            <div class="panel-body">
+                <div class="alert alert-info text-center">
+                    <p>扫完二维码,支付完成后。记得回来 点击👇【下一步】 直到 点击👇【{{trans('common.submit')}}】 才算正式支付完成呦!</p>
+                </div>
                 <div class="steps row w-p100">
                     <div class="step col-lg-4 current">
                         <span class="step-number">1</span>
@@ -59,7 +95,7 @@
                     <div class="step col-lg-4">
                         <span class="step-number">3</span>
                         <div class="step-desc">
-                            <span class="step-title">等待</span>
+                            <span class="step-title">完成</span>
                             <p>等待支付被确认</p>
                         </div>
                     </div>
@@ -120,7 +156,7 @@
                     <div class="alert alert-danger text-center">
                         支付时,请充值正确金额(多不退,少要补)
                     </div>
-                    <div class="mx-auto w-md-p50">
+                    <div class="mx-auto w-md-p50 w-lg-p25">
                         <ul class="list-group list-group-dividered">
                             <li class="list-group-item">{{trans('user.shop.service').':'.$name}}</li>
                             <li class="list-group-item">{{trans('user.shop.price').':¥'.$payment->amount}}</li>
@@ -133,7 +169,7 @@
 
                 <div class="clearfix">
                     <button type="button" class="btn btn-lg btn-default float-left" id="prevBtn" onclick="nextPrev(-1)">上一步</button>
-                    <button type="button" class="btn btn-lg btn-default float-right" id="nextBtn" onclick="nextPrev(1)">下一步</button>
+                    <button type="button" class="btn btn-lg btn-primary float-right" id="nextBtn" onclick="nextPrev(1)">下一步</button>
                 </div>
             </div>
         </div>
@@ -159,12 +195,14 @@
 
             if (n === x.length - 1) {
                 document.getElementById('payment-group').style.display = 'none';
-                document.getElementById('nextBtn').classList.remove('btn-default');
-                document.getElementById('nextBtn').classList.add('btn-primary');
-                document.getElementById('nextBtn').innerHTML = '{{trans('user.status.completed')}}';
+                document.getElementById('nextBtn').classList.remove('btn-primary');
+                document.getElementById('nextBtn').classList.add('btn-success');
+                document.getElementById('nextBtn').innerHTML = '{{trans('common.submit')}}';
             } else {
                 document.getElementById('payment-group').style.display = 'inline-flex';
                 document.getElementById('nextBtn').innerHTML = '下一步';
+                document.getElementById('nextBtn').classList.remove('btn-success');
+                document.getElementById('nextBtn').classList.add('btn-primary');
                 document.getElementById('nextBtn').style.display = 'inline';
             }
 
@@ -174,10 +212,8 @@
         function nextPrev(n) {
             // This function will figure out which tab to display
             const x = document.getElementsByClassName('tab');
-            // Hide the current tab:
-            x[currentTab].style.display = 'none';
             // if you have reached the end of the form... :
-            if (currentTab === x.length - 1) {
+            if (currentTab === x.length - 1 && n === 1) {
                 //...the form gets submitted:
                 $.post('{{route('manual.inform', ['payment' => $payment->trade_no])}}', {_token: '{{csrf_token()}}'}, function(ret) {
                     if (ret.status === 'success') {
@@ -188,11 +224,11 @@
                 });
                 return false;
             } else {
-                // Increase or decrease the current tab by 1:
-                currentTab += n;
-                showTab(currentTab);
+                x[currentTab].style.display = 'none';// Hide the current tab:
+                currentTab += n;// Increase or decrease the current tab by 1:
             }
 
+            showTab(currentTab);
         }
 
         function fixStepIndicator(n) {

+ 12 - 16
resources/views/user/help.blade.php

@@ -198,25 +198,21 @@
                                         <div class="panel-collapse collapse show" id="answer-5"
                                              aria-labelledby="question-5" role="tabpanel">
                                             <div class="panel-body">
+                                                <h4>方法一</h4>
+                                                <p>电脑有安装任何电脑管家类的软件,都可以使用他们自带的网络修复工具来重置网络。</p>
+                                                <h4>方法二</h4>
                                                 <ol>
                                                     <li>
-                                                        电脑有安装任何电脑管家类的软件,都可以使用他们自带的网络修复工具来重置网络。
+                                                        键盘操作<code>Win</code> + <code>X</code>,或右击左下角开始菜单键
+                                                        (Win键看起来像 <i class="fab fa-windows" aria-hidden="true"></i> 这样)
                                                     </li>
                                                     <li>
-                                                        <ol>
-                                                            <li>
-                                                                键盘操作<code>Win</code> + <code>X</code>,或右击左下角开始菜单键
-                                                                (Win键看起来像 <i class="fab fa-windows" aria-hidden="true"></i> 这样)
-                                                            </li>
-                                                            <li>
-                                                                按下 <code>A</code>键 或者 手动选择
-                                                                <code>命令提示符(管理员)/ Windows PowerShell(管理员)</code>
-                                                            </li>
-                                                            <li>
-                                                                输入<code>Netsh winsock reset</code> 后回车,再输入
-                                                                <code>netsh advfirewall reset</code> 后回车;
-                                                            </li>
-                                                        </ol>
+                                                        按下 <code>A</code>键 或者 手动选择
+                                                        <code>命令提示符(管理员)/ Windows PowerShell(管理员)</code>
+                                                    </li>
+                                                    <li>
+                                                        输入<code>Netsh winsock reset</code> 后回车,再输入
+                                                        <code>netsh advfirewall reset</code> 后回车;
                                                     </li>
                                                 </ol>
                                             </div>
@@ -237,7 +233,7 @@
                                                 账号在2种情况下会显示禁用;
                                                 <ol>
                                                     <li>
-                                                        套餐过期/流量枯竭;此情况您需要重新
+                                                        套餐过期/流量枯竭;此情况您需要重新购买/重置
                                                         <a href="{{route('shop')}}">【{{trans('user.menu.shop')}}】</a>;
                                                     </li>
                                                     <li>

+ 1 - 1
resources/views/user/layouts.blade.php

@@ -181,7 +181,7 @@
     </div>
     <footer class="site-footer">
         <div class="site-footer-legal">
-            © 2017 - 2021 <a href="https://github.com/ProxyPanel/ProxyPanel" target="_blank">{{config('version.name')}} {{__('All rights reserved.')}}</a>
+            © 2017 - 2022 <a href="https://github.com/ProxyPanel/ProxyPanel" target="_blank">{{config('version.name')}} {{__('All rights reserved.')}}</a>
             🚀 Version: <code> {{config('version.number')}} </code>
         </div>
         <div class="site-footer-right">

+ 2 - 2
resources/views/vendor/log-viewer/remark/layouts.blade.php

@@ -194,9 +194,9 @@
             @yield('content')
         </div>
     </div>
-    <footer class="site-footer">
+    <footer class="site-footer ml-0">
         <div class="site-footer-legal">
-            © 2017 - 2021 <a href="https://github.com/ProxyPanel/ProxyPanel" target="_blank">{{config('version.name')}} </a> {{__('All rights reserved
+            © 2017 - 2022 <a href="https://github.com/ProxyPanel/ProxyPanel" target="_blank">{{config('version.name')}} </a> {{__('All rights reserved
             .')}}
         </div>
         <div class="site-footer-right">

+ 0 - 1
routes/user.php

@@ -38,6 +38,5 @@ Route::prefix('payment')->group(function () {
 Route::prefix('pay')->group(function () {
     Route::get('/manual/{payment}', 'Gateway\Manual@redirectPage')->name('manual.checkout'); // 人工支付详细
     Route::post('/manual/{payment}/inform', 'Gateway\Manual@inform')->name('manual.inform'); // 人工支付通知
-
     Route::get('/stripe/{session_id}', 'Gateway\Stripe@redirectPage')->name('stripe.checkout'); // Stripe Checkout page
 });

+ 1 - 0
routes/web.php

@@ -11,6 +11,7 @@ if (config('app.key') && config('settings')) {
 Route::get('callback/checkout', 'Gateway\PayPal@getCheckout')->name('paypal.checkout'); // 支付回调相关
 Route::post('api/telegram/webhook', 'TelegramController@webhook')->middleware('telegram'); // Telegram fallback
 Route::get('api/wechat/verify', '\App\Channels\WeChatChannel@verify')->name('wechat.verify'); // 微信回调验证
+Route::get('/message/{type}/{msg_id}/show', 'MessageController@index')->name('message.show'); // 微信回调验证
 
 // 登录相关
 Route::middleware(['isForbidden', 'affiliate', 'isMaintenance'])->group(function () {