Laravel Vuejs 实战:开发知乎 (37-41)私信标为已读

1.自定义MessageCollection类:

  1 <?php
  2 
  3 namespace App;
  4 
  5 use Illuminate\Database\Eloquent\Collection;
  6 
  7 class MessageCollection extends Collection
  8 {
  9     public function markAsRead()
 10     {
 11         $this->each(function ($message) {
 12             $message->markAsRead();
 13         });
 14     }
 15 }
 16 
 17 
MessageCollection.php

2.向Message中添加一个newCollection方法:

  1 public function newCollection(array $models = [])
  2 {
  3     return new MessageCollection($models);
  4 }
  5 

及markAsRead方法:

  1 public function markAsRead()
  2 {
  3     if (is_null($this->read_at)) {
  4         $this->forceFill(
  5             [
  6                 'read_at' => $this->freshTimestamp(),
  7             ])->save();
  8     }
  9 }
 10 
  1 <?php
  2 
  3 namespace App;
  4 
  5 use Illuminate\Database\Eloquent\Model;
  6 
  7 class Message extends Model
  8 {
  9     //
 10 
 11     protected $table = 'messages';
 12 
 13     protected $fillable = ['from_user_id', 'to_user_id', 'content'];
 14 
 15     public function fromUser()
 16     {
 17         return $this->belongsTo(User::class, 'from_user_id');
 18     }
 19 
 20     public function toUser()
 21     {
 22         return $this->belongsTo(User::class, 'to_user_id');
 23     }
 24 
 25     public function markAsRead()
 26     {
 27         if (is_null($this->read_at)) {
 28             $this->forceFill(
 29                 [
 30                     'read_at' => $this->freshTimestamp(),
 31                 ])->save();
 32         }
 33     }
 34 
 35     public function newCollection(array $models = [])
 36     {
 37         return new MessageCollection($models);
 38     }
 39 }
 40 
 41 
Message.php


3.这样在InboxCollection.php中调用的时候:

  1 //设置信息已读
  2 $messages->markAsRead();
  3 

即:

  1 public function show($userId)
  2 {
  3     if (auth()->user()->id == $userId) {
  4         return redirect()->back()->with('不能回复自己');
  5     }
  6     $messages = auth()->user()->messages->where('from_user_id', $userId);
  7 
  8     //设置信息已读
  9     $messages->markAsRead();
 10 
 11     //获取回复信息
 12     $replies = Message::query()->where('to_user_id', $userId)
 13         ->where('from_user_id', auth()->user()->id)
 14         ->get();
 15     if ($replies) {
 16         //整合
 17         foreach ($replies as $reply) {
 18             $messages->push($reply);
 19         }
 20     }
 21     //排序
 22     $messages = $messages->sortBy('created_at');
 23     return view('inbox.show', compact('messages'));
 24 }
 25 


4.显示视图:

  1 @extends('layouts.app')
  2 @section('content')
  3     <div class="container">
  4         <div class="row">
  5             <div class="card">
  6                 @if($messages->first())
  7                     <div class="card-header">
  8                         <a href="#">
  9 
 10                             <img src="{{ $messages->first()->fromUser->avatar }}"
 11                                  alt="{{ $messages->first()->fromUser->name }}"
 12                                  class="img-thumbnail img-fluid card-img" style="height: 30px;width: 30px">
 13                             {{ $messages->first()->fromUser->name }}
 14 
 15                         </a>
 16                     </div>
 17                     <div class="card-body">
 18                         <div class="messaging">
 19                             <div class="inbox_msg">
 20 
 21                                 <div class="mesgs">
 22                                     <div class="msg_history">
 23                                         @forelse($messages as $message)
 24                                             @if($message->fromUser->id===auth()->user()->id)
 25                                                 <div class="outgoing_msg">
 26                                                     <div class="sent_msg">
 27                                                         @if($message->read_at)
 28                                                             <span class="text-black-50">已读</span>
 29                                                         @endif
 30                                                         <p> {{$message->content}}</p>
 31                                                         <span
 32                                                             class="time_date"> {{$message->created_at->diffForHumans()}}</span>
 33                                                     </div>
 34                                                 </div>
 35                                             @else
 36                                                 <div class="incoming_msg">
 37                                                     <div class="incoming_msg_img"><img
 38                                                             src="{{ $messages->first()->fromUser->avatar }}"
 39                                                             alt="{{ $messages->first()->fromUser->name }}">
 40                                                     </div>
 41                                                     <div class="received_msg">
 42                                                         <div class="received_withd_msg">
 43                                                             <p> {{$message->content}}</p>
 44                                                             <span
 45                                                                 class="time_date">  {{$message->created_at->diffForHumans()}}</span>
 46                                                         </div>
 47                                                     </div>
 48                                                 </div>
 49                                             @endif
 50                                         @empty
 51                                         @endforelse
 52                                     </div>
 53                                 </div>
 54                             </div>
 55                         </div>
 56                         <div class="type_msg mt-2">
 57                             <div class="input_msg_write">
 58                                 <form
 59                                     action="{{ route('inbox.store',($message->fromUser->id===auth()->user()->id)?$message->toUser->id:$message->fromUser->id) }}"
 60                                     method="post">
 61                                     @csrf
 62                                     <input type="text" class="write_msg" name="content" placeholder="输入信息回复"/>
 63                                     <button class="msg_send_btn" type="submit">
 64                                         <i class="fa fa-paper-plane-o"
 65                                            aria-hidden="true"></i>
 66                                     </button>
 67                                 </form>
 68                             </div>
 69                         </div>
 70                     </div>
 71                 @else
 72                     <div class="card-header">不好意思!找不到你要的数据!</div>
 73                 @endif
 74             </div>
 75         </div>
 76     </div>
 77 @endsection
 78 <style>
 79     .container {
 80         margin: auto;
 81     }
 82 
 83     img {
 84         max-width: 100%;
 85     }
 86 
 87     .inbox_people {
 88         background: #f8f8f8 none repeat scroll 0 0;
 89         float: left;
 90         overflow: hidden;
 91         width: 40%;
 92         border-right: 1px solid #c4c4c4;
 93     }
 94 
 95     .inbox_msg {
 96         border: 1px solid #c4c4c4;
 97         clear: both;
 98         overflow: hidden;
 99     }
100 
101     .top_spac {
102         margin: 20px 0 0;
103     }
104 
105     .recent_heading {
106         float: left;
107         width: 40%;
108     }
109 
110     .srch_bar {
111         display: inline-block;
112         text-align: right;
113         width: 60%;
114     }
115 
116     .recent_heading h4 {
117         color: #05728f;
118         font-size: 21px;
119         margin: auto;
120     }
121 
122     .srch_bar input {
123         border: 1px solid #cdcdcd;
124         border-width: 0 0 1px 0;
125         width: 80%;
126         padding: 2px 0 4px 6px;
127         background: none;
128     }
129 
130     .srch_bar .input-group-addon button {
131         background: rgba(0, 0, 0, 0) none repeat scroll 0 0;
132         border: medium none;
133         padding: 0;
134         color: #707070;
135         font-size: 18px;
136     }
137 
138     .srch_bar .input-group-addon {
139         margin: 0 0 0 -27px;
140     }
141 
142     .chat_ib h5 {
143         font-size: 15px;
144         color: #464646;
145         margin: 0 0 8px 0;
146     }
147 
148     .chat_ib h5 span {
149         font-size: 13px;
150         float: right;
151     }
152 
153     .chat_ib p {
154         font-size: 14px;
155         color: #989898;
156         margin: auto
157     }
158 
159     .chat_img {
160         float: left;
161         width: 11%;
162     }
163 
164     .chat_ib {
165         float: left;
166         padding: 0 0 0 15px;
167         width: 88%;
168     }
169 
170     .chat_people {
171         overflow: hidden;
172         clear: both;
173     }
174 
175     .chat_list {
176         border-bottom: 1px solid #c4c4c4;
177         margin: 0;
178         padding: 18px 16px 10px;
179     }
180 
181     .inbox_chat {
182         height: 550px;
183         overflow-y: scroll;
184     }
185 
186     .active_chat {
187         background: #ebebeb;
188     }
189 
190     .incoming_msg_img {
191         display: inline-block;
192         width: 6%;
193     }
194 
195     .received_msg {
196         display: inline-block;
197         padding: 0 0 0 10px;
198         vertical-align: top;
199         width: 92%;
200     }
201 
202     .received_withd_msg p {
203         background: #ebebeb none repeat scroll 0 0;
204         border-radius: 3px;
205         color: #646464;
206         font-size: 14px;
207         margin: 0;
208         padding: 5px 10px 5px 12px;
209         width: 100%;
210     }
211 
212     .time_date {
213         color: #747474;
214         display: block;
215         font-size: 12px;
216         margin: 8px 0 0;
217     }
218 
219     .received_withd_msg {
220         width: 57%;
221     }
222 
223     .mesgs {
224         float: left;
225         padding: 30px 15px 0 25px;
226         width: 60%;
227     }
228 
229     .sent_msg p {
230         background: #05728f none repeat scroll 0 0;
231         border-radius: 3px;
232         font-size: 14px;
233         margin: 0;
234         color: #fff;
235         padding: 5px 10px 5px 12px;
236         width: 100%;
237     }
238 
239     .outgoing_msg {
240         overflow: hidden;
241         margin: 26px 0 26px;
242     }
243 
244     .sent_msg {
245         float: right;
246         width: 46%;
247     }
248 
249     .input_msg_write input {
250         background: rgba(0, 0, 0, 0) none repeat scroll 0 0;
251         border: medium none;
252         color: #4c4c4c;
253         font-size: 15px;
254         min-height: 48px;
255         width: 100%;
256     }
257 
258     .type_msg {
259         border-top: 1px solid #c4c4c4;
260         position: relative;
261     }
262 
263     .msg_send_btn {
264         background: #05728f none repeat scroll 0 0;
265         border: medium none;
266         border-radius: 50%;
267         color: #fff;
268         cursor: pointer;
269         font-size: 17px;
270         height: 33px;
271         position: absolute;
272         right: 0;
273         top: 11px;
274         width: 33px;
275     }
276 
277     .msg_history {
278         height: 516px;
279         overflow-y: auto;
280     }
281 </style>
282 
283 
show.blade.php

效果:

批注 2020-03-04 134815

5.添加新的未读消息加特效:

当前状态:

批注 2020-03-04 135048

代码:

  1 @extends('layouts.app')
  2 @section('content')
  3     <div class="container">
  4         <div class="row">
  5             <div class="card">
  6                 <div class="card-header">
  7                     @if($messages->filter(function ($value, $key){
  8                         return $value->where('read_at',null)->count()>0;})->count()>0)
  9                         <div class="alert alert-danger">
 10                             你有新的消息!
 11                         </div>
 12                     @endif
 13                 </div>
 14                 <div class="card-body">
 15 
 16                     @forelse($messages as $messageGroup)
 17                         <div class="card">
 18                             <div class="card-header">
 19                                 <a href="#">
 20                                     <img src="{{ $messageGroup->first()->fromUser->avatar }}"
 21                                          alt="{{ $messageGroup->first()->fromUser->name }}"
 22                                          class="img-thumbnail img-fluid card-img" style="height: 30px;width: 30px">
 23                                     {{ $messageGroup->first()->fromUser->name }}
 24                                 </a>
 25                             </div>
 26                             <div class="card-body">
 27                                 <p class="text-success "> 查看详细对话请点击:</p>
 28                                 @if($messageGroup->where('read_at',null)->count()>0)
 29                                     <p class="alert alert-warning">{{$messageGroup->where('read_at',null)->count()}}
 30                                         条未读消息</p>
 31                                 @endif
 32                                 <a href=" {{ route('inbox.show', $messageGroup->first()->fromUser->id) }}"
 33                                    class="btn btn-block bg-light"> {{ $messageGroup->first()->content }}</a>
 34                             </div>
 35                         </div>
 36                     @empty
 37                     @endforelse
 38                 </div>
 39             </div>
 40         </div>
 41     </div>
 42 @endsection
 43 
 44 
index.blade.php


修改后:

批注 2020-03-04 140701批注 2020-03-04 140758批注 2020-03-04 140919

修复 bug 和实现 Repository 模式:

我的代码没有那个bug。其次我这不实现Repository 模式


6.实现私信通知:

当用户收到新的私信的时候,发送一个通知告知用户。

执行:

  1 php artisan make:notification NewMessageNotification

代码:

暂时只实现站内通知,

  1 <?php
  2 
  3 namespace App\Notifications;
  4 
  5 use App\Message;
  6 use Illuminate\Bus\Queueable;
  7 use Illuminate\Contracts\Queue\ShouldQueue;
  8 use Illuminate\Notifications\Messages\MailMessage;
  9 use Illuminate\Notifications\Notification;
 10 
 11 class NewMessageNotification extends Notification
 12 {
 13     use Queueable;
 14     /**
 15      * @var Message
 16      */
 17     private $message;
 18 
 19     /**
 20      * Create a new notification instance.
 21      *
 22      * @return void
 23      */
 24     public function __construct(Message $message)//使用依赖注入
 25     {
 26         //
 27         $this->message = $message;
 28     }
 29 
 30     /**
 31      * Get the notification's delivery channels.
 32      *
 33      * @param mixed $notifiable
 34      * @return array
 35      */
 36     public function via($notifiable)
 37     {
 38         return ['database'];
 39     }
 40 
 41     /**
 42      * Get the mail representation of the notification.
 43      *
 44      * @param mixed $notifiable
 45      * @return \Illuminate\Notifications\Messages\MailMessage
 46      */
 47     public function toMail($notifiable)
 48     {
 49         return (new MailMessage)
 50             ->line('The introduction to the notification.')
 51             ->action('Notification Action', url('/'))
 52             ->line('Thank you for using our application!');
 53     }
 54 
 55     /**
 56      * Get the array representation of the notification.
 57      *
 58      * @param mixed $notifiable
 59      * @return array
 60      */
 61     public function toArray($notifiable)
 62     {
 63         return [
 64             //
 65         ];
 66     }
 67 
 68 
 69     /**
 70      * @param $notifiable
 71      * @return array
 72      */
 73     public function toDatabase($notifiable)
 74     {
 75         //要记录的数据
 76         return [
 77             'fromUser' => $this->message->fromUser->name,
 78             'id' => $this->message->fromUser->id,
 79             'content' => $this->message->content,
 80         ];
 81     }
 82 }
 83 
 84 
NewMessageNotification.php

添加:

  1 //发送通知
  2 $message
  3     ->toUser //通知接受方,所以是toUser
  4     ->notify(new NewMessageNotification($message));//用户类使用了Notifiable这个 trait
  5 
到:
  1 <?php
  2 
  3 namespace App\Http\Controllers;
  4 
  5 use App\Message;
  6 
  7 use App\Notifications\NewMessageNotification;
  8 use Illuminate\Http\Request;
  9 use Illuminate\Support\Facades\Notification;
 10 
 11 
 12 class InboxController extends Controller
 13 {
 14     public function __construct()
 15     {
 16         $this->middleware('auth');
 17     }
 18 
 19     //
 20     public function index()
 21     {
 22         $messages = auth()->user()->messages->groupBy('from_user_id');
 23 //        $messages->map(function ($message) {
 24 //            return $message->map(function ($item) {
 25 ////                return $item->with('user');
 26 //                return $item->fromUser;
 27 //            });
 28 //        });
 29         return view('inbox.index', compact('messages'));
 30     }
 31 
 32     public function show($userId)
 33     {
 34         if (auth()->user()->id == $userId) {
 35             return redirect()->back()->with('不能回复自己');
 36         }
 37         $messages = auth()->user()->messages->where('from_user_id', $userId);
 38 
 39         //设置信息已读
 40         $messages->markAsRead();
 41 
 42         //获取回复信息
 43         $replies = Message::query()->where('to_user_id', $userId)
 44             ->where('from_user_id', auth()->user()->id)
 45             ->get();
 46         if ($replies) {
 47             //整合
 48             foreach ($replies as $reply) {
 49                 $messages->push($reply);
 50             }
 51         }
 52         //排序
 53         $messages = $messages->sortBy('created_at');
 54         return view('inbox.show', compact('messages'));
 55     }
 56 
 57     public function store(Request $request, $userId)
 58     {
 59 
 60         if (auth()->user()->id == $userId) {
 61             return redirect()->back()->with('不能回复自己');
 62         }
 63         $message = Message::create(
 64             [
 65                 'from_user_id' => auth()->user()->id,
 66                 'to_user_id' => $userId,
 67                 'content' => $request->get('content')
 68             ]
 69         );
 70 
 71         //发送通知
 72         $message
 73             ->toUser //通知接受方,所以是toUser
 74             ->notify(new NewMessageNotification($message));//用户类使用了Notifiable这个 trait
 75 
 76         return redirect()->route('inbox.show', $userId)->with('success', '发送成功');
 77     }
 78 }
 79 
 80 
InboxController

view添加:

new_message_notification.blade.php:

  1 <li class="badge badge-light text-primary">
  2     <p> "你好!"
  3         <a href="{{ route('inbox.show',$notification->data['id']) }}">
  4             {{ $notification->data['fromUser']."给你发来了新私信:" }}
  5         </a>
  6     </p>
  7     <p>  {{ $notification->data['content'] }} </p>
  8 </li>
  9 
 10 

7.设置通知已读:

  1 <?php
  2 
  3 namespace App\Http\Controllers;
  4 
  5 use App\User;
  6 use Illuminate\Http\Request;
  7 
  8 class NotificationController extends Controller
  9 {
 10     //
 11     public function index()
 12     {
 13         $user = auth()->user();
 14 
 15         //设置已读字段数据
 16         $user->notifications->map(function ($notification) {
 17             $notification->forceFill([
 18                 'read_at' => now(),
 19             ])->save();
 20         });
 21         return view('notifications.index', compact('user'));
 22     }
 23 }
 24 
 25 
NotificationController.php


视图:略

posted @ 2020-03-04 13:47  dzkjz  阅读(431)  评论(0编辑  收藏  举报