着色方法,color.empty,清空颜色,不要用color.white

博客提及着色方法,强调使用 color.empty 清空颜色,且提醒不要用 color.white 进行此操作,聚焦于信息技术领域的着色相关内容。
着色方法,color.empty,清空颜色,不要用color.white
import tkinter as tk from tkinter import ttk, simpledialog, messagebox, filedialog import pandas as pd import subprocess import queue from datetime import datetime import concurrent.futures import time import os import re from PIL import Image, ImageDraw, ImageFont import numpy as np class SettingsDialog(tk.Toplevel): """设置对话框""" def __init__(self, parent, current_settings): super().__init__(parent) self.title("监控设置") self.geometry("400x350") self.parent = parent self.settings = current_settings.copy() self.result = None # 使对话框模态化 self.transient(parent) self.grab_set() # 创建表单框架 form_frame = tk.Frame(self, padx=10, pady=10) form_frame.pack(fill=tk.BOTH, expand=True) # 线程数设置 tk.Label(form_frame, text="并发线程数 (1-1000):").grid(row=0, column=0, sticky=tk.W, pady=5) self.threads_var = tk.IntVar(value=self.settings['thread_count']) tk.Spinbox(form_frame, from_=1, to=1000, textvariable=self.threads_var, width=10).grid(row=0, column=1, sticky=tk.W, padx=5) # Ping间隔设置 tk.Label(form_frame, text="Ping间隔 (秒):").grid(row=1, column=0, sticky=tk.W, pady=5) self.interval_var = tk.DoubleVar(value=self.settings['ping_interval']) tk.Spinbox(form_frame, from_=0.1, to=10, increment=0.1, textvariable=self.interval_var, width=10).grid(row=1, column=1, sticky=tk.W, padx=5) # Ping超时设置 tk.Label(form_frame, text="Ping超时 (毫秒):").grid(row=2, column=0, sticky=tk.W, pady=5) self.timeout_var = tk.IntVar(value=self.settings['ping_timeout']) tk.Spinbox(form_frame, from_=100, to=5000, increment=100, textvariable=self.timeout_var, width=10).grid(row=2, column=1, sticky=tk.W, padx=5) # Excel文件路径 tk.Label(form_frame, text="Excel文件路径:").grid(row=3, column=0, sticky=tk.W, pady=5) self.excel_path_var = tk.StringVar(value=self.settings['excel_path']) tk.Entry(form_frame, textvariable=self.excel_path_var, width=30).grid(row=3, column=1, sticky=tk.W, padx=5) tk.Button(form_frame, text="浏览...", command=self.browse_excel).grid(row=3, column=2, padx=5) # 断开计数阈值 tk.Label(form_frame, text="断开报警阈值:").grid(row=4, column=0, sticky=tk.W, pady=5) self.threshold_var = tk.IntVar(value=self.settings['disconnect_threshold']) tk.Spinbox(form_frame, from_=1, to=100, increment=1, textvariable=self.threshold_var, width=10).grid(row=4, column=1, sticky=tk.W, padx=5) # 关键设备类型 tk.Label(form_frame, text="关键设备类型:").grid(row=5, column=0, sticky=tk.W, pady=5) self.critical_types_var = tk.StringVar(value=",".join(self.settings['critical_types'])) tk.Entry(form_frame, textvariable=self.critical_types_var, width=30).grid(row=5, column=1, columnspan=2, sticky=tk.W, padx=5) tk.Label(form_frame, text="(逗号分隔,如:二层交换机,三层交换机,服务器,UPS)").grid(row=6, column=1, sticky=tk.W, padx=5) # 按钮框架 button_frame = tk.Frame(self) button_frame.pack(pady=10) tk.Button(button_frame, text="确定", width=10, command=self.ok).grid(row=0, column=0, padx=10) tk.Button(button_frame, text="取消", width=10, command=self.cancel).grid(row=0, column=1, padx=10) self.protocol("WM_DELETE_WINDOW", self.cancel) def browse_excel(self): """浏览Excel文件""" file_path = filedialog.askopenfilename( filetypes=[("Excel files", "*.xlsx *.xls"), ("All files", "*.*")], title="选择设备列表Excel文件" ) if file_path: self.excel_path_var.set(file_path) def ok(self): """确定按钮处理""" self.settings = { 'thread_count': self.threads_var.get(), 'ping_interval': self.interval_var.get(), 'ping_timeout': self.timeout_var.get(), 'excel_path': self.excel_path_var.get(), 'disconnect_threshold': self.threshold_var.get(), 'critical_types': [t.strip() for t in self.critical_types_var.get().split(",")] } self.destroy() def cancel(self): """取消按钮处理""" self.settings = None self.destroy() def show(self): """显示对话框并返回设置""" self.wait_window() return self.settings class PingMonitorApp: def __init__(self, root): self.root = root self.root.title("IP Ping 监控工具 - 专业版") self.root.geometry("1100x700") # 窗口大小 # 控制面板框架 control_frame = tk.Frame(root) control_frame.pack(fill=tk.X, padx=10, pady=5) # 操作按钮框架 button_frame = tk.Frame(control_frame) button_frame.pack(side=tk.LEFT) # 开始/停止按钮 self.start_btn = tk.Button(button_frame, text="开始监控", command=self.toggle_monitoring, width=10) self.start_btn.pack(side=tk.LEFT, padx=5) # 设置按钮 self.settings_btn = tk.Button(button_frame, text="设置", command=self.open_settings, width=10) self.settings_btn.pack(side=tk.LEFT, padx=5) # 导出按钮 export_frame = tk.Frame(control_frame) export_frame.pack(side=tk.LEFT, padx=20) tk.Label(export_frame, text="导出断网设备:").pack(side=tk.LEFT) self.export_excel_btn = tk.Button(export_frame, text="Excel", command=self.export_disconnected_to_excel, width=8) self.export_excel_btn.pack(side=tk.LEFT, padx=2) self.export_txt_btn = tk.Button(export_frame, text="TXT", command=self.export_disconnected_to_txt, width=8) self.export_txt_btn.pack(side=tk.LEFT, padx=2) self.export_img_btn = tk.Button(export_frame, text="图片", command=self.export_disconnected_to_image, width=8) self.export_img_btn.pack(side=tk.LEFT, padx=2) # 状态指示框架 status_frame = tk.Frame(control_frame) status_frame.pack(side=tk.RIGHT) # 状态指示器 self.status_indicator = tk.Canvas(status_frame, width=20, height=20) self.status_indicator.pack(side=tk.LEFT, padx=5) self.draw_indicator("gray") # 初始灰色 # 速度显示 self.speed_label = tk.Label(status_frame, text="速度: --") self.speed_label.pack(side=tk.LEFT, padx=10) # 断开设备计数 self.disconnected_count = tk.IntVar(value=0) tk.Label(status_frame, text="断开设备:").pack(side=tk.LEFT) self.disconnected_label = tk.Label(status_frame, textvariable=self.disconnected_count) self.disconnected_label.pack(side=tk.LEFT, padx=5) # 创建表格 self.tree = ttk.Treeview(root) self.tree["columns"] = ("#1", "#2", "#3", "#4", "#5", "#6", "#7", "#8") self.tree.column("#0", width=0, stretch=tk.NO) # 隐藏首列 self.tree.column("#1", width=50, anchor=tk.CENTER) # 序号 self.tree.column("#2", width=160, anchor=tk.CENTER) # 时间戳 self.tree.column("#3", width=120, anchor=tk.CENTER) # sheet页名 self.tree.column("#4", width=120, anchor=tk.CENTER) # 设备IP self.tree.column("#5", width=150, anchor=tk.CENTER) # 车站 self.tree.column("#6", width=200, anchor=tk.CENTER) # 设备名称 self.tree.column("#7", width=100, anchor=tk.CENTER) # 断开次数 self.tree.column("#8", width=150, anchor=tk.CENTER) # Ping结果 self.tree.heading("#1", text="序号") self.tree.heading("#2", text="时间戳") self.tree.heading("#3", text="sheet页名") self.tree.heading("#4", text="设备IP") self.tree.heading("#5", text="车站") self.tree.heading("#6", text="设备名称") self.tree.heading("#7", text="断开次数") self.tree.heading("#8", text="Ping结果") self.tree.pack(fill=tk.BOTH, expand=True) # 配置标签颜色 self.tree.tag_configure("critical", background="#ffffcc") # 关键设备断开 - 黄色 self.tree.tag_configure("failed", background="#ffe6e6") # 普通设备超过阈值 - 红色 # 状态栏 self.status_var = tk.StringVar() self.status_bar = tk.Label(root, textvariable=self.status_var, bd=1, relief=tk.SUNKEN, anchor=tk.W) self.status_bar.pack(side=tk.BOTTOM, fill=tk.X) # 创建线程安全队列 self.results_queue = queue.Queue() self.device_queue = queue.Queue() # 存储所有设备信息 self.devices = [] self.device_map = {} # IP到设备的映射 # 线程控制 self.running = False self.thread_pool = None self.executor = None # 默认设置 self.settings = { 'thread_count': 100, 'ping_interval': 1.0, 'ping_timeout': 300, # 毫秒 'excel_path': "D:/1.xlsx", 'disconnect_threshold': 5, # 断开次数报警阈值 'critical_types': ['二层交换机', '三层交换机', '服务器', 'UPS'] # 关键设备类型 } # 性能统计 self.last_update_time = time.time() self.ping_count = 0 # 加载IP列表 self.load_ips() # GUI更新循环 self.update_gui() # 关闭窗口时清理资源 self.root.protocol("WM_DELETE_WINDOW", self.on_close) def draw_indicator(self, color): """绘制状态指示灯""" self.status_indicator.delete("all") self.status_indicator.create_oval(2, 2, 18, 18, fill=color, outline="black") def open_settings(self): """打开设置对话框""" # 如果正在运行,先停止监控 was_running = self.running if was_running: self.stop_monitoring() # 打开设置对话框 dialog = SettingsDialog(self.root, self.settings) new_settings = dialog.show() if new_settings: # 应用新设置 self.settings = new_settings self.status_var.set("设置已更新") # 重新加载设备列表 self.load_ips() # 如果之前正在运行,重新启动监控 if was_running: self.start_monitoring() def toggle_monitoring(self): """切换监控状态""" if self.running: self.stop_monitoring() self.start_btn.config(text="开始监控") self.draw_indicator("red") self.status_var.set("监控已停止") else: self.start_monitoring() self.start_btn.config(text="停止监控") self.draw_indicator("green") self.status_var.set("监控已启动") def is_critical_device(self, device_name): """检查设备是否为关键设备""" device_name = str(device_name).lower() for device_type in self.settings['critical_types']: if device_type.lower() in device_name: return True return False def load_ips(self): """从Excel文件加载设备信息""" try: # 读取Excel文件 excel_path = self.settings['excel_path'] if not os.path.exists(excel_path): self.status_var.set(f"错误:文件不存在 - {excel_path}") return xls = pd.ExcelFile(excel_path) # 存储所有设备 self.devices = [] self.device_map = {} device_counter = 1 # 遍历所有sheet页 for sheet_name in xls.sheet_names: df = pd.read_excel(excel_path, sheet_name=sheet_name) # 检查必要列是否存在 required_columns = ["设备IP", "车站", "设备名称"] if not all(col in df.columns for col in required_columns): self.status_var.set(f"错误:Sheet '{sheet_name}' 缺少必要列") continue # 提取设备信息 for _, row in df.iterrows(): ip = row["设备IP"] device_name = row["设备名称"] # 检查设备是否为关键设备 is_critical = self.is_critical_device(device_name) device_info = { "id": device_counter, "sheet": sheet_name, "ip": ip, "station": row["车站"], "device_name": device_name, "is_critical": is_critical, # 标记关键设备 "status": "等待开始...", "timestamp": "", "success": None, "last_failed": False, # 记录最近一次是否失败 "disconnect_count": 0, # 断开次数计数器 "last_ping_time": 0, # 上次Ping时间 "last_status_change": None # 上次状态变更时间 } self.devices.append(device_info) self.device_map[ip] = device_info device_counter += 1 self.status_var.set(f"成功加载 {len(self.devices)} 个设备,点击开始按钮开始监控") # 清空设备队列 while not self.device_queue.empty(): self.device_queue.get_nowait() # 清空表格并添加设备 self.tree.delete(*self.tree.get_children()) for device in self.devices: self.tree.insert("", "end", values=( device["id"], device["timestamp"], device["sheet"], device["ip"], device["station"], device["device_name"], device["disconnect_count"], device["status"] )) # 添加设备到队列 self.device_queue.put(device["ip"]) except Exception as e: self.status_var.set(f"加载Excel文件错误: {str(e)}") def start_monitoring(self): """启动监控服务""" if not self.running: self.running = True self.executor = concurrent.futures.ThreadPoolExecutor( max_workers=self.settings['thread_count']) # 启动线程池工作线程 for _ in range(self.settings['thread_count']): self.executor.submit(self.ping_worker) # 更新设备状态 for device in self.devices: device["status"] = "监控中..." self.status_var.set(f"监控已启动 ({self.settings['thread_count']}线程)") def stop_monitoring(self): """停止监控服务""" if self.running: self.running = False if self.executor: self.executor.shutdown(wait=False) # 更新设备状态 for device in self.devices: device["status"] = "已停止" self.status_var.set("监控已停止") def ping_worker(self): """工作线程:执行Ping操作""" while self.running: try: # 从队列获取设备IP ip = self.device_queue.get(timeout=1.0) # 检查设备是否存在 if ip not in self.device_map: self.device_queue.put(ip) continue device = self.device_map[ip] # 检查是否需要Ping(根据时间间隔) current_time = time.time() if current_time - device["last_ping_time"] < self.settings['ping_interval']: # 还没到时间,放回队列等待 self.device_queue.put(ip) time.sleep(0.01) # 短暂休眠避免忙等待 continue # 更新最后Ping时间 device["last_ping_time"] = current_time # 执行Ping命令 timeout_ms = self.settings['ping_timeout'] result = subprocess.run( ["ping", "-n", "1", "-w", str(timeout_ms), str(ip)], capture_output=True, text=True ) # 解析结果 timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") success = "请求超时" not in result.stdout and "无法访问" not in result.stdout status = "成功" if success else "失败" # 更新性能计数 self.ping_count += 1 # 将结果放入队列 self.results_queue.put((ip, timestamp, status, success)) # 将设备放回队列以继续监控 self.device_queue.put(ip) except queue.Empty: # 如果队列为空,短暂休眠后重试 time.sleep(0.1) except Exception as e: self.results_queue.put((None, None, f"错误: {str(e)}", False)) time.sleep(1.0) # 出错时休眠避免频繁错误 def update_gui(self): """更新GUI界面,确保不通的设备显示在最上方""" try: # 更新性能统计 if self.running: current_time = time.time() if current_time - self.last_update_time >= 1.0: # 每秒更新一次速度 speed = self.ping_count / (current_time - self.last_update_time) self.speed_label.config(text=f"速度: {speed:.1f} Ping/秒") self.last_update_time = current_time self.ping_count = 0 # 处理结果队列 disconnected_devices = 0 while not self.results_queue.empty(): ip, timestamp, status, success = self.results_queue.get_nowait() if ip and ip in self.device_map: device = self.device_map[ip] # 记录状态变更 if success != device["success"]: device["last_status_change"] = timestamp # 更新断开次数 if not success: device["disconnect_count"] += 1 device["timestamp"] = timestamp device["status"] = status device["success"] = success device["last_failed"] = not success self.results_queue.task_done() # 重新排序设备:不通的设备在前,通的在后 self.devices.sort(key=lambda x: (not x["last_failed"], x["id"])) # 清空表格并重新添加所有设备(按新顺序) self.tree.delete(*self.tree.get_children()) disconnected_devices = 0 for device in self.devices: if not device["success"]: disconnected_devices += 1 # 根据设备状态和类型设置标签 tags = () if not device["success"]: # 设备断开 if device["is_critical"]: # 关键设备断开(黄色) tags = ("critical",) elif device["disconnect_count"] >= self.settings['disconnect_threshold']: # 普通设备超过阈值(红色) tags = ("failed",) self.tree.insert("", "end", values=( device["id"], device["timestamp"], device["sheet"], device["ip"], device["station"], device["device_name"], device["disconnect_count"], device["status"] ), tags=tags) # 更新断开设备计数 self.disconnected_count.set(disconnected_devices) except queue.Empty: pass except Exception as e: self.status_var.set(f"GUI更新错误: {str(e)}") # 每100毫秒检查一次更新 self.root.after(100, self.update_gui) def on_close(self): """关闭窗口时的清理操作""" self.running = False if self.executor: self.executor.shutdown(wait=False) self.root.destroy() def get_disconnected_devices(self): """获取所有断网设备列表""" return [device for device in self.devices if not device["success"]] def export_disconnected_to_excel(self): """导出断网设备到Excel文件(已取消关键设备列)""" disconnected = self.get_disconnected_devices() if not disconnected: messagebox.showinfo("无断网设备", "当前没有断网设备") return try: # 创建DataFrame data = [] for device in disconnected: data.append({ "序号": device["id"], "时间戳": device["timestamp"], "Sheet页名": device["sheet"], "设备IP": device["ip"], "车站": device["station"], "设备名称": device["device_name"], "断开次数": device["disconnect_count"], "状态": device["status"] }) df = pd.DataFrame(data) # 弹出保存对话框 file_path = filedialog.asksaveasfilename( defaultextension=".xlsx", filetypes=[("Excel 文件", "*.xlsx"), ("所有文件", "*.*")], title="保存断网设备列表" ) if not file_path: # 用户取消 return # 保存到Excel df.to_excel(file_path, index=False) self.status_var.set(f"成功导出 {len(disconnected)} 个断网设备到 {file_path}") except Exception as e: messagebox.showerror("导出错误", f"导出Excel时出错: {str(e)}") def export_disconnected_to_txt(self): """导出断网设备到TXT文件(已取消关键设备列)""" disconnected = self.get_disconnected_devices() if not disconnected: messagebox.showinfo("无断网设备", "当前没有断网设备") return try: # 弹出保存对话框 file_path = filedialog.asksaveasfilename( defaultextension=".txt", filetypes=[("文本文件", "*.txt"), ("所有文件", "*.*")], title="保存断网设备列表" ) if not file_path: # 用户取消 return # 写入文件 with open(file_path, "w", encoding="utf-8") as f: # 写入标题行 f.write("序号\t时间戳\tSheet页名\t设备IP\t车站\t设备名称\t断开次数\t状态\n") # 写入设备数据 for device in disconnected: f.write(f"{device['id']}\t{device['timestamp']}\t{device['sheet']}\t") f.write(f"{device['ip']}\t{device['station']}\t{device['device_name']}\t") f.write(f"{device['disconnect_count']}\t{device['status']}\n") self.status_var.set(f"成功导出 {len(disconnected)} 个断网设备到 {file_path}") except Exception as e: messagebox.showerror("导出错误", f"导出TXT时出错: {str(e)}") def export_disconnected_to_image(self): """导出断网设备到图片文件(已取消关键设备列)""" disconnected = self.get_disconnected_devices() if not disconnected: messagebox.showinfo("无断网设备", "当前没有断网设备") return try: # 弹出保存对话框 file_path = filedialog.asksaveasfilename( defaultextension=".png", filetypes=[("PNG 图片", "*.png"), ("JPEG 图片", "*.jpg"), ("所有文件", "*.*")], title="保存断网设备列表图片" ) if not file_path: # 用户取消 return # 创建图片 columns = ["序号", "时间戳", "Sheet页名", "设备IP", "车站", "设备名称", "断开次数", "状态"] row_height = 30 col_widths = [50, 160, 120, 120, 150, 200, 100, 150] header_height = 40 # 计算图片尺寸 width = sum(col_widths) + 20 height = header_height + len(disconnected) * row_height + 40 # 创建白色背景图片 img = Image.new("RGB", (width, height), "white") draw = ImageDraw.Draw(img) try: # 尝试加载系统字体 font = ImageFont.truetype("simsun.ttc", 12) # 宋体 header_font = ImageFont.truetype("simsun.ttc", 14, encoding="unic") except: # 回退到默认字体 font = ImageFont.load_default() header_font = ImageFont.load_default() # 绘制标题 draw.text((10, 10), f"断网设备列表 - 共 {len(disconnected)} 台", fill="black", font=header_font) # 绘制表头 x = 10 for i, col in enumerate(columns): draw.rectangle([x, header_height, x + col_widths[i], header_height + row_height], outline="black") draw.text((x + 5, header_height + 5), col, fill="black", font=font) x += col_widths[i] # 绘制设备行 y = header_height + row_height for device in disconnected: x = 10 values = [ str(device["id"]), device["timestamp"], device["sheet"], device["ip"], device["station"], device["device_name"], str(device["disconnect_count"]), device["status"] ] # 根据设备类型设置行背景色 bg_color = "white" if not device["success"]: if device["is_critical"]: bg_color = "#ffffcc" # 黄色 elif device["disconnect_count"] >= self.settings['disconnect_threshold']: bg_color = "#ffe6e6" # 红色 # 绘制行背景 draw.rectangle([x, y, width - 10, y + row_height], fill=bg_color) # 绘制单元格内容 for i, value in enumerate(values): draw.rectangle([x, y, x + col_widths[i], y + row_height], outline="black") draw.text((x + 5, y + 5), str(value), fill="black", font=font) x += col_widths[i] y += row_height # 保存图片 img.save(file_path) self.status_var.set(f"成功导出 {len(disconnected)} 个断网设备图片到 {file_path}") except Exception as e: messagebox.showerror("导出错误", f"导出图片时出错: {str(e)}") if __name__ == "__main__": root = tk.Tk() app = PingMonitorApp(root) root.mainloop() 添加导出时设备名称中有二层交换机,三层交换机,服务器,UPS时直接标记为黄色,sheet页和车站名称相同的情况下设备名称中有AGM超过3台,TVM超过2台标记为红色,源代码保持不变
最新发布
11-27
import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot3d import Axes3D import matplotlib.animation as animation from matplotlib import font_manager as fm import matplotlib.patheffects as path_effects # 设置中文字体 plt.rcParams['font.sans-serif'] = ['SimHei', 'Microsoft YaHei'] # 用来正常显示中文标签 plt.rcParams['axes.unicode_minus'] = False # 用来正常显示负号 # 创建图形和3D坐标轴 fig = plt.figure(figsize=(10, 8)) ax = fig.add_subplot(111, projection='3d') # 设置背景颜色 fig.patch.set_facecolor('black') ax.set_facecolor('black') # 隐藏坐标轴 ax.set_axis_off() # 设置视角 ax.view_init(elev=30, azim=45) # 创建爱心函数 def heart_3d(t): x = 16 * np.sin(t) ** 3 y = 13 * np.cos(t) - 5 * np.cos(2 * t) - 2 * np.cos(3 * t) - np.cos(4 * t) z = np.sin(t) * 5 # 添加z坐标使其成为3D return x, y, z # 生成爱心数据 t = np.linspace(0, 2 * np.pi, 1000) x, y, z = heart_3d(t) # 创建动画函数 def update(frame): ax.clear() ax.set_facecolor('black') ax.set_axis_off() # 设置视角旋转 ax.view_init(elev=20, azim=frame / 2) # 绘制3D爱心 colors = plt.cm.rainbow(np.linspace(0, 1, len(x))) for i in range(len(x) - 1): ax.plot([x[i], x[i + 1]], [y[i], y[i + 1]], [z[i], z[i + 1]], color='pink', linewidth=3, alpha=0.8) # 添加填充效果 ax.plot_trisurf(x, y, z, color='pink', alpha=0.3) # 添加文字 text = ax.text(0, 0, 5, "王绾绾,我爱你", fontsize=24, color='red', ha='center', va='center', fontweight='bold') # 添加文字特效 text.set_path_effects([path_effects.withStroke(linewidth=3, foreground='white')]) # 设置坐标轴范围 ax.set_xlim(-20, 20) ax.set_ylim(-20, 20) ax.set_zlim(-10, 10) return ax, # 创建动画 ani = animation.FuncAnimation(fig, update, frames=360, interval=50, blit=False) # 显示动画 plt.tight_layout() plt.show() # 如果需要保存动画,取消下面的注释 # ani.save('heart_animation.gif', writer='pillow', fps=20)
09-29
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值