python:PyQt5 开发一个邮件客户端,能编写邮件,发送邮件及附件

PyQt5 邮件客户端

下面是一个简洁高效的邮件客户端实现,支持编写邮件、添加附件和发送邮件功能:
编写 eMailClient_qt.py 如下

# -*- coding: utf-8 -*-
""" 用 PyQt5 开发一个邮件客户端,能编写邮件,发送邮件及附件 """
import os
import sys
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout, QFileDialog,QLineEdit, QTextEdit, QPushButton, QLabel,QListWidget, QMessageBox, QStatusBar, QGridLayout)
from PyQt5.QtGui import QFont, QPalette, QColor
from PyQt5.QtCore import Qt, QSizeclass EmailClient(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("邮件客户端")# 设置窗口大小为1000x600self.setGeometry(100, 100, 1000, 600)# 设置现代化UI样式self.setStyleSheet("""QMainWindow {background-color: #f0f2f5;}QLabel {color: #333;font-size: 12px;font-weight: bold;padding: 2px 0;}QLineEdit, QTextEdit {background-color: white;border: 1px solid #dcdfe6;border-radius: 4px;padding: 8px;font-size: 13px;}QLineEdit:focus, QTextEdit:focus {border: 1px solid #4a90e2;}QPushButton {background-color: #4a90e2;color: white;border: none;border-radius: 4px;padding: 8px 15px;font-size: 13px;min-height: 30px;}QPushButton:hover {background-color: #3a7bc8;}QPushButton:pressed {background-color: #2a65a8;}QPushButton#attachButton {background-color: #f5f7fa;color: #4a90e2;border: 1px solid #4a90e2;}QPushButton#sendButton {background-color: #27ae60;padding: 10px 25px;font-size: 14px;font-weight: bold;}QPushButton#sendButton:hover {background-color: #219653;}QListWidget {background-color: white;border: 1px solid #dcdfe6;border-radius: 4px;padding: 5px;font-size: 12px;alternate-background-color: #f8f9fa;}QStatusBar {background-color: #e0e6ed;color: #666;font-size: 11px;padding: 5px;}QFrame#headerFrame {background-color: #4a90e2;border-radius: 5px;padding: 10px;}""")# 创建中央部件central_widget = QWidget()self.setCentralWidget(central_widget)# 主布局 - 使用网格布局更灵活main_layout = QGridLayout(central_widget)main_layout.setSpacing(15)main_layout.setContentsMargins(15, 15, 15, 15)# 标题区域title_label = QLabel("邮件客户端")title_label.setFont(QFont("Arial", 18, QFont.Bold))title_label.setStyleSheet("color: #2c3e50;")main_layout.addWidget(title_label, 0, 0, 1, 3, alignment=Qt.AlignLeft)# 发件人信息main_layout.addWidget(QLabel("发件人:"), 1, 0, alignment=Qt.AlignRight)self.sender_email = QLineEdit()self.sender_email.setPlaceholderText("your_email@qq.com")main_layout.addWidget(self.sender_email, 1, 1, 1, 2)main_layout.addWidget(QLabel("密码:"), 1, 3, alignment=Qt.AlignRight)self.password = QLineEdit()self.password.setEchoMode(QLineEdit.Password)self.password.setPlaceholderText("邮箱密码或应用密码")main_layout.addWidget(self.password, 1, 4)# 收件人 - 标签和输入框在同一行main_layout.addWidget(QLabel("收件人:"), 2, 0, alignment=Qt.AlignRight)self.recipient_email = QLineEdit()self.recipient_email.setPlaceholderText("recipient@qq.com")main_layout.addWidget(self.recipient_email, 2, 1, 1, 4)# 主题 - 标签和输入框在同一行main_layout.addWidget(QLabel("主题:"), 3, 0, alignment=Qt.AlignRight)self.subject = QLineEdit()self.subject.setPlaceholderText("邮件主题")main_layout.addWidget(self.subject, 3, 1, 1, 4)# 附件main_layout.addWidget(QLabel("附件:"), 4, 0, alignment=Qt.AlignRight | Qt.AlignTop)# 附件列表和按钮attachment_widget = QWidget()attachment_layout = QVBoxLayout(attachment_widget)self.attachment_list = QListWidget()self.attachment_list.setMinimumHeight(80)attachment_layout.addWidget(self.attachment_list)# 按钮布局btn_layout = QHBoxLayout()attach_button = QPushButton("添加附件")attach_button.setObjectName("attachButton")attach_button.clicked.connect(self.add_attachment)btn_layout.addWidget(attach_button)remove_button = QPushButton("移除附件")remove_button.setObjectName("attachButton")remove_button.clicked.connect(self.remove_attachment)btn_layout.addWidget(remove_button)attachment_layout.addLayout(btn_layout)main_layout.addWidget(attachment_widget, 4, 1, 1, 4)# 邮件正文 - 扩大区域main_layout.addWidget(QLabel("正文:"), 5, 0, alignment=Qt.AlignRight | Qt.AlignTop)self.body = QTextEdit()self.body.setPlaceholderText("在此输入邮件内容...")# 设置正文区域的行数(相对扩大)main_layout.addWidget(self.body, 5, 1, 1, 4)# 发送按钮send_button = QPushButton("发送邮件")send_button.setObjectName("sendButton")send_button.clicked.connect(self.send_email)main_layout.addWidget(send_button, 6, 4, alignment=Qt.AlignRight)# 设置行和列的比例,使正文区域扩大main_layout.setRowStretch(5, 3)  # 正文区域行权重设为3main_layout.setColumnStretch(1, 1)main_layout.setColumnStretch(2, 1)main_layout.setColumnStretch(3, 1)main_layout.setColumnStretch(4, 2)  # 右侧列权重更大# 状态栏self.status_bar = QStatusBar()self.setStatusBar(self.status_bar)self.status_bar.showMessage(f"就绪 - 窗口大小: {self.width()}x{self.height()}")# 存储附件路径self.attachments = []# 设置示例数据self.sender_email.setText("your_email@qq.com")self.recipient_email.setText("recipient@qq.com")self.subject.setText("PyQt5 邮件客户端测试")self.body.setPlainText("这是一封测试邮件,使用 PyQt5 邮件客户端发送。\n\n""此邮件支持添加多个附件,并采用现代化的界面设计。\n\n""功能包括:\n""• 邮件编写\n""• 附件添加/移除\n""• 邮件发送\n""• 状态反馈\n\n""祝您使用愉快!")def add_attachment(self):files, _ = QFileDialog.getOpenFileNames(self, "选择附件", "", "所有文件 (*.*)")if files:self.attachments.extend(files)self.attachment_list.addItems(files)self.status_bar.showMessage(f"已添加 {len(files)} 个附件")def remove_attachment(self):current_row = self.attachment_list.currentRow()if current_row >= 0:item = self.attachment_list.takeItem(current_row)del self.attachments[current_row]self.status_bar.showMessage(f"已移除附件: {item.text()}")else:self.status_bar.showMessage("请选择要移除的附件")def send_email(self):sender = self.sender_email.text()password = self.password.text()recipient = self.recipient_email.text()subject = self.subject.text()body = self.body.toPlainText()  # 使用纯文本格式if not sender or not password or not recipient:QMessageBox.warning(self, "输入错误", "请填写完整的发件人、密码和收件人信息")returntry:# 创建邮件对象msg = MIMEMultipart()msg['From'] = sendermsg['To'] = recipientmsg['Subject'] = subject# 添加邮件正文msg.attach(MIMEText(body, 'plain'))# 添加附件for file_path in self.attachments:try:with open(file_path, "rb") as attachment:part = MIMEBase("application", "octet-stream")part.set_payload(attachment.read())encoders.encode_base64(part)# 获取文件名filename = file_path.split('/')[-1] if '/' in file_path else file_pathfilename = filename.split('\\')[-1]  # 处理Windows路径part.add_header("Content-Disposition",f"attachment; filename={filename}",)msg.attach(part)except Exception as e:self.status_bar.showMessage(f"添加附件失败: {str(e)}")return# 连接SMTP服务器并发送邮件self.status_bar.showMessage("正在连接服务器...")server = smtplib.SMTP_SSL('smtp.gmail.com', 465)  # 使用Gmail SMTP服务器self.status_bar.showMessage("正在登录...")server.login(sender, password)self.status_bar.showMessage("正在发送邮件...")server.sendmail(sender, recipient, msg.as_string())server.quit()# 发送成功后的操作self.status_bar.showMessage("邮件发送成功!")QMessageBox.information(self, "发送成功", "邮件已成功发送!")# 清空附件列表self.attachment_list.clear()self.attachments = []except smtplib.SMTPAuthenticationError:QMessageBox.critical(self, "认证失败", "邮箱或密码错误,请检查您的登录信息")self.status_bar.showMessage("认证失败")except Exception as e:QMessageBox.critical(self, "发送失败", f"邮件发送失败: {str(e)}")self.status_bar.showMessage(f"发送失败: {str(e)}")def resizeEvent(self, event):"""窗口大小改变时更新状态栏信息"""self.status_bar.showMessage(f"就绪 - 窗口大小: {self.width()}x{self.height()}")super().resizeEvent(event)if __name__ == "__main__":app = QApplication(sys.argv)# 设置应用样式palette = QPalette()palette.setColor(QPalette.Window, QColor(240, 242, 245))palette.setColor(QPalette.WindowText, QColor(51, 51, 51))palette.setColor(QPalette.Base, QColor(255, 255, 255))palette.setColor(QPalette.AlternateBase, QColor(248, 249, 250))palette.setColor(QPalette.Button, QColor(74, 144, 226))palette.setColor(QPalette.ButtonText, QColor(255, 255, 255))palette.setColor(QPalette.Highlight, QColor(74, 144, 226))palette.setColor(QPalette.HighlightedText, QColor(255, 255, 255))app.setPalette(palette)client = EmailClient()client.show()sys.exit(app.exec_())

功能说明

这个邮件客户端实现了以下核心功能:

  1. 邮件编写

    • 发件人邮箱和密码输入
    • 收件人地址输入
    • 邮件主题输入
    • 邮件正文编辑区域
  2. 附件管理

    • 添加多个附件
    • 查看附件列表
    • 移除选中的附件
  3. 邮件发送

    • 使用SMTP协议发送邮件
    • 支持纯文本格式的邮件内容
    • 支持发送多个附件
    • 错误处理和状态反馈

使用说明

  1. 在"发件人"字段输入您的邮箱地址
  2. 在"密码"字段输入您的邮箱密码(或应用专用密码)
  3. 在"收件人"字段输入收件人邮箱地址
  4. 填写邮件主题和正文内容
  5. 点击"添加附件"按钮选择要发送的文件
  6. 点击"发送邮件"按钮发送邮件

注意事项

  1. 该程序默认使用Gmail的SMTP服务器(smtp.gmail.com:465),如果您使用其他邮箱服务:

    • QQ邮箱:smtp.qq.com:465
    • 163邮箱:smtp.163.com:465
    • Outlook:smtp.office365.com:587(需要使用TLS)
  2. 部分邮箱服务需要开启SMTP服务并获取授权码:

    • Gmail:需要在账户设置中开启"安全性较低的应用的访问权限"
    • QQ/163:需要在邮箱设置中开启SMTP服务并获取授权码
  3. 出于安全考虑,程序不会保存您的密码,每次发送邮件都需要输入

这个程序提供了一个简洁高效的邮件发送解决方案,代码结构清晰,去除了不必要的装饰元素,专注于核心功能的实现。

eMailClient_qt


PyQt5 邮件客户端 - 优化布局

下面是一个优化布局的邮件客户端实现,窗口大小调整为1000x600,提供更舒适的编辑体验:
编写 eMailClient_qt5.py 如下

import sys
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,QLineEdit, QTextEdit, QPushButton, QLabel, QFileDialog,QListWidget, QMessageBox, QStatusBar, QSplitter, QFrame)
from PyQt5.QtGui import QFont, QPalette, QColor
from PyQt5.QtCore import Qtclass EmailClient(QMainWindow):def __init__(self):super().__init__()self.setWindowTitle("邮件客户端")# 设置窗口大小为1000x600self.setGeometry(100, 100, 1000, 600)# 设置现代化UI样式self.setStyleSheet("""QMainWindow {background-color: #f0f2f5;}QLabel {color: #333;font-size: 12px;font-weight: bold;padding: 2px 0;}QLineEdit, QTextEdit {background-color: white;border: 1px solid #dcdfe6;border-radius: 4px;padding: 8px;font-size: 13px;}QLineEdit:focus, QTextEdit:focus {border: 1px solid #4a90e2;}QPushButton {background-color: #4a90e2;color: white;border: none;border-radius: 4px;padding: 8px 15px;font-size: 13px;min-height: 30px;}QPushButton:hover {background-color: #3a7bc8;}QPushButton:pressed {background-color: #2a65a8;}QPushButton#attachButton {background-color: #f5f7fa;color: #4a90e2;border: 1px solid #4a90e2;}QPushButton#sendButton {background-color: #27ae60;padding: 10px 25px;font-size: 14px;font-weight: bold;}QPushButton#sendButton:hover {background-color: #219653;}QListWidget {background-color: white;border: 1px solid #dcdfe6;border-radius: 4px;padding: 5px;font-size: 12px;alternate-background-color: #f8f9fa;}QStatusBar {background-color: #e0e6ed;color: #666;font-size: 11px;padding: 5px;}QFrame#headerFrame {background-color: #4a90e2;border-radius: 5px;padding: 10px;}""")# 创建中央部件central_widget = QWidget()self.setCentralWidget(central_widget)# 主布局main_layout = QVBoxLayout(central_widget)main_layout.setSpacing(15)main_layout.setContentsMargins(15, 15, 15, 15)# 标题区域header_frame = QFrame()header_frame.setObjectName("headerFrame")header_layout = QHBoxLayout(header_frame)header_layout.setContentsMargins(10, 5, 10, 5)title_label = QLabel("邮件客户端")title_label.setFont(QFont("Arial", 18, QFont.Bold))title_label.setStyleSheet("color: white;")header_layout.addWidget(title_label)header_layout.addStretch()main_layout.addWidget(header_frame)# 创建分割器,左侧为设置区域,右侧为编辑区域splitter = QSplitter(Qt.Horizontal)main_layout.addWidget(splitter, 1)# 左侧设置面板settings_panel = QWidget()settings_layout = QVBoxLayout(settings_panel)settings_layout.setContentsMargins(0, 0, 10, 0)# 发件人信息sender_group = QWidget()sender_layout = QVBoxLayout(sender_group)sender_layout.addWidget(QLabel("发件人设置"))sender_form = QHBoxLayout()sender_form.addWidget(QLabel("邮箱:"))self.sender_email = QLineEdit()self.sender_email.setPlaceholderText("your_email@example.com")sender_form.addWidget(self.sender_email)sender_layout.addLayout(sender_form)sender_form2 = QHBoxLayout()sender_form2.addWidget(QLabel("密码:"))self.password = QLineEdit()self.password.setEchoMode(QLineEdit.Password)self.password.setPlaceholderText("邮箱密码或应用密码")sender_form2.addWidget(self.password)sender_layout.addLayout(sender_form2)settings_layout.addWidget(sender_group)# 收件人recipient_group = QWidget()recipient_layout = QVBoxLayout(recipient_group)recipient_layout.addWidget(QLabel("收件人"))self.recipient_email = QLineEdit()self.recipient_email.setPlaceholderText("recipient@example.com")recipient_layout.addWidget(self.recipient_email)settings_layout.addWidget(recipient_group)# 主题subject_group = QWidget()subject_layout = QVBoxLayout(subject_group)subject_layout.addWidget(QLabel("主题"))self.subject = QLineEdit()self.subject.setPlaceholderText("邮件主题")subject_layout.addWidget(self.subject)settings_layout.addWidget(subject_group)# 附件attachment_group = QWidget()attachment_layout = QVBoxLayout(attachment_group)attachment_layout.addWidget(QLabel("附件"))# 附件列表self.attachment_list = QListWidget()self.attachment_list.setMinimumHeight(100)attachment_layout.addWidget(self.attachment_list)# 附件按钮btn_layout = QHBoxLayout()attach_button = QPushButton("添加附件")attach_button.setObjectName("attachButton")attach_button.clicked.connect(self.add_attachment)btn_layout.addWidget(attach_button)remove_button = QPushButton("移除附件")remove_button.setObjectName("attachButton")remove_button.clicked.connect(self.remove_attachment)btn_layout.addWidget(remove_button)attachment_layout.addLayout(btn_layout)settings_layout.addWidget(attachment_group)settings_layout.addStretch()# 右侧编辑区域editor_panel = QWidget()editor_layout = QVBoxLayout(editor_panel)editor_layout.setContentsMargins(0, 0, 0, 0)# 邮件正文editor_layout.addWidget(QLabel("邮件正文"))self.body = QTextEdit()self.body.setPlaceholderText("在此输入邮件内容...")editor_layout.addWidget(self.body, 1)# 发送按钮send_button = QPushButton("发送邮件")send_button.setObjectName("sendButton")send_button.clicked.connect(self.send_email)editor_layout.addWidget(send_button, 0, Qt.AlignRight)# 添加左右面板到分割器splitter.addWidget(settings_panel)splitter.addWidget(editor_panel)splitter.setSizes([300, 700])# 状态栏self.status_bar = QStatusBar()self.setStatusBar(self.status_bar)self.status_bar.showMessage("就绪 - 窗口大小: 1000x600")# 存储附件路径self.attachments = []# 设置示例数据self.sender_email.setText("your_email@example.com")self.recipient_email.setText("recipient@example.com")self.subject.setText("PyQt5 邮件客户端测试")self.body.setPlainText("这是一封测试邮件,使用 PyQt5 邮件客户端发送。\n\n""此邮件支持添加多个附件,并采用现代化的界面设计。\n\n""功能包括:\n""• 邮件编写\n""• 附件添加/移除\n""• 邮件发送\n""• 状态反馈\n\n""祝您使用愉快!")def add_attachment(self):files, _ = QFileDialog.getOpenFileNames(self, "选择附件", "", "所有文件 (*.*)")if files:self.attachments.extend(files)self.attachment_list.addItems(files)self.status_bar.showMessage(f"已添加 {len(files)} 个附件")def remove_attachment(self):current_row = self.attachment_list.currentRow()if current_row >= 0:item = self.attachment_list.takeItem(current_row)del self.attachments[current_row]self.status_bar.showMessage(f"已移除附件: {item.text()}")else:self.status_bar.showMessage("请选择要移除的附件")def send_email(self):sender = self.sender_email.text()password = self.password.text()recipient = self.recipient_email.text()subject = self.subject.text()body = self.body.toPlainText()  # 使用纯文本格式if not sender or not password or not recipient:QMessageBox.warning(self, "输入错误", "请填写完整的发件人、密码和收件人信息")returntry:# 创建邮件对象msg = MIMEMultipart()msg['From'] = sendermsg['To'] = recipientmsg['Subject'] = subject# 添加邮件正文msg.attach(MIMEText(body, 'plain'))# 添加附件for file_path in self.attachments:try:with open(file_path, "rb") as attachment:part = MIMEBase("application", "octet-stream")part.set_payload(attachment.read())encoders.encode_base64(part)# 获取文件名filename = file_path.split('/')[-1] if '/' in file_path else file_pathfilename = filename.split('\\')[-1]  # 处理Windows路径part.add_header("Content-Disposition",f"attachment; filename={filename}",)msg.attach(part)except Exception as e:self.status_bar.showMessage(f"添加附件失败: {str(e)}")return# 连接SMTP服务器并发送邮件self.status_bar.showMessage("正在连接服务器...")server = smtplib.SMTP_SSL('smtp.gmail.com', 465)  # 使用Gmail SMTP服务器self.status_bar.showMessage("正在登录...")server.login(sender, password)self.status_bar.showMessage("正在发送邮件...")server.sendmail(sender, recipient, msg.as_string())server.quit()# 发送成功后的操作self.status_bar.showMessage("邮件发送成功!")QMessageBox.information(self, "发送成功", "邮件已成功发送!")# 清空附件列表self.attachment_list.clear()self.attachments = []except smtplib.SMTPAuthenticationError:QMessageBox.critical(self, "认证失败", "邮箱或密码错误,请检查您的登录信息")self.status_bar.showMessage("认证失败")except Exception as e:QMessageBox.critical(self, "发送失败", f"邮件发送失败: {str(e)}")self.status_bar.showMessage(f"发送失败: {str(e)}")if __name__ == "__main__":app = QApplication(sys.argv)# 设置应用样式palette = QPalette()palette.setColor(QPalette.Window, QColor(240, 242, 245))palette.setColor(QPalette.WindowText, QColor(51, 51, 51))palette.setColor(QPalette.Base, QColor(255, 255, 255))palette.setColor(QPalette.AlternateBase, QColor(248, 249, 250))palette.setColor(QPalette.Button, QColor(74, 144, 226))palette.setColor(QPalette.ButtonText, QColor(255, 255, 255))palette.setColor(QPalette.Highlight, QColor(74, 144, 226))palette.setColor(QPalette.HighlightedText, QColor(255, 255, 255))app.setPalette(palette)client = EmailClient()client.show()sys.exit(app.exec_())

功能说明

这个邮件客户端具有以下特点:

  1. 现代化UI设计

    • 蓝色主题与现代化界面元素
    • 分割布局(左侧设置区,右侧编辑区)
    • 响应式设计,适应1000x600窗口尺寸
  2. 邮件功能

    • 完整的邮件编写功能
    • 多附件支持(添加/移除)
    • SMTP邮件发送
  3. 用户体验优化

    • 状态提示(连接、登录、发送状态)
    • 详细的错误反馈
    • 清晰的视觉层次结构
  4. 布局优化

    • 左侧设置面板:发件人信息、收件人、主题、附件管理
    • 右侧编辑面板:邮件正文编辑区域
    • 底部状态栏:显示操作状态和反馈

使用说明

  1. 左侧设置面板

    • 输入发件人邮箱和密码
    • 输入收件人邮箱地址
    • 填写邮件主题
    • 管理附件(添加/移除)
  2. 右侧编辑面板

    • 在正文区域编写邮件内容
    • 点击"发送邮件"按钮发送
  3. 状态反馈

    • 状态栏显示当前操作状态
    • 发送成功/失败会有弹窗提示

技术特点

  1. 窗口尺寸

    • 主窗口设置为1000x600像素,提供宽敞的编辑空间
    • 使用QSplitter实现可调整大小的面板
  2. 邮件发送

    • 支持Gmail SMTP服务器(可修改为其他服务商)
    • 支持纯文本邮件内容
    • 支持多个附件发送
  3. 错误处理

    • 详细的错误捕获和反馈
    • 认证失败、发送失败等情况的专门处理

这个邮件客户端在保持功能完整性的同时,提供了更加现代化和专业的用户界面,充分利用了1000x600的窗口空间,为用户带来更舒适的邮件编辑体验。

eMailClient_qt5

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/909468.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

React【回顾】 深层次面试详解:函数式组件核心原理与高级优化

以下是对 React 深层次内容的全面解析,涵盖函数式组件的核心原理、性能优化、设计模式和最新特性: 🔧 一、React 核心机制剖析 1. Fiber 架构深解 Fiber 节点结构:function FiberNode(tag, pendingProps, key) {this.tag = tag; // 组件类型(函数组件=0, 类…

视觉语言模型的“视而不见“

这项研究发现,号称能“看图说话”的视觉语言模型(VLMs),在处理需要真正“看”懂图片的纯视觉任务(如判断深度、找对应点、认物体材质等)时,表现远不如它们自己内部的“眼睛”(视觉编…

Wyn 商业智能与 3D 大屏的深度融合应用

引言 在当今数字化快速发展的时代,数据可视化对于企业的决策和管理变得至关重要。商业智能软件作为数据可视化的重要工具,能够帮助企业将海量的数据转化为直观、易懂的信息。而 3D 大屏以其沉浸式、立体的展示效果,为数据可视化带来了全新的…

使用docker compose部署netmaker打通内网

准备 我看官网推荐都是使用ssl然后要ssl证书,不想走弯路了 一、docker-compose.yml version: "3.4"services:netmaker:container_name: netmakerimage: gravitl/netmaker:v0.90.0restart: unless-stoppedports:- "18081:18082"- "50051…

Linux集市采购指南[特殊字符]:yum和apt的“抢货”大战!

Linux集市采购指南🍅:yum和apt的“抢货”大战! ✨ 欢迎来到 Linux软件生态集市!这里分两大阵营: 🥬 CentOS/RHEL传统菜市场:派稳重的 yum 大叔当采购员,做事一板一眼;✨…

DataX 框架学习笔记

官方仓库: https://github.com/alibaba/DataX?tabreadme-ov-file 1. 介绍 1.1. 基本介绍: DadaX 是阿里云 DataWorks 数据集成 的开源版本(异构数据同步、离线数据同步工具 / 平台)。主要抽象为 Reader 和 Writer 插件&#…

MaxCompute的Logview分析详解

文章目录 一、Logview简介1、概述2、标题与功能3、基础信息 二、作业详情1、Job Details2、Fuxi Sensor3、Result①当前作业运行成功,显示的为运行结果。②当前作业运行失败,显示的为失败原因。 4、SourceXML5、SQL Script6、History7、SubStatusHistory…

HTML5白云飘飘动态效果教程

HTML5白云飘飘动态效果教程 这里写目录标题 HTML5白云飘飘动态效果教程效果介绍实现步骤步骤一:创建HTML结构步骤二:设计CSS样式步骤三:添加JavaScript交互 代码解析HTML结构解析CSS样式解析JavaScript功能解析 自定义调整总结 效果介绍 本教…

tcp高难度问题

以下是针对这些问题,在面试场景下,既保证理论扎实、逻辑清晰,又具备交流延展性的回答思路与内容,可根据实际面试节奏和面试官反馈灵活调整展开: 1. 客户端端口号如何确定的? 面试官您好,客户端…

广东省省考备考(第二十八天6.13)—资料分析(第二节课)

基期与现期 官方定义:作为对比参照的是基期,而相对于基期比较的是现期 通俗说法:时间靠前的为基期,时间靠后的为现期 增长量与增长率 增长量用来表述基期量与现期量变化的绝对量; 增长率用来表述基期量与现期量变化…

pytorch 中前向传播和后向传播的自定义函数

系列文章目录 文章目录 系列文章目录一、torch.autograd.function代码实例 在开始正文之前,请各位姥爷动动手指,给小店增加一点访问量吧,点击小店,同时希望我的文章对你的学习有所帮助。本文也很简单,主要讲解pytorch的…

【项目实训#08】HarmonyOS知识图谱前端可视化实现

【项目实训#08】HarmonyOS知识图谱前端可视化实现 文章目录 【项目实训#08】HarmonyOS知识图谱前端可视化实现一、背景简介二、技术方案与架构设计2.1 技术选型2.2 组件架构设计 三、知识图谱可视化组件实现3.1 KGResultTab组件设计组件模板结构不同状态的处理用户交互控制节点…

【软件开发】什么是DSL

什么是DSL DSL(Domain-Specific Language,领域特定语言)是一种为特定领域或任务设计的编程语言,目的在于提高该领域中的表达能力与开发效率。 1 在脚本语言中的 DSL 是什么? 在脚本语言(如 Python、Lua、…

JasperReport生成PDF/A类型文档

当JasperReport导出的文档为PDF/A模式时,该PDF为只读可以防止被修改。 设置导出参数 JRPdfExporter exporter new JRPdfExporter();exporter.setExporterInput(SimpleExporterInput.getInstance(jasperPrints));exporter.setExporterOutput(new SimpleOutputStre…

微信小程序使用画布实现飘落泡泡功能

微信小程序使用画布实现飘落泡泡功能:从组件封装到页面调用的完整实践 先看示例截图: 一、背景与技术选型 在微信小程序中实现类似于飘落的泡泡或者樱花飘落的功能,一般主要有 Canvas 和图片两种方案: (1&#xff…

使用STM32设置GPIO中断

使用S™ 32设置GPIO中断 中断示例按键中断实例设计:EXTI0和EXTI9硬件连接分析STM32代码实现代码说明 中断示例 设计一个按键中断的实例。设置两个中断:EXTI0、EXTI9, 在EXTI9的中断服务之程序中实现LED灯的控制 按键中断实例设计&#xff…

解决在微信小程序中view组件下的text和images设置了样式display: flex; align-items: center;对不齐

原始代码的问题 <view style"display: flex; align-items: center;"><text style"line-height: 1;">全国</text><image src"/images/xia.png" style"height: 20rpx; width: 20rpx; display: block;"></im…

归并排序详解:优雅的分治艺术

什么&#xff1f;归并排序&#xff1f;这让博主想起了大学那会被《数据结构与算法》支配的恐惧… 哈哈言归正传&#xff0c;一直想对算法做一个专栏&#xff0c;因为其实工作中很少很少有机会用到算法&#xff0c;倒是很多工具方法底层会使用&#xff0c;工作被各种需求业务“折…

新零售视域下实体与虚拟店融合的技术逻辑与商业模式创新——基于开源AI智能名片与链动2+1模式的S2B2C生态构建

摘要&#xff1a;新零售的核心在于打破线上线下边界&#xff0c;构建“人、货、场”的全场景融合生态。本文提出&#xff0c;实体线下店与虚拟店的协同发展是新零售的重要演进方向&#xff0c;其底层逻辑在于满足消费者作为“现实人”的体验需求与“虚拟人”的效率需求。通过引…

可视化图解算法51:寻找第K大(数组中的第K个最大的元素)

牛客网 面试笔试 TOP101 | LeetCode 215. 数组中的第K个最大元素 1. 题目 描述 有一个整数数组&#xff0c;请你找出数组中第 k 大的数。 给定一个整数数组 a ,同时给定它的大小n和要找的 k &#xff0c;请返回第 k 大的数(包括重复的元素&#xff0c;不用去重)&…