diff --git a/.github/workflows/crawler.yml b/.github/workflows/crawler.yml index cafac9f..2fe827c 100644 --- a/.github/workflows/crawler.yml +++ b/.github/workflows/crawler.yml @@ -53,6 +53,11 @@ jobs: TELEGRAM_CHAT_ID: ${{ secrets.TELEGRAM_CHAT_ID }} DINGTALK_WEBHOOK_URL: ${{ secrets.DINGTALK_WEBHOOK_URL }} WEWORK_WEBHOOK_URL: ${{ secrets.WEWORK_WEBHOOK_URL }} + EMAIL_FROM: ${{ secrets.EMAIL_FROM }} + EMAIL_PASSWORD: ${{ secrets.EMAIL_PASSWORD }} + EMAIL_TO: ${{ secrets.EMAIL_TO }} + EMAIL_SMTP_SERVER: ${{ secrets.EMAIL_SMTP_SERVER }} + EMAIL_SMTP_PORT: ${{ secrets.EMAIL_SMTP_PORT }} GITHUB_ACTIONS: true run: python main.py diff --git a/config/config.yaml b/config/config.yaml index b7f092d..1edf013 100644 --- a/config/config.yaml +++ b/config/config.yaml @@ -53,6 +53,11 @@ notification: wework_url: "" # 企业微信机器人的 webhook URL telegram_bot_token: "" # Telegram Bot Token telegram_chat_id: "" # Telegram Chat ID + email_from: "" # 发件人邮箱地址 + email_password: "" # 发件人邮箱密码或授权码 + email_to: "" # 收件人邮箱地址,多个收件人用逗号分隔 + email_smtp_server: "" # SMTP服务器地址(可选,留空自动识别) + email_smtp_port: "" # SMTP端口(可选,留空自动识别) # 用于让关注度更高的新闻在更前面显示,即用算法重新组合不同平台的热搜排序形成你侧重的热搜,合起来是 1 就行 weight: diff --git a/docker/.env b/docker/.env index c9cc6b6..6539dae 100644 --- a/docker/.env +++ b/docker/.env @@ -4,6 +4,11 @@ TELEGRAM_BOT_TOKEN= TELEGRAM_CHAT_ID= DINGTALK_WEBHOOK_URL= WEWORK_WEBHOOK_URL= +EMAIL_FROM= +EMAIL_PASSWORD= +EMAIL_TO= +EMAIL_SMTP_SERVER= +EMAIL_SMTP_PORT= # 运行配置 CRON_SCHEDULE=*/30 * * * * # 定时任务表达式,每 30 分钟执行一次(比如 8点,8点半,9点,9点半这种时间规律执行) diff --git a/docker/docker-compose-build.yml b/docker/docker-compose-build.yml index 263bd2c..f38a870 100644 --- a/docker/docker-compose-build.yml +++ b/docker/docker-compose-build.yml @@ -17,6 +17,11 @@ services: - TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID:-} - DINGTALK_WEBHOOK_URL=${DINGTALK_WEBHOOK_URL:-} - WEWORK_WEBHOOK_URL=${WEWORK_WEBHOOK_URL:-} + - EMAIL_FROM=${EMAIL_FROM:-} + - EMAIL_PASSWORD=${EMAIL_PASSWORD:-} + - EMAIL_TO=${EMAIL_TO:-} + - EMAIL_SMTP_SERVER=${EMAIL_SMTP_SERVER:-} + - EMAIL_SMTP_PORT=${EMAIL_SMTP_PORT:-} - CRON_SCHEDULE=${CRON_SCHEDULE:-*/5 * * * *} - RUN_MODE=${RUN_MODE:-cron} - IMMEDIATE_RUN=${IMMEDIATE_RUN:-true} diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index d633572..a7aea8d 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -15,6 +15,11 @@ services: - TELEGRAM_CHAT_ID=${TELEGRAM_CHAT_ID:-} - DINGTALK_WEBHOOK_URL=${DINGTALK_WEBHOOK_URL:-} - WEWORK_WEBHOOK_URL=${WEWORK_WEBHOOK_URL:-} + - EMAIL_FROM=${EMAIL_FROM:-} + - EMAIL_PASSWORD=${EMAIL_PASSWORD:-} + - EMAIL_TO=${EMAIL_TO:-} + - EMAIL_SMTP_SERVER=${EMAIL_SMTP_SERVER:-} + - EMAIL_SMTP_PORT=${EMAIL_SMTP_PORT:-} - CRON_SCHEDULE=${CRON_SCHEDULE:-*/5 * * * *} - RUN_MODE=${RUN_MODE:-cron} - IMMEDIATE_RUN=${IMMEDIATE_RUN:-true} diff --git a/main.py b/main.py index 6a6bda8..f4f43a4 100644 --- a/main.py +++ b/main.py @@ -6,6 +6,11 @@ import random import re import time import webbrowser +import smtplib +from email.mime.text import MIMEText +from email.mime.multipart import MIMEMultipart +from email.header import Header +from email.utils import formataddr, formatdate, make_msgid from datetime import datetime from pathlib import Path from typing import Dict, List, Tuple, Optional, Union @@ -15,9 +20,69 @@ import requests import yaml -VERSION = "2.2.0" +VERSION = "2.3.0" +# === SMTP邮件配置 === +SMTP_CONFIGS = { + # Gmail + 'gmail.com': { + 'server': 'smtp.gmail.com', + 'port': 587, + 'encryption': 'TLS' + }, + + # QQ邮箱 + 'qq.com': { + 'server': 'smtp.qq.com', + 'port': 587, + 'encryption': 'TLS' + }, + + # Outlook + 'outlook.com': { + 'server': 'smtp-mail.outlook.com', + 'port': 587, + 'encryption': 'TLS' + }, + 'hotmail.com': { + 'server': 'smtp-mail.outlook.com', + 'port': 587, + 'encryption': 'TLS' + }, + 'live.com': { + 'server': 'smtp-mail.outlook.com', + 'port': 587, + 'encryption': 'TLS' + }, + + # 网易邮箱 + '163.com': { + 'server': 'smtp.163.com', + 'port': 587, + 'encryption': 'TLS' + }, + '126.com': { + 'server': 'smtp.126.com', + 'port': 587, + 'encryption': 'TLS' + }, + + # 新浪邮箱 + 'sina.com': { + 'server': 'smtp.sina.com', + 'port': 587, + 'encryption': 'TLS' + }, + + # 搜狐邮箱 + 'sohu.com': { + 'server': 'smtp.sohu.com', + 'port': 587, + 'encryption': 'TLS' + } +} + # === 配置管理 === def load_config(): """加载配置文件""" @@ -96,6 +161,23 @@ def load_config(): config["TELEGRAM_CHAT_ID"] = os.environ.get( "TELEGRAM_CHAT_ID", "" ).strip() or webhooks.get("telegram_chat_id", "") + + # 邮件配置 + config["EMAIL_FROM"] = os.environ.get( + "EMAIL_FROM", "" + ).strip() or webhooks.get("email_from", "") + config["EMAIL_PASSWORD"] = os.environ.get( + "EMAIL_PASSWORD", "" + ).strip() or webhooks.get("email_password", "") + config["EMAIL_TO"] = os.environ.get( + "EMAIL_TO", "" + ).strip() or webhooks.get("email_to", "") + config["EMAIL_SMTP_SERVER"] = os.environ.get( + "EMAIL_SMTP_SERVER", "" + ).strip() or webhooks.get("email_smtp_server", "") + config["EMAIL_SMTP_PORT"] = os.environ.get( + "EMAIL_SMTP_PORT", "" + ).strip() or webhooks.get("email_smtp_port", "") # 输出配置来源信息 webhook_sources = [] @@ -114,7 +196,10 @@ def load_config(): ) chat_source = "环境变量" if os.environ.get("TELEGRAM_CHAT_ID") else "配置文件" webhook_sources.append(f"Telegram({token_source}/{chat_source})") - + if config["EMAIL_FROM"] and config["EMAIL_PASSWORD"] and config["EMAIL_TO"]: + from_source = "环境变量" if os.environ.get("EMAIL_FROM") else "配置文件" + webhook_sources.append(f"邮件({from_source})") + if webhook_sources: print(f"Webhook 配置来源: {', '.join(webhook_sources)}") else: @@ -1464,6 +1549,7 @@ def generate_html_report( id_to_name: Optional[Dict] = None, mode: str = "daily", is_daily_summary: bool = False, + update_info: Optional[Dict] = None, ) -> str: """生成HTML报告""" if is_daily_summary: @@ -1481,7 +1567,7 @@ def generate_html_report( report_data = prepare_report_data(stats, failed_ids, new_titles, id_to_name, mode) html_content = render_html_content( - report_data, total_titles, is_daily_summary, mode + report_data, total_titles, is_daily_summary, mode, update_info ) with open(file_path, "w", encoding="utf-8") as f: @@ -1500,6 +1586,7 @@ def render_html_content( total_titles: int, is_daily_summary: bool = False, mode: str = "daily", + update_info: Optional[Dict] = None, ) -> str: """渲染HTML内容""" html = """ @@ -1876,7 +1963,7 @@ def render_html_content( .footer-content { font-size: 13px; color: #6b7280; - line-height: 1.4; + line-height: 1.6; } .footer-link { @@ -2157,7 +2244,16 @@ def render_html_content( 由 TrendRadar 生成 · GitHub 开源项目 - + """ + + if update_info: + html += f""" + + + 发现新版本 {update_info['remote_version']},当前版本 {update_info['current_version']} + """ + + html += """ @@ -2823,6 +2919,7 @@ def send_to_webhooks( update_info: Optional[Dict] = None, proxy_url: Optional[str] = None, mode: str = "daily", + html_file_path: Optional[str] = None, ) -> Dict[str, bool]: """发送数据到多个webhook平台""" results = {} @@ -2851,6 +2948,11 @@ def send_to_webhooks( wework_url = CONFIG["WEWORK_WEBHOOK_URL"] telegram_token = CONFIG["TELEGRAM_BOT_TOKEN"] telegram_chat_id = CONFIG["TELEGRAM_CHAT_ID"] + email_from = CONFIG["EMAIL_FROM"] + email_password = CONFIG["EMAIL_PASSWORD"] + email_to = CONFIG["EMAIL_TO"] + email_smtp_server = CONFIG.get("EMAIL_SMTP_SERVER", "") + email_smtp_port = CONFIG.get("EMAIL_SMTP_PORT", "") update_info_to_send = update_info if CONFIG["SHOW_VERSION_UPDATE"] else None @@ -2884,6 +2986,18 @@ def send_to_webhooks( mode, ) + # 发送邮件 + if email_from and email_password and email_to: + results["email"] = send_to_email( + email_from, + email_password, + email_to, + report_type, + html_file_path, + email_smtp_server, + email_smtp_port, + ) + if not results: print("未配置任何webhook URL,跳过通知发送") @@ -3156,6 +3270,137 @@ def send_to_telegram( print(f"Telegram所有 {len(batches)} 批次发送完成 [{report_type}]") return True +def send_to_email( + from_email: str, + password: str, + to_email: str, + report_type: str, + html_file_path: str, + custom_smtp_server: Optional[str] = None, + custom_smtp_port: Optional[int] = None, +) -> bool: + """发送邮件通知""" + try: + if not html_file_path or not Path(html_file_path).exists(): + print(f"错误:HTML文件不存在或未提供: {html_file_path}") + return False + + print(f"使用HTML文件: {html_file_path}") + with open(html_file_path, "r", encoding="utf-8") as f: + html_content = f.read() + + domain = from_email.split('@')[-1].lower() + + if custom_smtp_server and custom_smtp_port: + # 使用自定义 SMTP 配置 + smtp_server = custom_smtp_server + smtp_port = int(custom_smtp_port) + use_tls = smtp_port == 587 + elif domain in SMTP_CONFIGS: + # 使用预设配置 + config = SMTP_CONFIGS[domain] + smtp_server = config['server'] + smtp_port = config['port'] + use_tls = config['encryption'] == 'TLS' + else: + print(f"未识别的邮箱服务商: {domain},使用通用 SMTP 配置") + smtp_server = f"smtp.{domain}" + smtp_port = 587 + use_tls = True + + msg = MIMEMultipart('alternative') + + # 严格按照 RFC 标准设置 From header + sender_name = "TrendRadar" + msg['From'] = formataddr((sender_name, from_email)) + + # 设置收件人 + recipients = [addr.strip() for addr in to_email.split(',')] + if len(recipients) == 1: + msg['To'] = recipients[0] + else: + msg['To'] = ', '.join(recipients) + + # 设置邮件主题 + now = get_beijing_time() + subject = f"TrendRadar 热点分析报告 - {report_type} - {now.strftime('%m月%d日 %H:%M')}" + msg['Subject'] = Header(subject, 'utf-8') + + # 设置其他标准 header + msg['MIME-Version'] = '1.0' + msg['Date'] = formatdate(localtime=True) + msg['Message-ID'] = make_msgid() + + # 添加纯文本部分(作为备选) + text_content = f""" +TrendRadar 热点分析报告 +======================== +报告类型:{report_type} +生成时间:{now.strftime('%Y-%m-%d %H:%M:%S')} + +请使用支持HTML的邮件客户端查看完整报告内容。 + """ + text_part = MIMEText(text_content, 'plain', 'utf-8') + msg.attach(text_part) + + html_part = MIMEText(html_content, 'html', 'utf-8') + msg.attach(html_part) + + print(f"正在发送邮件到 {to_email}...") + print(f"SMTP 服务器: {smtp_server}:{smtp_port}") + print(f"发件人: {from_email}") + + try: + if use_tls: + # TLS 模式 + server = smtplib.SMTP(smtp_server, smtp_port, timeout=30) + server.set_debuglevel(0) # 设为1可以查看详细调试信息 + server.ehlo() + server.starttls() + server.ehlo() + else: + # SSL 模式 + server = smtplib.SMTP_SSL(smtp_server, smtp_port, timeout=30) + server.set_debuglevel(0) + server.ehlo() + + # 登录 + server.login(from_email, password) + + # 发送邮件 + server.send_message(msg) + server.quit() + + print(f"邮件发送成功 [{report_type}] -> {to_email}") + return True + + except smtplib.SMTPServerDisconnected: + print(f"邮件发送失败:服务器意外断开连接,请检查网络或稍后重试") + return False + + except smtplib.SMTPAuthenticationError as e: + print(f"邮件发送失败:认证错误,请检查邮箱和密码/授权码") + print(f"详细错误: {str(e)}") + return False + except smtplib.SMTPRecipientsRefused as e: + print(f"邮件发送失败:收件人地址被拒绝 {e}") + return False + except smtplib.SMTPSenderRefused as e: + print(f"邮件发送失败:发件人地址被拒绝 {e}") + return False + except smtplib.SMTPDataError as e: + print(f"邮件发送失败:邮件数据错误 {e}") + return False + except smtplib.SMTPConnectError as e: + print(f"邮件发送失败:无法连接到 SMTP 服务器 {smtp_server}:{smtp_port}") + print(f"详细错误: {str(e)}") + return False + except Exception as e: + print(f"邮件发送失败 [{report_type}]:{e}") + import traceback + traceback.print_exc() + return False + # === 主分析器 === class NewsAnalyzer: @@ -3374,6 +3619,7 @@ class NewsAnalyzer: id_to_name=id_to_name, mode=mode, is_daily_summary=is_daily_summary, + update_info=self.update_info if CONFIG["SHOW_VERSION_UPDATE"] else None, ) return stats, html_file @@ -3386,6 +3632,7 @@ class NewsAnalyzer: failed_ids: Optional[List] = None, new_titles: Optional[Dict] = None, id_to_name: Optional[Dict] = None, + html_file_path: Optional[str] = None, ) -> bool: """统一的通知发送逻辑,包含所有判断条件""" has_webhook = self._has_webhook_configured() @@ -3404,6 +3651,7 @@ class NewsAnalyzer: self.update_info, self.proxy_url, mode=mode, + html_file_path=html_file_path, ) return True elif CONFIG["ENABLE_NOTIFICATION"] and not has_webhook: @@ -3456,14 +3704,16 @@ class NewsAnalyzer: ) print(f"{summary_type}报告已生成: {html_file}") - + # 发送通知 self._send_notification_if_needed( stats, mode_strategy["summary_report_type"], mode_strategy["summary_mode"], + failed_ids=[], new_titles=new_titles, id_to_name=id_to_name, + html_file_path=html_file, ) return html_file @@ -3596,6 +3846,7 @@ class NewsAnalyzer: failed_ids=failed_ids, new_titles=historical_new_titles, id_to_name=combined_id_to_name, + html_file_path=html_file, ) else: print("❌ 严重错误:无法读取刚保存的数据文件") @@ -3624,6 +3875,7 @@ class NewsAnalyzer: failed_ids=failed_ids, new_titles=new_titles, id_to_name=id_to_name, + html_file_path=html_file, ) # 生成汇总报告(如果需要) diff --git a/readme.md b/readme.md index 789e01f..4257aab 100644 --- a/readme.md +++ b/readme.md @@ -9,12 +9,13 @@ [](https://github.com/sansan0/TrendRadar/stargazers) [](https://github.com/sansan0/TrendRadar/network/members) [](LICENSE) -[](https://github.com/sansan0/TrendRadar) +[](https://github.com/sansan0/TrendRadar) -[](https://work.weixin.qq.com/) -[](https://telegram.org/) -[](#) -[](https://www.feishu.cn/) +[](https://work.weixin.qq.com/) +[](https://telegram.org/) +[](#) +[](https://www.feishu.cn/) +[](mailto:) [](https://github.com/sansan0/TrendRadar) [](https://sansan0.github.io/TrendRadar) [](https://hub.docker.com/) @@ -29,7 +30,7 @@ - 遇到问题可选择以上 2 种方式获得帮助,[点此跳转到两者的区别](#问题答疑与1元点赞) -👉 点击查看致谢名单 (当前 🔥22🔥 位) +👉 点击查看致谢名单 (当前 🔥23🔥 位) ### 数据支持 @@ -49,6 +50,7 @@ | 点赞人 | 金额 | 日期 | 备注 | | :-------------------------: | :----: | :----: | :-----------------------: | +| *🍍 | 10 | 2025.9.21 | | | E*f | 1 | 2025.9.20 | | | *记 | 1 | 2025.9.20 | | | z*u | 2 | 2025.9.19 | | @@ -186,7 +188,11 @@ weight: ### **多渠道实时推送** -支持**企业微信**(微信方案)、**飞书**、**钉钉**、**Telegram**,消息直达手机 +支持**企业微信**(+ 微信推送方案)、**飞书**、**钉钉**、**Telegram**、**邮件**,消息直达手机和邮箱 + +- **邮件推送**:支持 QQ邮箱、Gmail、Outlook、163邮箱等主流邮箱服务 +- **智能识别**:自动识别邮箱服务商,也可以手动配置 SMTP 服务器 +- **HTML 格式**:精美的 HTML 邮件格式,与网页版效果一致 ### **多端适配** - **GitHub Pages**:自动生成精美网页报告,PC/移动端适配 @@ -212,7 +218,7 @@ GitHub 一键 Fork 即可使用,无需编程基础。 **典型场景:** 股市投资监控、品牌舆情追踪、行业动态关注、生活资讯获取 -| Github Pages 网页效果(手机端适配) | 飞书推送效果 | +| Github Pages 效果(手机端适配、邮箱推送效果) | 飞书推送效果 | |:---:|:---:| |  |  | @@ -290,6 +296,28 @@ GitHub 一键 Fork 即可使用,无需编程基础。 > > 下一次**新功能**,大概会是 ai 分析功能(●'◡'●) +### 2025/09/22 - v2.3.0 + +- **新增邮件推送功能**,支持将热点新闻报告发送到邮箱 +- **智能 SMTP 识别**:自动识别 Gmail、QQ邮箱、Outlook、网易邮箱等 10+ 种邮箱服务商配置 +- **HTML 精美格式**:邮件内容采用与网页版相同的 HTML 格式,排版精美,移动端适配 +- **批量发送支持**:支持多个收件人,用逗号分隔即可同时发送给多人 +- **自定义 SMTP**:可自定义 SMTP 服务器和端口 + +**使用说明**: +- 适用场景:适合需要邮件归档、团队分享、定时报告的用户 +- 注意事项:为防止邮件群发功能被**滥用**,当前的群发是所有收件人都能看到彼此的邮箱地址,适合熟人间交流资讯 + +**支持的邮箱服务**: +- Gmail、QQ邮箱、Outlook/Hotmail、163/126邮箱、新浪邮箱、搜狐邮箱等 + +**更新提示**: +- 此次更新的内容比较多,建议删除原有 fork, 重新 fork 并配置 + + + +👉 历史更新 + ### 2025/09/17 - v2.2.0 - 新增一键保存新闻图片功能,让你轻松分享关注的热点 @@ -300,9 +328,6 @@ GitHub 一键 Fork 即可使用,无需编程基础。 - 实际效果:系统会自动将当前的新闻报告制作成一张精美图片,保存到你的手机相册或电脑桌面 - 分享便利:你可以直接把这张图片发给朋友、发到朋友圈,或分享到工作群,让别人也能看到你发现的重要资讯 - -👉 历史更新 - ### 2025/09/13 - v2.1.2 - 解决钉钉的推送容量限制导致的新闻推送失败问题(采用分批推送) @@ -581,6 +606,49 @@ frequency_words.txt 文件增加了一个【必须词】功能,使用 + 号 - `TELEGRAM_CHAT_ID`:填入第 2 步获得的 Chat ID + + 👉 邮件推送(支持所有主流邮箱) + + + - 注意事项:为防止邮件群发功能被**滥用**,当前的群发是所有收件人都能看到彼此的邮箱地址,适合熟人间交流资讯。 + - 仅供参考:请根据实际情况调整,邮箱方面并没有一一验证,是按照 SMTP 的标准配置的 + + **GitHub Secret 配置:** + - 名称:`EMAIL_FROM` - 发件人邮箱地址 + - 名称:`EMAIL_PASSWORD` - 邮箱密码或授权码 + - 名称:`EMAIL_TO` - 收件人邮箱地址(多个收件人用英文逗号分隔) + - 名称:`EMAIL_SMTP_SERVER` - SMTP服务器地址(可选,留空则自动识别) + - 名称:`EMAIL_SMTP_PORT` - SMTP端口(可选,留空则自动识别) + + **常见邮箱设置:** + + #### QQ邮箱: + 1. 登录 QQ邮箱网页版 → 设置 → 账户 + 2. 开启 POP3/SMTP 服务 + 3. 生成授权码(16位字母) + 4. `EMAIL_PASSWORD` 填写授权码,而非 QQ 密码 + + #### Gmail: + 1. 开启两步验证 + 2. 生成应用专用密码 + 3. `EMAIL_PASSWORD` 填写应用专用密码 + + #### 163/126邮箱: + 1. 登录网页版 → 设置 → POP3/SMTP/IMAP + 2. 开启 SMTP 服务 + 3. 设置客户端授权码 + 4. `EMAIL_PASSWORD` 填写授权码 + + **高级配置**: + 如果自动识别失败,可手动配置 SMTP: + - `EMAIL_SMTP_SERVER`:如 smtp.gmail.com + - `EMAIL_SMTP_PORT`:如 587(TLS)或 465(SSL) + + **多收件人设置**: + - EMAIL_TO="user1@example.com,user2@example.com,user3@example.com" + + + 3. **主要配置**: - **推送设置:** : 在 [config/config.yaml](config/config.yaml) 中进行,可根据里面的描述文字操作,这里不重复了 @@ -765,7 +833,7 @@ docker run -d --name trend-radar \ -e IMMEDIATE_RUN="true" \ wantcat/trendradar:latest -# 或者启用手机应用推送通知 +# 或者启用手机应用推送通知或邮件通知 docker run -d --name trend-radar \ -v ./config:/app/config:ro \ -v ./output:/app/output \ @@ -774,6 +842,9 @@ docker run -d --name trend-radar \ -e WEWORK_WEBHOOK_URL="你的企业微信webhook" \ -e TELEGRAM_BOT_TOKEN="你的telegram_bot_token" \ -e TELEGRAM_CHAT_ID="你的telegram_chat_id" \ + -e EMAIL_FROM="你的发件邮箱" \ + -e EMAIL_PASSWORD="你的邮箱密码或授权码" \ + -e EMAIL_TO="收件人邮箱" \ -e CRON_SCHEDULE="*/30 * * * *" \ -e RUN_MODE="cron" \ -e IMMEDIATE_RUN="true" \ @@ -946,21 +1017,14 @@ docker exec -it trend-radar ls -la /app/config/ > 心意到就行,收到的**点赞**用于提高开发者开源的积极性。你们的**点赞**已记录于最顶部的【致谢名单】 - - |公众号关注 |微信点赞 | 支付宝点赞 | |:---:|:---:|:---:| | | | | - - - -| 答疑方式 | 适用场景 | 响应时间 | 详细程度 | 如何提问 | -|---------|---------|---------|---------|---------| -| **GitHub Issues** | 部署配置问题功能异常 | 1-2天内 | 针对性强 | 📋 **提供完整信息**:• 尽量截图• 错误日志• 系统环境等等 | -| **公众号留言** | 快速咨询使用疑问功能了解 | 几小时 | 简要指导 | 💡 **抓住问题核心**:• 一句话描述问题• 说明想要的效果 | - - +| 答疑方式 | 适用场景 | 响应时间 | 详细程度 | 社区参与度 | 如何提问 | +|:---:|:---:|:---:|:---:|:---:|:---:| +| **GitHub Issues** | 部署配置问题功能异常 | 1-2天内 | 针对性强 | **公开讨论**其他用户可参与问题记录可搜索 | 📋 **提供完整信息**:• 尽量截图• 错误日志• 系统环境等等 | +| **公众号交流** | 快速咨询使用疑问功能了解 | 几小时 | 简要指导 | 可以文章下留言也可以私信交流 | 💡 **抓住问题核心**:• 一句话描述问题• 说明想要的效果 | ### 项目相关 diff --git a/version b/version index e3a4f19..cc6612c 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.2.0 \ No newline at end of file +2.3.0 \ No newline at end of file