当前位置:首页>python>Python Tkinter之工业用触摸屏界面优化技巧

Python Tkinter之工业用触摸屏界面优化技巧

  • 2026-06-30 13:14:18
Python Tkinter之工业用触摸屏界面优化技巧

🏭 当触摸屏遇上工控现场

车间里那台老旧的触摸屏,手指划过去,界面卡了整整两秒——操作工扭头看了我一眼,那眼神我至今记得。那是我接手第一个工控HMI项目的第三周。

工业触摸屏不是手机。这句话听起来像废话,但真正踩过坑的开发者才明白这里面藏着多少门道。工厂现场的屏幕分辨率往往是固定的800×480或1024×600,操作工戴着手套,手指触点面积是普通人的三倍,而且同一个按钮一天可能被点击上千次。用写桌面应用的思路去做工控HMI,结果往往是——界面好看,但用起来一塌糊涂。

这篇文章,我把这几年在Windows工控项目里摸索出来的Tkinter触摸屏优化技巧整理出来,从布局到响应,从字体到线程,每一条都是真实项目里踩过的坑。


🔍 工控触摸屏的核心矛盾

在动手写代码之前,咱们得先把问题想清楚。工控触摸屏界面和普通桌面应用,本质矛盾集中在三个地方:

触控精度与操作效率的矛盾。 工业触摸屏的触控精度远不如电容屏手机,误触率高,所以按钮必须足够大,间距必须足够宽。但屏幕就那么大,控件一多,布局就会很难看。

实时数据刷新与界面流畅度的矛盾。 工控软件要不断从PLC、传感器读取数据并刷新显示,频繁的UI更新很容易让主线程阻塞,界面变得迟钝。

稳定性要求与开发效率的矛盾。 工厂现场要求软件7×24小时运行,内存泄漏、线程死锁这些问题在办公软件里可能只是小麻烦,在工控现场就是停产事故。

搞清楚这三对矛盾,后面所有的优化技巧都是围绕它们展开的。


🎨 布局优化:让手套也能精准操作

触控友好的控件尺寸标准

工业界有个非正式的经验值:触摸按钮的最小尺寸不低于44×44像素,推荐60×60像素以上,按钮间距不低于8像素。这个数字来自人机工程学研究,也被我在现场反复验证过。

import tkinter as tk
from tkinter import ttk

classIndustrialButton(tk.Button):
"""
    工业触控按钮基类
    封装了触控友好的尺寸和视觉反馈逻辑
    """

def__init__(self, parent, **kwargs):
# 工控场景下的默认样式
        defaults = {
'width'10,
'height'3,
'font': ('微软雅黑'16'bold'),
'relief''raised',
'bd'3,
'activebackground''
#cccccc',
'cursor''hand2'
        }
        defaults.update(kwargs)
super().__init__(parent, **defaults)

# 绑定触摸反馈动画
self.bind('<ButtonPress-1>'self._on_press)
self.bind('<ButtonRelease-1>'self._on_release)

def_on_press(self, event):
"""按下时视觉下沉效果,给操作工明确的触觉反馈替代"""
self.config(relief='sunken', bd=2)

def_on_release(self, event):
self.config(relief='raised', bd=3)

这里有个细节值得说一下——cursor='hand2' 在工控现场其实用处不大,因为操作工用手指不用鼠标,但如果调试阶段工程师要用鼠标操作,这个光标样式能明显提示可点击区域。小细节,但体现专业度。

全屏无边框布局

工控HMI几乎清一色全屏运行,标题栏和菜单栏是多余的。

import  tkinter as tk  
classHMIApplication:  
def__init__(self):  
self.root = tk.Tk()  

# 全屏无边框设置  
self.root.attributes('-fullscreen'True)  
self.root.overrideredirect(True)  # 去掉系统标题栏  

# 获取实际屏幕分辨率(工控屏可能有DPI缩放)  
        screen_w = self.root.winfo_screenwidth()  
        screen_h = self.root.winfo_screenheight()  
self.root.geometry(f'{screen_w}x{screen_h}+0+0')  

# 禁止窗口缩放,工控软件布局必须固定  
self.root.resizable(FalseFalse)  

# 防止误触关闭窗口  
self.root.protocol('WM_DELETE_WINDOW'self._on_close_request)  

def_on_close_request(self):  
"""关闭请求需要二次确认,防止误操作停机"""
# 实际项目里这里会弹出密码验证对话框  
pass

if __name__ == '__main__':  
    app = HMIApplication()  
    app.root.mainloop()

overrideredirect(True) 这个属性要小心——它会让窗口失去系统级的窗口管理,在Windows上有时会导致Alt+Tab切换异常。我的做法是同时注册一个全局热键(比如Ctrl+Alt+Q)用于开发调试时退出,生产环境再把这个热键移除。

响应式网格布局

工控屏幕分辨率不统一,用绝对坐标定位是大忌。grid 布局加上权重配置,能让界面在不同分辨率下自适应缩放。

import tkinter as tk  
from tkinter import ttk  
import datetime  


classIndustrialControlGUI:  
def__init__(self):  
self.root = tk.Tk()  
self.root.title('工控布局示例')  
self.root.geometry('1024x768')  
self.root.configure(bg='#0f1419')  

# 初始化界面  
self.setup_main_layout()  
self.setup_status_bar()  
self.setup_main_area()  
self.setup_alarm_bar()  

# 启动定时更新  
self.update_status()  

defsetup_main_layout(self):  
"""  
        三区域经典工控布局:  
        顶部状态栏 | 中间主操作区 | 底部报警栏  
        """
self.root.grid_rowconfigure(0, weight=0, minsize=60)  # 状态栏,固定高度  
self.root.grid_rowconfigure(1, weight=1)  # 主操作区,占大部分空间  
self.root.grid_rowconfigure(2, weight=0, minsize=80)  # 报警栏,固定高度  
self.root.grid_columnconfigure(0, weight=1)  

# 状态栏  
self.status_frame = tk.Frame(self.root, bg='#1a1a2e', height=60)  
self.status_frame.grid(row=0, column=0, sticky='ew', padx=2, pady=1)  
self.status_frame.grid_propagate(False)  # 锁定高度,不随内容变化  

# 主操作区  
self.main_frame = tk.Frame(self.root, bg='#16213e')  
self.main_frame.grid(row=1, column=0, sticky='nsew', padx=2, pady=1)  

# 报警栏  
self.alarm_frame = tk.Frame(self.root, bg='#0f3460', height=80)  
self.alarm_frame.grid(row=2, column=0, sticky='ew', padx=2, pady=1)  
self.alarm_frame.grid_propagate(False)  

defsetup_status_bar(self):  
"""设置状态栏内容"""
self.status_frame.grid_columnconfigure(1, weight=1)  

# 系统状态指示灯  
        status_indicator = tk.Label(  
self.status_frame,  
            text="● 系统运行",  
            fg='#00ff00',  
            bg='#1a1a2e',  
            font=('Arial'10'bold')  
        )  
        status_indicator.grid(row=0, column=0, padx=10, pady=5, sticky='w')  

# 系统时间  
self.time_label = tk.Label(  
self.status_frame,  
            text="",  
            fg='white',  
            bg='#1a1a2e',  
            font=('Arial'12)  
        )  
self.time_label.grid(row=0, column=1, padx=10, pady=5)  

# 用户信息  
        user_label = tk.Label(  
self.status_frame,  
            text="操作员:Admin",  
            fg='#87ceeb',  
            bg='#1a1a2e',  
            font=('Arial'10)  
        )  
        user_label.grid(row=0, column=2, padx=10, pady=5, sticky='e')  

defsetup_main_area(self):  
"""设置主操作区内容"""
self.main_frame.grid_rowconfigure(0, weight=1)  
self.main_frame.grid_columnconfigure(0, weight=1)  
self.main_frame.grid_columnconfigure(1, weight=2)  

# 左侧控制面板  
        control_panel = tk.Frame(self.main_frame, bg='#1e293b', relief='raised', bd=2)  
        control_panel.grid(row=0, column=0, sticky='nsew', padx=5, pady=5)  

# 控制面板标题  
        tk.Label(  
            control_panel,  
            text="控制面板",  
            fg='white',  
            bg='#1e293b',  
            font=('Arial'14'bold')  
        ).pack(pady=10)  

# 控制按钮  
        button_frame = tk.Frame(control_panel, bg='#1e293b')  
        button_frame.pack(pady=10, padx=10, fill='x')  

        buttons = ["启动系统""停止系统""复位""参数设置""数据查看"]  
for i, btn_text inenumerate(buttons):  
            btn = tk.Button(  
                button_frame,  
                text=btn_text,  
                bg='#3b82f6',  
                fg='white',  
                font=('Arial'10),  
                relief='raised',  
                bd=2,  
                width=12,  
                command=lambda t=btn_text: self.button_click(t)  
            )  
            btn.pack(pady=5, fill='x')  

# 右侧监控显示区  
        monitor_panel = tk.Frame(self.main_frame, bg='#0f172a', relief='raised', bd=2)  
        monitor_panel.grid(row=0, column=1, sticky='nsew', padx=5, pady=5)  

# 监控面板标题  
        tk.Label(  
            monitor_panel,  
            text="实时监控",  
            fg='white',  
            bg='#0f172a',  
            font=('Arial'14'bold')  
        ).pack(pady=10)  

# 创建参数显示区域  
        params_frame = tk.Frame(monitor_panel, bg='#0f172a')  
        params_frame.pack(pady=10, padx=20, fill='both', expand=True)  

# 模拟参数显示  
self.create_parameter_display(params_frame)  

defcreate_parameter_display(self, parent):  
"""创建参数显示区域"""
# 创建表格样式的参数显示  
        params = [  
            ("温度""25.6°C""#00ff00"),  
            ("压力""1.2bar""#00ff00"),  
            ("流量""45.2L/min""#ffff00"),  
            ("电压""380V""#00ff00"),  
            ("转速""1450rpm""#00ff00")  
        ]  
for i, (name, value, color) inenumerate(params):  
            param_frame = tk.Frame(parent, bg='#1e293b', relief='raised', bd=1)  
            param_frame.pack(fill='x', pady=5, padx=10)  

            tk.Label(  
                param_frame,  
                text=name + ":",  
                fg='white',  
                bg='#1e293b',  
                font=('Arial'12),  
                width=8,  
                anchor='w'
            ).pack(side='left', padx=10, pady=5)  

            tk.Label(  
                param_frame,  
                text=value,  
                fg=color,  
                bg='#1e293b',  
                font=('Arial'12'bold'),  
                anchor='e'
            ).pack(side='right', padx=10, pady=5)  

defsetup_alarm_bar(self):  
"""设置报警栏内容"""
self.alarm_frame.grid_columnconfigure(1, weight=1)  

# 报警指示灯  
self.alarm_indicator = tk.Label(  
self.alarm_frame,  
            text="● 正常",  
            fg='#00ff00',  
            bg='#0f3460',  
            font=('Arial'12'bold')  
        )  
self.alarm_indicator.grid(row=0, column=0, padx=10, pady=5, sticky='w')  

# 滚动报警信息  
self.alarm_text = tk.Label(  
self.alarm_frame,  
            text="系统运行正常,无报警信息",  
            fg='white',  
            bg='#0f3460',  
            font=('Arial'11)  
        )  
self.alarm_text.grid(row=0, column=1, padx=10, pady=5, sticky='ew')  

# 确认按钮  
        ack_button = tk.Button(  
self.alarm_frame,  
            text="确认",  
            bg='#dc2626',  
            fg='white',  
            font=('Arial'10),  
            width=8,  
            command=self.acknowledge_alarm  
        )  
        ack_button.grid(row=0, column=2, padx=10, pady=5, sticky='e')  

defupdate_status(self):  
"""更新状态信息"""
        current_time = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")  
self.time_label.configure(text=current_time)  

# 每秒更新一次  
self.root.after(1000self.update_status)  

defbutton_click(self, button_name):  
"""按钮点击事件处理"""
if button_name == "启动系统":  
self.alarm_text.configure(text=f"系统启动命令已执行 - {datetime.datetime.now().strftime('%H:%M:%S')}")  
elif button_name == "停止系统":  
self.alarm_text.configure(text=f"系统停止命令已执行 - {datetime.datetime.now().strftime('%H:%M:%S')}")  
elif button_name == "复位":  
self.alarm_text.configure(text=f"系统复位命令已执行 - {datetime.datetime.now().strftime('%H:%M:%S')}")  
else:  
self.alarm_text.configure(text=f"{button_name}功能已触发 - {datetime.datetime.now().strftime('%H:%M:%S')}")  

defacknowledge_alarm(self):  
"""报警确认"""
self.alarm_text.configure(text="报警已确认")  
self.alarm_indicator.configure(text="● 正常", fg='#00ff00')  

defrun(self):  
"""运行主循环"""
self.root.mainloop()  


if __name__ == '__main__':  
    app = IndustrialControlGUI()  
    app.run()

grid_propagate(False) 这个调用很关键。工控界面的状态栏和报警栏高度必须固定,否则当报警信息文字变长时,整个布局会跟着变形,操作工的肌肉记忆会被破坏——他们记住了按钮在屏幕上的位置,布局一动,误操作概率直线上升。


⚡ 数据刷新优化:主线程的救命稻草

这是工控Tkinter开发里最容易翻车的地方。我见过太多项目,把串口读取、Modbus通信直接塞进主线程,然后界面卡成PPT。

线程分离 + 队列通信

正确的姿势是:数据采集在子线程,UI更新在主线程,通过队列传递数据

import threading
import queue
import time

classDataCollector:
"""
    数据采集器,运行在独立线程
    通过队列向UI线程推送数据,绝不直接操作UI控件
    """

def__init__(self, data_queue: queue.Queue):
self.data_queue = data_queue
self._stop_event = threading.Event()
self._thread = threading.Thread(
            target=self._collect_loop,
            daemon=True,  # 守护线程,主程序退出时自动结束
            name='DataCollector'
        )

defstart(self):
self._thread.start()

defstop(self):
self._stop_event.set()

def_collect_loop(self):
whilenotself._stop_event.is_set():
try:
# 模拟从PLC读取数据(实际项目替换为Modbus/OPC-UA读取)
                sensor_data = {
'temperature'self._read_temperature(),
'pressure'self._read_pressure(),
'timestamp': time.time()
                }

# 队列满时丢弃旧数据,保证实时性
# 工控场景里实时性比完整性更重要
ifself.data_queue.full():
try:
self.data_queue.get_nowait()
except queue.Empty:
pass

self.data_queue.put_nowait(sensor_data)

except Exception as e:
# 采集异常不能让程序崩溃,记录日志继续运行
print(f'数据采集异常: {e}')

            time.sleep(0.1)  # 10Hz采集频率,根据实际需求调整

def_read_temperature(self):
# 实际项目里这里是Modbus读取逻辑
import random
returnround(random.uniform(20.080.0), 1)

def_read_pressure(self):
import random
returnround(random.uniform(0.11.0), 3)


classHMIDisplay:
"""UI显示层,只负责渲染,数据来自队列"""

def__init__(self, root):
self.root = root
self.data_queue = queue.Queue(maxsize=5)  # 队列不宜过大

self._build_ui()
self._collector = DataCollector(self.data_queue)
self._collector.start()

# 启动UI刷新循环
self._schedule_ui_update()

def_build_ui(self):
self.temp_var = tk.StringVar(value='--.-°C')
self.pressure_var = tk.StringVar(value='-.---MPa')

        tk.Label(
self.root,
            textvariable=self.temp_var,
            font=('微软雅黑'36'bold'),
            fg='#00ff88',
            bg='#16213e'
        ).pack(pady=20)

        tk.Label(
self.root,
            textvariable=self.pressure_var,
            font=('微软雅黑'28),
            fg='#ffaa00',
            bg='#16213e'
        ).pack(pady=10)

def_schedule_ui_update(self):
"""
        用after()代替while循环刷新UI
        这是Tkinter多线程安全更新的标准做法
        """

self._process_queue()
# 每200ms刷新一次UI,5Hz对工控显示够用了
self.root.after(200self._schedule_ui_update)

def_process_queue(self):
"""批量处理队列中的数据,取最新值显示"""
        latest_data = None

# 把队列里积压的数据全部取出,只用最新的
whileTrue:
try:
                latest_data = self.data_queue.get_nowait()
except queue.Empty:
break

if latest_data:
self.temp_var.set(f"{latest_data['temperature']:.1f}°C")
self.pressure_var.set(f"{latest_data['pressure']:.3f}MPa")

注意 _process_queue 里那个循环——它会把队列里积压的所有数据取出来,只显示最新的一条。这个细节很重要:如果UI刷新速度跟不上数据采集速度,队列会越积越深,显示的数据会越来越滞后。工控现场要的是"现在"的数据,不是"五秒前"的数据。

Canvas绘图的性能陷阱

工控界面里经常有仪表盘、趋势曲线这类自绘控件。Canvas是Tkinter里画这些东西的利器,但有个坑很多人踩过——每次刷新都delete再重画,会导致Canvas对象ID不断增长,内存慢慢泄漏

classTrendChart:
"""
    趋势曲线控件
    使用tag管理画布元素,避免重复创建对象
    """

def__init__(self, parent, width=600, height=200):
self.canvas = tk.Canvas(
            parent,
            width=width,
            height=height,
            bg='#0a0a1a',
            highlightthickness=0
        )
self.canvas.pack()

self.width = width
self.height = height
self.data_points = []
self.max_points = 100

# 预先创建折线对象,后续只更新坐标,不重建对象
self._line_id = self.canvas.create_line(
0000,
            fill='#00ff88',
            width=2,
            tags='trend_line'
        )

# 绘制静态背景网格(只画一次)
self._draw_grid()

def_draw_grid(self):
"""背景网格只需绘制一次,用单独的tag管理"""
        step_x = self.width // 10
        step_y = self.height // 4

for i inrange(110):
            x = i * step_x
self.canvas.create_line(
                x, 0, x, self.height,
                fill='#1a1a3a', width=1, tags='grid'
            )

for i inrange(14):
            y = i * step_y
self.canvas.create_line(
0, y, self.width, y,
                fill='#1a1a3a', width=1, tags='grid'
            )

defupdate(self, new_value: float, value_min=0, value_max=100):
"""更新趋势线,只修改坐标,不重建Canvas对象"""
self.data_points.append(new_value)

iflen(self.data_points) > self.max_points:
self.data_points.pop(0)

iflen(self.data_points) < 2:
return

# 计算折线坐标
        coords = []
for i, val inenumerate(self.data_points):
            x = int(i * self.width / (self.max_points - 1))
# 数值映射到画布Y坐标(注意Y轴方向)
            y = int(self.height - (val - value_min) / (value_max - value_min) * self.height)
            y = max(0min(self.height, y))  # 夹紧到画布范围内
            coords.extend([x, y])

# 直接修改现有折线的坐标,不delete不create
self.canvas.coords(self._line_id, *coords)

canvas.coords() 修改现有对象坐标,比 delete + create_line 的性能好不少,在低配工控机上这个差距会被放大。


🎨 工业风视觉设计:深色主题与高对比度

工控现场的环境光线复杂——有时候强光直射,有时候车间灯光昏暗。深色背景配高亮前景色,是工控HMI的行业惯例,也是有科学依据的。

# 工控HMI配色方案
INDUSTRIAL_THEME = {
# 背景色系
'bg_primary':    '#0d1117',   # 主背景,近黑
'bg_secondary':  '#161b22',   # 次级背景
'bg_panel':      '#21262d',   # 面板背景

# 状态色(遵循工业标准:红停绿运黄警)
'status_run':    '#39d353',   # 运行中 - 绿
'status_stop':   '#f85149',   # 停止/故障 - 红
'status_warn':   '#e3b341',   # 警告 - 黄
'status_idle':   '#58a6ff',   # 待机 - 蓝

# 文字色
'text_primary':  '#f0f6fc',   # 主要文字
'text_secondary':'#8b949e',   # 次要文字
'text_value':    '#79c0ff',   # 数值显示

# 边框
'border':        '#30363d',
}

defapply_theme(widget, theme=INDUSTRIAL_THEME):
"""递归应用主题到所有子控件"""
try:
        widget_type = widget.winfo_class()

if widget_type in ('Frame''LabelFrame'):
            widget.config(bg=theme['bg_secondary'])
elif widget_type == 'Label':
            widget.config(
                bg=theme['bg_secondary'],
                fg=theme['text_primary']
            )
elif widget_type == 'Button':
            widget.config(
                bg=theme['bg_panel'],
                fg=theme['text_primary'],
                activebackground=theme['bg_primary'],
                activeforeground=theme['status_run'],
                relief='flat',
                bd=1
            )
except tk.TclError:
pass

for child in widget.winfo_children():
        apply_theme(child, theme)

字体选择上,工控场景强烈推荐使用等宽或半等宽字体显示数值,比如 Consolas 或 Courier New。原因很实际:数值在刷新时,等宽字体不会因为数字宽度不同而导致界面"抖动"——1 和 8 的宽度一样,显示 100.0 和 88.8 时布局不会跳动,操作工读数更稳定。


🛡️ 稳定性加固:7×24小时运行的底线

工控软件的稳定性要求是苛刻的。我在一个项目里见过因为Tkinter内存泄漏,软件运行72小时后崩溃,直接导致一条产线停工4小时。

全局异常捕获

import sys
import logging
import traceback
from datetime import datetime

# 配置日志,工控软件的日志要写到本地文件
logging.basicConfig(
    filename=f'hmi_{datetime.now().strftime("%Y%m%d")}.log',
    level=logging.ERROR,
format='%(asctime)s - %(levelname)s - %(message)s',
    encoding='utf-8'
)

defglobal_exception_handler(exc_type, exc_value, exc_traceback):
"""
    全局未捕获异常处理
    记录日志后尝试恢复,而不是直接崩溃
    """

ifissubclass(exc_type, KeyboardInterrupt):
        sys.__excepthook__(exc_type, exc_value, exc_traceback)
return

    error_msg = ''.join(traceback.format_exception(exc_type, exc_value, exc_traceback))
    logging.error(f'未捕获异常:\n{error_msg}')

# 实际项目里这里可以触发自动重启逻辑
print(f'程序异常,已记录日志: {exc_value}')

sys.excepthook = global_exception_handler

定时内存检查

长时间运行的Tkinter应用,Canvas对象、StringVar、图片资源是最常见的内存泄漏来源。加一个定时检查,至少能在出问题之前发现端倪。

import psutil
import os

classMemoryWatchdog:
"""
    内存看门狗
    监控进程内存占用,超阈值时触发告警或自动重启
    """

def__init__(self, root, threshold_mb=500, check_interval=60000):
self.root = root
self.threshold_mb = threshold_mb
self.check_interval = check_interval  # 毫秒
self._schedule_check()

def_schedule_check(self):
self._check_memory()
self.root.after(self.check_interval, self._schedule_check)

def_check_memory(self):
        process = psutil.Process(os.getpid())
        mem_mb = process.memory_info().rss / 1024 / 1024

        logging.info(f'当前内存占用: {mem_mb:.1f}MB')

if mem_mb > self.threshold_mb:
            logging.warning(f'内存占用超过阈值 {self.threshold_mb}MB,当前: {mem_mb:.1f}MB')
# 触发告警,通知运维人员
self._trigger_memory_alarm(mem_mb)

def_trigger_memory_alarm(self, mem_mb):
# 实际项目里这里可以发送告警短信或邮件
print(f'[内存告警] 当前占用 {mem_mb:.1f}MB')

🔧 实战小结

工业触摸屏界面开发,说到底是在约束条件下做设计。屏幕小、硬件弱、环境恶劣、可靠性要求极高——这些约束反而逼着你把每一行代码都想清楚。

几个核心原则总结一下:触控控件够大、布局固定不跳动、数据采集与UI严格分离、Canvas对象复用而非重建、全局异常一定要兜底。这五条,是我在多个工控项目里反复验证过的。

Tkinter不是最炫的GUI框架,但在Windows工控场景里,它的轻量、稳定、无外部依赖,反而是优势。用好了,完全可以撑起一套专业的工业HMI系统。

完整的工程源码已整理并开源,供学习参考。欢迎在评论区分享你在工控HMI开发中遇到的问题,或者你有更好的优化思路,也很期待交流。


#Python开发#Tkinter#工控HMI#触摸屏优化#工业自动化

最新文章

随机文章

基本 文件 流程 错误 SQL 调试
  1. 请求信息 : 2026-07-03 17:55:34 HTTP/2.0 GET : https://f.mffb.com.cn/a/486932.html
  2. 运行时间 : 0.119787s [ 吞吐率:8.35req/s ] 内存消耗:4,757.94kb 文件加载:140
  3. 缓存信息 : 0 reads,0 writes
  4. 会话信息 : SESSION_ID=c448b1785c3cc164dec030fad5da0e06
  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.001037s ] mysql:host=127.0.0.1;port=3306;dbname=f_mffb;charset=utf8mb4
  2. SHOW FULL COLUMNS FROM `fenlei` [ RunTime:0.001508s ]
  3. SELECT * FROM `fenlei` WHERE `fid` = 0 [ RunTime:0.000674s ]
  4. SELECT * FROM `fenlei` WHERE `fid` = 63 [ RunTime:0.000706s ]
  5. SHOW FULL COLUMNS FROM `set` [ RunTime:0.001352s ]
  6. SELECT * FROM `set` [ RunTime:0.000623s ]
  7. SHOW FULL COLUMNS FROM `article` [ RunTime:0.001480s ]
  8. SELECT * FROM `article` WHERE `id` = 486932 LIMIT 1 [ RunTime:0.001472s ]
  9. UPDATE `article` SET `lasttime` = 1783072534 WHERE `id` = 486932 [ RunTime:0.014465s ]
  10. SELECT * FROM `fenlei` WHERE `id` = 66 LIMIT 1 [ RunTime:0.000392s ]
  11. SELECT * FROM `article` WHERE `id` < 486932 ORDER BY `id` DESC LIMIT 1 [ RunTime:0.004428s ]
  12. SELECT * FROM `article` WHERE `id` > 486932 ORDER BY `id` ASC LIMIT 1 [ RunTime:0.000479s ]
  13. SELECT * FROM `article` WHERE `id` < 486932 ORDER BY `id` DESC LIMIT 10 [ RunTime:0.002404s ]
  14. SELECT * FROM `article` WHERE `id` < 486932 ORDER BY `id` DESC LIMIT 10,10 [ RunTime:0.001152s ]
  15. SELECT * FROM `article` WHERE `id` < 486932 ORDER BY `id` DESC LIMIT 20,10 [ RunTime:0.001683s ]
0.123486s