当前位置:首页>python>《排课排到想摔电脑?我花一晚上写的python小工具,全校课表3秒自动生成》

《排课排到想摔电脑?我花一晚上写的python小工具,全校课表3秒自动生成》

  • 2026-06-30 17:17:27
《排课排到想摔电脑?我花一晚上写的python小工具,全校课表3秒自动生成》

“带你横跨办公自动化的数据江海”

@摸鱼

闻道有先后,术业有专攻。

各位大佬朋友们好!

~我依旧是你们的老朋友摸鱼~

往来千里路常在,聚散十年人不同

但见时光流似箭,岂知天道曲如弓

♥ 1

在职场摸爬滚打的这十多年里,我用Python悄悄干了不少“正事”——不知不觉攒下了一整套办公自动化的实用项目技巧。去年10月初创立了公众号 「码海听潮」 ,初衷很简单:把重复的劳动交给代码,把摸鱼的时间留给生活。

目前已经吭哧吭哧更新了100多篇原创文章,每一篇都是实操干货,不讲虚的,只聊怎么用代码真正解放双手,帮大家早点下班、准点摸鱼

♥ 2

♥ 3好叻,多了不说,少了不唠,咱直接上干货。

办公需求场景

从崩溃到优雅的进化

有一所神秘的学校,内有多个班级、多位教师和多门课程等资源。现在的需求是:依据最优规则,自动编排出一份完整的全校课表,并按照各班原有的课表结构(或统一模板)导出归档。假如这种级别的任务,你的 Big Boss 直接甩给你来负责,请问阁下该如何挠头?

办公痛点分析

01

 痛点1:冲突难以实时检测

    • 人工排课时,教师、班级之间的时间冲突往往需要反复核对,很容易遗漏,导致课表存在逻辑错误,后期调整成本高。

    02

     痛点2:多约束条件难以同时满足

      • 教师的时间偏好、课程的连排要求、班级的空闲时段等多种约束交织在一起,人工很难全局权衡,往往只能牺牲部分合理性来换取排完。

      03

      痛点3:调整维护极其繁琐

      • 一旦出现教师调课等突发情况,已排好的课表需要大量手动修改,牵一发而动全身,耗时长且容易引发新的冲突,缺乏灵活高效的应对机制。

      由此可见,若人工进行操作的话,整个操作流程繁琐且耗时,高频次的鼠标点击和键盘输入使操作者手指疲劳,堪称"键盘敲冒烟"式的体力劳动,加上人工疲劳操作极易导致遗漏文件夹。于是乎这时候,按以往的 “解题套路”,Python 的专属 BGM 该响起来了 ——go~ go~ go~,救苦救难的大救星这不就来了!!勇士战歌搞起来.......

      @摸鱼

      问题拆解思路

      1. 明确约束条件:确认班级数量、教师任课限制、课程连排要求、教师不排课时间段等硬约束和软优化目标。

      2. 设计算法:采用遗传算法、贪心回溯或约束满足问题(CSP)结合启发式规则,优先处理约束多的课程。

      3. 模块化开发:数据库设计(班级、教师、课程)、冲突检测模块、自动排课引擎、手动调整界面、课表导出(按班级/教师)。

      下面,我就用python代码让各位大佬见识一下,什么叫"传统文化遇上赛博效率"

      import osimport syscurrent_dir = os.path.dirname(os.path.abspath(__file__))if current_dir not in sys.path:    sys.path.insert(0, current_dir)from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout,                              QHBoxLayoutQTableWidgetQTableWidgetItem                             QPushButtonQComboBoxQLabelQHeaderView                             QMessageBoxQFileDialogQCheckBox)from PyQt6.QtCore import Qt, QSize, QThread, pyqtSignalfrom PyQt6.QtGui import QIcon, QFont, QPixmapfrom datetime import datetimefrom models import DataManagerfrom scheduler import Schedulerfrom dialogs import DataManagementDialog, CourseSelectionDialog, HistoryDialog, TeacherStatisticsDialogclass SchedulingThread(QThread):    finished = pyqtSignal(bool, str)    def __init__(self, scheduler: Scheduler):        super().__init__()        self.scheduler = scheduler    def run(self):        try:            success = self.scheduler.schedule()            self.finished.emit(success, "")        except Exception as e:            self.finished.emit(False, str(e))class MainWindow(QMainWindow):    def __init__(self):        super().__init__()        self.dm = DataManager()        self.scheduler = Scheduler(self.dm)        self.view_mode = "class" # "class" or "teacher"        self.scheduling_thread = None        self.setWindowTitle("全校智能自动化排课系统工具(欢迎关注微信公众号:码海听潮)")        self.resize(1400900)        self.setMinimumSize(1024768)        self.load_styles()        self.init_ui()        self.update_entity_selector()        self.refresh_timetable()    def load_styles(self):        if os.path.exists("styles.qss"):            with open("styles.qss""r", encoding="utf-8"as f:                self.setStyleSheet(f.read())    def init_ui(self):        central_widget = QWidget()        self.setCentralWidget(central_widget)        main_layout = QHBoxLayout(central_widget)        main_layout.setContentsMargins(15151515)        main_layout.setSpacing(15)        sidebar = QWidget()        sidebar.setFixedWidth(280)        sidebar.setObjectName("sidebar")        sidebar_layout = QVBoxLayout(sidebar)        sidebar_layout.addWidget(QLabel("展示维度:"))        self.view_type_selector = QComboBox()        self.view_type_selector.addItem("班级视角""class")        self.view_type_selector.addItem("教师视角""teacher")        self.view_type_selector.currentIndexChanged.connect(self.on_view_type_changed)        sidebar_layout.addWidget(self.view_type_selector)        sidebar_layout.addSpacing(10)        self.entity_label = QLabel("当前班级:")        sidebar_layout.addWidget(self.entity_label)        self.entity_selector = QComboBox()        self.entity_selector.currentIndexChanged.connect(self.refresh_timetable)        sidebar_layout.addWidget(self.entity_selector)        sidebar_layout.addSpacing(30)        self.manage_data_btn = QPushButton("数据管理")        self.manage_data_btn.setObjectName("secondary_btn")        self.manage_data_btn.clicked.connect(self.open_data_management)        sidebar_layout.addWidget(self.manage_data_btn)        self.run_scheduler_btn = QPushButton("一键自动排课")        self.run_scheduler_btn.setObjectName("run_scheduler_btn")        self.run_scheduler_btn.clicked.connect(self.run_auto_scheduling)        sidebar_layout.addWidget(self.run_scheduler_btn)        self.export_btn = QPushButton("导出 Excel")        self.export_btn.setObjectName("secondary_btn")        self.export_btn.clicked.connect(self.export_to_excel)        sidebar_layout.addWidget(self.export_btn)        self.screenshot_btn = QPushButton("保存课表为图片")        self.screenshot_btn.setObjectName("secondary_btn")        self.screenshot_btn.clicked.connect(self.take_screenshot)        sidebar_layout.addWidget(self.screenshot_btn)        self.history_btn = QPushButton("历史版本管理")        self.history_btn.setObjectName("secondary_btn")        self.history_btn.clicked.connect(self.open_history)        sidebar_layout.addWidget(self.history_btn)        self.stats_btn = QPushButton("🔍 查看排课统计")        self.stats_btn.setObjectName("secondary_btn")        self.stats_btn.clicked.connect(self.open_statistics)        sidebar_layout.addWidget(self.stats_btn)        self.export_global_btn = QPushButton("导出全校总表")        self.export_global_btn.setObjectName("secondary_btn")        self.export_global_btn.setStyleSheet("background-color: #28a745; color: white;")         self.export_global_btn.clicked.connect(self.export_global_excel)        sidebar_layout.addWidget(self.export_global_btn)        sidebar_layout.addSpacing(15)        self.manual_mode_checkbox = QCheckBox("开启手动调课 (双击单元格)")        self.manual_mode_checkbox.setStyleSheet("color: #d73a49;")         sidebar_layout.addWidget(self.manual_mode_checkbox)        sidebar_layout.addStretch()        display_area = QVBoxLayout()        display_area.setSpacing(10)        self.info_label = QLabel("请选择对象查看课表")        self.info_label.setObjectName("info_label")        self.info_label.setStyleSheet("font-size: 24px; color: #1f2328; font-weight: bold; margin-bottom: 10px;")        display_area.addWidget(self.info_label)        self.table = QTableWidget()        self.table.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers)        self.table.cellDoubleClicked.connect(self.on_cell_double_clicked)        display_area.addWidget(self.table)        main_layout.addWidget(sidebar)        main_layout.addLayout(display_area)        self.statusBar().showMessage("系统就绪")    def on_view_type_changed(self):        self.view_mode = self.view_type_selector.currentData()        self.entity_label.setText("当前班级:" if self.view_mode == "class" else "当前教师:")        self.update_entity_selector()    def update_entity_selector(self):        self.entity_selector.blockSignals(True)        self.entity_selector.clear()        if self.view_mode == "class":            for c in self.dm.classes:                self.entity_selector.addItem(c.name, c.id)        else:            for t in self.dm.teachers:                self.entity_selector.addItem(t.name, t.id)        self.entity_selector.blockSignals(False)        if self.entity_selector.count() > 0:            self.refresh_timetable()    def refresh_timetable(self):        entity_id = self.entity_selector.currentData()        if not entity_id:            return        if self.view_mode == "class":            class_obj = self.dm.get_class_by_id(entity_id)            if class_obj:                self.info_label.setText(f"{class_obj.name} 课表")            schedule = self.dm.timetable.get(entity_id, [])        else:            teacher_obj = self.dm.get_teacher_by_id(entity_id)            if teacher_obj:                self.info_label.setText(f"{teacher_obj.name} 老师课表")            schedule = self.dm.get_teacher_timetable(entity_id)        # 设置标签居中显示        self.info_label.setAlignment(Qt.AlignmentFlag.AlignCenter)        days = self.dm.settings["days_per_week"]        periods = self.dm.total_periods        self.table.setRowCount(periods)        self.table.setColumnCount(days)        day_names = ["周一""周二""周三""周四""周五""周六""周日"]        self.table.setHorizontalHeaderLabels(day_names[:days])        labels = []        m_p = self.dm.morning_count        s_p = self.dm.standard_count        e_p = self.dm.evening_count        for i in range(m_p): labels.append(f"早{i+1}")        for i in range(s_p): labels.append(f"正{i+1}")        for i in range(e_p): labels.append(f"晚{i+1}")        self.table.setVerticalHeaderLabels(labels)        self.table.horizontalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)        self.table.verticalHeader().setSectionResizeMode(QHeaderView.ResizeMode.Stretch)        self.table.clearContents()        if schedule:            for r in range(min(len(schedule), periods)):                for c in range(min(len(schedule[r]), days)):                    item_data = schedule[r][c]                    if isinstance(item_data, dict):                        course_name = item_data.get("name""")                        teacher_name = item_data.get("teacher_name""")                        if self.view_mode == "class" and teacher_name:                            display_text = f"{course_name} ({teacher_name})"                        else:                            display_text = course_name                    elif isinstance(item_data, str):                        display_text = item_data                    item = QTableWidgetItem(display_text)                    item.setTextAlignment(Qt.AlignmentFlag.AlignCenter)                    if self.view_mode == "class" and course_name:                         if r < m_p: item.setBackground(Qt.GlobalColor.cyan)                         elif r >= m_p + s_p: item.setBackground(Qt.GlobalColor.lightGray)                         else: item.setBackground(Qt.GlobalColor.white)                    self.table.setItem(r, c, item)    def open_data_management(self):        dialog = DataManagementDialog(self.dm, self)        if dialog.exec():            self.dm.load_all()             self.update_entity_selector()            self.refresh_timetable()            self.statusBar().showMessage("数据已更新")    def open_statistics(self):        dialog = TeacherStatisticsDialog(self.dm, self)        dialog.exec()    def open_history(self):        dialog = HistoryDialog(self.dm, self)        if dialog.exec():            self.update_entity_selector()            self.refresh_timetable()            self.statusBar().showMessage("历史版本已载入")    def run_auto_scheduling(self):        if self.scheduling_thread and self.scheduling_thread.isRunning():            return        gaps = self.dm.check_curriculum_completeness()        if gaps:            gap_list = "\n".join([f" - {name}: 缺 {count} 节" for name, count in gaps[:10]])            if len(gaps) > 10: gap_list += "\n..."            reply = QMessageBox.warning(self"课程设置不完整警示"                                       f"以下班级的课时总数不满 40 节,排完后会出现空时间段:\n\n{gap_list}\n\n提醒:建议去数据管理增加老师的授课课时。\n是否仍要继续排课?",                                       QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.NoQMessageBox.StandardButton.No)            if reply == QMessageBox.StandardButton.No:                return        reply = QMessageBox.question(self"确认""确定要重新排课吗?当前课表将被覆盖。",                                     QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.NoQMessageBox.StandardButton.No)        if reply == QMessageBox.StandardButton.Yes:            self.statusBar().showMessage("正在排课中,请稍候...")            self.run_scheduler_btn.setEnabled(False)            self.scheduling_thread = SchedulingThread(self.scheduler)            self.scheduling_thread.finished.connect(self.handle_scheduling_finished)            self.scheduling_thread.start()    def handle_scheduling_finished(self, success, error_msg):        self.run_scheduler_btn.setEnabled(True)        if success:            results = self.scheduler.get_result()            self.dm.timetable = results            # Auto save snapshot            self.dm.save_snapshot("自动排课生成")            self.dm.save_all()            self.refresh_timetable()            QMessageBox.information(self"成功""课表已自动生成!")            self.statusBar().showMessage("排课成功")        else:            msg = error_msg if error_msg else "无法在当前约束下找到可行解。请尝试减少课时或放宽限制。"            QMessageBox.warning(self"失败", f"排课失败:{msg}")            self.statusBar().showMessage("排课失败")    def take_screenshot(self):        if not os.path.exists("screenshots"):            os.makedirs("screenshots")        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")        filename = f"screenshots/课表_{self.entity_selector.currentText()}_{timestamp}.png"        pixmap = self.table.grab()        pixmap.save(filename, "PNG")        QMessageBox.information(self"截图成功", f"课表截图已保存至:\n{os.path.abspath(filename)}")    def on_cell_double_clicked(self, row, col):        if not self.manual_mode_checkbox.isChecked():            return        if self.view_mode != "class":            QMessageBox.warning(self"提示""请切换到'班级视角'后再进行调课。")            return        class_id = self.entity_selector.currentData()        if not class_id: return        class_courses = [c for c in self.dm.courses if c.class_id == class_id]        class_schedule = self.dm.timetable.get(class_id, [])        current_course_id = None        if row < len(class_schedule) and col < len(class_schedule[row]):            item = class_schedule[row][col]            if isinstance(item, dict):                current_course_id = item.get("course_id")        dialog = CourseSelectionDialog(class_courses, current_course_id, self)        if dialog.exec():            new_course_id = dialog.selected_course_id            if new_course_id:                can_place, msg = self.dm.check_slot_available(new_course_id, col, row)                if not can_place:                    QMessageBox.critical(self"冲突警告", msg)                    return                course = self.dm.get_course_by_id(new_course_id)                new_data = {"course_id": new_course_id, "name": course.name}            else:                new_data = {"course_id"None"name"""}            days = self.dm.settings["days_per_week"]            periods = self.dm.total_periods            if class_id not in self.dm.timetable:                self.dm.timetable[class_id] = [[{"course_id"None"name"""for _ in range(days)] for _ in range(periods)]            grid = self.dm.timetable[class_id]            while len(grid) <= row: grid.append([{"course_id"None"name"""for _ in range(days)])            while len(grid[row]) <= col: grid[row].append({"course_id"None"name"""})            grid[row][col] = new_data            self.dm.save_all()            self.refresh_timetable()            self.statusBar().showMessage("手动调课成功")    def export_to_excel(self):        entity_id = self.entity_selector.currentData()        if not entity_id:            QMessageBox.warning(self"提示""请选择查看对象。")            return        path, _ = QFileDialog.getSaveFileName(self"导出课表", f"{self.entity_selector.currentText()}课表.xlsx""Excel Files (*.xlsx)")        if not path:            return        try:            from openpyxl import Workbook            from openpyxl.styles import Alignment, Font, Border, Side, PatternFill            wb = Workbook()            ws = wb.active            ws.title = "课表"            days = self.dm.settings["days_per_week"]            periods = self.dm.total_periods            m_p = self.dm.morning_count            s_p = self.dm.standard_count            e_p = self.dm.evening_count            day_names = ["周一""周二""周三""周四""周五""周六""周日"]            headers = ["节次"+ day_names[:days]            ws.append(headers)            bold_font = Font(bold=True, color="FFFFFF")            fill = PatternFill(start_color="24292E", end_color="24292E", fill_type="solid")            alignment = Alignment(horizontal="center", vertical="center")            for cell in ws[1]:                cell.font = bold_font                cell.fill = fill                cell.alignment = alignment            if self.view_mode == "class":                schedule = self.dm.timetable.get(entity_id, [])            else:                schedule = self.dm.get_teacher_timetable(entity_id)            labels = []            for i in range(m_p): labels.append(f"早{i+1}")            for i in range(s_p): labels.append(f"正{i+1}")            for i in range(e_p): labels.append(f"晚{i+1}")            for r in range(periods):                row_data = [labels[r] if r < len(labels) else f"{r+1}"]                for d in range(days):                    course_str = ""                    if r < len(schedule) and d < len(schedule[r]):                        item = schedule[r][d]                        if isinstance(item, dict):                            course_name = item.get("name""")                            teacher_name = item.get("teacher_name""")                            if self.view_mode == "class" and teacher_name:                                course_str = f"{course_name} ({teacher_name})"                            else:                                course_str = course_name                        else:                            course_str = str(item or "")                    row_data.append(course_str)                ws.append(row_data)            border = Border(left=Side(style='thin'), right=Side(style='thin'),                             top=Side(style='thin'), bottom=Side(style='thin'))            for row in ws.iter_rows(min_row=2, max_row=periods+1, min_col=1, max_col=days+1):                for cell in row:                    cell.alignment = alignment                    cell.border = border            for col in ws.columns:                ws.column_dimensions[col[0].column_letter].width = 15            wb.save(path)            QMessageBox.information(self"成功", f"课表已成功导出至:\n{path}")        except Exception as e:            QMessageBox.critical(self"错误", f"导出失败:{e}")    def export_global_excel(self):        path, _ = QFileDialog.getSaveFileName(self"导出全校总表""全校总课表.xlsx""Excel Files (*.xlsx)")        if not path:            return        try:            from openpyxl import Workbook            from openpyxl.styles import Alignment, Font, Border, Side, PatternFill            wb = Workbook()            ws = wb.active            ws.title = "全校总课表"            days = self.dm.settings["days_per_week"]            periods = self.dm.total_periods            classes = self.dm.classes            day_names = ["周一""周二""周三""周四""周五""周六""周日"]            labels = []            m_p = self.dm.morning_count            s_p = self.dm.standard_count            e_p = self.dm.evening_count            for i in range(m_p): labels.append(f"早{i+1}")            for i in range(s_p): labels.append(f"正{i+1}")            for i in range(e_p): labels.append(f"晚{i+1}")            headers = ["时间段"+ [c.name for c in classes]            ws.append(headers)            header_fill = PatternFill(start_color="24292E", end_color="24292E", fill_type="solid")            header_font = Font(bold=True, color="FFFFFF")            align_center = Alignment(horizontal="center", vertical="center", wrap_text=True)            border = Border(left=Side(style='thin'), right=Side(style='thin'),                            top=Side(style='thin'), bottom=Side(style='thin'))            for cell in ws[1]:                cell.fill = header_fill                cell.font = header_font                cell.alignment = align_center                cell.border = border            for d in range(days):                day_name = day_names[d]                for p in range(periods):                    row_idx = d * periods + p                    label = f"{day_name} - {labels[p]}"                    row_data = [label]                    for cls in classes:                        class_schedule = self.dm.timetable.get(cls.id, [])                        course_str = ""                        if p < len(class_schedule) and d < len(class_schedule[p]):                            item = class_schedule[p][d]                            if isinstance(item, dict) and item.get("name"):                                course_id = item.get("course_id")                                course = self.dm.get_course_by_id(course_id)                                teacher_name = ""                                if course:                                    teacher = self.dm.get_teacher_by_id(course.teacher_id)                                    teacher_name = f"({teacher.name})" if teacher else ""                                course_str = f"{item['name']}{teacher_name}"                        row_data.append(course_str)                    ws.append(row_data)                    excel_row = ws.max_row                    day_fills = ["E8F5E9""E3F2FD""FFF3E0""F3E5F5""FBE9E7"]                    fill = PatternFill(start_color=day_fills[d % len(day_fills)],                                       end_color=day_fills[d % len(day_fills)], fill_type="solid")                    for cell in ws[excel_row]:                        cell.alignment = align_center                        cell.border = border                        if cell.column == 1:                            cell.font = Font(bold=True)                        else:                            cell.fill = fill            ws.column_dimensions['A'].width = 15            for i in range(2, len(headers) + 1):                col_letter = ws.cell(row=1, column=i).column_letter                ws.column_dimensions[col_letter].width = 18            ws.freeze_panes = "B2"            wb.save(path)            QMessageBox.information(self"成功", f"全校总表已导出至:\n{path}")        except Exception as e:            QMessageBox.critical(self"导出失败", f"错误详情:{str(e)}")if __name__ == "__main__":    app = QApplication(sys.argv)    font = QFont("Microsoft YaHei"9)    app.setFont(font)    window = MainWindow()    window.show()    sys.exit(app.exec())

      运行程序后短短几秒就自动排出了全校课表,完美实现了之前既定的需求.......

      通过上面Python自动化脚本,仅用几秒钟的时间就完成原需手动操作数小时甚至数天的工作任务。从最初准备手动人工机械操作的麻木到用python实现高效自动化的畅快,工作效率获得指数级提升,终于实现了不加班熬夜的自由!

      大佬们也可以举一反三,参照上面的代码思路根据自己工作中的实际情况来具体问题具体分析,实现自己定制化的需求。

      结语

      当Python遇见办公,牛马打工人终于笑出了猪叫声

      【职场人必看】每天早上一睁眼,想到又要面对:

      1.📊 堆积如山的Excel表格

      2.📑 机械重复的复制粘贴

      3.✍️ 永远改不完的各类文档

      4.诸如此类的更多........

      是不是连Ctrl+Alt+Delete的心都有了?

      别慌!别急,摸鱼这位“职场外挂”已经带着Python代码来拯救你了!

      友情提示:考虑到没有python环境的朋友需要打包好的成品exe,摸鱼早已贴心打包好,本篇文章代码打包的exe截图如下:

      另外,《码海听潮》公众号百分之九十五的文章 python代码和exe程序已打包好上传绿联nas私有云,感谢各位大佬观看~

      最新文章

      随机文章

      基本 文件 流程 错误 SQL 调试
      1. 请求信息 : 2026-07-03 20:45:07 HTTP/2.0 GET : https://f.mffb.com.cn/a/492841.html
      2. 运行时间 : 0.200294s [ 吞吐率:4.99req/s ] 内存消耗:4,951.71kb 文件加载:140
      3. 缓存信息 : 0 reads,0 writes
      4. 会话信息 : SESSION_ID=222eb858d15de308d4fac7794439a7a6
      1. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/public/index.php ( 0.79 KB )
      2. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/autoload.php ( 0.17 KB )
      3. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_real.php ( 2.49 KB )
      4. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/platform_check.php ( 0.90 KB )
      5. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/ClassLoader.php ( 14.03 KB )
      6. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/composer/autoload_static.php ( 4.90 KB )
      7. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper.php ( 8.34 KB )
      8. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/helper.php ( 2.19 KB )
      9. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/helper.php ( 1.47 KB )
      10. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/stubs/load_stubs.php ( 0.16 KB )
      11. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Exception.php ( 1.69 KB )
      12. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Facade.php ( 2.71 KB )
      13. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/deprecation-contracts/function.php ( 0.99 KB )
      14. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap.php ( 8.26 KB )
      15. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/polyfill-mbstring/bootstrap80.php ( 9.78 KB )
      16. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/Resources/functions/dump.php ( 1.49 KB )
      17. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-dumper/src/helper.php ( 0.18 KB )
      18. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/symfony/var-dumper/VarDumper.php ( 4.30 KB )
      19. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/App.php ( 15.30 KB )
      20. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-container/src/Container.php ( 15.76 KB )
      21. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/container/src/ContainerInterface.php ( 1.02 KB )
      22. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/provider.php ( 0.19 KB )
      23. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Http.php ( 6.04 KB )
      24. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Str.php ( 7.29 KB )
      25. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Env.php ( 4.68 KB )
      26. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/common.php ( 0.03 KB )
      27. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/helper.php ( 18.78 KB )
      28. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Config.php ( 5.54 KB )
      29. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/app.php ( 0.95 KB )
      30. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cache.php ( 0.78 KB )
      31. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/console.php ( 0.23 KB )
      32. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/cookie.php ( 0.56 KB )
      33. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/database.php ( 2.48 KB )
      34. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Env.php ( 1.67 KB )
      35. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/filesystem.php ( 0.61 KB )
      36. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/lang.php ( 0.91 KB )
      37. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/log.php ( 1.35 KB )
      38. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/middleware.php ( 0.19 KB )
      39. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/route.php ( 1.89 KB )
      40. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/session.php ( 0.57 KB )
      41. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/trace.php ( 0.34 KB )
      42. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/config/view.php ( 0.82 KB )
      43. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/event.php ( 0.25 KB )
      44. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Event.php ( 7.67 KB )
      45. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/service.php ( 0.13 KB )
      46. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/AppService.php ( 0.26 KB )
      47. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Service.php ( 1.64 KB )
      48. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Lang.php ( 7.35 KB )
      49. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/lang/zh-cn.php ( 13.70 KB )
      50. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/Error.php ( 3.31 KB )
      51. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/RegisterService.php ( 1.33 KB )
      52. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/services.php ( 0.14 KB )
      53. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/PaginatorService.php ( 1.52 KB )
      54. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ValidateService.php ( 0.99 KB )
      55. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/service/ModelService.php ( 2.04 KB )
      56. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Service.php ( 0.77 KB )
      57. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Middleware.php ( 6.72 KB )
      58. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/initializer/BootService.php ( 0.77 KB )
      59. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Paginator.php ( 11.86 KB )
      60. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-validate/src/Validate.php ( 63.20 KB )
      61. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/Model.php ( 23.55 KB )
      62. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Attribute.php ( 21.05 KB )
      63. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/AutoWriteData.php ( 4.21 KB )
      64. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/Conversion.php ( 6.44 KB )
      65. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/DbConnect.php ( 5.16 KB )
      66. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/ModelEvent.php ( 2.33 KB )
      67. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/concern/RelationShip.php ( 28.29 KB )
      68. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Arrayable.php ( 0.09 KB )
      69. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/contract/Jsonable.php ( 0.13 KB )
      70. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/model/contract/Modelable.php ( 0.09 KB )
      71. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Db.php ( 2.88 KB )
      72. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/DbManager.php ( 8.52 KB )
      73. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Log.php ( 6.28 KB )
      74. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Manager.php ( 3.92 KB )
      75. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerTrait.php ( 2.69 KB )
      76. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/log/src/LoggerInterface.php ( 2.71 KB )
      77. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cache.php ( 4.92 KB )
      78. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/psr/simple-cache/src/CacheInterface.php ( 4.71 KB )
      79. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/helper/Arr.php ( 16.63 KB )
      80. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/driver/File.php ( 7.84 KB )
      81. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/cache/Driver.php ( 9.03 KB )
      82. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/CacheHandlerInterface.php ( 1.99 KB )
      83. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/Request.php ( 0.09 KB )
      84. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Request.php ( 55.78 KB )
      85. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/middleware.php ( 0.25 KB )
      86. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Pipeline.php ( 2.61 KB )
      87. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/TraceDebug.php ( 3.40 KB )
      88. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/middleware/SessionInit.php ( 1.94 KB )
      89. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Session.php ( 1.80 KB )
      90. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/driver/File.php ( 6.27 KB )
      91. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/SessionHandlerInterface.php ( 0.87 KB )
      92. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/session/Store.php ( 7.12 KB )
      93. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Route.php ( 23.73 KB )
      94. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleName.php ( 5.75 KB )
      95. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Domain.php ( 2.53 KB )
      96. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleGroup.php ( 22.43 KB )
      97. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Rule.php ( 26.95 KB )
      98. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/RuleItem.php ( 9.78 KB )
      99. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/route/app.php ( 1.72 KB )
      100. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/Route.php ( 4.70 KB )
      101. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/dispatch/Controller.php ( 4.74 KB )
      102. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/route/Dispatch.php ( 10.44 KB )
      103. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/controller/Index.php ( 4.81 KB )
      104. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/app/BaseController.php ( 2.05 KB )
      105. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/facade/Db.php ( 0.93 KB )
      106. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/connector/Mysql.php ( 5.44 KB )
      107. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/PDOConnection.php ( 52.47 KB )
      108. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Connection.php ( 8.39 KB )
      109. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/ConnectionInterface.php ( 4.57 KB )
      110. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/builder/Mysql.php ( 16.58 KB )
      111. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Builder.php ( 24.06 KB )
      112. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseBuilder.php ( 27.50 KB )
      113. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/Query.php ( 15.71 KB )
      114. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/BaseQuery.php ( 45.13 KB )
      115. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TimeFieldQuery.php ( 7.43 KB )
      116. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/AggregateQuery.php ( 3.26 KB )
      117. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ModelRelationQuery.php ( 20.07 KB )
      118. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ParamsBind.php ( 3.66 KB )
      119. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/ResultOperation.php ( 7.01 KB )
      120. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/WhereQuery.php ( 19.37 KB )
      121. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/JoinAndViewQuery.php ( 7.11 KB )
      122. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/TableFieldInfo.php ( 2.63 KB )
      123. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-orm/src/db/concern/Transaction.php ( 2.77 KB )
      124. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/driver/File.php ( 5.96 KB )
      125. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/LogHandlerInterface.php ( 0.86 KB )
      126. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/log/Channel.php ( 3.89 KB )
      127. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/event/LogRecord.php ( 1.02 KB )
      128. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-helper/src/Collection.php ( 16.47 KB )
      129. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/facade/View.php ( 1.70 KB )
      130. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/View.php ( 4.39 KB )
      131. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Response.php ( 8.81 KB )
      132. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/response/View.php ( 3.29 KB )
      133. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/Cookie.php ( 6.06 KB )
      134. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-view/src/Think.php ( 8.38 KB )
      135. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/framework/src/think/contract/TemplateHandlerInterface.php ( 1.60 KB )
      136. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/Template.php ( 46.61 KB )
      137. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/driver/File.php ( 2.41 KB )
      138. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-template/src/template/contract/DriverInterface.php ( 0.86 KB )
      139. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/runtime/temp/067d451b9a0c665040f3f1bdd3293d68.php ( 11.98 KB )
      140. /yingpanguazai/ssd/ssd1/www/f.mffb.com.cn/vendor/topthink/think-trace/src/Html.php ( 4.42 KB )
      1. CONNECT:[ UseTime:0.001019s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
      2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001566s ]
      3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000711s ]
      4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000749s ]
      5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001684s ]
      6. SELECT * FROM `set` [ RunTime:0.000557s ]
      7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001565s ]
      8. SELECT * FROM `article` WHERE `id` = 492841 LIMIT 1 [ RunTime:0.001236s ]
      9. UPDATE `article` SET `lasttime` = 1783082707 WHERE `id` = 492841 [ RunTime:0.007445s ]
      10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000696s ]
      11. SELECT * FROM `article` WHERE `id` < 492841 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.001363s ]
      12. SELECT * FROM `article` WHERE `id` > 492841 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.001137s ]
      13. SELECT * FROM `article` WHERE `id` < 492841 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002025s ]
      14. SELECT * FROM `article` WHERE `id` < 492841 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.002920s ]
      15. SELECT * FROM `article` WHERE `id` < 492841 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.009287s ]
      0.203968s