当前位置:首页>教案>第5次课教案:美化界面 + 颜色选择 + 亮度调节

第5次课教案:美化界面 + 颜色选择 + 亮度调节

  • 2026-06-23 01:35:48
第5次课教案:美化界面 + 颜色选择 + 亮度调节

备课用


🎯 一、备课信息

项目

内容

课时

2课时(90分钟)

前置课程

第1-4课(已掌握:点灯、WiFi联网、基础网页控制)

教学目标

① 美化手机控制界面 ② 实现颜色选择功能 ③ 实现亮度调节功能

教学形式

教师演示 + 学生同步实操(边写代码边讲解,每写完一段立即测试)

所需材料

ESP32开发板、WS2812B灯条(10灯)、杜邦线、USB线、电脑、手机


📝 二、课前准备(5分钟)

2.1 检查学生前置知识

提问环节:

  • "上一课我们实现了什么功能?"(答案:手机开关灯)
  • "我们的网页长什么样?"(答案:几个简单的文字链接)
  • "大家觉得这个界面好看吗?想不想让它变漂亮?"

2.2 本课预告

教师话术:

"今天我们要给我们的灯控系统来个大装修!我们要做三件事:

  1. 🎨 给网页穿上漂亮衣服——渐变背景、圆角卡片、阴影效果
  2. 🌈 让灯条变色——点一下红色按钮,灯变红;点蓝色,灯变蓝
  3. 🔆 让灯条变亮变暗——像调台灯一样拖动滑块

最终效果:拿出手机,打开一个像APP一样漂亮的页面,点颜色、拖滑块,灯条实时响应!"

展示最终效果视频/图片(教师课前准备好)


🔧 三、教学流程:边写边讲边测

【第一阶段】复习回顾 + 引入美化(15分钟)

步骤1:打开第4课代码,回顾基础框架

教师操作: 打开Arduino IDE,加载第4课的最终代码。

讲解要点:

// 第4课我们已经有这些基础:
#include <WiFi.h>      // WiFi功能
#include <WebServer.h> // 网页服务器
#include <FastLED.h>   // LED控制

#define LED_PIN   2    // 灯条接GPIO 2
#define NUM_LEDS  10   // 10颗灯珠

const char* ssid = "你的WiFi名";     // WiFi名称
const char* password = "你的WiFi密码"; // WiFi密码

CRGB leds[NUM_LEDS];    // LED数组,像10个抽屉,每个放一种颜色
WebServer server(80);   // 服务器开在80端口(网页默认端口)

bool lightOn = true;    // 灯的状态:开着

提问: "这些代码是什么意思?谁来解释一下CRGB leds[NUM_LEDS]?"

预期回答: "这是一个数组,有10个元素,每个元素是一个颜色对象,对应一颗灯珠。"


步骤2:引入"状态变量"概念——为颜色和亮度做准备

教师操作: 在第4课代码基础上,添加两个新变量。

新增代码(在全局变量区域):

// ========== 【新增】状态变量 ==========
// 为什么要加这两个变量?
// 因为我们要记住:用户选了什么颜色?亮度调到多少?
// 就像你调台灯,调完后关掉,下次打开应该还是这个亮度

CRGB currentColor = CRGB(255, 255, 255);  
// currentColor = 当前颜色,默认白色(255,255,255)
// CRGB是FastLED的颜色类型,三个数字分别代表红、绿、蓝的强度
// 每个颜色范围0-255,0是最暗,255是最亮
// 所以(255,255,255)就是红满+绿满+蓝满 = 白色

int brightness = 128;  
// brightness = 亮度,范围0-255
// 128刚好是一半,作为默认值比较温和,不会太刺眼

教师讲解:

"大家看,我加了两个'记忆变量'。

currentColor像是一个调色盘,记住你现在选的颜色。默认白色。

brightness像是音量旋钮,记住亮度大小。默认128,一半亮度。

为什么要记住?因为当你关灯后再开灯,应该恢复之前的状态,而不是每次都回到默认。"

学生操作: 在自己的代码中添加这两个变量。

测试验证: 编译上传,串口监视器观察是否正常启动。没有功能变化,只是加了变量,确保不报错。


【第二阶段】美化网页界面——CSS装修(25分钟)

步骤3:认识HTML字符串原始字面量

教师讲解:

"第4课的网页代码是怎么写的?是不是有很多转义符号,看起来很乱?

今天教大家一个C++秘技:R"rawliteral(...)rawliteral"

它的作用:把一大段HTML原封不动地塞进程序里,不用转义任何符号!"

教师板书/投影对比:

旧写法(痛苦):

const char* html = "<html><head><title>\"灯控\"</title></head><body>...</body></html>";
// 每个引号前都要加反斜杠,写一行就眼花了

新写法(清爽):

const char* htmlPage = R"rawliteral(
<!DOCTYPE html>
<html>
<head>
    <title>灯控</title>
</head>
<body>
    ...
</body>
</html>
)rawliteral";
// 从R"rawliteral( 开始,到 )rawliteral" 结束
// 中间所有内容原样保留,双引号、换行、缩进全部保留

关键规则强调:

  • R 表示Raw(原始),后面的 "标记( 和 )标记" 必须成对出现
  • 标记名可以随便取,常用 rawliteral 或 EOF
  • 标记名本身不能出现在内容中,否则会提前结束

学生操作: 把第4课的HTML部分替换成这种新写法。

测试验证: 编译上传,手机访问,页面应该和第4课一样能正常显示。


步骤4:添加CSS样式——让页面变漂亮

教师操作: 在<head>标签内添加<style>块。

讲解策略: 不要一次性贴出全部CSS,而是分块讲解,每块立即看效果

【第4.1块】基础重置 + 页面背景

<style>
    /* ========== CSS基础重置 ========== */
    * { 
        margin: 0;      /* 去掉所有元素默认外边距 */
        padding: 0;     /* 去掉所有元素默认内边距 */
        box-sizing: border-box;  /* 盒子模型:宽高包含边框和内边距 */
        /* 什么意思?比如一个div宽300px,加了padding和border后还是300px,不会撑大 */
    }

    /* ========== 页面整体背景 ========== */
    body { 
        font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
        /* 字体栈:优先用苹果系统字体,其次Windows的Segoe UI,最后通用无衬线体 */
        /* 这样在不同手机上都能显示好看的字体 */

        background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
        /* linear-gradient = 线性渐变 */
        /* 135deg = 渐变方向:从左上到右下 */
        /* #667eea 是起点颜色(蓝紫色),#764ba2 是终点颜色(深紫色) */
        /* 0%和100%表示颜色在渐变中的位置 */
        /* 效果:整个页面背景是漂亮的紫蓝渐变,像极光一样 */

        min-height: 100vh;  /* 最小高度 = 视口高度的100%,确保背景铺满全屏 */
        padding: 20px;       /* 四周留白20像素,内容不贴边 */
    }
</style>

教师讲解要点:

"box-sizing: border-box是CSS中最重要的一句话。没有它,你设置宽度300px,加了padding和border后会变成300+padding+border,布局会乱。有了它,300px就是最终宽度,padding和border从内部扣减。"

学生操作: 添加这部分CSS,编译上传,手机刷新看效果。

预期效果: 页面背景变成漂亮的紫蓝渐变,文字可能看不清(因为默认黑色),没关系,下一步解决。


【第4.2块】容器和标题

<style>
    /* ... 接上面的CSS ... */

    /* ========== 内容容器 ========== */
    .container { 
        max-width: 400px;  /* 最宽400像素 */
        /* 为什么?手机屏幕宽度各异,400px在大多数手机上显示舒适 */
        /* 在大屏幕(如平板)上,内容不会无限撑宽,保持美观 */
        margin: 0 auto;      /* 上下边距0,左右自动(居中) */
    }

    h1 { 
        color: white;           /* 标题白色,在深色背景上清晰 */
        text-align: center;      /* 文字居中 */
        margin-bottom: 20px;     /* 标题下方留白 */
        font-size: 24px;         /* 字号 */
    }
</style>

教师讲解:

".container是一个'盒子',把所有内容装进去。max-width: 400px就像给水流加一个400px宽的渠道,水(内容)在里面流,不会泛滥。"

学生操作: 在HTML的<body>里添加容器:

<body>
    <div class="container">
        <h1>🏠 灯条控制中心</h1>
        <!-- 后续内容都放在这个container里面 -->
    </div>
</body>

测试验证: 手机刷新,看到标题居中、白色、背景渐变。


【第4.3块】卡片样式——让内容分区清晰

<style>
    /* ... 接上面的CSS ... */

    /* ========== 卡片样式 ========== */
    .card {
        background: white;           /* 卡片背景白色,与深色页面形成对比 */
        border-radius: 16px;           /* 圆角16像素,像iOS的卡片 */
        padding: 20px;               /* 内边距20px,内容与边框保持距离 */
        margin-bottom: 15px;         /* 卡片之间间距15px */
        box-shadow: 0 10px 30px rgba(0,0,0,0.2);
        /* box-shadow = 盒子阴影,四个值:
           0 = 水平偏移(不左右偏)
           10px = 垂直偏移(向下偏10像素)
           30px = 模糊半径(阴影边缘虚化30像素)
           rgba(0,0,0,0.2) = 颜色:黑色,20%透明度
           效果:卡片像浮在背景之上,有立体感 */
    }

    .card-title { 
        font-size: 18px; 
        font-weight: bold;           /* 加粗 */
        margin-bottom: 15px; 
        color: #333;                 /* 深灰色,比纯黑柔和 */
    }
</style>

教师讲解:

"border-radius: 16px让方角变圆角,这是现代UI设计的标志。iPhone的按钮、微信的对话框都是圆角。

box-shadow是'魔法'——没有阴影的卡片像贴在墙上,有了阴影像悬浮在空中,层次立刻出来。"

学生操作: 在HTML中添加第一个卡片(开关控制):

<div class="card">
    <div class="card-title">开关控制</div>
    <button onclick="fetch('/on')">开灯</button>
    <button onclick="fetch('/off')">关灯</button>
</div>

测试验证: 手机刷新,看到白色圆角卡片,按钮在卡片内。对比第4课的简陋界面,学生应该有"哇"的感觉。


【第4.4块】按钮美化

<style>
    /* ... 接上面的CSS ... */

    /* ========== 按钮样式 ========== */
    .btn {
        padding: 15px 30px;      /* 上下15px,左右30px,胖胖的按钮 */
        margin: 5px;             /* 按钮之间间距 */
        border: none;            /* 去掉默认边框 */
        border-radius: 10px;      /* 圆角 */
        font-size: 16px;          /* 字号 */
        cursor: pointer;         /* 鼠标悬停时变成手型 */
        color: white;            /* 文字白色 */
        font-weight: bold;       /* 文字加粗 */
    }

    .on { background: #4CAF50; }   /* 绿色 = 开灯,像交通灯 */
    .off { background: #f44336; }  /* 红色 = 关灯,像停止按钮 */

    /* 按钮悬停效果:鼠标放上去稍微变暗 */
    .btn:hover {
        opacity: 0.9;            /* 透明度90%,变暗一点点 */
        transform: scale(1.02);  /* 微微放大2%,有按下去的感觉 */
    }
</style>

教师讲解:

"#4CAF50是Material Design(谷歌设计规范)中的标准绿色,#f44336是标准红色。用这些'标准色',界面看起来就专业。

:hover是CSS伪类,表示'鼠标悬停时'。在手机上,点击瞬间也会触发hover效果,给用户反馈。"

学生操作: 给按钮加上class:

<button class="btn on" onclick="fetch('/on')">开灯</button>
<button class="btn off" onclick="fetch('/off')">关灯</button>

测试验证: 手机刷新,看到绿色"开灯"按钮、红色"关灯"按钮,点击有颜色反馈。


【第4.5块】颜色选择按钮

<style>
    /* ... 接上面的CSS ... */

    /* ========== 颜色选择按钮 ========== */
    .color-btn {
        width: 50px;              /* 宽50像素 */
        height: 50px;             /* 高50像素 */
        border-radius: 50%;        /* 圆角50% = 正圆形! */
        border: 3px solid transparent;  /* 默认边框透明(占位置但看不见) */
        margin: 5px;              /* 间距 */
        cursor: pointer;
        display: inline-block;    /* 行内块,可以设置宽高又能排在一行 */
    }

    /* 被选中的颜色按钮 */
    .color-btn.selected { 
        border-color: #333;       /* 边框变深灰色 */
        transform: scale(1.1);  /* 放大10%,突出显示 */
    }
</style>

教师讲解:

"border-radius: 50%是CSS画圆的秘密。只要宽高相等,圆角50%就是正圆。

border: 3px solid transparent先放一个透明的边框占位。当选中时,把颜色改成#333,圆就突然有了边框,而且因为本来就有占位,页面不会跳动。"

学生操作: 在HTML中添加颜色选择区域:

<div class="card">
    <div class="card-title">🎨 选择颜色</div>
    <div class="color-picker">
        <!-- 白色按钮,默认选中(有selected类) -->
        <div class="color-btn selected" style="background:#fff" onclick="setColor(255,255,255)"></div>
        <div class="color-btn" style="background:#f00" onclick="setColor(255,0,0)"></div>
        <div class="color-btn" style="background:#0f0" onclick="setColor(0,255,0)"></div>
        <div class="color-btn" style="background:#00f" onclick="setColor(0,0,255)"></div>
        <div class="color-btn" style="background:#ff0" onclick="setColor(255,255,0)"></div>
        <div class="color-btn" style="background:#f0f" onclick="setColor(255,0,255)"></div>
        <div class="color-btn" style="background:#0ff" onclick="setColor(0,255,255)"></div>
        <div class="color-btn" style="background:#ffa500" onclick="setColor(255,165,0)"></div>
    </div>
</div>

教师讲解颜色值:

"这些颜色代码是十六进制表示法:

  • #fff = 白色 = (255,255,255)
  • #f00 = 红色 = (255,0,0)  
  • #0f0 = 绿色 = (0,255,0)
  • #00f = 蓝色 = (0,0,255)
  • #ff0 = 黄色 = 红+绿
  • #f0f = 紫色 = 红+蓝
  • #0ff = 青色 = 绿+蓝
  • #ffa500 = 橙色 = 标准橙色

onclick里的setColor(255,0,0)是JavaScript函数调用,我们下一步写这个函数。"

测试验证: 手机刷新,看到一排彩色圆点。点击暂时没反应(因为JS函数还没写),但界面已经漂亮。


【第4.6块】亮度滑块

<style>
    /* ... 接上面的CSS ... */

    /* ========== 滑块样式 ========== */
    .slider {
        width: 100%;              /* 宽度填满父容器 */
        height: 8px;              /* 滑轨道高度 */
        border-radius: 4px;        /* 圆角 */
        background: #ddd;         /* 浅灰色轨道 */
        outline: none;            /* 去掉点击时的蓝色轮廓 */
        -webkit-appearance: none;  /* 去掉浏览器默认样式(关键!) */
    }

    /* Webkit浏览器(Chrome、Safari)的滑块 thumb */
    .slider::-webkit-slider-thumb {
        -webkit-appearance: none;   /* 去掉默认thumb样式 */
        width: 24px;               /* thumb宽度 */
        height: 24px;              /* thumb高度 */
        border-radius: 50%;         /* 圆形thumb */
        background: #667eea;      /* 蓝紫色,和背景呼应 */
        cursor: pointer;
        box-shadow: 0 2px 6px rgba(0,0,0,0.3);  /* thumb阴影 */
    }

    /* Firefox浏览器的滑块 thumb */
    .slider::-moz-range-thumb {
        width: 24px;
        height: 24px;
        border-radius: 50%;
        background: #667eea;
        cursor: pointer;
        border: none;
    }
</style>

教师讲解:

"input type="range"是HTML5的新控件,浏览器自动渲染成滑块。

但不同浏览器渲染的样子不一样!Chrome用-webkit-slider-thumb,Firefox用-moz-range-thumb。我们要分别写,才能在所有手机上好看。

-webkit-appearance: none是'大杀器'——去掉浏览器默认样式,让我们完全自定义。"

学生操作: 在HTML中添加亮度区域:

<div class="card">
    <div class="card-title">🔆 亮度调节</div>
    <input type="range" class="slider" min="0" max="255" value="128" 
           onchange="setBrightness(this.value)">
    <div class="status">亮度: <span id="bval">50%</span></div>
</div>

教师讲解属性:

  • min="0":滑到最左 = 0(最暗)
  • max="255":滑到最右 = 255(最亮)
  • value="128":初始位置在中间(128/255 ≈ 50%)
  • onchange:值改变时触发(松开滑块时)
  • this.value:当前滑块的值

测试验证: 手机刷新,看到滑块,拖动有视觉反馈。


【第4.7块】状态文字

<style>
    /* ... 接上面的CSS ... */

    .status { 
        text-align: center;       /* 居中 */
        color: #666;             /* 中灰色 */
        margin-top: 10px;         /* 上方间距 */
        font-size: 14px;          /* 小字 */
    }
</style>

学生操作: 在HTML底部添加IP显示:

<div class="status">IP: <span id="ip">--</span></div>

【第三阶段】JavaScript交互——让按钮动起来(20分钟)

步骤5:编写JavaScript函数

教师操作: 在</body>前添加<script>标签。

【第5.1块】获取IP地址

<script>
    // ========== 页面加载时自动获取IP ==========
    // fetch('/ip') 发送请求到ESP32的/ip路径
    // .then(r => r.text()) 把响应转成文本
    // .then(ip => { ... }) 拿到IP字符串,更新页面

    fetch('/ip')
        .then(r => r.text())
        .then(ip => {
            document.getElementById('ip').textContent = ip;
        })
        .catch(err => {
            console.log('获取IP失败:', err);
        });

    /* 逐行解释:
       fetch('/ip')         → 向服务器发送GET请求,路径是/ip
       .then(r => r.text()) → 服务器返回的是纯文本,转成字符串
       .then(ip => ...)     → 拿到IP字符串(如"192.168.1.100")
       document.getElementById('ip') → 找到id="ip"的span元素
       .textContent = ip    → 把元素里的文字改成IP地址
    */
</script>

教师讲解Promise:

"fetch返回一个Promise(承诺)。就像你点外卖,店家承诺'做好了给你送'。
.then()就是'做好了之后做什么'。第一个.then处理响应,第二个.then处理数据。

这种写法叫'链式调用',避免了嵌套回调的地狱。"

测试验证: 手机刷新,看到IP地址从"--"变成实际IP(如192.168.1.100)。


【第5.2块】颜色设置函数

<script>
    // ... 接上面的代码 ...

    // ========== 设置颜色函数 ==========
    function setColor(r, g, b) {
        // 第1步:发送颜色指令到ESP32
        // 使用模板字符串(反引号),${变量}自动插入值
        fetch(`/color?r=${r}&g=${g}&b=${b}`);
        /* 生成的URL示例:/color?r=255&g=0&b=0
           ? 后面是查询参数
           r=255 表示红色通道值
           g=0   表示绿色通道值  
           b=0   表示蓝色通道值
           合起来就是:给我纯红色!
        */

        // 第2步:更新按钮选中状态(视觉反馈)
        // document.querySelectorAll('.color-btn') 
        // → 选中所有class含color-btn的元素,返回数组

        // .forEach(b => b.classList.remove('selected'))
        // → 对每个元素,移除selected类(去掉边框)

        document.querySelectorAll('.color-btn')
                .forEach(b => b.classList.remove('selected'));

        // event.target 是触发点击事件的那个元素(被点的颜色圆点)
        // .classList.add('selected') 给它加上selected类(显示边框+放大)
        event.target.classList.add('selected');
    }
</script>

教师讲解事件对象:

"event是浏览器自动传入的参数,包含这次点击的所有信息。
event.target就是'被点的是谁'。点白色圆点,target就是白色圆点;点红色圆点,target就是红色圆点。

classList是元素的'类名管理器',比直接改className安全,不会误删其他类。"

测试验证:

  1. 手机刷新,点击红色圆点
  2. 观察:红色圆点边框变粗、微微放大(selected类生效)
  3. 观察:灯条应该变红(如果后端代码已写好)

如果灯条没变红: 说明后端handleColor还没写,进入下一步。


【第5.3块】亮度设置函数

<script>
    // ... 接上面的代码 ...

    // ========== 设置亮度函数 ==========
    function setBrightness(val) {
        // 第1步:发送亮度值到ESP32
        fetch('/brightness?b=' + val);
        /* URL示例:/brightness?b=200
           b=200 表示亮度设为200(接近最亮)
        */

        // 第2步:更新页面显示的百分比
        // Math.round(val/255*100) → 把0-255转成0-100%,四舍五入
        // + '%' → 加上百分号

        document.getElementById('bval').textContent = 
            Math.round(val/255*100) + '%';

        /* 计算示例:
           val=0   → 0/255*100 = 0%    → "0%"
           val=128 → 128/255*100 = 50% → "50%"
           val=255 → 255/255*100 = 100% → "100%"
        */
    }
</script>

教师讲解计算:

"滑块给的是0-255,但用户想看百分比。怎么转换?
百分比 = (当前值 / 最大值) × 100%
所以 
val/255*100,再用Math.round四舍五入成整数。"

测试验证: 拖动滑块,页面上的百分比数字实时变化。


【第四阶段】后端代码——ESP32处理请求(20分钟)

步骤6:编写后端处理函数

教师操作: 在Arduino代码的loop()之前,添加处理函数。

【第6.1块】设置所有灯珠的辅助函数

// ========== 辅助函数:设置所有灯珠为同一种颜色 ==========
void setAllLeds(CRGB color) {
  // for循环遍历所有灯珠
  // int i = 0 从第0颗开始
  // i < NUM_LEDS 到第9颗结束(共10颗,索引0-9)
  // i++ 每次加1
  for(int i = 0; i < NUM_LEDS; i++) {
    leds[i] = color;    // 把第i颗灯珠设为指定颜色
    // leds是FastLED管理的数组,每个元素是CRGB类型
  }

  FastLED.show();       // ★★★ 关键!把内存数据发送到硬件 ★★★
  // 在此之前,所有操作只是改内存
  // 只有调用show(),GPIO 2才会输出精确的时序信号,真正点亮灯条
}

教师强调:

"FastLED.show()唯一真正控制硬件的语句。很多同学改了颜色但灯没变,就是忘了这行!"


【第6.2块】处理根路径——返回网页

// ========== 处理函数:返回主页面 ==========
void handleRoot() {
  // 当浏览器访问 http://IP地址/ 时,执行这个函数
  // server.send(状态码, 内容类型, 内容)

  server.send(200, "text/html", htmlPage);
  /* 参数解释:
     200         → HTTP状态码:OK,请求成功
     "text/html" → 内容类型:这是HTML网页
     htmlPage    → 实际发送的内容(我们定义的大段HTML字符串)
  */
}

教师讲解HTTP状态码:

"200表示'一切正常'。常见的还有:

  • 404 = 找不到页面(路径写错了)
  • 500 = 服务器内部错误(代码有bug)
  • 403 = 禁止访问(权限问题)"

【第6.3块】开灯处理

// ========== 处理函数:开灯 ==========
void handleOn() {
  lightOn = true;                    // 记住状态:灯现在是开着的
  setAllLeds(currentColor);          // 把所有灯珠设为当前记忆的颜色

  server.send(200, "text/plain", "OK"); // 回复手机:成功
  // text/plain = 纯文本,不是网页
  // "OK" = 简单的成功确认

  Serial.println("开灯");               // 串口打印日志,调试用
  // Serial.println = 打印并换行
  // 在串口监视器里能看到这行输出,确认代码执行到了这里
}

教师讲解状态管理:

"为什么要lightOn = true?因为后面颜色控制和亮度控制都要判断:
'如果灯是关着的,只更新记忆,不点亮灯条'。
这样关灯状态下选颜色,下次开灯自动显示新颜色。"


【第6.4块】关灯处理

// ========== 处理函数:关灯 ==========
void handleOff() {
  lightOn = false;                   // 记住状态:灯现在是关着的
  setAllLeds(CRGB(0, 0, 0));         // 所有灯珠设为黑色(0,0,0) = 熄灭

  server.send(200, "text/plain", "OK");
  Serial.println("关灯");
}

教师提问: "为什么关灯是CRGB(0,0,0)而不是关闭电源?"
预期回答: "WS2812B需要持续供电维持状态,设为黑色就是不发光,但芯片还在工作。"


【第6.5块】颜色处理——重点!

// ========== 处理函数:设置颜色 ==========
void handleColor() {
  // 第1步:检查请求中是否包含r、g、b三个参数
  // server.hasArg("参数名") 检查URL中有没有这个参数
  // 例如:/color?r=255&g=0&b=0  → hasArg("r")返回true

  if(server.hasArg("r") && server.hasArg("g") && server.hasArg("b")) {

    // 第2步:取出参数值并转成整数
    // server.arg("r") 获取参数r的值(字符串"255")
    // .toInt() 把字符串转成整数 255
    int r = server.arg("r").toInt();
    int g = server.arg("g").toInt();
    int b = server.arg("b").toInt();

    // 第3步:保存到全局变量
    currentColor = CRGB(r, g, b);
    // CRGB是FastLED的颜色构造器,三个整数生成颜色对象

    // 第4步:如果灯是开着的,立即更新显示
    if(lightOn) {
      setAllLeds(currentColor);
      // 只有灯开着才点亮,关着状态只记忆颜色
    }

    // 第5步:串口打印调试信息
    // Serial.printf 是格式化打印,类似C语言的printf
    // %d 表示整数,会按顺序替换为r、g、b的值
    Serial.printf("颜色: R=%d G=%d B=%d\n", r, g, b);
    // 输出示例:颜色: R=255 G=0 B=0
  }

  // 无论参数是否有效,都回复OK(前端不需要知道具体错误)
  server.send(200, "text/plain", "OK");
}

教师重点讲解:

"这段代码有防御性编程思想:

  1. hasArg检查参数是否存在,防止程序崩溃
  2. if(lightOn)判断状态,避免关灯时意外点亮
  3. 最后一定send回复,否则前端会卡住等响应

Serial.printf是调试利器。 %d是占位符,后面的变量按顺序填入。\n是换行符。"

测试验证:

  1. 编译上传
  2. 手机点红色按钮
  3. 观察:灯条变红!串口监视器显示"颜色: R=255 G=0 B=0"
  4. 点绿色、蓝色,验证颜色切换正常

【第6.6块】亮度处理

// ========== 处理函数:设置亮度 ==========
void handleBrightness() {
  // 检查是否有b参数(brightness的缩写)
  if(server.hasArg("b")) {

    // 取出亮度值并转成整数
    brightness = server.arg("b").toInt();

    // 设置FastLED的全局亮度
    FastLED.setBrightness(brightness);
    /* 注意:setBrightness不是改变颜色值!
       它改变的是LED驱动芯片的PWM占空比。
       颜色还是(255,255,255),但LED实际亮度按比例降低。
       这是硬件级调光,比软件改颜色值更平滑。
    */

    // 如果灯开着,更新显示
    if(lightOn) {
      setAllLeds(currentColor);
    }

    Serial.printf("亮度: %d\n", brightness);
  }

  server.send(200, "text/plain", "OK");
}

教师讲解PWM:

"PWM = 脉冲宽度调制。LED不是真的变暗,而是快速开关(每秒几千次)。
占空比50% = 亮一半时间,人眼看起来就是一半亮度。
FastLED.setBrightness()就是调这个占空比,所以很平滑。"

测试验证: 拖动滑块,观察灯条亮度变化。串口显示亮度值。


【第6.7块】IP地址处理

// ========== 处理函数:返回IP地址 ==========
void handleIP() {
  // WiFi.localIP() 获取ESP32在当前WiFi中的IP地址
  // .toString() 把IP地址对象转成字符串(如"192.168.1.100")

  server.send(200, "text/plain", WiFi.localIP().toString());
  // 纯文本发送IP字符串,前端JS收到后显示在页面上
}

步骤7:注册路由——把路径和函数关联起来

教师操作: 在setup()函数中,添加路由注册。

void setup() {
  Serial.begin(115200);    // 串口通信,波特率115200

  // ========== 初始化LED ==========
  FastLED.addLeds<<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
  /* 参数解释:
     WS2812B    → LED芯片型号
     LED_PIN    → 数据引脚(GPIO 2)
     GRB        → 颜色顺序:绿-红-蓝(WS2812B的标准顺序)
     leds       → LED数组
     NUM_LEDS   → 灯珠数量(10)
  */

  FastLED.setBrightness(brightness);  // 设置初始亮度(128)
  setAllLeds(currentColor);           // 点亮所有灯(默认白色)
  FastLED.show();                     // 发送数据到硬件

  Serial.println("\n=== 第5次课:美化界面 ===");

  // ========== 连接WiFi ==========
  WiFi.begin(ssid, password);         // 开始连接WiFi

  while(WiFi.status() != WL_CONNECTED) {
    // WiFi.status() 返回连接状态
    // WL_CONNECTED = 已连接(WiFi库定义的常量)
    delay(500);                       // 等500毫秒
    Serial.print(".");                // 打印一个点,像进度条
  }
  // 循环直到连接成功,点会越来越多:..........

  Serial.println("\nWiFi已连接");
  Serial.print("IP: ");
  Serial.println(WiFi.localIP());      // 打印IP地址

  // ========== 【关键】注册HTTP路由 ==========
  // server.on("路径", 处理函数) 
  // 当收到对应路径的请求时,自动调用处理函数

  server.on("/", handleRoot);              // 根路径 → 返回网页
  server.on("/on", handleOn);              // /on → 开灯
  server.on("/off", handleOff);            // /off → 关灯
  server.on("/color", handleColor);        // /color → 设置颜色
  server.on("/brightness", handleBrightness); // /brightness → 设置亮度
  server.on("/ip", handleIP);              // /ip → 返回IP

  server.begin();                          // 启动服务器
  Serial.println("服务器启动");
}

教师强调路由匹配:

"这6行server.on就是'指令分发大厅'。
手机访问
/on,ESP32知道去执行handleOn
访问
/color?r=255,去执行handleColor

顺序不重要,但路径必须写对。少一个字母就404!"


步骤8:主循环

void loop() {
  server.handleClient();  // 检查是否有客户端请求,有就处理
  delay(1);               // 延时1毫秒,让系统喘口气
  /* 为什么加delay?
     ESP32是双核,但WiFi任务需要CPU时间。
     不加delay可能导致WiFi不稳定、响应变慢。
     1毫秒很短,人感知不到,但系统更稳定。
  */
}

【第五阶段】完整测试与排错(10分钟)

步骤9:完整功能测试流程

教师带领学生按顺序测试:

步骤

操作

预期结果

如果不成功

1

编译上传

无报错,串口显示连接信息

检查库是否安装、板子是否选对

2

手机访问IP

看到漂亮界面

检查同WiFi、IP是否正确

3

点击"开灯"

灯亮(白色)

检查GPIO接线、灯条方向

4

点击"关灯"

灯灭

检查handleOff代码

5

点击红色

灯变红,红按钮有边框

检查handleColor、串口输出

6

点击绿色

灯变绿,绿按钮有边框

检查RGB值是否正确

7

拖动滑块

亮度变化,百分比更新

检查handleBrightness

8

关灯→选蓝→开灯

直接显示蓝色

检查状态记忆逻辑


步骤10:常见错误与排错

教师提前准备,学生遇到问题时引导自查:

错误1:编译报错 R"rawliteral 相关

  • 原因:标记名在HTML内容中出现了,导致提前结束
  • 解决:换一个更独特的标记名,如 R"MYHTML(... )MYHTML"

错误2:网页显示乱码

  • 原因:缺少<meta charset="UTF-8">
  • 解决:在<head>第一行添加字符集声明

错误3:颜色按钮点击后灯不变色

  • 排查步骤:
    1. 看串口监视器:有没有"颜色: R=..."输出?
    2. 有输出 → 前端正常,检查灯条接线
    3. 无输出 → 前端可能没发请求,检查JS的fetch路径

错误4:亮度调节无效

  • 原因FastLED.setBrightness()必须在addLeds之后调用
  • 解决:检查setup中的调用顺序

错误5:GPIO 2导致ESP32无法启动

  • 原因:GPIO 2在启动时有特殊功能(Boot模式选择)
  • 解决:换用GPIO 4或GPIO 5,同时修改#define LED_PIN

🎓 四、课后作业与拓展

基础作业(必做)

  1. 把界面颜色改成自己喜欢的配色方案(改CSS中的颜色值)
  2. 增加3种新颜色按钮(如粉色、棕色、灰色)
  3. 给按钮添加emoji图标(如🔴🟢🔵

进阶挑战(选做)

  1. 呼吸灯效果:在loop()中用millis()实现亮度正弦变化
  2. 断电记忆:用Preferences库保存颜色和亮度,重启后恢复
  3. 多灯条控制:增加第二组灯条,独立控制
  4. 颜色渐变动画:点击颜色后,灯条从当前色平滑过渡到新颜色

📋 五、备课检查清单

课前检查:

  • 示例代码在教师设备上能正常运行
  • 准备了最终效果演示(视频或实物)
  • 检查教室WiFi是否2.4GHz,学生手机能否连接
  • 准备备用ESP32和灯条(防止学生设备故障)

课中注意:

  • 每写一段代码,留出3-5分钟让学生同步操作
  • 走动观察,及时发现学生卡住的地方
  • 鼓励学生先抄代码再理解,不要纠结于每个细节
  • 用串口输出作为调试抓手,教会学生"看串口找问题"

课后跟进:

  • 收集学生遇到的问题,下节课统一讲解
  • 把最终完整代码发到班级群,供学生对照
  • 布置进阶挑战,激发学习兴趣

🏷️ 六、板书设计建议

主板书(保留到下课):

第5课:美化界面 + 颜色 + 亮度

核心概念:
├─ R"rawliteral(...)rawliteral"  → 原样嵌入HTML
├─ CSS三大杀招:渐变背景 / 圆角卡片 / 阴影悬浮
├─ HTTP路由:server.on("路径", 函数)
├─ URL参数:?r=255&g=0&b=0
└─ FastLED.show() → 唯一真正控制硬件

状态管理:
lightOn(开关) → currentColor(颜色) → brightness(亮度)
     ↓                ↓                  ↓
  记忆状态         记忆颜色            记忆亮度

副板书(随写随擦):

  • 学生提出的错误及解决方法
  • RGB颜色速查表
  • 常见HTTP状态码

本文标签:#少儿编程 #科创 #电子爱好者 #物联网 #arduino  #ESP32

微信号
视频号
公众号

关注我们,方便学习和答疑

如果还需完整代码,请联系我

最新文章

随机文章

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