基于CodeRider-Kilo和MySQL开发一款书店管理系统

引言:开发模式的效率变革

在传统的软件开发流程中,开发者往往需要在浏览器搜索引擎、AI 问答网页以及集成开发环境(IDE)之间频繁切换。这种碎片化的工作方式不仅降低了代码编写的连贯性,还容易在复制粘贴的过程中引入缩进错误、格式不兼容或上下文丢失等问题。CodeRider-Kilo 的出现彻底改变了这一现状。它不是一个独立的外部工具,而是深度集成在 VSCode 内部的智能助手。它通过直接读取项目文件、理解代码逻辑结构以及实时感知开发上下文,为开发者提供了一站式的编程支持。这种深度集成的特性,使得它在处理复杂的项目逻辑时,比通用的网页版 AI 具有更高的准确性和执行效率。

第一阶段:环境部署与插件初始化

在开始任何项目之前,工具的准备工作是至关重要的。CodeRider-Kilo 的安装过程非常便捷,这体现了其作为现代开发辅助工具的易用性。

如上图所示,在 VSCode 的插件市场中,通过搜索"CodeRider-Kilo"即可找到该插件。安装完成后,它会出现在编辑器的侧边栏或底部面板中。CodeRider-Kilo 的核心优势在于其"上下文理解能力"。普通的 AI 助手只能看到用户输入的当前这段话,而 CodeRider-Kilo 可以感知整个工作区的文件结构。在安装完毕后,插件会自动扫描项目的根目录,为后续的逻辑推导建立基础索引。

安装完成后,接下来需要进行后端基础设施的准备。对于一个管理系统而言,数据库是核心。在这里,我们需要将 MySQL 数据库的相关配置信息告知 CodeRider-Kilo。这包括数据库的主机地址(Host)、数据库名称(Database)、端口号(Port)以及访问密码(Password)。

在服务器端,我们需要执行基础的 SQL 命令来创建一个空的数据库,为接下来的自动化开发提供载体。

上图展示了在服务器终端创建数据库的过程。通过执行 CREATE DATABASE 指令,我们建立了一个名为 coderider_demo(或类似名称)的数据库实例。CodeRider-Kilo 的强大之处在于,一旦它获得了这些连接信息,它就能在后续的代码生成中,自动填充数据库连接池的配置,生成符合特定数据库版本的 SQL 建表语句,并确保前后端交互逻辑的闭环。这种从环境配置到代码实现的无缝对接,极大地减少了开发者手动编写配置文件的繁琐劳动。

第二阶段:需求定义与文档驱动开发

在现代软件工程中,README 文件不仅是项目的说明书,更是开发的蓝图。CodeRider-Kilo 能够识别并解析 README 文件中的自然语言描述,将其转化为可执行的开发计划。

如上图所示,我们编写了一个清晰的 README.md 文件。在这个文件中,我们定义了书店销售管理系统的核心功能模块:书籍管理、库存监控、销售记录以及用户权限。CodeRider-Kilo 的逻辑处理机制会对这些描述进行分词处理和语义分析。它不仅仅是读取文字,而是通过内部的知识图谱,理解"书籍管理"意味着需要具备增删改查(CRUD)的功能,理解"库存监控"意味着需要数据库触发器或定时查询任务。

第三阶段:自然语言交互与项目规划

当环境和需求都准备就绪后,我们进入了实际的交互开发阶段。在 CodeRider-Kilo 的输入框中,我们不需要编写复杂的代码,只需要使用自然语言进行指令下达。

bash 复制代码
#README.md 根据文件进行开发

这一行指令触发了 CodeRider-Kilo 的"项目级推理"功能。它会首先读取项目根目录下的 README.md 文件,将其作为最高权重的指令来源。

上图展示了 CodeRider-Kilo 在接收到指令后的反馈------规划布局。它没有盲目地开始写代码,而是先给出了项目的架构设计建议。这种规划包括了前端框架的选择、后端 API 的路由设计、以及数据库表之间的关联关系。这种"先规划后执行"的模式,有效避免了代码开发过程中的逻辑冲突。它会将系统拆分为多个逻辑层:数据持久层(DAO)、业务逻辑层(Service)和表现层(Controller)。

第四阶段:代码自动化生成与模块实现

在规划获得认可后,CodeRider-Kilo 开始进行大规模的代码生成。这一过程体现了其对编程规范的严谨遵守。

如上图所示,CodeRider-Kilo 正在生成系统的核心逻辑代码。它生成的代码具有极高的可读性,严格遵循了变量命名规范和代码注释标准。在生成过程中,它会根据之前配置的 MySQL 信息,自动引入相应的驱动库(如 Node.js 中的 mysql2 或 Python 中的 pymysql)。

1. 数据库连接模块的构建

数据库连接是任何信息系统的命脉。如果连接配置不当,系统将无法运行。

上图展示了 CodeRider-Kilo 生成的数据库连接模块。该模块不仅仅是一个简单的连接字符串,它还包含了异常处理机制(Try-Catch)、连接池管理以及连接状态的实时校验。这意味着当数据库服务器出现波动时,系统能够自动尝试重连,或者输出精确的错误日志以便排查。CodeRider-Kilo 识别到了开发者在前期提供的 Host 和 Password,并将其安全地集成到配置文件中,这种智能化的填充避免了手动输入可能产生的拼写错误。

2. 数据库监控模块的实现

对于管理系统而言,实时掌握数据库的状态是运维的关键。CodeRider-Kilo 自动生成了一个功能强大的监控模块。

如上图所示,监控模块可以实时反馈当前数据库的负载情况、活动连接数以及查询响应时间。CodeRider-Kilo 通过调用底层 SQL 的 SHOW STATUSINFORMATION_SCHEMA 视图,提取出关键的运行指标,并将其转化为前端可展示的数据格式。这一功能模块的自动生成,体现了 CodeRider-Kilo 对于系统完整性的深刻理解,它知道一个成熟的系统不仅要有业务功能,还要有自我感知能力。

第五阶段:成果展示与系统功能分析

经过 CodeRider-Kilo 的快速开发,一个完整的书店销售管理系统正式成型。

上图是系统的登录与主导航界面。界面布局清晰,符合用户交互逻辑。CodeRider-Kilo 在生成 UI 代码时,充分考虑了响应式布局,确保系统在不同分辨率的屏幕上都能保持良好的视觉效果。

进入书籍管理模块(如上图),我们可以看到书籍的列表展示、搜索过滤以及操作按钮。CodeRider-Kilo 自动实现了分页功能,这在处理大量书籍数据时显得尤为重要。每一条记录都对应着数据库中的一行数据,修改操作会触发精准的 SQL Update 语句,这些逻辑全部由 AI 自动完成,无需开发者手工编写繁琐的 HTML 模板和 Ajax 请求。

销售记录模块(如上图)展示了系统的事务处理能力。每当一本书被售出,系统会自动更新库存数量,并在销售记录表中新增一条流水。CodeRider-Kilo 在生成这部分代码时,采用了数据库事务(Transaction)机制,确保了库存减少和记录增加这两个操作的原子性。如果其中一个步骤失败,整个操作将回滚,从而保证了财务数据的准确性。

最后是系统的报表分析界面(如上图)。CodeRider-Kilo 通过复杂的 SQL 聚合查询(GROUP BY),实现了对销售额的按日、按月统计。它甚至能自动生成可视化图表所需的数据结构,使得管理人员可以直观地看到书店的经营趋势。这种从原始数据到高阶信息的转化能力,是 CodeRider-Kilo 深度理解业务逻辑的最好体现。

核心技术深度挖掘:为什么 CodeRider-Kilo 如此出色?

1. 全局上下文的精准锚定

CodeRider-Kilo 与传统 AI 的最大区别在于其"项目意识"。它会扫描当前工作区的所有文件,建立一个局部的向量数据库。当开发者询问"如何修改这个函数"时,它知道这个函数在哪个文件定义,被哪些模块调用,以及修改它会对系统的其他部分产生什么影响。这种全局视野使得生成的代码能够无缝嵌入现有工程,无需进行二次大规模重构。

2. 实时错误预测与自动纠错

在代码生成的过程中,CodeRider-Kilo 会调用 VSCode 内置的语言服务器协议(LSP)。这意味着它在写代码的同时,就在进行语法检查和类型推断。如果生成的代码存在潜在的空指针异常或变量未定义,CodeRider-Kilo 会在代码落盘前进行内部修正。这种自我审查机制极大地提升了交付代码的质量。

3. 灵活的配置与高度的定制化

虽然 CodeRider-Kilo 能够自动化完成大部分工作,但它依然给开发者留下了充足的控制空间。无论是数据库的连接参数,还是前端 UI 的样式风格,开发者都可以通过自然语言指令进行微调。例如,如果觉得生成的表格颜色太暗,只需输入"将所有表格的主题色改为浅蓝色",CodeRider-Kilo 就能精准地定位到相关的 CSS 文件或组件属性并完成修改。

4. 极低的上手门槛与极高的生产力

对于初学者来说,CodeRider-Kilo 降低了掌握复杂框架的难度;对于资深开发者来说,它接管了大量重复性的"体力活"。这种生产力的释放,使得开发者能够将更多的精力投入到业务逻辑的设计和系统架构的优化上,而不是被琐碎的语法细节所困扰。

python 复制代码
import ttkbootstrap as ttk
from ttkbootstrap.constants import *
from tkinter import messagebox
import threading
from datetime import datetime
from database import Database
from book_manager import BookManager
from sales_manager import SalesManager


class BookstoreGUI:
    """书店管理系统GUI"""
    
    def __init__(self):
        self.root = ttk.Window(themename="cosmo")
        self.root.title("书店销售管理系统")
        self.root.geometry("1200x700")
        
        # 禁用窗口调整大小时的重绘,减少闪烁
        self.root.resizable(True, True)
        
        # 创建主框架,避免黑边
        self.main_frame = ttk.Frame(self.root)
        self.main_frame.pack(fill=BOTH, expand=YES)
        
        # 显示加载提示
        self.loading_label = ttk.Label(self.main_frame, text="正在初始化...", 
                                       font=("Arial", 14))
        self.loading_label.place(relx=0.5, rely=0.5, anchor=CENTER)
        
        # 延迟初始化,让窗口先显示
        self.root.after(100, self.init_database)
    
    def init_database(self):
        """初始化数据库"""
        def init_thread():
            try:
                db = Database()
                if not db.connect():
                    self.root.after(0, lambda: messagebox.showerror("错误", "无法连接到数据库"))
                    return
                db.init_tables()
                db.close()
                
                # 初始化完成后创建界面
                self.root.after(0, self.create_widgets)
            except Exception as e:
                self.root.after(0, lambda: messagebox.showerror("错误", f"初始化失败: {e}"))
        
        threading.Thread(target=init_thread, daemon=True).start()
    
    def create_widgets(self):
        """创建界面组件"""
        # 移除加载提示
        self.loading_label.destroy()
        
        # 创建Notebook(标签页)
        notebook = ttk.Notebook(self.main_frame)
        notebook.pack(fill=BOTH, expand=YES, padx=5, pady=5)
        
        # 图书管理页面
        book_frame = ttk.Frame(notebook)
        notebook.add(book_frame, text="图书管理")
        self.create_book_page(book_frame)
        
        # 销售管理页面
        sales_frame = ttk.Frame(notebook)
        notebook.add(sales_frame, text="销售管理")
        self.create_sales_page(sales_frame)
        
        # 库存管理页面
        inventory_frame = ttk.Frame(notebook)
        notebook.add(inventory_frame, text="库存管理")
        self.create_inventory_page(inventory_frame)
        
        # 会员管理页面
        member_frame = ttk.Frame(notebook)
        notebook.add(member_frame, text="会员管理")
        self.create_member_page(member_frame)
        
        # 统计报表页面
        stats_frame = ttk.Frame(notebook)
        notebook.add(stats_frame, text="统计报表")
        self.create_stats_page(stats_frame)
        
        # 绑定标签页切换事件,延迟加载数据
        notebook.bind("<<NotebookTabChanged>>", self.on_tab_changed)
        self.notebook = notebook
        
        # 只加载第一个页面的数据
        self.refresh_books()
    
    def create_book_page(self, parent):
        """创建图书管理页面"""
        # 左侧:表单
        left_frame = ttk.Frame(parent)
        left_frame.pack(side=LEFT, fill=BOTH, padx=10, pady=10)
        
        ttk.Label(left_frame, text="图书信息", font=("Arial", 14, "bold")).pack(pady=10)
        
        # 表单字段
        form_frame = ttk.Frame(left_frame)
        form_frame.pack(fill=BOTH, expand=YES)
        
        fields = [
            ("ISBN:", "isbn"),
            ("书名:", "title"),
            ("作者:", "author"),
            ("出版社:", "publisher"),
            ("价格:", "price"),
            ("库存:", "stock"),
            ("分类:", "category")
        ]
        
        self.book_entries = {}
        for i, (label, key) in enumerate(fields):
            ttk.Label(form_frame, text=label).grid(row=i, column=0, sticky=W, pady=5, padx=5)
            entry = ttk.Entry(form_frame, width=30)
            entry.grid(row=i, column=1, pady=5, padx=5)
            self.book_entries[key] = entry
        
        # 按钮
        btn_frame = ttk.Frame(left_frame)
        btn_frame.pack(pady=20)
        
        ttk.Button(btn_frame, text="添加图书", bootstyle=SUCCESS, 
                  command=self.add_book).pack(side=LEFT, padx=5)
        ttk.Button(btn_frame, text="更新图书", bootstyle=WARNING,
                  command=self.update_book).pack(side=LEFT, padx=5)
        ttk.Button(btn_frame, text="删除图书", bootstyle=DANGER,
                  command=self.delete_book).pack(side=LEFT, padx=5)
        ttk.Button(btn_frame, text="清空表单", bootstyle=SECONDARY,
                  command=self.clear_book_form).pack(side=LEFT, padx=5)
        
        # 右侧:搜索和列表
        right_frame = ttk.Frame(parent)
        right_frame.pack(side=RIGHT, fill=BOTH, expand=YES, padx=10, pady=10)
        
        # 搜索框和导出
        search_frame = ttk.Frame(right_frame)
        search_frame.pack(fill=X, pady=10)
        
        ttk.Label(search_frame, text="搜索:").pack(side=LEFT, padx=5)
        self.book_search_entry = ttk.Entry(search_frame, width=25)
        self.book_search_entry.pack(side=LEFT, padx=5)
        ttk.Button(search_frame, text="搜索", bootstyle=INFO,
                  command=self.search_books).pack(side=LEFT, padx=5)
        ttk.Button(search_frame, text="刷新", bootstyle=PRIMARY,
                  command=self.refresh_books).pack(side=LEFT, padx=5)
        ttk.Button(search_frame, text="导出Excel", bootstyle=SUCCESS,
                  command=self.export_books).pack(side=LEFT, padx=5)
        
        # 图书列表
        list_frame = ttk.Frame(right_frame)
        list_frame.pack(fill=BOTH, expand=YES)
        
        # 滚动条
        scrollbar = ttk.Scrollbar(list_frame)
        scrollbar.pack(side=RIGHT, fill=Y)
        
        # Treeview
        columns = ("ID", "ISBN", "书名", "作者", "出版社", "价格", "库存", "分类")
        self.book_tree = ttk.Treeview(list_frame, columns=columns, show="headings",
                                      yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.book_tree.yview)
        
        for col in columns:
            self.book_tree.heading(col, text=col)
            self.book_tree.column(col, width=100)
        
        self.book_tree.pack(fill=BOTH, expand=YES)
        self.book_tree.bind("<ButtonRelease-1>", self.on_book_select)

    def create_sales_page(self, parent):
        """创建销售管理页面"""
        # 左侧:销售表单
        left_frame = ttk.Frame(parent)
        left_frame.pack(side=LEFT, fill=BOTH, padx=10, pady=10)
        
        ttk.Label(left_frame, text="创建销售", font=("Arial", 14, "bold")).pack(pady=10)
        
        form_frame = ttk.Frame(left_frame)
        form_frame.pack(fill=BOTH, expand=YES)
        
        ttk.Label(form_frame, text="图书ID:").grid(row=0, column=0, sticky=W, pady=5, padx=5)
        self.sale_book_id = ttk.Entry(form_frame, width=30)
        self.sale_book_id.grid(row=0, column=1, pady=5, padx=5)
        
        ttk.Label(form_frame, text="数量:").grid(row=1, column=0, sticky=W, pady=5, padx=5)
        self.sale_quantity = ttk.Entry(form_frame, width=30)
        self.sale_quantity.grid(row=1, column=1, pady=5, padx=5)
        
        ttk.Label(form_frame, text="会员手机号:").grid(row=2, column=0, sticky=W, pady=5, padx=5)
        self.sale_member_phone = ttk.Entry(form_frame, width=30)
        self.sale_member_phone.grid(row=2, column=1, pady=5, padx=5)
        ttk.Label(form_frame, text="(可选,享受折扣)", font=("Arial", 8)).grid(row=3, column=1, sticky=W, padx=5)
        
        ttk.Button(form_frame, text="创建销售", bootstyle=SUCCESS,
                  command=self.create_sale).grid(row=4, column=0, columnspan=2, pady=20)
        
        # 右侧:销售记录
        right_frame = ttk.Frame(parent)
        right_frame.pack(side=RIGHT, fill=BOTH, expand=YES, padx=10, pady=10)
        
        ttk.Label(right_frame, text="销售记录", font=("Arial", 14, "bold")).pack(pady=10)
        
        # 刷新和导出按钮
        btn_frame = ttk.Frame(right_frame)
        btn_frame.pack(pady=5)
        ttk.Button(btn_frame, text="刷新记录", bootstyle=PRIMARY,
                  command=self.refresh_sales).pack(side=LEFT, padx=5)
        ttk.Button(btn_frame, text="导出Excel", bootstyle=SUCCESS,
                  command=self.export_sales).pack(side=LEFT, padx=5)
        
        # 销售记录列表
        list_frame = ttk.Frame(right_frame)
        list_frame.pack(fill=BOTH, expand=YES)
        
        scrollbar = ttk.Scrollbar(list_frame)
        scrollbar.pack(side=RIGHT, fill=Y)
        
        columns = ("ID", "书名", "作者", "数量", "折扣", "总价", "会员", "销售时间")
        self.sales_tree = ttk.Treeview(list_frame, columns=columns, show="headings",
                                       yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.sales_tree.yview)
        
        widths = [50, 150, 100, 60, 60, 80, 100, 150]
        for col, width in zip(columns, widths):
            self.sales_tree.heading(col, text=col)
            self.sales_tree.column(col, width=width)
        
        self.sales_tree.pack(fill=BOTH, expand=YES)
    
    def create_inventory_page(self, parent):
        """创建库存管理页面"""
        # 左侧:入库表单和导出
        left_frame = ttk.Frame(parent)
        left_frame.pack(side=LEFT, fill=BOTH, padx=10, pady=10)
        
        ttk.Label(left_frame, text="库存入库", font=("Arial", 14, "bold")).pack(pady=10)
        
        form_frame = ttk.Frame(left_frame)
        form_frame.pack(fill=BOTH, expand=YES)
        
        ttk.Label(form_frame, text="图书ID:").grid(row=0, column=0, sticky=W, pady=5, padx=5)
        self.inv_book_id = ttk.Entry(form_frame, width=30)
        self.inv_book_id.grid(row=0, column=1, pady=5, padx=5)
        
        ttk.Label(form_frame, text="入库数量:").grid(row=1, column=0, sticky=W, pady=5, padx=5)
        self.inv_quantity = ttk.Entry(form_frame, width=30)
        self.inv_quantity.grid(row=1, column=1, pady=5, padx=5)
        
        ttk.Button(form_frame, text="确认入库", bootstyle=SUCCESS,
                  command=self.add_inventory).grid(row=2, column=0, columnspan=2, pady=20)
        
        # 导出功能
        export_frame = ttk.LabelFrame(left_frame, text="数据导出", padding=10)
        export_frame.pack(fill=X, pady=10)
        
        ttk.Button(export_frame, text="导出库存记录", bootstyle=INFO,
                  command=self.export_inventory).pack(fill=X, pady=5)
        
        # 右侧:库存记录和时间筛选
        right_frame = ttk.Frame(parent)
        right_frame.pack(side=RIGHT, fill=BOTH, expand=YES, padx=10, pady=10)
        
        ttk.Label(right_frame, text="库存变动记录", font=("Arial", 14, "bold")).pack(pady=10)
        
        # 时间筛选
        filter_frame = ttk.Frame(right_frame)
        filter_frame.pack(fill=X, pady=5)
        
        ttk.Label(filter_frame, text="时间筛选:").pack(side=LEFT, padx=5)
        self.inv_period = ttk.Combobox(filter_frame, width=12, state='readonly')
        self.inv_period['values'] = ('全部', '今日', '本周', '本月', '本季度')
        self.inv_period.current(0)
        self.inv_period.pack(side=LEFT, padx=5)
        
        ttk.Button(filter_frame, text="筛选", bootstyle=PRIMARY,
                  command=self.filter_inventory).pack(side=LEFT, padx=5)
        ttk.Button(filter_frame, text="刷新", bootstyle=SECONDARY,
                  command=self.refresh_inventory).pack(side=LEFT, padx=5)
        
        list_frame = ttk.Frame(right_frame)
        list_frame.pack(fill=BOTH, expand=YES)
        
        scrollbar = ttk.Scrollbar(list_frame)
        scrollbar.pack(side=RIGHT, fill=Y)
        
        columns = ("ID", "书名", "变动数量", "操作类型", "操作时间")
        self.inv_tree = ttk.Treeview(list_frame, columns=columns, show="headings",
                                     yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.inv_tree.yview)
        
        for col in columns:
            self.inv_tree.heading(col, text=col)
            self.inv_tree.column(col, width=120)
        
        self.inv_tree.pack(fill=BOTH, expand=YES)
    
    def create_member_page(self, parent):
        """创建会员管理页面"""
        # 左侧:表单
        left_frame = ttk.Frame(parent)
        left_frame.pack(side=LEFT, fill=BOTH, padx=10, pady=10)
        
        ttk.Label(left_frame, text="会员信息", font=("Arial", 14, "bold")).pack(pady=10)
        
        form_frame = ttk.Frame(left_frame)
        form_frame.pack(fill=BOTH, expand=YES)
        
        ttk.Label(form_frame, text="姓名:").grid(row=0, column=0, sticky=W, pady=5, padx=5)
        self.member_name = ttk.Entry(form_frame, width=30)
        self.member_name.grid(row=0, column=1, pady=5, padx=5)
        
        ttk.Label(form_frame, text="手机号:").grid(row=1, column=0, sticky=W, pady=5, padx=5)
        self.member_phone = ttk.Entry(form_frame, width=30)
        self.member_phone.grid(row=1, column=1, pady=5, padx=5)
        
        ttk.Label(form_frame, text="等级:").grid(row=2, column=0, sticky=W, pady=5, padx=5)
        self.member_level = ttk.Combobox(form_frame, width=28, state='readonly')
        self.member_level['values'] = ('普通会员', '银卡会员', '金卡会员', '钻石会员')
        self.member_level.current(0)
        self.member_level.grid(row=2, column=1, pady=5, padx=5)
        
        # 折扣说明
        discount_frame = ttk.LabelFrame(form_frame, text="会员折扣", padding=10)
        discount_frame.grid(row=3, column=0, columnspan=2, pady=10, padx=5, sticky=W+E)
        ttk.Label(discount_frame, text="普通会员: 无折扣").pack(anchor=W)
        ttk.Label(discount_frame, text="银卡会员: 95折").pack(anchor=W)
        ttk.Label(discount_frame, text="金卡会员: 90折").pack(anchor=W)
        ttk.Label(discount_frame, text="钻石会员: 85折").pack(anchor=W)
        
        # 按钮
        btn_frame = ttk.Frame(left_frame)
        btn_frame.pack(pady=20)
        
        ttk.Button(btn_frame, text="添加会员", bootstyle=SUCCESS,
                  command=self.add_member).pack(side=LEFT, padx=5)
        ttk.Button(btn_frame, text="更新会员", bootstyle=WARNING,
                  command=self.update_member).pack(side=LEFT, padx=5)
        ttk.Button(btn_frame, text="删除会员", bootstyle=DANGER,
                  command=self.delete_member).pack(side=LEFT, padx=5)
        ttk.Button(btn_frame, text="清空表单", bootstyle=SECONDARY,
                  command=self.clear_member_form).pack(side=LEFT, padx=5)
        
        # 右侧:会员列表
        right_frame = ttk.Frame(parent)
        right_frame.pack(side=RIGHT, fill=BOTH, expand=YES, padx=10, pady=10)
        
        # 搜索框和导出
        search_frame = ttk.Frame(right_frame)
        search_frame.pack(fill=X, pady=10)
        
        ttk.Label(search_frame, text="搜索:").pack(side=LEFT, padx=5)
        self.member_search_entry = ttk.Entry(search_frame, width=20)
        self.member_search_entry.pack(side=LEFT, padx=5)
        ttk.Button(search_frame, text="搜索", bootstyle=INFO,
                  command=self.search_members).pack(side=LEFT, padx=5)
        ttk.Button(search_frame, text="刷新", bootstyle=PRIMARY,
                  command=self.refresh_members).pack(side=LEFT, padx=5)
        ttk.Button(search_frame, text="导出Excel", bootstyle=SUCCESS,
                  command=self.export_members).pack(side=LEFT, padx=5)
        
        # 会员列表
        list_frame = ttk.Frame(right_frame)
        list_frame.pack(fill=BOTH, expand=YES)
        
        scrollbar = ttk.Scrollbar(list_frame)
        scrollbar.pack(side=RIGHT, fill=Y)
        
        columns = ("ID", "姓名", "手机号", "等级", "积分", "注册时间")
        self.member_tree = ttk.Treeview(list_frame, columns=columns, show="headings",
                                        yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.member_tree.yview)
        
        widths = [50, 100, 120, 100, 80, 150]
        for col, width in zip(columns, widths):
            self.member_tree.heading(col, text=col)
            self.member_tree.column(col, width=width)
        
        self.member_tree.pack(fill=BOTH, expand=YES)
        self.member_tree.bind("<ButtonRelease-1>", self.on_member_select)
    
    def create_stats_page(self, parent):
        """创建统计报表页面"""
        main_frame = ttk.Frame(parent)
        main_frame.pack(fill=BOTH, expand=YES, padx=20, pady=20)
        
        ttk.Label(main_frame, text="销售统计", font=("Arial", 16, "bold")).pack(pady=10)
        
        # 时间段选择和排序方式
        period_frame = ttk.Frame(main_frame)
        period_frame.pack(fill=X, pady=10)
        
        ttk.Label(period_frame, text="统计周期:", font=("Arial", 11)).pack(side=LEFT, padx=10)
        self.stats_period = ttk.Combobox(period_frame, width=10, state='readonly')
        self.stats_period['values'] = ('今日', '本月', '本季度', '全部')
        self.stats_period.current(3)
        self.stats_period.pack(side=LEFT, padx=5)
        
        ttk.Label(period_frame, text="排序方式:", font=("Arial", 11)).pack(side=LEFT, padx=10)
        self.stats_sort = ttk.Combobox(period_frame, width=18, state='readonly')
        self.stats_sort['values'] = ('📊 按销量排序(最受欢迎)', '💰 按销售额排序(最赚钱)', '🎯 按综合评分排序(平衡考虑)')
        self.stats_sort.current(0)
        self.stats_sort.pack(side=LEFT, padx=5)
        
        ttk.Button(period_frame, text="刷新统计", bootstyle=INFO,
                  command=self.refresh_stats).pack(side=LEFT, padx=5)
        ttk.Button(period_frame, text="导出报表", bootstyle=SUCCESS,
                  command=self.export_statistics).pack(side=LEFT, padx=5)
        
        # 统计信息框
        stats_frame = ttk.LabelFrame(main_frame, text="销售数据", padding=20)
        stats_frame.pack(fill=X, pady=10)
        
        self.total_revenue_label = ttk.Label(stats_frame, text="销售额: ¥0.00", 
                                             font=("Arial", 14, "bold"))
        self.total_revenue_label.pack(pady=5)
        
        self.total_quantity_label = ttk.Label(stats_frame, text="销售量: 0 本",
                                              font=("Arial", 14, "bold"))
        self.total_quantity_label.pack(pady=5)
        
        # 畅销图书排行
        ttk.Label(main_frame, text="畅销图书排行", font=("Arial", 14, "bold")).pack(pady=10)
        
        list_frame = ttk.Frame(main_frame)
        list_frame.pack(fill=BOTH, expand=YES)
        
        scrollbar = ttk.Scrollbar(list_frame)
        scrollbar.pack(side=RIGHT, fill=Y)
        
        columns = ("书名", "作者", "销量", "销售额")
        self.stats_tree = ttk.Treeview(list_frame, columns=columns, show="headings",
                                       yscrollcommand=scrollbar.set)
        scrollbar.config(command=self.stats_tree.yview)
        
        for col in columns:
            self.stats_tree.heading(col, text=col)
            self.stats_tree.column(col, width=200)
        
        self.stats_tree.pack(fill=BOTH, expand=YES)
    
    def on_tab_changed(self, event):
        """标签页切换时延迟加载数据"""
        tab_id = self.notebook.select()
        tab_text = self.notebook.tab(tab_id, "text")
        
        # 根据标签页名称加载对应数据
        if tab_text == "销售管理":
            if not self.sales_tree.get_children():
                self.refresh_sales()
        elif tab_text == "库存管理":
            if not self.inv_tree.get_children():
                self.refresh_inventory()
        elif tab_text == "会员管理":
            if not self.member_tree.get_children():
                self.refresh_members()
        elif tab_text == "统计报表":
            self.refresh_stats()
    
    # 图书管理功能
    def add_book(self):
        """添加图书"""
        try:
            bm = BookManager()
            isbn = self.book_entries['isbn'].get().strip()
            title = self.book_entries['title'].get().strip()
            author = self.book_entries['author'].get().strip()
            publisher = self.book_entries['publisher'].get().strip()
            price = float(self.book_entries['price'].get().strip())
            stock = int(self.book_entries['stock'].get().strip())
            category = self.book_entries['category'].get().strip()
            
            if not all([isbn, title, price, stock]):
                messagebox.showwarning("警告", "请填写必填字段")
                return
            
            if bm.add_book(isbn, title, author, publisher, price, stock, category):
                messagebox.showinfo("成功", "图书添加成功")
                self.clear_book_form()
                self.refresh_books()
        except ValueError:
            messagebox.showerror("错误", "价格和库存必须是数字")
        except Exception as e:
            messagebox.showerror("错误", f"添加失败: {str(e)}")
    
    def update_book(self):
        """更新图书"""
        selected = self.book_tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要更新的图书")
            return
        
        try:
            book_id = self.book_tree.item(selected[0])['values'][0]
            bm = BookManager()
            
            title = self.book_entries['title'].get().strip() or None
            author = self.book_entries['author'].get().strip() or None
            publisher = self.book_entries['publisher'].get().strip() or None
            price_str = self.book_entries['price'].get().strip()
            price = float(price_str) if price_str else None
            category = self.book_entries['category'].get().strip() or None
            
            if bm.update_book(book_id, title=title, author=author, publisher=publisher,
                            price=price, category=category):
                messagebox.showinfo("成功", "图书更新成功")
                self.clear_book_form()
                self.refresh_books()
        except Exception as e:
            messagebox.showerror("错误", f"更新失败: {str(e)}")
    
    def delete_book(self):
        """删除图书"""
        selected = self.book_tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要删除的图书")
            return
        
        if messagebox.askyesno("确认", "确定要删除这本图书吗?"):
            try:
                book_id = self.book_tree.item(selected[0])['values'][0]
                bm = BookManager()
                if bm.delete_book(book_id):
                    messagebox.showinfo("成功", "图书删除成功")
                    self.refresh_books()
            except Exception as e:
                messagebox.showerror("错误", f"删除失败: {str(e)}")
    
    def search_books(self):
        """搜索图书"""
        keyword = self.book_search_entry.get().strip()
        bm = BookManager()
        books = bm.search_books(keyword=keyword) if keyword else bm.search_books()
        self.display_books(books)
    
    def refresh_books(self):
        """刷新图书列表"""
        # 清空列表
        for item in self.book_tree.get_children():
            self.book_tree.delete(item)
        
        # 异步加载数据
        def load_data():
            bm = BookManager()
            books = bm.search_books()
            self.root.after(0, lambda: self.display_books(books))
        
        threading.Thread(target=load_data, daemon=True).start()
    
    def display_books(self, books):
        """显示图书列表"""
        # 批量插入,提高性能
        for item in self.book_tree.get_children():
            self.book_tree.delete(item)
        
        # 分批插入,避免界面卡顿
        batch_size = 20
        for i in range(0, len(books), batch_size):
            batch = books[i:i+batch_size]
            for book in batch:
                self.book_tree.insert("", END, values=(
                    book['id'], book['isbn'], book['title'], book['author'],
                    book['publisher'], f"¥{book['price']}", book['stock'], book['category']
                ))
            # 让界面有机会更新
            self.root.update_idletasks()
    
    def on_book_select(self, event):
        """选择图书时填充表单"""
        selected = self.book_tree.selection()
        if selected:
            values = self.book_tree.item(selected[0])['values']
            self.book_entries['isbn'].delete(0, END)
            self.book_entries['isbn'].insert(0, values[1])
            self.book_entries['title'].delete(0, END)
            self.book_entries['title'].insert(0, values[2])
            self.book_entries['author'].delete(0, END)
            self.book_entries['author'].insert(0, values[3])
            self.book_entries['publisher'].delete(0, END)
            self.book_entries['publisher'].insert(0, values[4])
            self.book_entries['price'].delete(0, END)
            self.book_entries['price'].insert(0, str(values[5]).replace('¥', ''))
            self.book_entries['stock'].delete(0, END)
            self.book_entries['stock'].insert(0, values[6])
            self.book_entries['category'].delete(0, END)
            self.book_entries['category'].insert(0, values[7])
    
    def clear_book_form(self):
        """清空图书表单"""
        for entry in self.book_entries.values():
            entry.delete(0, END)
    
    # 销售管理功能
    def create_sale(self):
        """创建销售"""
        try:
            book_id = int(self.sale_book_id.get().strip())
            quantity = int(self.sale_quantity.get().strip())
            member_phone = self.sale_member_phone.get().strip()
            
            member_id = None
            if member_phone:
                from member_manager import MemberManager
                mm = MemberManager()
                member = mm.get_member_by_phone(member_phone)
                if member:
                    member_id = member['id']
                else:
                    messagebox.showwarning("提示", "会员不存在,将按普通价格销售")
            
            sm = SalesManager()
            if sm.create_sale(book_id, quantity, member_id):
                messagebox.showinfo("成功", "销售创建成功")
                self.sale_book_id.delete(0, END)
                self.sale_quantity.delete(0, END)
                self.sale_member_phone.delete(0, END)
                self.refresh_sales()
                self.refresh_books()
                if member_id:
                    self.refresh_members()
        except ValueError:
            messagebox.showerror("错误", "图书ID和数量必须是数字")
        except Exception as e:
            messagebox.showerror("错误", f"创建失败: {str(e)}")
    
    def refresh_sales(self):
        """刷新销售记录(只显示最近50条)"""
        for item in self.sales_tree.get_children():
            self.sales_tree.delete(item)
        
        def load_data():
            db = Database()
            db.connect()
            # 只查询最近50条记录
            sales = db.fetchall("""
                SELECT s.id, b.title, b.author, s.quantity, s.discount, s.total_price, 
                       s.sale_date, m.name as member_name
                FROM sales s
                JOIN books b ON s.book_id = b.id
                LEFT JOIN members m ON s.member_id = m.id
                ORDER BY s.sale_date DESC
                LIMIT 50
            """)
            db.close()
            
            def update_ui():
                for item in self.sales_tree.get_children():
                    self.sales_tree.delete(item)
                
                for sale in sales:
                    discount_text = f"{sale['discount']*100:.0f}%" if sale['discount'] < 1.0 else "无"
                    member_name = sale['member_name'] if sale['member_name'] else "非会员"
                    self.sales_tree.insert("", END, values=(
                        sale['id'], sale['title'], sale['author'], sale['quantity'],
                        discount_text, f"¥{sale['total_price']:.2f}", member_name,
                        sale['sale_date'].strftime('%Y-%m-%d %H:%M:%S')
                    ))
            
            self.root.after(0, update_ui)
        
        threading.Thread(target=load_data, daemon=True).start()
    
    # 库存管理功能
    def add_inventory(self):
        """添加库存"""
        try:
            book_id = int(self.inv_book_id.get().strip())
            quantity = int(self.inv_quantity.get().strip())
            
            bm = BookManager()
            if bm.update_stock(book_id, quantity, '入库'):
                messagebox.showinfo("成功", "入库成功")
                self.inv_book_id.delete(0, END)
                self.inv_quantity.delete(0, END)
                self.filter_inventory()  # 刷新当前筛选
                self.refresh_books()
        except ValueError:
            messagebox.showerror("错误", "图书ID和数量必须是数字")
        except Exception as e:
            messagebox.showerror("错误", f"入库失败: {str(e)}")
    
    def filter_inventory(self):
        """按时间筛选库存记录"""
        for item in self.inv_tree.get_children():
            self.inv_tree.delete(item)
        
        def load_data():
            db = Database()
            db.connect()
            
            period = self.inv_period.get()
            date_condition = ""
            
            if period == '今日':
                date_condition = "WHERE DATE(il.operation_date) = CURDATE()"
            elif period == '本周':
                date_condition = "WHERE YEARWEEK(il.operation_date, 1) = YEARWEEK(CURDATE(), 1)"
            elif period == '本月':
                date_condition = "WHERE YEAR(il.operation_date) = YEAR(CURDATE()) AND MONTH(il.operation_date) = MONTH(CURDATE())"
            elif period == '本季度':
                date_condition = "WHERE YEAR(il.operation_date) = YEAR(CURDATE()) AND QUARTER(il.operation_date) = QUARTER(CURDATE())"
            
            sql = f"""
                SELECT il.*, b.title 
                FROM inventory_log il
                JOIN books b ON il.book_id = b.id
                {date_condition}
                ORDER BY il.operation_date DESC
                LIMIT 100
            """
            logs = db.fetchall(sql)
            db.close()
            
            def update_ui():
                for item in self.inv_tree.get_children():
                    self.inv_tree.delete(item)
                
                if not logs:
                    self.inv_tree.insert("", END, values=("暂无数据", "", "", "", ""))
                else:
                    for log in logs:
                        self.inv_tree.insert("", END, values=(
                            log['id'], log['title'], log['change_quantity'],
                            log['operation_type'], log['operation_date'].strftime('%Y-%m-%d %H:%M:%S')
                        ))
            
            self.root.after(0, update_ui)
        
        threading.Thread(target=load_data, daemon=True).start()
    
    def export_inventory(self):
        """导出库存记录"""
        try:
            from export_manager import ExportManager
            from tkinter import filedialog
            
            # 选择保存位置
            filename = filedialog.asksaveasfilename(
                defaultextension=".xlsx",
                filetypes=[("Excel文件", "*.xlsx")],
                initialfile=f"库存记录_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
            )
            
            if filename:
                em = ExportManager()
                
                # 根据当前筛选条件导出
                period = self.inv_period.get()
                if period == '全部':
                    em.export_inventory_log(filename=filename)
                else:
                    # 计算日期范围
                    from datetime import datetime, timedelta
                    end_date = datetime.now()
                    
                    if period == '今日':
                        start_date = end_date.replace(hour=0, minute=0, second=0)
                    elif period == '本周':
                        start_date = end_date - timedelta(days=end_date.weekday())
                        start_date = start_date.replace(hour=0, minute=0, second=0)
                    elif period == '本月':
                        start_date = end_date.replace(day=1, hour=0, minute=0, second=0)
                    elif period == '本季度':
                        quarter_month = ((end_date.month - 1) // 3) * 3 + 1
                        start_date = end_date.replace(month=quarter_month, day=1, hour=0, minute=0, second=0)
                    
                    em.export_inventory_log(start_date, end_date, filename)
                
                messagebox.showinfo("成功", f"数据已导出到:\n{filename}")
        except Exception as e:
            messagebox.showerror("错误", f"导出失败: {str(e)}")
    
    def refresh_inventory(self):
        """刷新库存记录(只显示最近50条)"""
        for item in self.inv_tree.get_children():
            self.inv_tree.delete(item)
        
        def load_data():
            db = Database()
            db.connect()
            logs = db.fetchall("""
                SELECT il.*, b.title 
                FROM inventory_log il
                JOIN books b ON il.book_id = b.id
                ORDER BY il.operation_date DESC
                LIMIT 50
            """)
            db.close()
            
            def update_ui():
                for item in self.inv_tree.get_children():
                    self.inv_tree.delete(item)
                
                for log in logs:
                    self.inv_tree.insert("", END, values=(
                        log['id'], log['title'], log['change_quantity'],
                        log['operation_type'], log['operation_date'].strftime('%Y-%m-%d %H:%M:%S')
                    ))
            
            self.root.after(0, update_ui)
        
        threading.Thread(target=load_data, daemon=True).start()
    
    # 会员管理功能
    def add_member(self):
        """添加会员"""
        try:
            from member_manager import MemberManager
            mm = MemberManager()
            name = self.member_name.get().strip()
            phone = self.member_phone.get().strip()
            level = self.member_level.get()
            
            if not all([name, phone]):
                messagebox.showwarning("警告", "请填写姓名和手机号")
                return
            
            # 验证手机号格式
            if not mm.validate_phone(phone):
                messagebox.showerror("错误", "手机号格式错误!\n必须是11位数字,以1开头,第二位是3-9\n例如:13800138000")
                return
            
            if mm.add_member(name, phone, level):
                messagebox.showinfo("成功", "会员添加成功")
                self.clear_member_form()
                self.refresh_members()
        except Exception as e:
            messagebox.showerror("错误", f"添加失败: {str(e)}")
    
    def update_member(self):
        """更新会员"""
        selected = self.member_tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要更新的会员")
            return
        
        try:
            from member_manager import MemberManager
            mm = MemberManager()
            member_id = self.member_tree.item(selected[0])['values'][0]
            
            name = self.member_name.get().strip() or None
            phone = self.member_phone.get().strip() or None
            level = self.member_level.get() or None
            
            if mm.update_member(member_id, name=name, phone=phone, level=level):
                messagebox.showinfo("成功", "会员更新成功")
                self.clear_member_form()
                self.refresh_members()
        except Exception as e:
            messagebox.showerror("错误", f"更新失败: {str(e)}")
    
    def delete_member(self):
        """删除会员"""
        selected = self.member_tree.selection()
        if not selected:
            messagebox.showwarning("警告", "请先选择要删除的会员")
            return
        
        if messagebox.askyesno("确认", "确定要删除这个会员吗?"):
            try:
                from member_manager import MemberManager
                mm = MemberManager()
                member_id = self.member_tree.item(selected[0])['values'][0]
                if mm.delete_member(member_id):
                    messagebox.showinfo("成功", "会员删除成功")
                    self.refresh_members()
            except Exception as e:
                messagebox.showerror("错误", f"删除失败: {str(e)}")
    
    def search_members(self):
        """搜索会员"""
        from member_manager import MemberManager
        mm = MemberManager()
        keyword = self.member_search_entry.get().strip()
        members = mm.search_members(keyword=keyword) if keyword else mm.search_members()
        self.display_members(members)
    
    def refresh_members(self):
        """刷新会员列表"""
        for item in self.member_tree.get_children():
            self.member_tree.delete(item)
        
        def load_data():
            from member_manager import MemberManager
            mm = MemberManager()
            members = mm.search_members()
            self.root.after(0, lambda: self.display_members(members))
        
        threading.Thread(target=load_data, daemon=True).start()
    
    def display_members(self, members):
        """显示会员列表"""
        for item in self.member_tree.get_children():
            self.member_tree.delete(item)
        
        for member in members:
            self.member_tree.insert("", END, values=(
                member['id'], member['name'], member['phone'],
                member['level'], member['points'],
                member['created_at'].strftime('%Y-%m-%d')
            ))
    
    def on_member_select(self, event):
        """选择会员时填充表单"""
        selected = self.member_tree.selection()
        if selected:
            values = self.member_tree.item(selected[0])['values']
            self.member_name.delete(0, END)
            self.member_name.insert(0, values[1])
            self.member_phone.delete(0, END)
            self.member_phone.insert(0, values[2])
            self.member_level.set(values[3])
    
    def clear_member_form(self):
        """清空会员表单"""
        self.member_name.delete(0, END)
        self.member_phone.delete(0, END)
        self.member_level.current(0)
    
    # 统计功能
    def refresh_stats(self):
        """刷新统计数据"""
        self.total_revenue_label.config(text="销售额: 计算中...")
        self.total_quantity_label.config(text="销售量: 计算中...")
        
        for item in self.stats_tree.get_children():
            self.stats_tree.delete(item)
        
        def load_data():
            try:
                sm = SalesManager()
                
                # 获取选择的时间段
                period_map = {'今日': 'day', '本月': 'month', '本季度': 'quarter', '全部': 'all'}
                period = period_map[self.stats_period.get()]
                
                # 获取选择的排序方式
                sort_text = self.stats_sort.get()
                if '销量' in sort_text:
                    sort_by = 'quantity'
                elif '销售额' in sort_text:
                    sort_by = 'revenue'
                elif '综合评分' in sort_text:
                    sort_by = 'score'
                else:
                    sort_by = 'quantity'
                
                # 获取统计数据
                stats = sm.get_sales_statistics(period, sort_by)
                
                def update_ui():
                    self.total_revenue_label.config(text=f"销售额: ¥{stats['revenue']:.2f}")
                    self.total_quantity_label.config(text=f"销售量: {stats['quantity']} 本")
                    
                    # 畅销图书
                    for item in self.stats_tree.get_children():
                        self.stats_tree.delete(item)
                    
                    for book in stats['bestsellers']:
                        self.stats_tree.insert("", END, values=(
                            book['title'], book['author'], book['sold'], f"¥{book['revenue']:.2f}"
                        ))
                
                self.root.after(0, update_ui)
            except Exception as e:
                self.root.after(0, lambda: messagebox.showerror("错误", f"统计失败: {e}"))
        
        threading.Thread(target=load_data, daemon=True).start()
    
    # 导出功能
    def export_books(self):
        """导出图书数据"""
        try:
            from export_manager import ExportManager
            from tkinter import filedialog
            
            filename = filedialog.asksaveasfilename(
                defaultextension=".xlsx",
                filetypes=[("Excel文件", "*.xlsx")],
                initialfile=f"图书数据_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
            )
            
            if filename:
                em = ExportManager()
                em.export_books(filename)
                messagebox.showinfo("成功", f"数据已导出到:\n{filename}")
        except Exception as e:
            messagebox.showerror("错误", f"导出失败: {str(e)}")
    
    def export_members(self):
        """导出会员数据"""
        try:
            from export_manager import ExportManager
            from tkinter import filedialog
            
            filename = filedialog.asksaveasfilename(
                defaultextension=".xlsx",
                filetypes=[("Excel文件", "*.xlsx")],
                initialfile=f"会员数据_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
            )
            
            if filename:
                em = ExportManager()
                em.export_members(filename)
                messagebox.showinfo("成功", f"数据已导出到:\n{filename}")
        except Exception as e:
            messagebox.showerror("错误", f"导出失败: {str(e)}")
    
    def export_sales(self):
        """导出销售数据"""
        try:
            from export_manager import ExportManager
            from tkinter import filedialog
            
            filename = filedialog.asksaveasfilename(
                defaultextension=".xlsx",
                filetypes=[("Excel文件", "*.xlsx")],
                initialfile=f"销售数据_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
            )
            
            if filename:
                em = ExportManager()
                em.export_sales(filename=filename)
                messagebox.showinfo("成功", f"数据已导出到:\n{filename}")
        except Exception as e:
            messagebox.showerror("错误", f"导出失败: {str(e)}")
    
    def export_statistics(self):
        """导出统计报表"""
        try:
            from export_manager import ExportManager
            from tkinter import filedialog
            
            # 获取当前选择的时间段
            period_map = {'今日': 'day', '本月': 'month', '本季度': 'quarter', '全部': 'all'}
            period = period_map[self.stats_period.get()]
            period_name = self.stats_period.get()
            
            # 获取排序方式
            sort_text = self.stats_sort.get()
            if '销量' in sort_text:
                sort_by = 'quantity'
            elif '销售额' in sort_text:
                sort_by = 'revenue'
            elif '综合评分' in sort_text:
                sort_by = 'score'
            else:
                sort_by = 'quantity'
            
            filename = filedialog.asksaveasfilename(
                defaultextension=".xlsx",
                filetypes=[("Excel文件", "*.xlsx")],
                initialfile=f"{period_name}销售统计_{datetime.now().strftime('%Y%m%d_%H%M%S')}.xlsx"
            )
            
            if filename:
                em = ExportManager()
                em.export_statistics(period, filename, sort_by)
                messagebox.showinfo("成功", f"统计报表已导出到:\n{filename}\n\n包含以下工作表:\n- 总体统计\n- 畅销图书({sort_text})\n- 会员消费\n- 分类统计")
        except Exception as e:
            messagebox.showerror("错误", f"导出失败: {str(e)}")
    
    def run(self):
        """运行应用"""
        self.root.mainloop()


if __name__ == "__main__":
    app = BookstoreGUI()
    app.run()

总结

CodeRider-Kilo 不仅仅是一个代码生成插件,它是一个运行在编辑器内部的智能开发者伙伴。它通过对项目上下文的深度挖掘、对环境配置的智能感知以及对复杂逻辑的自动化实现,将开发效率提升到了一个新的高度。从最初的数据库建立,到最终复杂的书店管理系统的完整呈现,CodeRider-Kilo 证明了 AI 辅助开发已经从简单的代码补全演进到了全链路自动化构建的新阶段。在未来的软件开发实践中,拥有这样一位深度理解项目背景、具备严密逻辑推导能力且能实时响应需求的助手,将成为每一个开发团队追求卓越效率的必备选择。CodeRider-Kilo 的表现无愧于其在 VSCode 生态中的领先地位,它确实为开发者创造了一个更加专注、高效且充满创造力的编程环境。

相关推荐
图乐aj2 小时前
MySQL 运维之日常运维篇 二
运维·mysql
Elastic 中国社区官方博客2 小时前
通过 Elasticsearch 中的 function score query 按利润和受欢迎程度提升电商搜索效果
大数据·数据库·elasticsearch·搜索引擎·全文检索
qq_366336372 小时前
mysql-5.7.38-winx64.zip 启动教程(免安装版)
数据库·mysql·adb
不穿格子的程序员2 小时前
Redis篇5——Redis深度剖析:系统的“隐形杀手”——热Key与大Key问题
数据库·redis·缓存·热key·大key
·云扬·2 小时前
深入理解MySQL元数据锁(MDL):原理、问题与实践
数据库·mysql
guoyiguang22 小时前
mysql in 查询 没有限制1000个,默认是sql大小4M大小
数据库·sql·mysql
IT教程资源D2 小时前
[N_115]基于springboot,vue教务管理系统
mysql·vue·前后端分离·springboot教务系统
镜花水月linyi2 小时前
执行SELECT/INSERT/UPDATE/DELETE的SQL语句,MySQL流程是怎么样的?
后端·mysql
luoluoal2 小时前
基于python的des算法的企业用户数据安全软件(源码+文档)
python·mysql·毕业设计·源码