IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> PHP知识库 -> 小程序token -> 正文阅读

[PHP知识库]小程序token

后台,安装laravel7配置passport

用passport实现接口的登录和jwt生成(生成token)

安装passport插件

composer require laravel/passport
或
composer require laravel/passport "^9.0"

在这里插入图片描述
执迁迁移文件,生成数据表,保存token数据

php artisan migrate

在这里插入图片描述

生成客户端授权码

php artisan passport:install
Encryption keys generated successfully.
Personal access client created successfully.
Client ID: 1
Client secret: 6AS6JW79GMdhTUAJhjMN6nVFy8HMvtIGXFNqJiGX
Password grant client created successfully.
Client ID: 2
Client secret: KpZOwXE321ytcNuIYuWoJoVeEOhvcL3odLLIVbFJ

在这里插入图片描述

修改接口账号模型

use Laravel\Passport\HasApiTokens;

在这里插入图片描述

修改config/auth.php文件中的api配置
在这里插入图片描述

令牌的有效期

在app/Proivders/AuthServiceProvide.php文件中的boot方法添加有效期

use Laravel\Passport\Passport;

// token认证有效期2小时
Passport::tokensExpireIn(now()->addHour(2));

// 刷新token认证有效期30天
Passport::refreshTokensExpireIn(now()->addDays(30));

在这里插入图片描述

实现登录,并且注意,如果登录不成功,数据返回符合restful规范
** return response()->json([‘errorCode’ => 0, ‘data’ => [‘token’ => $token, ‘expire’ => 7200,‘time’=>time()], ‘msg’ => ‘登录成功’],200);**

路由

<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::middleware('auth:api')->get('/user', function (Request $request) {
    return $request->user();
});

//不需要校验的登录, 获取openid,
Route::group(['prefix'=>'v1','namespace'=>'Api'],function (){
    //微信登录路由
    Route::post('wx_login','LoginController@wxLogin');
});

//分组路由  middleware 中间件  prefix 版本号 namespace:命名空间前缀 'throttle:3,1' 一秒钟请求次数,接口访问频次限制
//Route::group(['middleware'=>['auth:api','throttle:3,1'],'prefix'=>'v1','namespace'=>'Api'],function (){
Route::group(['middleware'=>'auth:api','prefix'=>'v1','namespace'=>'Api'],function (){
//    //更新用户信息
    Route::put('users','LoginController@saveUsers');
    //秒杀商品列表
    Route::get('activity_list','GoodsController@activityList');
    //商品详情
    Route::get('goods_detail','GoodsController@goodsDetail');
    //抢购接口
    Route::post('snap_up','GoodsController@checkStock');

    //创建订单
    Route::post('goods_order','GoodsController@createOrder');

});

//更新用户信息
Route::get('stock','Api\GoodsController@syncStock');


微信登录获取openid

配置文件

在这里插入图片描述

<?php
return [
    'AppID' => 'wxf9c53e0a497cc457',
    'AppSecret' => '47646ed2a1f74e056ab42cd6777cd500',
    'wxLoginUrl'=>'https://api.weixin.qq.com/sns/jscode2session?appid=%s&secret=%s&js_code=%s&grant_type=authorization_code'
];

login控制器

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use Illuminate\Http\Request;

//文件存储
use GuzzleHttp\Client;
//调用模型层
use App\Models\Renting;
//缓存系统
use Illuminate\Support\Facades\Cache;

class LoginController extends Controller
{


    /**
     * 注:secret保存起来
     *  Encryption keys generated successfully.
     *  Personal access client created successfully.
     *  Client ID: 1
     *  Client secret: annKa8WJdwmhDhz4Hj3lEv3IBbTJI4ebCkmsEwT6
     *  Password grant client created successfully.
     *  Client ID: 2
     *  Client secret: 32G1jFCUNM0iTMf3LBEp3VAe7J9W9Ao665G9uSdR
     */

    //微信登录方法
    public function wxLogin(Request $request)
    {
        //接收参数
        $params = $request->all();
        //微信小程序登录的url地址
        $url = sprintf(config('wx.wxLoginUrl'), config('wx.AppID'), config('wx.AppSecret'), $params['code']);
        $client = new Client(['timeout' => 5, 'verify' => false]);
        $response = $client->get($url);
        $data = (string)$response->getBody();
        //转成数据
        $data = json_decode($data, true);
        //进行查询数据,如果没有进行添加,如果则进行生成token
        $renting = Renting::where('openid', $data['openid'])
            ->first();
        if (empty($renting)) {
            //存sql数据库
            //$renting = Renting::create($data);
            $renting = Renting::create(['openid'=>$data['openid']]);
        }
        //生成token
        $token = $renting->createToken('api')->accessToken;
        //清缓存 Cache::flush();
        //存缓存
        Cache::set($token, $renting, 7200);
        //取缓存 Cache::get($token);  var_dump($data);die();
        //返回
        return response()->json(['errorCode' => 0, 'data' => ['token' => $token, 'expire' => 7200,'time'=>time()], 'msg' => '登录成功'],200);

    }
    //更新用户信息
    public function saveUsers(Request $request)
    {
        //接收参数
        $params = $request->all();
        //获取token
        $token = explode(' ',$request->header('authorization'))[1];
        //进行查看
        $userInfo = Cache::get($token);
        //更新用户信息完成
        $userInfo->update($params);
        return response()->json(['errorCode' => 0, 'data' => '', 'msg' => '修改成功']);
    }

}

商品控制器

<?php

namespace App\Http\Controllers\Api;

use App\Http\Controllers\Controller;
use App\Models\Goods;
use Illuminate\Http\Request;
//
use Illuminate\Support\Facades\DB;
//启用redis
use Illuminate\Support\Facades\Redis;
//商品活动(秒杀表)
use App\Models\ActivityGoods;
//缓存系统
use Illuminate\Support\Facades\Cache;

class GoodsController extends Controller
{
    //商品秒杀列表
    public function activityList()
    {
        $result = ActivityGoods::with(['goods'])
            ->get();
        return response()->json(['errorCode' => 0, 'data' => $result, 'msg' => '查询成功']);
    }

    //商品秒杀详情
    public function goodsDetail(Request $request)
    {
        $goods_id = $request->get('goods_id');
        $result = ActivityGoods::with(['goods'])
            ->where('goods_id',$goods_id)
            ->first();
        return response()->json(['errorCode' => 0, 'data' => $result, 'msg' => '查询成功']);
    }
    //同步库存 可以使用postman 生成队列,
    public function syncStock()
    {
        //去掉双引号,使用postman ,查看队列的长度
//        $count = Redis::llen('activity_goods_1');
//        echo $count;
//        die;

        //查出所有参与秒杀活动列表
        $result = ActivityGoods::with(['goods'])
            ->get()->toArray();
        //进行把参与秒杀的商品写入到数据库
        foreach ($result as $val){
            //生成对应商品库存队列
            $goods = "activity_goods_".$val['goods_id'];
            for ($i=0; $i < $val['sku_nums']; $i++) {
                Redis::lpush($goods, 1);
//                Redis::lpush($goods, 1);
            }
        }
    }
    //校验库存 抢购接口
    public function checkStock(Request $request)
    {
        //获取token
        $token = explode(' ',$request->header('authorization'))[1];
        //进行查看
        $userInfo = Cache::get($token);
        //抢购用户id
        $userID = $userInfo->id;
        //商品id
        $goodsID = $request->input("goods_id");
        //对应商品库存队列
        $goods = "activity_goods_".$goodsID;
        //对应商品抢购成功用户集合 {1,3,4}
        $robSuccessUser = "success_user".$goodsID;
        //进行判断当前用户是否在抢成功的队列里面
        $result = Redis::sismember($robSuccessUser,$userID);
        //如果你在这里面,就抢完了
        if ($result) {
            //如果抢购成功 返回状态码,进行下单
            return response()->json(['errorCode' => 20000, 'data' => '', 'msg' => '已经抢购过了']);
        }
        //减库存,把队列里面的数据从左边 头
        $count = Redis::lpop($goods);
        if (!$count) {
            //如果抢购成功 返回状态码,进行下单
            return response()->json(['errorCode' => 20001, 'data' => '', 'msg' => '已经抢光了哦']);
        }
        //把当前这个秒杀的uid存储到中奖的队列里set
        $success = Redis::sadd($robSuccessUser, $userID);
        if(!$success){
            //已经在成功队列里了,加回库存,防止的是同个用户并发请求
            Redis::lpush($goods, 1);
            //如果抢购成功 返回状态码,进行下单
            return response()->json(['errorCode' => 20002, 'data' => '', 'msg' => '已经抢购过了']);
        }

        //如果抢购成功 返回状态码,进行下单
        return response()->json(['errorCode' => 0, 'data' => '', 'msg' => '秒杀成功']);
    }

    //创建订单
    public function createOrder(Request $request)
    {
        //获取token
        $token = explode(' ',$request->header('authorization'))[1];
        //进行查看
        $userInfo = Cache::get($token);
        //抢购用户id
        $userID = $userInfo->id;
        //商品id
        $goodsID = $request->input("goods_id");
        //print_r($goodsID);die();
        //对应商品抢购成功用户集合 {1,3,4}
        $robSuccessUser = "success_user".$goodsID;
        //进行判断当前用户是否在抢成功的队列里面
        $result = Redis::sismember($robSuccessUser,$userID);
        //如果你在这里面,就抢完了
        if (!$result) {
            //如果抢购成功 返回状态码,进行下单
            return response()->json(['errorCode' => 20003, 'data' => '', 'msg' => '手慢了!']);
        }

        DB::beginTransaction();//开始一个事务
        try{
            $goodsID = (int)$goodsID; // $bar 是整型
            //减sql数据库库存
            //商品活动(秒杀表)
            $Act=ActivityGoods::find($goodsID);
            $Act->sku_nums=$Act->sku_nums-1;
            $Act->save();

            //商品表
            //$id = $request->input('id');
            $goodsID = (int)$goodsID; // $bar 是整型
            $data=Goods::find($goodsID);
            $data->goods_nums=$data->goods_nums-1;
            $data->save();
            //return ['code'=>200,'msg'=>'库存已减'];
            //模拟生成订单表的订单号
            $data=MD5(123);
            DB::commit();//提交事务
            //下单成功,跳转支付页面
            return response()->json(['errorCode' => 0, 'data' => $data, 'msg' => '下单成功!']);
        }catch (\Exception $e){
            DB::rollBack();//回滚事务
        }


    }
}

模型配置

用户modek

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
//api 验证方法
use Laravel\Passport\HasApiTokens;
//软删除
use Illuminate\Database\Eloquent\SoftDeletes;
//引用AuthUser
use Illuminate\Foundation\Auth\User as AuthUser;

class Renting extends AuthUser
{
    use HasApiTokens,SoftDeletes;
    //拒绝不添加字段,软删除
    protected $guarded = [];
    //软删除字段
    protected $dates = ['deleted_at'];

}

秒杀model

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
//软删除
use Illuminate\Database\Eloquent\SoftDeletes;

class ActivityGoods extends Model
{
    use SoftDeletes;
    //拒绝不添加字段,软删除
    protected $guarded = [];
    //软删除字段
    protected $dates = ['deleted_at'];
    //模型关联
    public function goods()
    {
        return $this->belongsTo(Goods::class,'goods_id');
    }
}

goods_model

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Model;
//软删除
use Illuminate\Database\Eloquent\SoftDeletes;

class Goods extends Model
{
    use SoftDeletes;
    //拒绝不添加字段,软删除
    protected $guarded = [];
    //软删除字段
    protected $dates = ['deleted_at'];

}

小程序前台

自动登录

在这里插入图片描述

// app.js
App({
  onLaunch() {

    // logs.unshift(Date.now())
    // wx.setStorageSync('logs', logs)

    let token = wx.getStorageSync('token')
    //token过期时间
    let token_expire = wx.getStorageSync('token_expire')
    //当前的时间戳
    let now_time = Math.round(new Date().getTime() / 1000).toString();
    //还剩余多久过期
    let expire_time = token_expire - now_time;
    
    if (expire_time <= 0) {
      //如果过期,清空缓存
      wx.clearStorageSync('token')
      wx.clearStorageSync('token_expire')
    }


    if (!token) {
      // 登录
      wx.login({
        success: res => {
          //获取code码
          let code = res.code
          // 发送 res.code 到后台换取 openId, sessionKey, unionId
          wx.request({
            url: 'http://www.lianxi.com/api/v1/wx_login',
            method: 'POST',
            data: {
              code
            },
            success: res => {
              let token = res.data.data.token;
              wx.setStorageSync('token', token)
              wx.setStorageSync('token_expire', res.data.data.time + res.data.data.expire - 100)
            }
          })
        }
      })
    }
  },


  globalData: {
    userInfo: null
  }
})

全局配置

在这里插入图片描述

const formatTime = date => {
  const year = date.getFullYear()
  const month = date.getMonth() + 1
  const day = date.getDate()
  const hour = date.getHours()
  const minute = date.getMinutes()
  const second = date.getSeconds()

  return `${[year, month, day].map(formatNumber).join('/')} ${[hour, minute, second].map(formatNumber).join(':')}`
}

const formatNumber = n => {
  n = n.toString()
  return n[1] ? n : `0${n}`
}


// 防抖
export const debounce =  (fn, interval)=>{
  var timer;
  var gapTime = interval || 1000;//间隔时间,如果interval不传,则默认1000ms
  return function() {
    clearTimeout(timer);
    var context = this;
    var args = arguments;//保存此处的arguments,因为setTimeout是全局的,arguments不是防抖函数需要的。
    timer = setTimeout(function() {
      fn.call(context,args);
    }, gapTime);
  };
}
//引用 debounce
module.exports = {
  formatTime,debounce
}

app.json

{
  "pages":[
    "pages/index/index",
    "pages/goods_detail/goods_detail",
    "pages/my/my",
    "pages/order/order",
    
    "pages/login/login",
    "pages/logs/logs"

  ],
  "window":{
    "backgroundTextStyle":"light",
    "navigationBarBackgroundColor": "#fff",
    "navigationBarTitleText": "Weixin",
    "navigationBarTextStyle":"black"
  },
  "tabBar": {
    "list": [{
      "pagePath": "pages/index/index",
      "text": "首页"
    }, {
      "pagePath": "pages/my/my",
      "text": "我的"
    }]
  },
  "usingComponents": {
    "l-card":"/miniprogram_npm/lin-ui/card",
    "l-button":"/miniprogram_npm/lin-ui/button"
  },
  "style": "v2",
  "sitemapLocation": "sitemap.json"
}

我的

授权登录

js

// pages/my/my.js
Page({
  /**
   * 页面的初始数据
   */
  data: {
    avatarIcon: 'user',
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {

    //页面加载事件,进行获取用户授权信息
    let userInfo = wx.getStorageSync('userInfo')
    //如果有用户授权信息,进行展示用户信息
    if (userInfo) {
      this.setData({
        ...userInfo,
        avatarIcon: ''
      })
    }
  },
  
  getUser() {
    let userInfo = wx.getStorageSync('userInfo')
    if(userInfo){
      return
    }
    // 推荐使用wx.getUserProfile获取用户信息,开发者每次通过该接口获取用户个人信息均需用户确认
    // 开发者妥善保管用户快速填写的头像昵称,避免重复弹窗
    wx.getUserProfile({
      desc: '用于完善会员资料', // 声明获取用户个人信息后的用途,后续会展示在弹窗中,请谨慎填写
      success: (res) => {
        //第一步要进行存缓存
        wx.setStorageSync('userInfo', res.userInfo)
        //第二步 请求接口,更新用户基本信息
        var token = wx.getStorageSync('token')
        wx.request({
          url: 'http://www.lianxi.com/api/v1/users',
          method: 'PUT',
          header: {
            'Authorization':`Bearer ${token}`
          },
          data:{
            'nickname':res.userInfo.nickName,
            'avatar':res.userInfo.avatarUrl
          },
          success: res => {
            console.log(res)
          }
        })
        this.setData({
          ...res.userInfo,
          avatarIcon: ''
        })
      }
    })
  }

})

my.json

{
  "usingComponents": { 
    "l-button":"/miniprogram_npm/lin-ui/button",
    "l-avatar":"/miniprogram_npm/lin-ui/avatar"
  }
}

my.wxml

<!-- 点击头像进行授权登录 -->
<l-avatar src="{{ avatarUrl }}" l-class="avatar-bg" size="120" icon="{{ avatarIcon }}" icon-style="color:#5bf320" bindtap="getUser"/>

<view>
  <text>昵称:{{nickName}}</text>
</view>

首页

秒杀列表

index. js

// index.js
// 获取应用实例
const app = getApp()

Page({
  data: {
    goods:[]

  },
    /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.getActivityList();
  },
  getActivityList() {
    var token = wx.getStorageSync('token')
    wx.request({
      url: 'http://www.lianxi.com/api/v1/activity_list',
      header: {
        'Authorization': `Bearer ${token}`
      },
      success: res => {
        this.setData({
          goods:res.data.data
        })
      }
    })
  }
})

index.json

{
  "usingComponents": {
    "l-card":"/miniprogram_npm/lin-ui/card",
    "l-button":"/miniprogram_npm/lin-ui/button"
  }
}

my.wxml

<block wx:for="{{ goods}}" wx:key="unique">

<l-card type="primary" full="{{true}}" image="{{item.goods.goods_image}}" title="{{ item.goods.goods_name}}">
   <view>
     价格:{{ item.goods.goods_price}}
   </view>
   <view>
   <navigator url="/pages/goods_detail/goods_detail?goods_id={{ item.goods_id }}">  <l-button type="error">立即抢购</l-button></navigator>
   </view>
</l-card>
</block>

index.wxss

/**index.wxss**/
.userinfo {
  display: flex;
  flex-direction: column;
  align-items: center;
  color: #aaa;
}

.userinfo-avatar {
  overflow: hidden;
  width: 128rpx;
  height: 128rpx;
  margin: 20rpx;
  border-radius: 50%;
}

.usermotto {
  margin-top: 200px;
}

秒杀详情

详情

goods_detail. js

import {
  debounce
} from "../../utils/util"

Page({

  /**
   * 页面的初始数据
   */
  data: {
   goods:{},
   expire_time:0,
   btn_disable:false
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (e) {
     //商品id
     let goods_id = e.goods_id;
     this.getGoodsDetail(goods_id)
  },
  //获取商品详情
  getGoodsDetail(goods_id){
    var token = wx.getStorageSync('token')
    wx.request({
      url: 'http://www.lianxi.com/api/v1/goods_detail?goods_id='+goods_id,
      header: {
        'Authorization': `Bearer ${token}`
      },
      success: res => {
        //当前的时间戳
        let now_time = Math.round(new Date().getTime() / 1000).toString();
        //倒计时剩余时间 = 活动开始时间减去当前的时间
        let expire_time = res.data.data.start_time - now_time;

        this.setData({
          goods:res.data.data,
          expire_time
        })
        if(expire_time > 0){
          this.setData({
            btn_disable:true
          })
        }
        console.log(this.data.goods)
      }
    })
  },
  //立即抢购
  buyGoods:debounce(function (e) {
    let goods_id = e[0].currentTarget.dataset.goods_id
    var token = wx.getStorageSync('token')
    wx.request({
      url: 'http://www.lianxi.com/api/v1/snap_up',
      header: {
        'Authorization': `Bearer ${token}`
      },
      method:"POST",
      data:{
        goods_id
      },
      success: res => {
        let code = res.statusCode.toString()
        //
        if (!code.startsWith('2')){
           wx.showToast({
             title: '异常!',
             icon:1
           })
        }
       
        if(res.data.errorCode == 0){
            wx.redirectTo({
              url: '/pages/order/order?goods_id='+goods_id,
            })
        }else{
          wx.showToast({
            title: res.data.msg,
          })
        }
        console.log(res.data)
      }
    })
  }),
  
  changeBtn(){
    this.setData({
      btn_disable:false
    })
  }
})

goods_detail. json

{
  "usingComponents": {
    "l-card":"/miniprogram_npm/lin-ui/card",
    "l-button":"/miniprogram_npm/lin-ui/button",
    "l-countdown":"/miniprogram_npm/lin-ui/countdown"
  }
}```

#### goods_detail. wxss

```javascript
<view>商品秒杀页面</view>
<!-- 时间倒计时 -->
<l-countdown time-type="second" time="{{expire_time}}" bind:linend="changeBtn" />

<l-card type="primary" full="{{true}}" image="{{goods.goods.goods_image}}" title="{{goods.goods.goods_name}}">
     <view>
       价格:{{goods.goods.goods_price}}
     </view>
     <view>
     <!-- <button disabled="true" bindtap="buyGoods" >抢购</button> -->
      <l-button disabled="{{ btn_disable }}" bind:lintap="buyGoods" type="error" data-goods_id="{{ goods.goods.id }}">立即秒杀</l-button>
     </view>
  </l-card>

查看订单编号

订单编号

order. js

// pages/order/order.js
Page({

  /**
   * 页面的初始数据
   */
  data: {
    goods_id: 0,
    dingdan:{}
  },

  /**
   * 生命周期函数--监听页面加载
   */
  onLoad: function (e) {
    //商品id
    var goods_id = e.goods_id;
    var token = wx.getStorageSync('token')
    wx.request({
      url: 'http://www.lianxi.com/api/v1/goods_order',
      header: {
        'Authorization': `Bearer ${token}`
      },
      method: "POST",
      data: {
        goods_id
      },
      success: res => {
        let code = res.statusCode.toString()
        if (!code.startsWith('2')){
           wx.showToast({
             title: '异常!',
             icon:1
           })
        }

        if(res.data.errorCode == 0){
          this.setData({
            dingdan:res.data.data
          })
        //     wx.redirectTo({
        //       url: '/pages/order/order?goods_id='+goods_id,
        //     })
        // }else{
        //   wx.showToast({
        //     title: res.data.msg,
        //   })
        }
        console.log(res.data.data)
      }
    })


  },

.........
})

order. js

<view>抢购成功</view>
<view>订单编号:</view>
<view>{{dingdan}}</view>

  PHP知识库 最新文章
Laravel 下实现 Google 2fa 验证
UUCTF WP
DASCTF10月 web
XAMPP任意命令执行提升权限漏洞(CVE-2020-
[GYCTF2020]Easyphp
iwebsec靶场 代码执行关卡通关笔记
多个线程同步执行,多个线程依次执行,多个
php 没事记录下常用方法 (TP5.1)
php之jwt
2021-09-18
上一篇文章      下一篇文章      查看所有文章
加:2021-07-10 14:19:19  更:2021-07-10 14:20:21 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/3 14:22:47-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码