Ver Fonte

[SAAS] 智价云采集清洗情况通知补充

tangyuanwang há 1 mês atrás
pai
commit
6d6fae39bd

+ 1 - 0
app/Http/Middleware/Manager/AccessAuth.php

@@ -27,6 +27,7 @@ class AccessAuth
         'manager/personnel_employee/personal_info',
         'manager/login/wechat_bind',
         'manager/citys/list_zoning',
+        'manager/statistics/product_surveillance/push_data_notice'
     ];
     //默认配置
     protected   $_config    = [

+ 56 - 184
app/Jobs/Manager/CollectData/Statistics/ProductSurveillanceJobs.php

@@ -33,7 +33,8 @@ class ProductSurveillanceJobs implements ShouldQueue
     public $tries = 3; // 限制重试次数
     public $timeout = 600; // 10分钟超时
 
-    protected  $message_data;
+    protected $message_data;
+    
     /**
      * Create a new job instance.
      *
@@ -214,9 +215,11 @@ class ProductSurveillanceJobs implements ShouldQueue
                 $config_violation_product_content,
                 $cleaned_violation_product_content,
                 $config_violation_store_content,
-                $cleaned_violation_store_content
+                $cleaned_violation_store_content,
+                $start_time_string,
+                $end_time_string
             );
-            // echo $email_content_html; exit;
+            // echo $email_content_html;exit;
             //发送预警通知
             foreach ($email_notice_list as $email_notice) {
                 $message_data = [
@@ -227,16 +230,12 @@ class ProductSurveillanceJobs implements ShouldQueue
             }
             //记录日志
         } catch (\Exception $e) {
-            print_r($e->getMessage());
-            exit;
             Log::info('job_error', '低价商品数据数据-监控采集清洗情况队列失败', ['data' => $this->message_data, 'error' => $e->getMessage()]);
         }
     }
 
-
-
     /**
-     * 构建美观的邮件HTML内容
+     * 构建美观的邮件HTML内容(内联样式版本)
      */
     private function buildEmailHtml(
         $config_collect,
@@ -246,182 +245,76 @@ class ProductSurveillanceJobs implements ShouldQueue
         $config_violation_product,
         $cleaned_violation_product,
         $config_violation_store,
-        $cleaned_violation_store
+        $cleaned_violation_store,
+        $start_time_string,
+        $end_time_string
     ) {
         $html = '
-    <!DOCTYPE html>
-    <html>
-    <head>
-        <meta charset="UTF-8">
-        <style>
-            body {
-                font-family: "Microsoft YaHei", Arial, sans-serif;
-                background-color: #f5f7fa;
-                margin: 0;
-                padding: 20px;
-            }
-            .email-container {
-                max-width: 800px;
-                margin: 0 auto;
-                background-color: #ffffff;
-                border-radius: 12px;
-                overflow: hidden;
-                box-shadow: 0 2px 12px rgba(0,0,0,0.1);
-            }
-            .email-header {
-                background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
-                color: white;
-                padding: 30px 20px;
-                text-align: center;
-            }
-            .email-header h1 {
-                margin: 0;
-                font-size: 24px;
-                font-weight: 600;
-            }
-            .email-header p {
-                margin: 10px 0 0;
-                opacity: 0.9;
-                font-size: 14px;
-            }
-            .email-body {
-                padding: 30px 25px;
-            }
-            .section {
-                margin-bottom: 25px;
-                border-left: 4px solid;
-                padding: 12px 20px;
-                background-color: #f8f9fc;
-                border-radius: 8px;
-            }
-            .section-title {
-                font-size: 16px;
-                font-weight: 600;
-                margin-bottom: 12px;
-                display: flex;
-                align-items: center;
-                gap: 8px;
-            }
-            .section-title .icon {
-                font-size: 20px;
-            }
-            .section-content {
-                font-size: 14px;
-                color: #555;
-                line-height: 1.8;
-                word-break: break-all;
-            }
-            .product-item {
-                display: inline-block;
-                background: #e8ecf1;
-                padding: 4px 12px;
-                border-radius: 20px;
-                margin: 4px 6px 4px 0;
-                font-size: 13px;
-            }
-            .product-item strong {
-                color: #667eea;
-            }
-            .empty-data {
-                color: #999;
-                font-style: italic;
-            }
-            .separator {
-                border-top: 1px dashed #e0e4e8;
-                margin: 20px 0;
-            }
-            .email-footer {
-                background-color: #f8f9fc;
-                padding: 15px 25px;
-                text-align: center;
-                font-size: 12px;
-                color: #999;
-                border-top: 1px solid #eef2f6;
-            }
-            .badge {
-                display: inline-block;
-                background: #667eea;
-                color: white;
-                font-size: 12px;
-                padding: 2px 8px;
-                border-radius: 12px;
-                margin-left: 8px;
-            }
-            .stats-number {
-                font-weight: 700;
-                color: #667eea;
-                font-size: 16px;
-            }
-        </style>
-    </head>
-    <body>
-        <div class="email-container">
-            <div class="email-header">
-                <h1>数据监控报告</h1>
-                <p>采集与清洗情况通知</p>
-            </div>
-            <div class="email-body">
-                ' . $this->buildSection('🎯 配置采集商品任务', 'config_collect', $config_collect, '#667eea') . '
-                ' . $this->buildSection('✅ 实际采集到的商品', 'actual_collect', $actual_collect, '#48bb78') . '
-                
-                <div class="separator"></div>
-                
-                ' . $this->buildSection('⚙️ 配置的低价清洗商品', 'config_low', $config_low, '#ed8936') . '
-                ' . $this->buildSection('🔍 实际清洗出来的低价商品', 'cleaned_low', $cleaned_low, '#ed8936') . '
-                
-                <div class="separator"></div>
-                
-                ' . $this->buildSection('⚠️ 配置的违规清洗商品', 'config_violation_product', $config_violation_product, '#e53e3e') . '
-                ' . $this->buildSection('🚫 实际清洗出来的违规商品', 'cleaned_violation_product', $cleaned_violation_product, '#e53e3e') . '
-                
-                <div class="separator"></div>
-                
-                ' . $this->buildSection('🏪 配置的违规店铺', 'config_violation_store', $config_violation_store, '#9b59b6') . '
-                ' . $this->buildSection('🚷 实际清洗出来的违规店铺', 'cleaned_violation_store', $cleaned_violation_store, '#9b59b6') . '
-            </div>
-            <div class="email-footer">
-                <p>此邮件由系统自动发送,请勿直接回复 | 数据统计时间:' . date('Y-m-d H:i:s') . '</p>
-            </div>
-        </div>
-    </body>
-    </html>';
+            <!DOCTYPE html>
+            <html>
+            <head>
+                <meta charset="UTF-8">
+            </head>
+            <body style="font-family: \'Microsoft YaHei\', Arial, sans-serif; background-color: #f5f7fa; margin: 0; padding: 20px;">
+                <div style="max-width: 800px; margin: 0 auto; background-color: #ffffff; border-radius: 12px; overflow: hidden;">
+                    <div style="background: #667eea; color: white; padding: 30px 20px; text-align: center;">
+                        <h1 style="margin: 0; font-size: 24px; font-weight: 600;">数据监控报告</h1>
+                        <p style="margin: 10px 0 0; opacity: 0.9; font-size: 14px;">' . $start_time_string . ' - ' . $end_time_string . ' 采集与清洗情况通知</p>
+                    </div>
+                    <div style="padding: 30px 25px;">
+                        ' . $this->buildSectionInline('🎯 配置采集商品任务', $config_collect, '#667eea') . '
+                        ' . $this->buildSectionInline('✅ 实际采集到的商品', $actual_collect, '#48bb78') . '
+                        <div style="border-top: 1px dashed #e0e4e8; margin: 20px 0;"></div>
+                        ' . $this->buildSectionInline('⚙️ 配置的低价清洗商品', $config_low, '#ed8936') . '
+                        ' . $this->buildSectionInline('🔍 实际清洗出来的低价商品', $cleaned_low, '#ed8936') . '
+                        <div style="border-top: 1px dashed #e0e4e8; margin: 20px 0;"></div>
+                        ' . $this->buildSectionInline('⚠️ 配置的违规清洗商品', $config_violation_product, '#e53e3e') . '
+                        ' . $this->buildSectionInline('🚫 实际清洗出来的违规商品', $cleaned_violation_product, '#e53e3e') . '
+                        <div style="border-top: 1px dashed #e0e4e8; margin: 20px 0;"></div>
+                        ' . $this->buildSectionInline('🏪 配置的违规店铺', $config_violation_store, '#9b59b6') . '
+                        ' . $this->buildSectionInline('🚷 实际清洗出来的违规店铺', $cleaned_violation_store, '#9b59b6') . '
+                    </div>
+                    <div style="background-color: #f8f9fc; padding: 15px 25px; text-align: center; font-size: 12px; color: #999; border-top: 1px solid #eef2f6;">
+                        <p style="margin: 0;">此邮件由系统自动发送,请勿直接回复 | 数据统计时间:' . date('Y-m-d H:i:s') . '</p>
+                    </div>
+                </div>
+            </body>
+            </html>';
 
         return $html;
     }
 
     /**
-     * 构建单个数据区块
+     * 构建单个数据区块(内联样式版本)
      */
-    private function buildSection($title, $type, $content, $color)
+    private function buildSectionInline($title, $content, $color)
     {
-        $icon = $this->getIconByType($type);
-        $formattedContent = $this->formatContent($content);
-
+        $formattedContent = $this->formatContentInline($content);
+        
         return '
-        <div class="section" style="border-left-color: ' . $color . ';">
-            <div class="section-title">
-                <span class="icon"></span>
-                <span>' . $title . '</span>
+        <div style="margin-bottom: 25px; border-left: 4px solid ' . $color . '; padding: 12px 20px; background-color: #f8f9fc; border-radius: 8px;">
+            <div style="font-size: 16px; font-weight: 600; margin-bottom: 12px;">
+                ' . htmlspecialchars($title) . '
             </div>
-            <div class="section-content">
+            <div style="font-size: 14px; color: #555; line-height: 1.8; word-break: break-all;">
                 ' . $formattedContent . '
             </div>
         </div>';
     }
 
     /**
-     * 格式化内容,将分号分隔的数据转换为美观的标签形式
+     * 格式化内容(内联样式版本)
      */
-    private function formatContent($content)
+    private function formatContentInline($content)
     {
         // 如果内容为空或者只包含分号
         if (empty($content) || trim($content) === ';' || trim($content) === '无;') {
-            return '<span class="empty-data">📭 暂无数据</span>';
+            return '<span style="color: #999; font-style: italic;">📭 暂无数据</span>';
         }
         
         // 检查是否包含"无;"的情况
         if (strpos($content, '无;') !== false && strlen($content) <= 6) {
-            return '<span class="empty-data">📭 暂无数据</span>';
+            return '<span style="color: #999; font-style: italic;">📭 暂无数据</span>';
         }
 
         // 移除末尾的分号
@@ -442,39 +335,18 @@ class ProductSurveillanceJobs implements ShouldQueue
             if (preg_match('/^(.+):数量(\d+)$/u', $item, $matches)) {
                 $productName = trim($matches[1]);
                 $count = $matches[2];
-                $html .= '<span class="product-item"><strong>' . htmlspecialchars($productName) . '</strong> <span class="stats-number">' . $count . '</span> 件</span>';
+                $html .= '<span style="display: inline-block; background: #e8ecf1; padding: 4px 12px; border-radius: 20px; margin: 4px 6px 4px 0; font-size: 13px;"><strong style="color: #667eea;">' . htmlspecialchars($productName) . '</strong> <strong style="font-weight: 700; color: #667eea; font-size: 16px;">' . $count . '</strong> 件</span>';
             } else {
                 // 普通商品名
-                $html .= '<span class="product-item">' . htmlspecialchars($item) . '</span>';
+                $html .= '<span style="display: inline-block; background: #e8ecf1; padding: 4px 12px; border-radius: 20px; margin: 4px 6px 4px 0; font-size: 13px;">' . htmlspecialchars($item) . '</span>';
             }
         }
         
-        return $html ?: '<span class="empty-data">📭 暂无数据</span>';
+        return $html ?: '<span style="color: #999; font-style: italic;">📭 暂无数据</span>';
     }
 
-    /**
-     * 根据类型获取对应的图标
-     */
-    private function getIconByType($type)
-    {
-        $icons = [
-            'config_collect' => '📋',
-            'actual_collect' => '📦',
-            'config_low' => '💰',
-            'cleaned_low' => '💎',
-            'config_violation_product' => '⚠️',
-            'cleaned_violation_product' => '🚫',
-            'config_violation_store' => '🏪',
-            'cleaned_violation_store' => '🔨',
-        ];
-
-        return $icons[$type] ?? '📌';
-    }
-
-
-
     public function failed(\Throwable $exception)
     {
         Log::info('job_error', '低价商品数据数据-监控采集清洗情况队列完全失败', ['data' => $this->message_data, 'error' => $exception->getMessage()]);
     }
-}
+}

+ 56 - 1
app/Servers/Email/VerifyCode.php

@@ -53,9 +53,64 @@ class VerifyCode extends Mailable
         $message = new Swift_Message($subject);
         $message->setFrom($from ?: config('mail.from.address'));
         $message->setTo($to);
-        $message->setBody($body);
+        // 自动识别 body 是否为 HTML 内容
+        if (self::isHtmlContent($body)) {
+            // HTML 内容
+            $message->setBody($body, 'text/html');
+            // 可选:同时添加纯文本版本作为备选
+            $message->addPart(strip_tags($body), 'text/plain');
+        } else {
+            // 纯文本内容
+            $message->setBody($body);
+        }
 
         // 发送邮件
         return $mailer->send($message);
     }
+
+    /**
+     * 判断内容是否为 HTML
+     *
+     * @param string $content
+     * @return bool
+     */
+    private static function isHtmlContent($content)
+    {
+        // 方法1:检查是否包含 HTML 标签
+        if (strip_tags($content) != $content) {
+            return true;
+        }
+
+        // 方法2:检查是否以 <!DOCTYPE html 或 <html 开头(忽略空白字符)
+        $trimmedContent = trim($content);
+        if (
+            strpos($trimmedContent, '<!DOCTYPE html') === 0 ||
+            strpos($trimmedContent, '<html') === 0
+        ) {
+            return true;
+        }
+
+        // 方法3:检查常见的 HTML 标签
+        $htmlPatterns = [
+            '/<div[^>]*>/i',
+            '/<p[^>]*>/i',
+            '/<span[^>]*>/i',
+            '/<table[^>]*>/i',
+            '/<br\s*\/?>/i',
+            '/<h[1-6][^>]*>/i',
+            '/<a[^>]*>/i',
+            '/<img[^>]*>/i',
+            '/<ul[^>]*>/i',
+            '/<ol[^>]*>/i',
+            '/<li[^>]*>/i'
+        ];
+
+        foreach ($htmlPatterns as $pattern) {
+            if (preg_match($pattern, $content)) {
+                return true;
+            }
+        }
+
+        return false;
+    }
 }