Web应用-Thinkphp框架-开发指南
Thinkphp框架
- 二级导航分类,模板继承,内置标签
- Public 修改
- MVC模块化 ——访问机制
- 传参
- 加载模版
- 模版引入 分离
- Runtime 缓存文件
- 管理员添加
- 数据验证及验证场景 控制器 validate
- 在sql执行(敏感操作)之前验证
- 数据模板 分页
- 数据表连接查询
- TP 关联查询
- -----------------
- 由于是3.2 版本的教程 后面会结合5.0版本进行改进 - 主要记录思路
- 无限分类模块实现
- 商品模块 设计
- Session
- 控制器初始化
- 模板布局
- 模板赋值
- 请求与响应
- 响应
- url及路由
- url和路由
二级导航分类,模板继承,内置标签
模板继承
{block name="title"}<title>网站标题</title>{/block}
{block name="title"}<title>{$web_title}</title>{/block}
{block name="include"}{include file="Public:header" /}{/block}
<html><head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>{block name="title"}标题{/block}</title> </head> <body> {block name="menu"}菜单{/block}{block name="left"}左边分栏{/block} {block name="main"}主内容{/block} {block name="right"}右边分栏{/block}{block name="footer"}底部{/block} </body>
</html>
{extend name="base" /} {block name="title"}{$title}{/block}
{block name="menu"}<a href="/" >首页</a><a href="/info/" >资讯</a> <a href="/bbs/" >论坛</a>
{/block}
{block name="left"}
{/block} {block name="main"}
{volist name="list" id="vo"}<a href="/new/{$vo.id}">{$vo.title}</a><br/> {$vo.content}{/volist} {/block} {block name="right"}最新资讯: {volist name="news" id="new"}<a href="/new/{$new.id}">{$new.title}</a><br/> {/volist}{/block} {block name="footer"} {__block__} @ThinkPHP 版权所有 {/block}
{block name="footer"} {__block__}@ThinkPHP 版权所有 {/block}
{extend name="Public:base" /}
{extend name="./Template/Public/base.html" /}
{block name="title"}<title>{$title}</title>{/block} <a href="/" >首页</a><a href="/info/" >资讯</a> <a href="/bbs/" >论坛</a>
内置标签
循环输出标签
$list = User::all(); $this->assign('list',$list);
{volist name="list" id="vo"}{$vo.id}:{$vo.name}<br/>{/volist}
{volist name="list" id="data"} {$data.id}:{$data.name}<br/> {/volist}
{volist name="list" id="vo" offset="5" length='10'} {$vo.name}{/volist}
{volist name="list" id="vo" mod="2" } {eq name="mod" value="1"}{$vo.name}{/eq} {/volist}
{volist name="list" id="vo" mod="5" }{$vo.name} {eq name="mod" value="4"}<br/>{/eq}{/volist}
{volist name="list" id="vo" empty="暂时没有数据" } {$vo.id}|{$vo.name} {/volist}
$this->assign('empty','<span class="empty">没有数据</span>'); $this->assign('list',$list);
{volist name="list" id="vo" empty="$empty" } {$vo.id}|{$vo.name} {/volist}
{volist name="list" id="vo" key="k" } {$k}.{$vo.name} {/volist}
{volist name="list" id="vo" } {$i}.{$vo.name} {/volist}
{volist name="list" id="vo" }{$key}.{$vo.name} {/volist}
{volist name=":fun('arg')" id="vo"}
{$vo.name}
{/volist}
FOREACH标签
{foreach $list as $vo} {$vo.id}:{$vo.name} {/foreach}
{foreach name="list" item="vo"}{$vo.id}:{$vo.name}{/foreach}
{foreach name="list" item="vo" } {$key}|{$vo} {/foreach}
{foreach name="list" item="vo" key="k" } {$k}|{$vo} {/foreach}
FOR标签
{for start="开始值" end="结束值" comparison="" step="步进值" name="循环变量名" } {/for}
{for start="1" end="100"} {$i} {/for}
for ($i=1;$i<100;$i+=1){echo $i; }
比较标签
{比较标签 name="变量" value="值"}内容{/比较标签}
{eq name="name" value="value"}value{/eq}
{equal name="name" value="value"}
value
{/equal}
{eq name="name" value="value"} 相等{else/}不相等{/eq}
{gt name="name" value="5"}value{/gt}
{egt name="name" value="5"}value{/egt}
{eq name="vo.name" value="5"}{$vo.name}{/eq}
{eq name="vo:name" value="5"} {$vo.name} {/eq}
{eq name="vo['name']" value="5"} {$vo.name}{/eq}
{eq name="vo:name|strlen" value="5"}{$vo.name}{/eq}
{eq name="Think.get.name" value="value"}相等{else/}不相等{/eq}
{eq name="vo:name" value="$a"}{$vo.name}{/eq}
{compare name="name" value="5" type="eq"}value{/compare}
{eq name="name" value="5" }value{/eq}
条件判断
SWITCH标签
{switch name="变量" }{case value="值1" break="0或1"}输出内容1{/case} {case value="值2"}输出内容2{/case} {default /}默认情况{/switch}
{switch name="User.level"} {case value="1"}value1{/case} {case value="2"}value2{/case} {default /}default {/switch}
{switch name="Think.get.userId|abs"} {case value="1"}admin{/case} {default /}default {/switch}
{switch name="Think.get.type"}{case value="gif|png|jpg"}图像格式{/case} {default /}其他格式 {/switch}
{switch name="Think.get.userId|abs"} {case value="1" break="0"}admin{/case}{case value="2"}admin{/case}{default /}default{/switch}
{switch name="User.userId"} {case value="$adminId"}admin{/case} {case value="$memberId"}member{/case}{default /}default {/switch}
{switch $User.userId}{case $adminId}admin{/case}{case $memberId}member{/case} {/switch}
IF标签
{if condition="($name == 1) OR ($name > 100) "} value1 {elseif condition="$name eq 2"/}value2 {else /} value3{/if}
{if condition="strtoupper($user['name']) neq 'THINKPHP'"}ThinkPHP {else /}other Framework {/if}
{if condition="$user.name neq 'ThinkPHP'"}ThinkPHP {else /} other Framework{/if}
{if condition="$user:name neq 'ThinkPHP'"}
ThinkPHP
{else /}
other Framework{/if}
{if condition="表达式"} {if (表达式)} {if 表达式}
IN和NOTIN
$id = 1; $this->assign('id',$id);
{in name="id" value="1,2,3"} id在范围内 {/in}
{notin name="id" value="1,2,3"}id不在范围内 {/notin}
{in name="id" value="1,2,3"} id在范围内 {else/} id不在范围内 {/in}
{in name="Think.get.id" value="1,2,3"} $_GET['id'] 在范围内{/in}
{in name="id" value="$range"}id在范围内 {/in}
{in name="id" value="$Think.post.ids"} id在范围内 {/in}
BETWEEN 和 NOTBETWEEN
{between name="id" value="1,10"} 输出内容1{/between}
{notbetween name="id" value="1,10"}输出内容2{/notbetween}
{between name="id" value="1,10"} 输出内容1 {else/} 输出内容2{/between}
{between name="id" value="1,3,10"} 输出内容1 {/between}
{between name="id" value="A,Z"} 输出内容1 {/between}
{between name="Think.post.id" value="1,5"} 输出内容1{/between}
{between name="id" value="$range"}输出内容1 {/between}
{between name="id" value="$Think.get.range"} 输出内容1{/between}
RANGE
{range name="id" value="1,2,3" type="in"} 输出内容1 {/range}
PRESENT NOTPRESENT标签
{present name="name"} name已经赋值 {/present}
{notpresent name="name"} name还没有赋值 {/notpresent}
{present name="name"}name已经赋值 {else /} name还没有赋值{/present}
{present name="Think.get.name"}$_GET['name']已经赋值 {/present}
EMPTY NOTEMPTY 标签
{empty name="name"} name为空值 {/empty}
{notempty name="name"} name不为空 {/notempty}
{empty name="name"} name为空{else /}name不为空 {/empty}
{empty name="Think.get.name"} $_GET['name']为空值 {/empty}
DEFINED 标签
{defined name="NAME"} NAME常量已经定义 {/defined}
{notdefined name="NAME"} NAME常量未定义 {/notdefined}
{defined name="NAME"} NAME常量已经定义 {else /} NAME常量未定义{/defined}
Public 修改
- 入口文件位置
- tp3---->tp5根路径
- tp5 —>public文件夹内
- 入口重定向
域名 重定向
更改网站目录到public—>访问index
hosts配置
MVC模块化 ——访问机制
application 应用模块 eg: index admin
模块里面 controller 控制器
- 访问非索引方法 ——自己写模块
传参
加载模版
- 没有 找到 方法fetch
- 引入空间/引入空间类元素
- 继承(类用类方法)用限定方法引入类也可以
- 使用引入空间 再继承相关类也可以
- 限定模版名称
模版引入 分离
-
复制模版进入
-
输出替换 --配置模版路径 tp3–>;
-
总config 和 分config之分
-
模版替换
-
拼装路径
- 静态文件 css images js
- 模版分离(公共文件)
Runtime 缓存文件
管理员添加
- 提交到 本文件下 即:list
- 打印测试 与tp3.2 不同
静态方法 —insert插入传出值
- 引入类
- 添加一条数据
- 批量添加 返回成功数据量
数据验证及验证场景 控制器 validate
-
后端验证 3.2字段验证 5.0以后变化很大
-
validate创建验证文件
-
控制器 validate
实例化 验证类
数组 验证字段/规则
传入验证字段
执行 验证策略
Dump 执行结果
在sql执行(敏感操作)之前验证
- 也可以引入 继承
- 打印调试验证规则
- 创建 拦截器文件
- 注意TP的namespace的根命名空间
- 一个元素就是一个验证场景
数据模板 分页
-
获取数据
-
创建model
-
分配到模板当中 名字/值
-
循环输出 分配过来的数组数据
-
空间类元素引入
-
完全限定名称
-
分页
-
排序 默认升序
- 查询数据 一维二维数组的区别
- 调试查询功能结果
-
修改数据 需要主键——判断哪一条数据
-
隐藏域 数据表主键
-
dump 一下 调试
-
数组传值
-
密码为空 不修改
-
验证 拦截器功能
- 数组传值
- 看一下传值
- 查看是否解析 (还是用数组写法)
- 初始化管理员 不可动摇
- 助手函数 (不用引用类了) 准备好那个id
- 写入组件/where
- 执行成功 跳回当前控制器
- 条件判断 来隐藏初始化管理员
- 模型—>引入类 使用静态方法
- 伪静态 .html可以不带
- id以隐藏于submit
- 控制器首字母要大写
- 唯一性验证
- 还是这样 重复造轮子 把上面的文档 复制 更改增加就行
- 根据策划 数据库 来写拼搭前端页面
- res 二维数组
- 前端 form 表单name 对应 数据库表单
- 调试 打印 上传图片信息
- 调试 上传结果
- 拼装路径
- 关联查询
数据表连接查询
- 生成sql查询 -->返回二维数组 ---->分配到模板
TP 关联查询
- 主 从表关系 相对关联关系
- 关联好了 取数据
-
文章修改
-
编辑
-
Ctrl + F5
-
隐藏域标记
-
这里调整 删除路径的
- 验证码类 管理登录逻辑
TP 拓展类 (下一个完整版)- composer/官网
- model 模型 处理数据
- 验证完 就执行
- 登陆跳转
- 写入session
- 清除 session
- 验证码配置放在公用 config内
- 样式对齐
- 字符提取 重置 点击刷新
- 验证验证码
- 复用功能代码 拆分 到public 控制器
- 代码继承
- base class 继承Controller 且 公用base 已经继承 think本身controller
- 科学权限认证 公用机制
- 前端页面调用
前端后台控制器 变量接收 获得数据库 二维数组数据 写入模板
并 排序
- 导航 链接 跳转 传参-当前栏目id
- 伪静态
- 加载模板
- header 加载导航变量 引导页面
也要 添加需要的数据 -助手函数很方便(不用引用类)
-
其他页面 的操作方法
分配页面数据
- 控制器复用 直接继承
构造初始化方法 调试
-
继承
-
前端 base 复用方法
- 根据id 查询并分页
- 数据 循环显示
- 更改分页 查询
- 调整样式
- 跳转到 文章页 分配
- 内容补全
- 时间戳变换
- 推荐 数据 查找 分配
- 首页 数据 分配
- 右侧栏 拆分
- 有一些图片 链接地址 更改
- 标签 关键字 字符替换
- 保证写进数据库 的是 英文“ ,” 分割方便
- 相关文章调用
- 数组合并
- 重复 匹配了 处理
- 去掉 数组里的 重复
- 打印调试
- 去重 数组变换
- 搜索功能 及分页
- input 数据 查询 分配到模板
- 载入模板
-
关键词 匹配逻辑 完整性
-
分页
-
model 处理分页查询问题
-
标签 也联系搜索
- 传参问题处理
-
关键词 加亮
-
后台 tag管理
数组拆分 数据调用
-
控制器
-
公用base 设定
类似于这种MVC架构的
可以写博客 CMS 或者公司宣传官网都可以
-----------------
由于是3.2 版本的教程 后面会结合5.0版本进行改进 - 主要记录思路
- 环境搭建
- SVN服务器 版本控制
- 服务器端VisualSVN 客户端 TortoiseSVN
- 导入账号
- 前后台分离 操作同一个数据库
- 创建一个WWW下的网站地址 存放源码
- 工作拷贝
- 复制 后台框架
- 配置前后台 apache虚拟命名
- 前后台模板搭建
- 单独后台
- 无限分类模块设计
- 测试数据库
- 遍历表中内容select
无限分类模块实现
- 字段排序
- sql连接函数 取别名
- 结果遍历
调试一下
-
取值 重新命名
再调试
-
添加 前台提交
-
添加方法
- 数据库操作
- 数据库操作
-
AJAX 无限分类
-
js写的
-
通过AJAX到数据库 取值
-
public 取数据 需要的字段 返回数组
变为json对象格式
-
传过去Id
-
信息传回 ajax
后台 删除方法
商品模块 设计
-
图片上传 异步处理
-
添加商品
-
测试数据
-
准备模板
Session
控制器初始化
模板布局
模板赋值
请求与响应
响应
url及路由
url和路由
-
参数调用
-
命名规范
-
定义路由
- 路由 + 传参
SEO不友好 搜索引擎收录不到 抓不到三层
比较友好 收录
- 路由 + 传参
-
定义路由
-
生成Url地址
相关文章:

Web应用-Thinkphp框架-开发指南
Thinkphp框架 二级导航分类,模板继承,内置标签Public 修改MVC模块化 ——访问机制传参加载模版模版引入 分离Runtime 缓存文件管理员添加数据验证及验证场景 控制器 validate 在sql执行(敏感操作)之前验证数据模板 分页数据表连接…...

LeetCode【300】最长递增子序列
题目: 思路: 通常来说,子序列不要求连续,而子数组或子字符串必须连续;对于子序列问题,第一种动态规划方法是,定义 dp 数组,其中 dp[i] 表示以 i 结尾的子序列的性质。在处理好每个…...

JRebel在IDEA中实现热部署 (JRebel实用版)
JRebel简介: JRebel是与应用程序服务器集成的JVM Java代理,可使用现有的类加载器重新加载类。只有更改的类会重新编译并立即重新加载到正在运行的应用程序中,JRebel特别不依赖任何IDE或开发工具(除编译器外)。但是&…...
uniapp微信小程序之分包异步化之组件分包
一、组件分包异步化解决的问题 日渐增加的通用组件造成的主包空间不足; 提升小程序访问速度,降低白屏率; 二、开启组件分包异步化过程中遇到的问题 如何进行占位组件配置; 如何解决通过$refs访问异步组件报错; 如何判断所有异步组件都已加载完毕; 多分包组件之间互相调用…...

Nacos(替代Eureka)注册中心
Nacos初步学习 Nacos 是一个开源的服务注册和配置中心,它允许您注册、注销和发现服务实例,并提供了配置管理的功能。下面是Nacos的最基础用法: 1. 服务注册和发现: 首先,您需要将您的应用程序或服务注册到Nacos中。…...

FHRP首跳冗余的解析
首跳冗余的解析 个人简介 HSRP hot standby router protocol 热备份路由协议 思科设备上 HSRP VRRP 华为设备上 VRRP HSRP v1 version 1 HSRP v2 version 2 虚拟一个HSRP虚拟IP地址 192.168.1.1 开启HSRP的抢占功能 通过其他参数 人为调整谁是主 谁是从 &a…...
垂直分表为什么能够加快查询效率?
前言 垂直分表是分库分表中分表操作上一个重要的实现方式,利用垂直分表可以提高数据的处理效率和查询速度,本节主要围绕 垂直分表为什么能够加快查询速度 展开说明,以mysql查询的底层流程为例。 垂直分表是将一张表按列分为多张表,…...
Linux网络基础知识全面总结
文章目录 linux网络基础知识1.1 IP地址和子网掩码1.2 网关和路由1.3 域名系统 (DNS)1.4 端口和协议 Linux网络配置2.1 ifconfig命令2.2 网络接口配置文件2.3 DHCP自动获取IP地址2.4 静态IP地址配置2.5 网络重启和应用配置3. 网络工具和命令3.1 ping命令3.2 traceroute和mtr命令…...

【arm实验2】按键中断事件控制实验
设置按键中断,按键1按下,LED亮,再次按下,灭 按键2按下,蜂鸣器叫,再次按下,停 按键3按下,风扇转,再次按下,停 主函数: linuxlinux:~/study/08-c$…...

【数据结构-栈 二】【单调栈】每日温度、接雨水
废话不多说,喊一句号子鼓励自己:程序员永不失业,程序员走向架构!本篇Blog的主题是【单调栈的应用】,使用【栈】这个基本的数据结构来实现,这个高频题的站点是:CodeTop,筛选条件为&am…...
基于Keil a51汇编 —— 控制语句
ALIGN ALIGN expression ALIGN 语句将位置计数器设置为下一个地址模 2^表达式。 这可用于确保下一条语句在 2^n 边界上对齐。例如,对齐缓存行中的代码或数据。如有必要,汇编程序会创建一个间隙。间隔字节的内容因各个部分而异: 在data中未定…...

单目标优化算法:火鹰优化算法(Fire Hawk Optimizer,FHO)求解23个函数--提供MATLAB代码
一、火鹰优化算法FHO 火鹰优化算法(Fire Hawk Optimizer,FHO)由Mahdi Azizi等人于2022年提出,该算法性能高效,思路新颖。 单目标优化:火鹰优化算法(Fire Hawk Optimizer,FHO&#…...

数据集笔记:分析OpenCellID 不同radio/ create_time update_time可视化
1 读取数据 (以新加坡的cellID为例) import geopandas as gpd import pandas as pdopencellidpd.read_csv(OpenCellID_SG.csv,headerNone,names[radio,mcc,net,area,cell,unit,lon,lat,range,samples,changeable1,created1,updated,AveSignal]) opence…...

【特纳斯电子】血氧饱和度监测仪设计-实物设计
视频及资料链接:血氧饱和度监测仪设计-实物设计 - 电子校园网 编号: T5662203M-SW 设计简介: 本设计是基于STM32的血氧饱和度监测仪系统,主要实现以下功能: 1. STM32单片机作为微处理器 2. MAX30102进行心率血氧检…...
雪花算法生成ID传到前端之后精度丢失问题
第一种:使用注解解决 使用方便简单,粒度高,适用于部分字段需要单独转换的场景,灵活度高 // 两种注解,选其一即可 // JsonFormat(shape JsonFormat.Shape.STRING) JsonSerialize(using ToStringSerializer.class) pri…...
Windows 10 - 适用于各种服务(Redis、MySQL)的文件迁移到其他目录后,导致的各种服务找不到的问题 - 注册服务 - 关闭服务 - 重启服务
目录 一、MySQL 服务找不到问题二、Redis 服务找不到问题Tips 三、PostgreSQL 服务找不到问题参考链接 必须要用管理员打开 doc 窗口,然后才进行以下操作。 通用命令 先关闭 xxx 服务 sc query xxx服务名,如 redis 服务 sc query redis sc query 删除…...
Java 串行接口调用优化
准备面试总结下 1.CompletableFuture static ThreadPoolExecutor poolExecutor new ThreadPoolExecutor(10, 20, 1000L, TimeUnit.MICROSECONDS, new ArrayBlockingQueue<>(100));public static void main(String[] args) throws ExecutionException, InterruptedExcep…...

【Java 进阶篇】JavaScript `typeof` 操作符详解
JavaScript是一种弱类型语言,这意味着变量的数据类型通常是灵活的。为了更好地理解和操作数据,JavaScript提供了typeof操作符,它可以用来确定一个值的数据类型。在本篇博客中,我们将详细讨论typeof操作符,包括它的用法…...

electron之进程间通信
Electron进程间通信 使用electron编写程序时经常遇到下面这种场景: 当用户点击一个按钮时,需要将页面输入的信息保存到本地电脑上; 或者是点击菜单时,需要页面窗口做出响应。 用户点击的按钮和窗口展示的内容是运行在渲染进程中&…...

Linux网络编程:UDP协议和TCP协议
目录 一. 对于端口号的理解 1.1 网络通信五元组 1.2 端口号的划分策略 二. 网络通信中常用的指令 2.1 netstat指令 2.2 pidof指令 三. udp协议 3.1 udp的概念及特点 3.2 udp协议端格式 3.3 对于面向数据报及应用层发送与读取数据的理解 四. tcp协议的概念及特点 五.…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...
JDK 17 新特性
#JDK 17 新特性 /**************** 文本块 *****************/ python/scala中早就支持,不稀奇 String json “”" { “name”: “Java”, “version”: 17 } “”"; /**************** Switch 语句 -> 表达式 *****************/ 挺好的ÿ…...
IP如何挑?2025年海外专线IP如何购买?
你花了时间和预算买了IP,结果IP质量不佳,项目效率低下不说,还可能带来莫名的网络问题,是不是太闹心了?尤其是在面对海外专线IP时,到底怎么才能买到适合自己的呢?所以,挑IP绝对是个技…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的
修改bug思路: 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑:async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

C/C++ 中附加包含目录、附加库目录与附加依赖项详解
在 C/C 编程的编译和链接过程中,附加包含目录、附加库目录和附加依赖项是三个至关重要的设置,它们相互配合,确保程序能够正确引用外部资源并顺利构建。虽然在学习过程中,这些概念容易让人混淆,但深入理解它们的作用和联…...

FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...
从面试角度回答Android中ContentProvider启动原理
Android中ContentProvider原理的面试角度解析,分为已启动和未启动两种场景: 一、ContentProvider已启动的情况 1. 核心流程 触发条件:当其他组件(如Activity、Service)通过ContentR…...

Ubuntu系统复制(U盘-电脑硬盘)
所需环境 电脑自带硬盘:1块 (1T) U盘1:Ubuntu系统引导盘(用于“U盘2”复制到“电脑自带硬盘”) U盘2:Ubuntu系统盘(1T,用于被复制) !!!建议“电脑…...
Python网页自动化Selenium中文文档
1. 安装 1.1. 安装 Selenium Python bindings 提供了一个简单的API,让你使用Selenium WebDriver来编写功能/校验测试。 通过Selenium Python的API,你可以非常直观的使用Selenium WebDriver的所有功能。 Selenium Python bindings 使用非常简洁方便的A…...

Sklearn 机器学习 缺失值处理 获取填充失值的统计值
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 使用 Scikit-learn 处理缺失值并提取填充统计信息的完整指南 在机器学习项目中,数据清…...