本文目录导读:

在Laravel中设计邮件通知视图时,需要兼顾美观、功能性和跨客户端兼容性,以下是系统化的设计指南和最佳实践:
项目结构规划
resources/views/emails/
├── layouts/
│ ├── default.blade.php # 主布局
│ └── notification.blade.php # 通知特定布局
├── notifications/
│ ├── order-confirmation.blade.php
│ ├── password-reset.blade.php
│ └── welcome.blade.php
├── partials/
│ ├── header.blade.php
│ ├── footer.blade.php
│ └── button.blade.php
└── components/
└── alert.blade.php
基础布局设计
主布局 (layouts/default.blade.php)
@php
$appName = config('app.name');
$primaryColor = '#3490dc';
@endphp
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta http-equiv="X-UA-Compatible" content="IE=edge">{{ $title ?? $appName }}</title>
<style>
/* 响应式设计 */
@media only screen and (max-width: 600px) {
.container { width: 100% !important; padding: 0 20px !important; }
.header { padding: 20px 15px !important; }
.content { padding: 30px 20px !important; }
.button { display: block !important; width: 100% !important; }
}
/* 主题变量 */
:root {
--primary-color: {{ $primaryColor }};
--text-primary: #333333;
--text-secondary: #666666;
--background: #f8f9fa;
--border: #e9ecef;
}
body {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Arial, sans-serif;
background-color: var(--background);
color: var(--text-primary);
margin: 0;
padding: 0;
-webkit-font-smoothing: antialiased;
}
/* 容器 */
.container {
max-width: 600px;
margin: 0 auto;
background-color: #ffffff;
border-radius: 8px;
overflow: hidden;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
/* 头部 */
.header {
background-color: var(--primary-color);
padding: 30px 40px;
text-align: center;
}
.header img {
max-width: 150px;
max-height: 60px;
object-fit: contain;
}
.header h1 {
color: #ffffff;
font-size: 24px;
margin: 0;
font-weight: 600;
}
/* 内容区域 */
.content {
padding: 40px;
line-height: 1.6;
}
h2 {
color: var(--text-primary);
font-size: 20px;
margin-bottom: 20px;
}
p {
margin: 0 0 15px;
color: var(--text-secondary);
font-size: 16px;
}
/* 按钮样式 */
.button {
display: inline-block;
background-color: var(--primary-color);
color: #ffffff !important;
text-decoration: none;
padding: 12px 30px;
border-radius: 4px;
font-weight: 500;
margin: 20px 0;
text-align: center;
font-size: 16px;
transition: opacity 0.3s;
}
.button:hover {
opacity: 0.9;
}
/* 事件块 */
.event-details {
background-color: var(--background);
border-left: 4px solid var(--primary-color);
padding: 20px;
margin: 20px 0;
border-radius: 4px;
}
.event-details h3 {
margin: 0 0 10px;
font-size: 18px;
color: var(--text-primary);
}
.event-details p {
margin: 5px 0;
font-size: 14px;
}
/* 表格样式 */
.table {
width: 100%;
border-collapse: collapse;
margin: 20px 0;
}
.table th, .table td {
padding: 12px;
border: 1px solid var(--border);
text-align: left;
}
.table th {
background-color: var(--background);
font-weight: 600;
}
/* 警告框 */
.alert {
padding: 15px 20px;
border-radius: 4px;
margin: 20px 0;
font-size: 14px;
}
.alert-danger {
background-color: #f8d7da;
border: 1px solid #f5c6cb;
color: #721c24;
}
.alert-success {
background-color: #d4edda;
border: 1px solid #c3e6cb;
color: #155724;
}
/* 页脚 */
.footer {
padding: 20px 40px;
text-align: center;
background-color: #f8f9fa;
border-top: 1px solid var(--border);
font-size: 13px;
color: #999;
}
.footer a {
color: #666;
text-decoration: none;
}
.footer a:hover {
color: var(--primary-color);
}
</style>
</head>
<body>
<table width="100%" cellpadding="0" cellspacing="0" border="0">
<tr>
<td align="center" style="padding: 40px 20px;">
<table class="container" cellpadding="0" cellspacing="0" border="0">
<tr>
<td class="header">
@include('emails.partials.header')
</td>
</tr>
<tr>
<td class="content">
{{ $slot }}
</td>
</tr>
<tr>
<td class="footer">
@include('emails.partials.footer')
</td>
</tr>
</table>
</td>
</tr>
</table>
</body>
</html>
通知视图示例
订单确认通知 (order-confirmation.blade.php)
@component('emails.layouts.notification', [ => '订单确认',
'user' => $user
])
<h2>感谢您的购买,{{ $user->name }}!</h2>
<p>您的订单已成功确认,以下是您的订单详情:</p>
<div class="event-details">
<h3>订单 #{{ $order->id }}</h3>
<p><strong>订单日期:</strong>{{ $order->created_at->format('Y-m-d H:i') }}</p>
<p><strong>支付方式:</strong>{{ $order->payment_method }}</p>
<p><strong>预计送达:</strong>{{ $order->expected_delivery_date }}</p>
</div>
<h3 style="margin-top: 30px;">商品清单</h3>
<table class="table">
<thead>
<tr>
<th>商品</th>
<th>数量</th>
<th>价格</th>
<th>小计</th>
</tr>
</thead>
<tbody>
@foreach($order->items as $item)
<tr>
<td>{{ $item->product_name }}</td>
<td>{{ $item->quantity }}</td>
<td>{{ number_format($item->price, 2, ',', '.') }} 元</td>
<td>{{ number_format($item->quantity * $item->price, 2, ',', '.') }} 元</td>
</tr>
@endforeach
</tbody>
<tfoot>
<tr>
<td colspan="3" style="text-align: right;"><strong>总计:</strong></td>
<td><strong>{{ number_format($order->total, 2, ',', '.') }} 元</strong></td>
</tr>
</tfoot>
</table>
<div style="text-align: center; margin-top: 30px;">
<a href="{{ url('/order/'.$order->id) }}" class="button">查看订单详情</a>
</div>
<p style="margin-top: 30px; font-size: 14px; color: #999;">
如对订单有任何疑问,请在 30 天内联系客服 <a href="mailto:{{ config('mail.support_email') }}">{{ config('mail.support_email') }}</a>
</p>
@endcomponent
响应式按钮组件
{{-- resources/views/emails/components/button.blade.php --}}
@props([
'url' => '#',
'color' => '#3490dc',
'width' => 'auto'
])
<table role="presentation" cellpadding="0" cellspacing="0" style="margin: 20px 0;">
<tr>
<td style="border-radius: 4px; background-color: {{ $color }}; padding: 12px 30px;">
<a href="{{ $url }}" style="color: #ffffff; text-decoration: none; display: inline-block; font-size: 16px;">
{{ $slot }}
</a>
</td>
</tr>
</table>
使用Laravel Mail类
<?php
namespace App\Mail;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Notifications\Notification;
class OrderConfirmationMail extends Mailable
{
use Queueable, SerializesModels;
public $order;
public $user;
public function __construct($order, $user)
{
$this->order = $order;
$this->user = $user;
}
public function build()
{
return $this->from(config('mail.from.address'), config('mail.from.name'))
->subject('订单确认')
->view('emails.notifications.order-confirmation')
->with([
'order' => $this->order,
'user' => $this->user,
'title' => '订单已确认'
]);
}
}
使用通知系统
<?php
namespace App\Notifications;
use Illuminate\Bus\Queueable;
use Illuminate\Notifications\Notification;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Notifications\Messages\MailMessage;
class OrderShipped extends Notification implements ShouldQueue
{
use Queueable;
protected $order;
public function __construct($order)
{
$this->order = $order;
}
public function via($notifiable)
{
return ['mail'];
}
public function toMail($notifiable)
{
return (new MailMessage)
->subject('您的订单已发货')
->greeting('您好,' . $notifiable->name . '!')
->line('您的订单已发货,正在运输途中。')
->line('订单号:' . $this->order->tracking_number)
->action('追踪订单', url('/track-order/' . $this->order->tracking_number))
->line('感谢您选择我们的服务!')
->view('emails.notifications.custom-view', [
'order' => $this->order,
'user' => $notifiable
]);
}
}
最佳实践
响应式设计检查清单
- 使用
table布局确保Outlook兼容 - 设置
max-width保证移动端显示 - 确保按钮在移动端全宽显示
- 使用
@media查询处理小屏适配
性能优化
- 避免使用过大的图片
- 使用CSS内联样式(可借助CSS inliner工具)
- 将邮件通知加入队列处理
测试建议
Mail::fake();
Mail::assertSent(OrderConfirmationMail::class, function ($mail) {
return $mail->hasTo('test@example.com');
});
个性化模板变量
@foreach($items as $item)
<tr>
<td>{{ $item->name }}</td>
<td>{{ $item->price }}</td>
</tr>
@endforeach
@if($hasDiscount)
<div class="alert alert-success">
您获得了 {{ $discount }} 元折扣!
</div>
@endif
@isset($referral)
<p>您的邀请码:{{ $referral->code }}</p>
@endisset
这种设计确保了邮件在各种设备和客户端上的良好表现,同时保持代码的可维护性和可复用性,根据项目需求,可以进一步定制样式和组件。