如何优雅的接入deepseek做一个优雅的聊天机器人~

写这个脚本是因为我想做个聊天机器人,能自动的帮我分析报错日志文档。并且分析文档出现的问题是否有问题。后续有时间再继续整理吧。

后续打算加上一个爬虫模块,自动接入jira,自动爬取文件爬取报错日志了。并分析用户给入的文档是不是有重复的,如果没有重复的话,就自动将日志上报提交。

import tkinter as tk
from datetime import datetime
from tkinter import scrolledtext, filedialog, messagebox
from tkinter import simpledialog
import threading
import os
import json
from openai import OpenAI
from pathlib import Path
import queue
class DeepSeekChat:
    def __init__(self, system_prompt=None):
        self.client = self._initialize_client()
        self.system_prompt = system_prompt or "You are a helpful assistant"
        self.history = [
            {"role": "system", "content": self.system_prompt}
        ]
        
    def _initialize_client(self):
        """初始化 API 客户端"""
        home_dir = str(Path.home())
        key_file_path = os.path.join(home_dir, '.api\\deepseekapi.txt')
        
        with open(key_file_path, 'r') as file:
            api_key = file.read().strip()
            
        return OpenAI(
            api_key=api_key,
            base_url="https://api.deepseek.com"
        )

    def update_system_prompt(self, new_prompt):
        """更新系统角色设定"""
        self.system_prompt = new_prompt
        # 保留历史对话但更新系统提示
        self.history[0]["content"] = new_prompt
        return f"系统提示已更新为:{new_prompt}"

    def chat(self, user_input):
        """执行单次对话并返回助手回复"""
        self.history.append({"role": "user", "content": user_input})
        
        # 默认推理者模式
        response = self.client.chat.completions.create(
            model="deepseek-reasoner",
            messages=self.history,
            max_tokens= 8192,
            temperature = 0,
            stream=False
        )
        
        assistant_response = response.choices[0].message.content
        self.history.append({"role": "assistant", "content": assistant_response})
        return assistant_response

    def start_chat_session(self):
        """启动交互式对话会话"""
        print(f"DeepSeek 聊天助手已启动(系统角色:{self.system_prompt})")
        print("输入 'exit' 退出,'reset' 重置对话历史\n")
        
        while True:
            try:
                user_input = input("用户: ")
                if user_input.lower() == 'exit':
                    print("\n对话结束!")
                    break
                if user_input.lower() == 'reset':
                    self.history = [{"role": "system", "content": self.system_prompt}]
                    print("\n对话历史已重置\n")
                    continue
                
                response = self.chat(user_input)
                print(f"\n助手: {response}\n")
                
            except KeyboardInterrupt:
                print("\n对话已中断")
                break

    def save_history(self, file_path):
        """保存对话历史到文件(支持中文可读)"""
        with open(file_path, 'w', encoding='utf-8') as f:
            json.dump({
                "system_prompt": self.system_prompt,
                "history": self.history
            }, f, indent=2, ensure_ascii=False)  # 关键参数

    def load_history(self, file_path):
        """从文件加载对话历史(支持中文)"""
        with open(file_path, 'r', encoding='utf-8') as f:
            data = json.load(f)
            self.system_prompt = data["system_prompt"]
            self.history = data["history"]

class ChatUI:
    def __init__(self, chat_bot):
        self.chat_bot = chat_bot
        self.window = tk.Tk()
        self.window.title("DeepSeek 智能助手")
        
        # 设置窗口尺寸
        self.window.geometry("800x600")
        
        # 新增日志相关属性
        self.current_log_path = None
        self.log_window = None
        self.selected_log_files =None
        self.anaylze_report = None
        
        # 创建菜单栏
        self._create_menu()
        
        # 创建界面组件
        self._create_widgets()
        
        
        # 绑定回车键事件
        self.window.bind('<Return>', lambda event: self.send_message())
        
    def _create_menu(self):
        """创建菜单栏"""
        menubar = tk.Menu(self.window)
        
        # 文件菜单
        file_menu = tk.Menu(menubar, tearoff=0)
        file_menu.add_command(label="保存对话", command=self.save_dialog)
        file_menu.add_command(label="加载对话", command=self.load_dialog)
        menubar.add_cascade(label="文件", menu=file_menu)

        # 日志菜单
        log_menu = tk.Menu(menubar, tearoff=0)
        log_menu.add_command(label="选择日志文件", command=self.select_log_file)
        log_menu.add_command(label="批量分析日志", command=self.analyze_logs)  # 修改菜单项名称
        log_menu.add_command(label="文档重复性分析", command=self.repet_analyze_logs)
        menubar.add_cascade(label="日志分析", menu=log_menu)
        
        # 设置菜单
        config_menu = tk.Menu(menubar, tearoff=0)
        config_menu.add_command(label="修改角色设定", command=self.change_prompt)
        config_menu.add_command(label="重置对话", command=self.reset_chat)
        menubar.add_cascade(label="设置", menu=config_menu)
        
        self.window.config(menu=menubar)
    
    def select_log_file(self):
        """选择多个日志文件"""
        file_paths = filedialog.askopenfilenames(
            filetypes=[("日志文件", "*.log *.txt"), ("所有文件", "*.*")]
        )
        if file_paths:
            self.selected_log_files = file_paths
            self.status_bar.config(
                text=f"已选择 {len(file_paths)} 个日志文件 | 角色设定: {self.chat_bot.system_prompt}"
            )
            messagebox.showinfo("成功", f"已选择 {len(file_paths)} 个日志文件")

    # 这一部分的代码需要好好改一下,我想要的是能分析已分析的日志,然后对比日志错误是不是有重复的
    def repet_analyze_logs(self):
        # 基本校验
        if not self.selected_log_files or len(self.selected_log_files) != 1:
            messagebox.showwarning("警告", "请选择且只能选择一个日志文件")
            return
        
        # 创建分析任务窗口
        self.log_window = tk.Toplevel(self.window)
        self.log_window.title("日志分析任务")
        self.log_window.geometry("400x300")

        # 任务类型选择
        task_frame = tk.LabelFrame(self.log_window, text="分析任务类型")
        task_frame.pack(padx=10, pady=5, fill=tk.X)

        self.task_type = tk.StringVar(value="summary")
        tasks = [
            ("总结日志", "summary"),
            ("错误分析", "error"),
            ("性能分析", "performance"),
            ("自定义任务", "custom")
        ]
        for text, value in tasks:
            tk.Radiobutton(
                task_frame,
                text=text,
                variable=self.task_type,
                value=value
            ).pack(anchor=tk.W)

        # 自定义任务输入
        self.custom_task_entry = tk.Entry(
            self.log_window,
            font=("微软雅黑", 10),
            width=40
        )
        self.custom_task_entry.pack(padx=10, pady=5, fill=tk.X)
        self.custom_task_entry.insert(0, "请输入自定义分析要求...")
        self.custom_task_entry.config(fg="grey")
        self.custom_task_entry.bind("<FocusIn>", self._clear_placeholder)
        self.custom_task_entry.bind("<FocusOut>", self._restore_placeholder)

        # 分析按钮
        analyze_btn = tk.Button(
            self.log_window,
            text="开始分析",
            command=self.log_repetitiveness_start_analysis,
            font=("微软雅黑", 12)
        )
        analyze_btn.pack(pady=10)

    def analyze_logs(self):
        """创建日志分析任务窗口(支持多文件)"""
        if not hasattr(self, 'selected_log_files') or not self.selected_log_files:
            messagebox.showwarning("警告", "请先选择日志文件")
            return

        # 创建分析任务窗口
        self.log_window = tk.Toplevel(self.window)
        self.log_window.title("日志分析任务")
        self.log_window.geometry("400x300")

        # 任务类型选择
        task_frame = tk.LabelFrame(self.log_window, text="分析任务类型")
        task_frame.pack(padx=10, pady=5, fill=tk.X)

        self.task_type = tk.StringVar(value="summary")
        tasks = [
            ("总结日志", "summary"),
            ("错误分析", "error"),
            ("性能分析", "performance"),
            ("自定义任务", "custom")
        ]
        for text, value in tasks:
            tk.Radiobutton(
                task_frame,
                text=text,
                variable=self.task_type,
                value=value
            ).pack(anchor=tk.W)

        # 自定义任务输入
        self.custom_task_entry = tk.Entry(
            self.log_window,
            font=("微软雅黑", 10),
            width=40
        )
        self.custom_task_entry.pack(padx=10, pady=5, fill=tk.X)
        self.custom_task_entry.insert(0, "请输入自定义分析要求...")
        self.custom_task_entry.config(fg="grey")
        self.custom_task_entry.bind("<FocusIn>", self._clear_placeholder)
        self.custom_task_entry.bind("<FocusOut>", self._restore_placeholder)

        # 分析按钮
        analyze_btn = tk.Button(
            self.log_window,
            text="开始分析",
            command=self.start_log_analysis,
            font=("微软雅黑", 12)
        )
        analyze_btn.pack(pady=10)

    def _clear_placeholder(self, event):
        if self.custom_task_entry.get() == "请输入自定义分析要求...":
            self.custom_task_entry.delete(0, tk.END)
            self.custom_task_entry.config(fg="black")

    def _restore_placeholder(self, event):
        if not self.custom_task_entry.get():
            self.custom_task_entry.insert(0, "请输入自定义分析要求...")
            self.custom_task_entry.config(fg="grey")
    # 这一部分的代码会卡住主窗口,导致主窗口无响应
    def log_repetitiveness_start_analysis(self):
        """启动文档重复性分析流程(优化线程版)"""
        # 基本校验
        if not self.selected_log_files or len(self.selected_log_files) != 1:
            messagebox.showwarning("警告", "请选择且只能选择一个日志文件")
            return
        
        # 关闭分析窗口
        self.log_window.destroy()
        
        # 禁用输入并清空输入队列
        self._toggle_input(False)
        self._create_analysis_worker()

    def _create_analysis_worker(self):
        """创建后台分析线程"""
        # 创建任务队列
        self.analysis_queue = queue.Queue()
        
        # 启动后台线程
        threading.Thread(target=self._analysis_worker, daemon=True).start()
        
        # 启动队列处理器
        self.window.after(100, self._process_analysis_queue)

    def _analysis_worker(self):
        """后台分析工作线程"""
        try:
            # 创建保存目录
            report_dir = os.path.join(os.getcwd(), "analysis_reports")
            os.makedirs(report_dir, exist_ok=True)

            # 第一阶段:分析当前日志文件
            log_path = self.selected_log_files[0]
            self._put_queue_action("update_status", f"正在分析: {os.path.basename(log_path)}...")
            
            # 读取并分析日志
            log_content = self._read_log_content(log_path)
            if not log_content:
                return

            # 生成分析报告
            custom_task = self.custom_task_entry.get().strip() if self.task_type.get() == "custom" else ""
            analysis_prompt = self._build_analysis_prompt(log_content, self.task_type.get(), custom_task)
            temp_bot = self._create_temp_bot()
            analysis_report = temp_bot.chat(analysis_prompt)

            # 保存初步分析报告
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            report_filename = f"analysis_{timestamp}.txt"
            report_path = os.path.join(report_dir, report_filename)
            self._save_analysis_report(report_path, analysis_report, "初步分析")

            # 第二阶段:对比历史报告
            compare_dir = os.path.join(os.getcwd(), "err_reporter/err_report")
            if not os.path.exists(compare_dir):
                self._put_queue_action("show_info", "无历史分析报告可供对比")
                return

            # 获取所有历史分析报告
            history_reports = [
                f for f in os.listdir(compare_dir) 
                if f.endswith(".txt") and f != report_filename
            ]

            # 执行对比分析
            total = len(history_reports)
            for idx, report_file in enumerate(history_reports, 1):
                self._put_queue_action("update_status", f"正在对比报告 ({idx}/{total}): {report_file}...")
                
                # 读取历史报告内容
                history_path = os.path.join(compare_dir, report_file)
                history_content = self._read_analysis_report(history_path)
                
                # 生成对比请求
                compare_prompt = self._build_comparison_prompt(analysis_report, history_content)
                self.get_response(compare_prompt)

            self._put_queue_action("complete", f"分析完成,生成报告: {report_filename}")

        except Exception as e:
            self._put_queue_action("error", f"分析出错: {str(e)}")
        finally:
            self._put_queue_action("finalize")

    def _process_analysis_queue(self):
        """处理分析队列(主线程执行)"""
        try:
            while True:
                action = self.analysis_queue.get_nowait()
                
                if action[0] == "update_status":
                    self._update_status(action[1])
                elif action[0] == "send_request":
                    self.input_entry.delete(0, tk.END)
                    self.input_entry.insert(0, action[1])
                    self.send_message()
                elif action[0] == "show_info":
                    messagebox.showinfo("提示", action[1])
                elif action[0] == "error":
                    self._update_status(action[1], is_error=True)
                elif action[0] == "complete":
                    self._update_status(action[1], show_dialog=True)
                elif action[0] == "finalize":
                    self._toggle_input(True)
                    self._update_status("就绪")
                    return
                
        except queue.Empty:
            self.window.after(100, self._process_analysis_queue)

    def _put_queue_action(self, action_type, data=None):
        """向队列添加操作"""
        self.analysis_queue.put((action_type, data))



    def _save_analysis_report(self, path, content, analysis_type):
        """保存分析报告(改进版)"""
        try:
            header = (
                f"=== 分析报告 ===\n"
                f"生成时间: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
                f"分析类型: {analysis_type}\n"
                f"文件大小: {os.path.getsize(path) if os.path.exists(path) else 0} bytes\n"
                "=========================\n\n"
            )
            
            with open(path, "w", encoding="utf-8") as f:
                f.write(header + content)
                
            self._update_status(f"报告已保存: {os.path.basename(path)}")
        except Exception as e:
            self._update_status(f"保存失败: {str(e)}", is_error=True)

    def _read_analysis_report(self, path):
        """读取分析报告内容"""
        try:
            with open(path, "r", encoding="utf-8") as f:
                return f.read(8192)  # 限制读取长度
        except Exception as e:
            self._update_status(f"读取报告失败: {os.path.basename(path)}", is_error=True)
            return "无法读取历史报告内容"

    def _build_comparison_prompt(self, current_report, history_report):
        """构建对比分析提示词"""
        return (
            "[日志相似度分析任务]\n"
            "请分析以下两个异常报告的相似性:\n"
            "1. 文件名"
            "2. 异常或者错误类型的重复程度(0-100%评分)\n"
            "3. 堆栈特征的相似性\n"
            "4. 上下文模式匹配度\n"
            "5. 可能属于同一根源的可能性\n"
            "6. 回复准确的答案,是或者不是"
            "\n[当前报告]\n" + current_report[:4000] +  # 限制内容长度
            "\n\n[历史报告]\n" + history_report[:4000] +
            "\n\n请用Markdown表格形式展示对比结果"
        )

            
    def start_log_analysis(self):
        """启动多文件分析流程"""
        task_type = self.task_type.get()
        custom_task = self.custom_task_entry.get().strip() if task_type == "custom" else ""
        
        # 关闭分析窗口
        self.log_window.destroy()
        
        # 启动后台处理线程
        threading.Thread(
            target=self._process_log_files,
            args=(task_type, custom_task)
        ).start()

    def _process_log_files(self, task_type, custom_task):
        """处理所有选中的日志文件"""
        try:
            total = len(self.selected_log_files)
            for idx, log_path in enumerate(self.selected_log_files, 1):
                # 更新状态
                self._update_status(f"正在分析 ({idx}/{total}): {os.path.basename(log_path)}...")
                
                # 读取日志内容
                log_content = self._read_log_content(log_path)
                if not log_content:
                    continue
                
                # 构造提示词
                prompt = self._build_analysis_prompt(log_content, task_type, custom_task)
                
                # 使用独立实例避免污染对话历史
                temp_bot = self._create_temp_bot()
                response = temp_bot.chat(prompt)
                
                # 保存分析结果
                self._save_analysis_result(log_path, response, task_type)
 
            self._update_status(f"分析完成,已处理 {total} 个文件", show_dialog=True)
        except Exception as e:
            self._update_status(f"分析出错: {str(e)}", is_error=True)
        finally:
            self._update_status("就绪")

    def _read_log_content(self, file_path):
        """安全读取日志内容(带截断)"""
        try:
            content = []
            with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
                while (chunk := f.read(40960)) and sum(len(c) for c in content) <= 15000:
                    content.append(chunk)
            if sum(len(c) for c in content) > 15000:
                content.append("\n[日志内容已截断...]")
            return "".join(content)
        except Exception as e:
            self._update_status(f"读取失败: {os.path.basename(file_path)}", is_error=True)
            return None

    def _build_analysis_prompt(self, content, task_type, custom_task):
        """构建分析提示模板"""
        task_mapping = {
            "summary": (
                "请分析以下日志并生成结构化报告:\n"
                "1. 按时间顺序总结关键事件\n"
                "2. 统计错误级别分布\n"
                "3. 列出出现频率最高的5个异常关键词\n"
                "4. 发现的重要异常信息"
            ),
            "error": (
                "请按以下格式分析日志错误:\n"
                "1. 错误总数统计\n"
                "2. 错误类型分类统计\n"
                "3. 首次/末次错误发生时间\n"
                "4. 错误关联性分析"
            ),
            "performance": (
                "请从以下维度分析性能指标:\n"
                "1. 响应时间分布统计\n"
                "2. 资源使用峰值检测\n"
                "3. 潜在性能瓶颈定位\n"
                "4. 优化建议"
            ),
            "custom": custom_task
        }
        
        prompt = task_mapping.get(task_type, "")

        return f"[分析任务]\n{prompt}\n\n[日志内容]\n{content}"

    def _save_analysis_result(self, src_path, result, task_type):
        """保存分析结果到文件"""
        try:
            base_name = os.path.basename(src_path)
            timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
            save_name = os.path.join("./err_reporter/err_report",f"{base_name}_{task_type}_analysis_{timestamp}.txt")
            
            with open(save_name, "w", encoding="utf-8") as f:
                f.write(f"=== 日志分析报告 ===\n")
                f.write(f"源文件: {base_name}\n")
                f.write(f"分析类型: {task_type}\n")
                f.write(f"生成时间: {timestamp}\n\n")
                f.write(result)
            
            self._update_status(f"已保存: {save_name}")
        except Exception as e:
            self._update_status(f"保存失败: {str(e)}", is_error=True)

    def _create_temp_bot(self):
        """创建临时聊天实例"""
        # 根据实际ChatBot实现调整初始化参数
        temp_bot = DeepSeekChat()
        temp_bot.update_system_prompt(self.chat_bot.system_prompt)
        return temp_bot

    def _update_status(self, text, is_error=False, show_dialog=False):
        """线程安全的状态更新"""
        def update():
            self.status_bar.config(text=text)
            if is_error:
                messagebox.showerror("错误", text)
            if show_dialog:
                messagebox.showinfo("完成", text)
        self.status_bar.after(0, update)

    def _send_analysis_request(self, prompt):
        """发送分析请求的通用方法"""
        self.input_entry.delete(0, tk.END)
        self.input_entry.insert(0, prompt)
        self.send_message()

    def _create_widgets(self):
        """创建界面组件"""
        # 历史对话显示区域
        self.history_area = scrolledtext.ScrolledText(
            self.window,
            wrap=tk.WORD,
            font=("微软雅黑", 12)
        )
        self.history_area.pack(padx=10, pady=10, fill=tk.BOTH, expand=True)
        self.history_area.config(state=tk.DISABLED)
        
        # 输入区域框架
        input_frame = tk.Frame(self.window)
        input_frame.pack(padx=10, pady=10, fill=tk.X)
        
        # 用户输入框
        self.input_entry = tk.Entry(
            input_frame,
            font=("微软雅黑", 12),
            width=50
        )
        self.input_entry.pack(side=tk.LEFT, fill=tk.X, expand=True)
        self.input_entry.focus_set()
        
        # 发送按钮
        send_btn = tk.Button(
            input_frame,
            text="发送",
            command=self.send_message,
            font=("微软雅黑", 12),
            width=8
        )
        send_btn.pack(side=tk.RIGHT, padx=(10, 0))
        
        # 状态栏
        self.status_bar = tk.Label(
            self.window,
            text=f"当前角色设定: {self.chat_bot.system_prompt}",
            anchor=tk.W,
            font=("微软雅黑", 10)
        )
        self.status_bar.pack(side=tk.BOTTOM, fill=tk.X)

    def send_message(self):
        """处理消息发送"""
        user_input = self.input_entry.get().strip()
        if not user_input:
            return
        
        # 清空输入框
        self.input_entry.delete(0, tk.END)
        
        # 显示用户消息
        self._append_message("用户", user_input)
        
        # 在独立线程中处理API请求
        threading.Thread(target=self.get_response, args=(user_input,)).start()

    def get_response(self, user_input):
        """获取助手回复"""
        try:
            # 禁用输入控件
            self._toggle_input(False)
            
            # 获取回复
            response = self.chat_bot.chat(user_input)
            
            # 显示助手回复
            self._append_message("助手", response)
            
            # 自动滚动到底部
            self.history_area.see(tk.END)
            
        except Exception as e:
            messagebox.showerror("错误", f"请求失败: {str(e)}")
        finally:
            # 重新启用输入
            self._toggle_input(True)

    def _append_message(self, role, content):
        """添加消息到历史区域"""
        self.history_area.config(state=tk.NORMAL)
        self.history_area.insert(tk.END, f"{role}: {content}\n\n")
        self.history_area.config(state=tk.DISABLED)

    def _toggle_input(self, enable):
        """切换输入状态"""
        state = tk.NORMAL if enable else tk.DISABLED
        self.input_entry.config(state=state)

        status_text = []
        if self.current_log_path:
            status_text.append(f"当前日志: {os.path.basename(self.current_log_path)}")
        status_text.append(f"角色设定: {self.chat_bot.system_prompt}")
        if not enable:
            status_text.append("(正在请求中...)")
        self.status_bar.config(text=" | ".join(status_text))

        # self.status_bar.config(
        #     text=f"当前角色设定: {self.chat_bot.system_prompt}" + 
        #          ("" if enable else " (正在请求中...)")
        # )

    def save_dialog(self):
        """保存对话对话框"""
        file_path = filedialog.asksaveasfilename(
            defaultextension=".json",
            filetypes=[("JSON文件", "*.json")]
        )
        if file_path:
            try:
                self.chat_bot.save_history(file_path)
                messagebox.showinfo("成功", "对话历史已保存!")
            except Exception as e:
                messagebox.showerror("错误", f"保存失败: {str(e)}")

    def load_dialog(self):
        """加载对话对话框"""
        file_path = filedialog.askopenfilename(
            filetypes=[("JSON文件", "*.json")]
        )
        if file_path:
            try:
                self.chat_bot.load_history(file_path)
                self._refresh_display()
                messagebox.showinfo("成功", "对话历史已加载!")
            except Exception as e:
                messagebox.showerror("错误", f"加载失败: {str(e)}")

    def change_prompt(self):
        """修改角色设定"""
        new_prompt = simpledialog.askstring(
            "修改角色设定",
            "请输入新的角色设定:",
            initialvalue=self.chat_bot.system_prompt
        )
        if new_prompt:
            self.chat_bot.update_system_prompt(new_prompt)
            self.status_bar.config(
                text=f"当前角色设定: {self.chat_bot.system_prompt}"
            )
            messagebox.showinfo("成功", "角色设定已更新!")

    def reset_chat(self):
        """重置对话"""
        if messagebox.askyesno("确认", "确定要重置对话历史吗?"):
            self.chat_bot.history = [{"role": "system", "content": self.chat_bot.system_prompt}]
            self._refresh_display()

    def _refresh_display(self):
        """刷新界面显示"""
        self.history_area.config(state=tk.NORMAL)
        self.history_area.delete(1.0, tk.END)
        for msg in self.chat_bot.history[1:]:  # 跳过系统消息
            role = "用户" if msg["role"] == "user" else "助手"
            self.history_area.insert(tk.END, f"{role}: {msg['content']}\n\n")
        self.history_area.config(state=tk.DISABLED)

    def run(self):
        """运行主循环"""
        self.window.mainloop()

if __name__ == "__main__":
    # 初始化聊天机器人
    bot = DeepSeekChat("您现在是一个CPP网络通信开发高手,并且你看日志的能力非常强")
    
    # 创建并运行UI
    ui = ChatUI(bot)
    ui.run()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值