php框架 3个目录 data protected public,ThinkPhp 笔记

本文详细介绍了ThinkPhp框架中的控制器定义与命名规范,包括视图加载方法、初始化方法、前置操作以及路由配置。同时,深入探讨了模型的创建、数据查询、增加、删除和更新操作,以及时间戳处理和软删除功能。此外,还涵盖了配置文件的管理和动态配置,以及数据库的连接和操作,包括查询、事务处理、数据过滤与验证等方面。
摘要由CSDN通过智能技术生成

控制器

新建控制器的定义

1/声明命名空间 app\模块\controller

2/控制器文件名首字母大写,采用驼峰命名

3/控制器名和文件名对应

控制器名字采用驼峰命名  那么访问时系统会自动转为全小写 ThinkPhp  用方法

加载页面

1/用系统函数view()

2/用系统类 view中的fecth方法

3/继承系统控制器Controller 用父级方法 fecth

数据的输出

1/字符串可以用return

2/'default_return_type'  可以设置一个数据返回格式 默认是Html

3/'default_ajax_return' ajax返回的类型

初始化

继承系统控制器后就可以用_initialize初始化方法

只要调用当前控制器下的任意方法 都会先调用初始化方法

作用:可以提取控制器下公共的代码,后台权限把控

前置操作

继承系统控制器用protected $beforeActionList数组:装前置方法顺序

这些方法会在调用任意的方法前执行  有except 和only的用法

路由

路由的作用

1/简化url地址,方便大家记忆

2/有利于搜索引擎的优化

入口文件

1/前后台分离  在Public目录下新建一个admin.php

2/绑定模块 实现功能:Index只能前台模块 admin只能去后台模块

具体操作:

define("BIND_MODULE","模块名")

// 开启入口文件自动绑定模块

auto_bind_module  =>  true  如果文件名和模块名都是一致的那么久不需要再绑定

3/url地址改变

可以省略模块

www.tp.com/admin.php/控制器/方法

隐藏入口文件

1/开启apache重写  conf/httpd.conf

注意

1/关闭路由  写在加载引导框架之后

2/支持三种方式的URL解析规则

3/路由只针对应用,不针对模块,因此路由的设置也是针对应用下面的模块

设置路由在app/route中

1/静态地址路由

Route::rule("1","2")用1代替2

2/动态路由

http://www.tp.com/coure/1

Route::rule("time/:year/:mouth","2")year 和mouth是动态参数随当前时间变化 time是静态

全动态路由ROute::rule(":a/:b","2")

可选参数路由Route::rule(":year/[:mouth]","2")mouth参数选填

3/完全匹配路由

http://www.tp.com/year

http://www.tp.com/year/1

Route::rule("year$","2")

year后不能带其他 要完全的匹配

路由请求类型

默认支持所有请求类型 *

支持Post请求

Route::post()

Route::rule()第三参数是post

支持所有

Route::any

Route::rule第三参数*

模拟put个delete  :请求必须是post  隐藏域 hidden

路由参数主要设置的是路由的后缀

indexGETblog        index  后台展示

createGETblog/createcreate 添加页面

savePOSTblog        save  增加操作

readGETblog/:idread

editGETblog/:id/editedit  修改页面

updatePUTblog/:idupdate

deleteDELETEblog/:iddelete

快捷路由 路由里的方法是a

那么在php中的方法应该是geta

模型

1/新建模型

手动创立

命令创建

*注意

数据库库建议和model名一致

如果不一致,可以设置表名    protected $table=""

如果表明有下划线yhw_user,模型名应该写成yhwUser

2/用模型

实例化数据模型

使用Loader::model()

使用助手函数model

-------------------------------------------------------------------------

查找

查询单条数据

get方法 get(条数)或者get([名=>值])

get(function($query){sql语句})

查找多条数据

User::all()

User::select

查找某个值

User::where()->value()

查找某列值

User::colum()

动态查询 只能获取查询到的第一条数据

getBy+字段名

User::getByAge()

-----------------------------------------------------------------

新增

增加单条数据 $user->save()

设置属性

通过data方法

实例化

如果有数据库不存在字段可以用用allowField(ture)来屏蔽

也可以指定哪些字段的写入 allowField(["name","age"])只有name age可以添加

增加多条数据

$array二维数组放入数据  $user->saveAll($array)

--------------------------------------------------------------------

删除

删除一条数据

$user=User::get(1)

$user=delete()

destory(1)

删除多条数据

destory(1,23,4)

destory([1,2,3,4])

条件删除

destory(["name"=>"dad"])

destory(function($query){$query->where("id",">",2)})

$user=User::where("id",">",2)->delete()

-----------------------------------------------------------------

更新

直接一条

$user=User::get(1)

$user->age=19;

$user->name=23;

$user->save()

数组修改

$user=new User;

$user->save(["name"=>dsad,"age"=>13],["id"=>1])

$data=[...]    $user->saveAll($data)

post修改

$user->allowField(限制)->save($_POST,["id"=>11])

条件修改

User::where()->updata

--------------------------------------------------------

增加

$user=new User;

$user->save();

查找

$user=new User

$user->get()

修改

$user=new User

$user->save([],[哪一条])

删除

User::destory()

post

增加

$user = new User($_POST);

$user->allField()->save()

$user=new User()

$user->allowField(true)->save($_POST,['id' => 1]);

-----------------------------------------------------------

聚合

统计

User::count()

User::where()->count()

最大最小值

User::max

User::min

平均值

User::avg()

User::sum()

--------------------------------------------------------------

获取器

用方法$user->toArray()

$user->sex

要经过获取器处理

但是用$user->getData

就不经过获取器处理

获取器名 get字段名Attr()

可用数组或者swich 来书写原则

-------------------------------------------------------------

修改器

在数据赋值时自动经行转化处理

set字段名Attr()

自动完成

没有手动赋值的情况下经行手动处理

protected $auto = []; 修改增加都执行

protected $insert = ['ip','status' => 1]; 增加的时候执行

protected $update = ['login_ip'];  修改数据执行

--------------------------------------------------------------

时间戳在配置文件中或者在模型中设置

可以自动写入时间戳

protected $createTime = 'create_at';

protected $updateTime = 'update_at';

可以写入时间更新时间的字段名

protected $updateTime = false;取消更新时间

protected $autoWriteTimestamp = false;// 关闭自动写入时间戳

--------------------------------------------------------------

软删除 数据库中数据存在但get方式获取不到

软删除只能用User::destroy

获取软删除数据

User::withTrashed()->find();

User::withTrashed()->select();

仅仅想查看软删除数据

User::onlyTrashed()->find();

User::onlyTrashed()->select();

配置

配置文件格式

1/以数组为主

配置的形式

1/惯例配置 think/convention.php

2/应用配置 app/config.php

3/扩展配置(属于上一配置的分类) app/database app/extra

4/环境配置(不同工作环境中的应用配置)  修改app_status=>home 并在app中新建home.php 书写相关配置即可

5/模块配置  每个模块不同配置 所以在index中新建config.php经行配置

6/动态配置  临时型配置  就是改写配置

读取配置

系统类:config("")

使用use:\think\Config::get()

也可以先use引入config 就用Config::get()调用

//获取数组时应该注意  获取数组中的某一元素用.代替[]

读取扩展配置

config("扩展名.扩展项")

改写配置

config("参数1","参数2")

给参数1配置参数2

\think\Config::set(参数1,参数2)

优先级

动态配置-模块配置-扩展配置-场景配置--应用配置-惯例配置

实现原理  后面加载的数据把前面加载的数据经行同名覆盖

环境变量配置

在www/tp5中新建.evn(不能出现中文)

获取坏境变量

通过系统类

\think\Env::get(参数)

不能读取整个数组

使用

1/打开配置文件  引入use \think\Evn

在需要修改的变量后 如  app_debug=>Evn::get("app_debug",false)

这样只用在.evn中改变就可以

www.top.com 域名

index.php入口文件

Index前台

uer控制器名

index类名

test方法

命名空间与目录有关

www/tp5/application/index/controller

namesapce app/index/controller

同名的时候取别名 as name

创建一个控制器或者模块 :

在app/index/controller中创建

1/控制器的文件名首字母大写

2/控制器必须声明命名空间

3/控制器中类名必须和文件名一致

调用当前模块的控制器

1/使用命名空间调用(面向对象)

3/使用use url    $model=new User

2/系统方法controller('模块/控制器')

调用当前控制器的方法

1/面向对象  self::  this->

2/系统方法  action()

调用其它控制器方法

1/面向对象 先加载其他页面实例对象再调用

2/action(该文件方法)

调用后台模块方法

1/面向对象

2/action(url)

TP的流程:

入口文件index.php

1/定义目录常量

2/加载框架的引导目录

加载框架引导目录thinkphp\start.php

1/引导基础文件

加载框架的基础引导文件 ThinkPhp/base

1/加载了系统常量

2/引入了一个loder类 是一个自动加载类

3/引入环境变量

4/注册自动加载和异常处理机制

5/加载惯例配置

运行应用 think/app.php下的run方法

1/加载了当前控制器中的initCommon方法

2/加载当前控制器中的 init方法(加载各种配置文件,公共文件)

3/设置时区

4/加载当前控制器中的routeCheck 路由检测

5/调用控制器中的exec方法(根据用户的请求进行分发处理)

6/根据不同的请求类型加载对应的文件

响应输出 :用户界面

请求和相应

如何获取请求类1/系统函数$request=request() 2/Request类是一个单列类 所以要用$request=Request::instance 不能直接new3/系统类引入Controller 和 Request 方法name(Rquest $request)实例化请求类可用$request->来获取各种信息$request->param 获得地址栏的参数有Only 和 expect 两种可用方法判断变量是否存在input('?post.name'); 或者$request->has('name')读取参数input('get.id') 或者 $request->get(id)---------------------------变量的过滤$request->filter('htmlspecialchars');" (大于)转换为 HTML 实体:防止恶意数据对数据库的影响$request->filter('strip_tags'),函数剥去字符串中的 HTML、XML 以及 PHP 的标签。strtolower把所有字符转换为小写FILTER_VALIDATE_EMAIL 过滤器把值作为电子邮件地址来验证。注意:filter是全局过滤get('name','','htmlspecialchars'); get局部过滤,针对变量进行过滤如想进行md5加密get('name','','htmlspecialchars,md5'); ----------------------------------------------获取部分变量或者排除部分变量用only expect 第二个参数是请求类型$request->only('name',post)-------------------------------------变量的修饰符->get('id/d'); 强制转化为整形修饰符作用s强制转换为字符串类型d强制转换为整型类型b强制转换为布尔类型a强制转换为数组类型f强制转换为浮点类型变量的更改$request->get(['id'=>10])请求类型$request->isGet 系统类request()->inGet 系统函数---------------------------------------模拟PUT请求1/表单类型是POST请求2/需要设置隐藏域,传递模拟的请求类型模拟ajax和Pjax请求http://localhost/index?_ajax=1 http://localhost/index?_pjax=1 ------------------------------------------伪静态在配置文件config中可以设置 后缀伪静态可以用$request->ext()访问后缀伪静态-----------------------------------------参数绑定1/参数的绑定的个数,少于地址栏参数的个数2/参数绑定的名字,必须和地址栏参数名字一一对应3/参数绑定可以设置默认值

视图

加载试图

1/继承控制器 $this->fetch

2/助手函数 view()

模板赋值

assign("使用名","变量名")

assign(["使用名"=>内容])

在页面中用{$使用名}

模板替换

全局替换可以在配置文件中修改view_replace_str

部分替换fetch和view的第三个参数["新路径"=>"要代替的路径"]

指定加载页面

$this->fetch("页面名")

fetch 和 view

参数1,参数2,参数3,参数4

字符串,数组,数组,数组

模板渲染,模板赋值,模板替换,

------------------------------------------------------------

{}是模板标签

使用函数

1/

{$pass|md5}使用md5加密

{$date|data="y-m-d h:i:s,###"}

{$pass|strtosupper|substr=0,10}

2/

{:md5($pass)}

:代表要使用函数

三元用算符

{$status?0,1}

运算

{$a/$b}  {$a*$b}

防止解析

{literal}{/literal}

系统变量输出

支持输出 $_SERVER、$_ENV、 $_POST、 $_GET、 $_REQUEST、$_SESSION和 $_COOKIE变量

1/

$_SERVER[""]

2/

$Think.get.id

------------------------------------------------------------

常量输出

配置输出  详见文件

---------------------------------------------------------------

包含文件

{include file=""}

----------------------------------------------------------------

模板布局  提取公共部分

1/新建一个文件在view下

2/在非公共页面部分用{__CONTENT__}只能存在一个

3/在非公共页面中 引入公共页面{layout name="" /}

模板继承  如果想替换多个区域

1/新建一个文件base在view下

2/在base中将其用{block name}{/block}分割

3/使用继承  在使用页面{extend name="base"}

在{block name""}中写相关内容 内容可以是引入的

{/block}

---------------------------------------------------------------

内置标签

循环

1/volist循环

{volist name="需要遍历的数据名" id="val" offset="起始位置" length="截取数据长度"}{val.id}{/volist}

mod 与当前循环次数取余数  value 余数的值  用于对不同行的操作

empty 数据为空时

key 循环的次数

2/foreach循环

{foreach name="遍历的数据名" item="val"  key="遍历的次数"}{/foreach}

3/for循环

{for start="开始值" end="结束值" comparison="条件" step="步数" name="循环的变量名"}

{for start=1 end=10 comparion="elt" step=1 name=abc}

相当于 for($i=1,i<10,i++)

4/比较标签

eq或者 equal等于

neq 或者notequal不等于

gt大于

egt大于等于

lt小于

elt小于等于

heq恒等于

nheq不恒等于

都是双标签

5/if

{if contdition="a=b"}

a等于b

{else/}a不等于b

{/if}

6/switch

{switch name=""}

{case value=""}1{/case}

{default/}2

{/switch}

7/in

{in name="a" value=1,23,4}

a在1,23,4范围内

{/in}

8/between

{between name="a" value=0,9}

a是否在0到9内

{/between}

{notbetween name=a value=0,3}

a不在0到3内

{/notbetween}

数据库的配置文件

1/配置链接数据库

设置数据库名 账号 密码 端口等 datebase.php中

使用系统类

导入Db类

$DB= new DB;

$date=$DB::table("admin")->select();

dump($date);

使用sql语句

$date=$Db::query("sql语句")

2/使用方法进行链接

Db::connect(数据库类型://用户名:密码@数据库地址:数据库端口/数据库名#字符集)

3/模型链接

用命令行 创建一个model模型php

在该文件中使用数组配置连接数据库  Model名要是表名

protected $connection = [

// 数据库类型

'type'        => 'mysql',

// 数据库连接DSN配置

'dsn'        => '',

// 服务器地址

'hostname'    => '127.0.0.1',

// 数据库名

'database'    => 'thinkphp',

// 数据库用户名

'username'    => 'root',

// 数据库密码

'password'    => '',

// 数据库连接端口

'hostport'    => '',

// 数据库连接参数

'params'      => [],

// 数据库编码默认采用utf8

'charset'    => 'utf8',

// 数据库表前缀

'prefix'      => 'think_',

];

在控制器中实例该model对象

并dump(对象) 查询所有的内容

基本使用

$db::query()或者$db::execute()

update 表名 set 数据更改=“”

Db::execute('insert into think_user (id,name,values(?, ?)',[8,'thinkphp']);

Db::execute('insert into think_user (id, name) values (:id, :name)',['id'=>8,'name'=>'thinkphp']);

Db::connect($config)->query('select * from think_user where id=:id',['id'=>8]);

------------------------------------------------

TP数据库处理

查询操作

1/用table方法查询

Db::table(表名)->select()查找全部

Db::table(表明)->find()查询第一条

注意table不会添加表前辍

2/name方法查询

把table换成name即可

注意name会自动添加配置文件的表前缀

3/助手函数查询

db()函数

db(表明)->select()

进行条件匹配

Db::table()->where(id,>,25)->where(id,select()

Db::table()->where("id>25 and id<28")->select()

Db::table()->where(['id'=>[">",25])->where(["id"=>["select()

查询id大于25小于28的所有数据

模糊查询

Db::table()->where(name,like,%qwe%)->select()

查询name类似qwe的数据

或者匹配

Db::table()->where(id,>=,9)->whereOr(id,select()

查询id小于0或者id大于等于9的数据

截取数据

Limit(2) 截取2个数据

limit(2,2)从2开始截取 截取2个数据

排序order

默认正序  desc倒序

order(id,desc)

*查询字段

field('name,pass')->select()  field(['name','pass'])->select()

查询所有数据中的name和pass字段

field('name uname,pass')->select 给name取别名为uname

field("count(*) as tot")->select

field(["count(*)" => "tot"])->select

得到结果是tot=>该数据的总和

field('name,pass',true)->select()  field(['name','pass',true])->select()

不查询name,pass

分页截取

page(1,5) 第一页从第一条展示到第五条

page(4,5) 第4页  从第15展示(5条)到20条

分组聚合

Db::table()->field("pass,count(*) tot")->group(pass)->select

查询各个密码的人数 比如设置123的有几个

对分组聚合的结果过滤

Db::table()->field("pass,count(*) tot")->having("tot >=2")->group(pass)->select  查询各个密码的人数 人数大于2的才被查询

别名

alias

Db::table(123)->alias(1)

关联join

Db::table(表1)->filed(表1*,表2.type)->join(表2,"表一和表二关系")->select()

查找出满足该关系式的所有数据  且显示出表1的所有数据和表2的type数据

还有左联和右联 就是以谁为主

合并集合union

Db::table(1)->union(select语句)->select()

合并1和select的所有结果

绑定bind

防止sql注入

一般不要使用原生的sql语句

tp语句一般都是防止注入的

--------------------------------------------

$data=[

.......

书写数据 一条就一维数据 多条就2维数据

]

Db::table()->where()->insert() 增加一条数据

Db::table()->where()->insertAll() 增加多条数据

Db::table()->where()->inserGetId() 增加数据并且取得id

db()->insert()  db()->insertAll  db()->inserGetId()

更新

更新一条数据

Db::table()->where("id",10)->update(["age"=>10])

Db::table()->update(["age"=>10,"id"=>10])

Db::table()->where("id",10)->setField("age",10)

更新多条数据

Db::table()->where("id",10)->update(["age"=>10,"name"=>"oo"])

自增自减

Db::table()->where("id",10)->setInc("age")  自增 每次执行age++

Db::table->where("id",10)->setDec("age") 自减 每次执行age--

可以设置增减幅度  setInc("age",3)  每次增加3

删除

删除一条数据

Db::table()->where("id",10)->delete();

Db::table()->delete(10)

删除多条数据

Db::table()->where("id in(1,2,3)")->delete()

Db::table()->where("id>=1 and id<=3")->delete()

---------------------------------------------------

事务机制

自动事务机制

Db::transaction(function(){

});

如果里面有错误没有执行 那么会停止执行

*自动事务机制

Db::startTrans(); 开启事务机制

try{

$a=Db::table('think_user')->find(1);

if($a){

throw new \Exception("异常信息");

}判断是否成功 错误就抛出异常

$b=Db::table('think_user')->delete(1);

if($a){

throw new \Exception("异常信息");

}

// 提交事务

Db::commit();

} catch (\Exception $e) {    捕捉异常

// 回滚事务

Db::rollback();

dump($e->getMessege) 可以获取异常信息

}

Db::startTrans();  开启事务

$a=Db::table(a)->delete();

$b=Db::table(b)->delete();

if($a && $b){

Db::commit();

}else{

Db::rollback();

}

系统类

config  修改和读取配置

Env 环境变量获取修改

controller  系统控制器

view  展示

route  路由

Url 生成地址

系统方法

controller 实例化控制器

action 调用模块的操作方法

config 设置和获取配置

dump 浏览器友好的变量输出

view 展现html画面

url 生成url地址

跳转

分为两种

成功跳转  失败调整

success(提示信息,跳转页面,用户自定义数据,跳转时间,header信息)

error参数一样

修改跳转页面(模板页面)

1/

tp5/thinkphp/tp1/dispatch_jump.tpl

模板页面数据

$data要返回的数据  用户自定义的数据

$msg页面提示信息

$code返回的code  成功1 失败0

$wait跳转等待时间 单位为秒

$url跳转页面地址

2/用户自定义模板页面

修改配置文件config中的跳转

在tp5/thinkphp/tp1中创建success.tp1 error.tp1

重定向

系统方法  redirect(跳转地址,其他参数,code编码,隐式参数)

空操作

_empty 在地址栏后随意添加

空方法

方法可以不存在

空控制器

Error控制器  控制器可不存在

使用命令行

1/命令行cmd

2/切换到tp5

3/输入php think

可以生成控制器或者清除临时文件等等

生成的资源控制器

和资源路由一一对应  配合资源路由一起使用

GETblogindex

GETblog/createcreate

POSTblogsave

GETblog/:idread

GETblog/:id/editedit

PUTblog/:idupdate

DELETEblog/:iddelete

杂项

1/缓存减少数据库压力设置缓存继承Cache 并用Cache::set(名,值,时间)助手函数 cache(名字,值,时间)读取缓存Cache::get(名) 或者 cache(名)清空缓存Cache::clear()2/Session设置Session继承Session Session::set(名,值)助手函数session(名,值)获取session继承后 Session::get(名,值)助手函数session(名)判断是否设置Session::has(名) 或者 session(?名)删除sessionSession::delete(名) 或者 session(名,null)清空sessionSession::clear(名) 或者 session(null)3/cookie设置cookie继承Cookie类 Cookie::set(名,值,时间)助手函数 cookie(名,值,时间)获取cookie继承后 Cookie::get(名) 或者cookie(名)判断cookieCookie::has(名) 或者 cookie(?名)删除cookieCookie::delete(名) 或者 cookie(名,null)清空cookieCookie::clear() 或者 cookie(null)4/分页在数据库读取数据时使用Db::table->paginate(数据条数)在Html页面中{$list->render()} 就可以得到导航栏页数5/文件上传获取数据$file=$request->file(名)移动文件$file->move(url)6/验证验证码的获取 {:captcha_img()} 或者

手动验证 if(!captcha_check($captcha)){ //验证失败};应用配置在config中 添加一个captcha进行配置7/图片处理获取图片  继承Image$img=Image::open(ur;)获取图片信息$image->width.....图片的裁剪$image->crop(裁剪的大小,裁剪的位置【默认是从顶点裁剪】)->save(裁剪后保存)crop(100,100,200,200) 裁剪一个100*100的图片 从x200-y200的位置开始裁剪图片缩放$image->thumb(缩放大小)->save(保存地址)  默认等比例变化thumb第三个参数是缩放类型图片的翻转$image->flip()->save()图片旋转$image->rotate(旋转的角度)->save()图片的水印图片水印$image->water("图片地址",水印位置类型,透明度)->save()$image->water("文字",字体文件,像素大小,颜色,透明度)->save()

专有名词和方法

www.top.com 域名

index.php入口文件

Index前台

uer控制器名

index类名

test方法

命名空间与目录有关

www/tp5/application/index/controller

namesapce app/index/controller

同名的时候取别名 as name

use引用命名空间

---------------------------------

创建一个控制器或者模块 :

在app/index/controller中创建

1/控制器的文件名首字母大写

2/控制器必须声明命名空间

3/控制器中类名必须和文件名一致

调用当前模块的控制器(跨控制器调用)

1/使用命名空间调用(面向对象)

3/使用use url    $model=new User

2/系统方法controller('模块/控制器')

调用当前控制器的方法(跨方法调用)

1/面向对象  self::  this->

2/系统方法  action()

调用其它控制器方法

1/面向对象 先加载其他页面实例对象再调用

2/action(该文件方法)

调用后台模块方法

1/面向对象

2/action(url)

-----------------------

TP的流程:

入口文件index.php

1/定义目录常量

2/加载框架的引导目录

加载框架引导目录thinkphp\start.php

1/引导基础文件

加载框架的基础引导文件 ThinkPhp/base

1/加载了系统常量

2/引入了一个loder类 是一个自动加载类

3/引入环境变量

4/注册自动加载和异常处理机制

5/加载惯例配置

运行应用 think/app.php下的run方法

1/加载了当前控制器中的initCommon方法

2/加载当前控制器中的 init方法(加载各种配置文件,公共文件)

3/设置时区

4/加载当前控制器中的routeCheck 路由检测

5/调用控制器中的exec方法(根据用户的请求进行分发处理)

6/根据不同的请求类型加载对应的文件

响应输出 :用户界面

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值