first commit

This commit is contained in:
LittleBoy 2021-01-04 13:45:02 +08:00
commit 477a818fc4
69 changed files with 2613 additions and 0 deletions

17
.env Normal file
View File

@ -0,0 +1,17 @@
APP_DEBUG = true
[APP]
DEFAULT_TIMEZONE = Asia/Shanghai
[DATABASE]
TYPE = mysql
HOSTNAME = 127.0.0.1
DATABASE = shop
USERNAME = root
PASSWORD = 123456
HOSTPORT = 3306
CHARSET = utf8
DEBUG = true
[LANG]
default_lang = zh-cn

22
.gitignore vendored Normal file
View File

@ -0,0 +1,22 @@
.DS_Store
node_modules
dist
vendor
# local env files
.env.local
.env.*.local
# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*

32
LICENSE.txt Normal file
View File

@ -0,0 +1,32 @@
ThinkPHP遵循Apache2开源协议发布并提供免费使用。
版权所有Copyright © 2006-2016 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
Apache Licence是著名的非盈利开源组织Apache采用的协议。
该协议和BSD类似鼓励代码共享和尊重原作者的著作权
允许代码修改,再作为开源或商业软件发布。需要满足
的条件:
1 需要给代码的用户一份Apache Licence
2 如果你修改了代码,需要在被修改的文件中说明;
3 在延伸的代码中(修改和有源代码衍生的代码中)需要
带有原来代码中的协议,商标,专利声明和其他原来作者规
定需要包含的说明;
4 如果再发布的产品中包含一个Notice文件则在Notice文
件中需要带有本协议内容。你可以在Notice中增加自己的
许可但不可以表现为对Apache Licence构成更改。
具体的协议参考http://www.apache.org/licenses/LICENSE-2.0
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.

56
README.md Normal file
View File

@ -0,0 +1,56 @@
ThinkPHP 6.0
===============
> 运行环境要求PHP7.1+。
[官方应用服务市场](https://market.topthink.com) | [`ThinkPHP`开发者扶持计划](https://sites.thinkphp.cn/1782366)
ThinkPHPV6.0版本由[亿速云](https://www.yisu.com/)独家赞助发布。
## 主要新特性
* 采用`PHP7`强类型(严格模式)
* 支持更多的`PSR`规范
* 原生多应用支持
* 更强大和易用的查询
* 全新的事件系统
* 模型事件和数据库事件统一纳入事件系统
* 模板引擎分离出核心
* 内部功能中间件化
* SESSION/Cookie机制改进
* 对Swoole以及协程支持改进
* 对IDE更加友好
* 统一和精简大量用法
## 安装
~~~
composer create-project topthink/think tp 6.0.*
~~~
如果需要更新框架使用
~~~
composer update topthink/framework
~~~
## 文档
[完全开发手册](https://www.kancloud.cn/manual/thinkphp6_0/content)
## 参与开发
请参阅 [ThinkPHP 核心框架包](https://github.com/top-think/framework)。
## 版权信息
ThinkPHP遵循Apache2开源协议发布并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2006-2020 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
更多细节参阅 [LICENSE.txt](LICENSE.txt)

8
api/.htaccess.txt Normal file
View File

@ -0,0 +1,8 @@
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>

8
api/.htaccess.txt.txt Normal file
View File

@ -0,0 +1,8 @@
<IfModule mod_rewrite.c>
Options +FollowSymlinks -Multiviews
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ index.php/$1 [QSA,PT,L]
</IfModule>

BIN
api/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

24
api/index.php Normal file
View File

@ -0,0 +1,24 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// [ 应用入口文件 ]
namespace think;
require __DIR__ . '/../vendor/autoload.php';
// 执行HTTP应用并响应
$http = (new App())->http;
$response = $http->run();
$response->send();
//header('Access-Control-Allow-Origin: *');
$http->end($response);

2
api/robots.txt Normal file
View File

@ -0,0 +1,2 @@
User-agent: *
Disallow:

19
api/router.php Normal file
View File

@ -0,0 +1,19 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2019 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// $Id$
if (is_file($_SERVER["DOCUMENT_ROOT"] . $_SERVER["SCRIPT_NAME"])) {
return false;
} else {
$_SERVER["SCRIPT_FILENAME"] = __DIR__ . '/index.php';
require __DIR__ . "/index.php";
}

2
api/static/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

1
app/.htaccess.txt Normal file
View File

@ -0,0 +1 @@
deny from all

22
app/AppService.php Normal file
View File

@ -0,0 +1,22 @@
<?php
declare (strict_types = 1);
namespace app;
use think\Service;
/**
* 应用服务类
*/
class AppService extends Service
{
public function register()
{
// 服务注册
}
public function boot()
{
// 服务启动
}
}

143
app/BaseController.php Normal file
View File

@ -0,0 +1,143 @@
<?php
declare (strict_types=1);
namespace app;
use app\model\Users;
use think\App;
use think\Collection;
use think\exception\ValidateException;
use think\Validate;
/**
* 控制器基础类
*/
abstract class BaseController
{
/**
* Request实例
* @var \think\Request
*/
protected $request;
/**
* 应用实例
* @var \think\App
*/
protected $app;
/**
* 是否批量验证
* @var bool
*/
protected $batchValidate = false;
/**
* 控制器中间件
* @var array
*/
protected $middleware = [];
/**
* 构造方法
* @access public
* @param App $app 应用对象
*/
public function __construct(App $app)
{
$this->app = $app;
$this->request = $this->app->request;
// 控制器初始化
$this->initialize();
}
// 初始化
protected function initialize()
{
}
/**
* 验证数据
* @access protected
* @param array $data 数据
* @param string|array $validate 验证器名或者验证规则数组
* @param array $message 提示信息
* @param bool $batch 是否批量验证
* @return array|string|true
* @throws ValidateException
*/
protected function validate(array $data, $validate, array $message = [], bool $batch = false)
{
if (is_array($validate)) {
$v = new Validate();
$v->rule($validate);
} else {
if (strpos($validate, '.')) {
// 支持场景
[$validate, $scene] = explode('.', $validate);
}
$class = false !== strpos($validate, '\\') ? $validate : $this->app->parseClass('validate', $validate);
$v = new $class();
if (!empty($scene)) {
$v->scene($scene);
}
}
$v->message($message);
// 是否批量验证
if ($batch || $this->batchValidate) {
$v->batch(true);
}
return $v->failException(true)->check($data);
}
/**
* @return Users|null
*/
protected function getUser()
{
return $this->request->user;
}
protected function getUserId()
{
$user = $this->getUser();
if (empty($user)) return 0;
return $user->uid;
}
protected function fail($msg, $code = 1)
{
return json(['code' => $code, 'message' => $msg]);
}
protected function success($data = null, $msg = 'success')
{
return json(['code' => 0, 'message' => $msg, 'data' => $data]);
}
protected function buildGoods(&$g){
$picture = is_array($g) ? $g['picture']:$g->picture;
if(substr($picture,0,4) != 'http'){
$picture = config('app.url').'/static/'.$picture;
}
if(is_array($g)){
$g['picture'] = $picture;
$g['category'] = explode(',',$g['category']);
}else{
$g->picture = $picture;
$g->category = explode(',',$g->category);
}
return $g;
}
protected function buildGoodsData($gs)
{
foreach($gs as &$g){
$this->buildGoods($g);
}
return $gs;
}
}

46
app/BaseModel.php Normal file
View File

@ -0,0 +1,46 @@
<?php
/**
* Created by PhpStorm.
* User: yancheng<cheng@love.xiaoyan.me>
* Date: 2020/12/10
* Time: 20:28
*/
namespace app;
use think\Model;
/**
* Class BaseModel
* @package app\model
*
* @property int $id
* @property int $create_time
* @property int $update_time
* @property int $status
*/
class BaseModel extends Model
{
/**
* @param null $data
* @return array|Model|static
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function find($data = null)
{
return parent::find($data); // TODO: Change the autogenerated stub
}
/**
* @param null $data
* @return array|Model|static
*/
public function findOrEmpty($data = null)
{
return parent::findOrEmpty($data);
}
}

66
app/ExceptionHandle.php Normal file
View File

@ -0,0 +1,66 @@
<?php
namespace app;
use think\db\exception\DataNotFoundException;
use think\db\exception\ModelNotFoundException;
use think\exception\ErrorException;
use think\exception\Handle;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\ValidateException;
use think\Response;
use Throwable;
/**
* 应用异常处理类
*/
class ExceptionHandle extends Handle
{
/**
* 不需要记录信息(日志)的异常类列表
* @var array
*/
protected $ignoreReport = [
HttpException::class,
HttpResponseException::class,
ModelNotFoundException::class,
DataNotFoundException::class,
ValidateException::class,
];
/**
* 记录异常信息(包括日志或者其它方式记录)
*
* @access public
* @param Throwable $exception
* @return void
*/
public function report(Throwable $exception): void
{
// 使用内置的方式记录异常日志
parent::report($exception);
}
/**
* Render an exception into an HTTP response.
*
* @access public
* @param \think\Request $request
* @param Throwable $e
* @return Response
*/
public function render($request, Throwable $e): Response
{
if($request->isAjax()){
// 添加自定义异常处理机制
if ($e instanceof \InvalidArgumentException) {
return json(['code' => -1, 'message' => '参数错误[' . $e->getMessage() . ']']);
}
if ($e instanceof ErrorException) {
return json(['code' => -1, 'message' => '服务器运行错误[' . $e->getMessage() . ']']);
}
}
// 其他错误交给系统处理
return parent::render($request, $e);
}
}

8
app/Request.php Normal file
View File

@ -0,0 +1,8 @@
<?php
namespace app;
// 应用请求对象类
class Request extends \think\Request
{
}

2
app/common.php Normal file
View File

@ -0,0 +1,2 @@
<?php
// 应用公共文件

119
app/controller/Index.php Normal file
View File

@ -0,0 +1,119 @@
<?php
namespace app\controller;
use app\BaseController;
use app\model\Goods;
use app\model\StringUtil;
use app\model\Users;
use think\facade\Cache;
class Index extends BaseController
{
public function index()
{
$str = '商城API接口';
return $str;
}
public function goods($id = null, $sort = 'default', $order = 'desc', $size = 30, $page = 1, $category = null, $list = 'no',$price = null)
{
sleep(1);
$g = new Goods();
if (!empty($id)) {
$goods = $g->find($id);
if (empty($goods)) {
return json(['code' => 1, 'message' => '不存在该商品或者商品已下架']);
}
$goods = $this->buildGoods($goods);
return json($goods);
}
$sf = ['time' => 'update_time', 'price' => 'sell_price', 'count' => 'sell_count','default'=>'sort'];
$sort = in_array($sort, array_keys($sf)) ? $sf[$sort] : 'sort';
$order = $order == 'asc' ? 'asc' : 'desc';
if (!empty($category)) {
$g = $g->whereFindInSet('category',$category);
}
if (!empty($price)) {
$price = explode('_',$price);
$min = 0;$max = 100000;
if(count($price) == 1) $max = $price[0];
else {
$min = $price[0];
$max = $price[1];
}
$g = $g->whereBetween('sell_price',[floatval($min),floatval($max)]);
}
$g = $g->order($sort, $order);
$total = $g->count();
$gs = $this->buildGoodsData($g->limit(($page - 1) * $size, $size)->select());
if ($list != 'no') {
return json([
'total' => $total,
'page' => $page,
'size' => $size,
'list' => $gs->toArray()
]);
}
return json($gs);
}
public function login($username = null, $password = null)
{
if (empty($username) || empty($password)) {
return json(['code' => 1, 'message' => '用户名和密码不允许为空']);
}
$u = (new Users())->where('username', $username)->where('password', md5($password))->find();
if (empty($u)) {
return json(['code' => 2, 'message' => '用户名或者密码错误']);
}
if ($u->status != 1) {
return json(['code' => 3, 'message' => '用户不存在或已经被冻结']);
}
$token = StringUtil::encryption($u->uid, StringUtil::USER_TOKEN, 0);
$u->token = $token;
Cache::set('login_user_'.$u->uid, $token, 3600);
return json($u);
}
public function reg($username = null, $password = null, $email = null)
{
if (empty($username) || empty($password) || empty($email)) {
return json(['code' => 1, 'message' => '用户名、密码及邮箱不允许为空']);
}
$u = (new Users())->where('username', $username)->findOrEmpty();
if (!$u->isEmpty()) {
return json(['code' => 2, 'message' => '用户名已经存在了']);
}
$u->username = $username;
$u->password = md5($password);
$u->avatar = $this->request->param('avatar','https://img2.woyaogexing.com/2020/12/01/828516da933d44ccac01302dc72e97ae!400x400.jpeg');
$u->nickname = $this->request->param('nickname');
$u->email = $email;
try {
$u->save();
return $u;
} catch (\Exception $e) {
return json(['code' => 3, 'message' => '注册用户失败了', 'error' => $e->getMessage()]);
}
}
public function saveGoods($title, $sell_price, $picture,$origin_key = null)
{
$g = new Goods();
if(!empty($origin_key)){
if(!empty($g->where('origin_key',$origin_key)->find())){
return $this->success();
}
}
// 过滤post数组中的非数据表字段数据
$data = $this->request->only([
'title', 'origin_price',
'sell_count', 'sell_price',
'desc', 'content', 'picture', 'category','origin_key'
]);
$g->save($data);
return $this->success($g->id);
}
}

158
app/controller/Shop.php Normal file
View File

@ -0,0 +1,158 @@
<?php
/**
* Created by PhpStorm.
* User: yancheng<cheng@love.xiaoyan.me>
* Date: 2020/12/10
* Time: 20:35
*/
namespace app\controller;
use app\BaseController;
use app\middleware\LoginCheck;
use app\model\Carts;
use app\model\Goods;
use app\model\Order;
use app\model\OrderGoods;
use think\response\Json;
use think\facade\Db;
class Shop extends BaseController
{
protected $middleware = [
LoginCheck::class
];
public function addToCart(int $goodsId = null,int $count = null){
if(empty($goodsId) || empty($count)){
return $this->fail('参数goodsId,count都必须填写');
}
$goods = (new Goods())->find($goodsId);
if(empty($goods) || $goods->status != 1){
return $this->fail('商品不存在或者已被下架');
}
$cart = new Carts();
$uid = $this->getUserId();
$cart = $cart->where('uid',$uid)
->where('goods_id',$goodsId)
->findOrEmpty();
if($cart->isEmpty()){
$cart->uid = $uid;
$cart->goods_id = $goodsId;
$cart->count = $count;
}else{
$cart->count += $count;
}
if($cart->count > $goods->stock){
return $this->fail('库存不足');
}
$cart->add_price = $goods->sell_price;
if($cart->save()){
return $this->success();
}
return $this->fail('添加购物车失败');
}
/**
* @return Json
*/
public function queryCart(){
$goods = (new Carts())->queryByUid($this->getUserId());
$goods = $this->buildGoodsData($goods->toArray());
return json($goods);
}
public function removeCart($id = null){
if(empty($id)){
return $this->fail('参数 id 必须填写');
}
Carts::destroy($id);
return $this->success();
}
public function updateCart($id = null,$count = null){
if(empty($id) || empty($count)){
return $this->fail('参数 id ,count 都必须填写');
}
if($count < 0){
return $this->fail('你是想我给你钱吗?count必须大于0');
}
$cart = new Carts();
$cart = $cart->find($id);
if(empty($cart)){
return $this->fail('购物车不存在这个商品');
}
if($cart->uid != $this->getUserId()){
return $this->fail('非法操作(不是你的数据)');
}
$goods = (new Goods())->find($cart->goods_id);
if($count > $goods->stock){
return $this->fail('库存不足');
}
$cart->count = $count;
if($cart->save()){
return $this->success($cart->toArray());
}
return $this->fail('添加购物车失败');
}
public function checkout($ids)
{
$cart = new Carts();
$carts = $cart->where('uid',$this->getUserId())->where('id','in',$ids)->select();
if($carts->count() == 0){
return $this->fail('结算失败:没有找到待结算商品');
}
Db::startTrans();
try{
$order = new Order();
$order->uid = $this->getUserId();
$order->amount = 0;
$order->paid = 0;
if($order->save()){
$totalAmount = 0;
foreach ($carts as $c){
$g = (new Goods())->find($c->goods_id);
if(empty($g)){
continue;
}
if($g->stock < $c->count){
throw new \Exception('库存不足');
}
$g->stock -= $c->count;
$g->sell_count += $c->count;
$totalAmount += $g->sell_price * $c->count; // 累加商品价格
OrderGoods::create([
'order_id' => $order->id,
'goods_id' => $c->goods_id,
'amount' => $g->sell_price,
'count' => $c->count,
]);
$c->delete();
$g->save();
}
$order->amount = $totalAmount;
if($order->save()){
Db::commit();
return \json($order);
}
}
}catch (\Exception $e){
Db::rollback();
return $this->fail('结算失败:'.$e->getMessage());
}
return $this->fail('结算失败');
}
public function queryOrder(){
$or = new Order();
$orders = $or->queryByUid($this->getUserId());
foreach ($orders as $o){
$o->goods = $this->buildGoodsData($or->getOrderGoods($o->id)->toArray());
}
return json($orders);
}
}

17
app/event.php Normal file
View File

@ -0,0 +1,17 @@
<?php
// 事件定义文件
return [
'bind' => [
],
'listen' => [
'AppInit' => [],
'HttpRun' => [],
'HttpEnd' => [],
'LogLevel' => [],
'LogWrite' => [],
],
'subscribe' => [
],
];

11
app/middleware.php Normal file
View File

@ -0,0 +1,11 @@
<?php
// 全局中间件定义文件
return [
// 全局请求缓存
// \think\middleware\CheckRequestCache::class,
// 多语言加载
// \think\middleware\LoadLangPack::class,
// Session初始化
// \think\middleware\SessionInit::class,
\think\middleware\AllowCrossDomain::class
];

View File

@ -0,0 +1,36 @@
<?php
declare (strict_types = 1);
namespace app\middleware;
use app\model\StringUtil;
use app\model\Users;
class LoginCheck
{
/**
* 处理请求
*
* @param \think\Request $request
* @param \Closure $next
* @return Response
*/
public function handle($request, \Closure $next)
{
$token = $request->param('token');
if(!empty($token)) {
$token = str_replace(' ','+',$token);
$token = StringUtil::decryption($token,StringUtil::USER_TOKEN);
}
if(empty($token)){
return json(['code'=>1,'message'=>'登录的用户数据不合法']);
}
$user = (new Users())->find($token);
if(empty($user)){
return json(['code'=>2,'message'=>'不存在当前请求的用户']);
}
$request->user = $user;
return $next($request);
}
}

26
app/model/BaseModel.php Normal file
View File

@ -0,0 +1,26 @@
<?php
/**
* Created by PhpStorm.
* User: yancheng<cheng@love.xiaoyan.me>
* Date: 2020/12/10
* Time: 20:28
*/
namespace app\model;
use think\Model;
/**
* Class BaseModel
* @package app\model
*
* @property int $id
* @property int $create_time
* @property int $update_time
* @property int $status
*/
class BaseModel extends Model
{
}

28
app/model/Carts.php Normal file
View File

@ -0,0 +1,28 @@
<?php
declare (strict_types = 1);
namespace app\model;
use app\BaseModel;
use think\facade\Db;
/**
* @mixin \think\Model
* @property float $add_price
* @property int $uid
* @property int $goods_id
* @property int $count
*/
class Carts extends BaseModel
{
//
public function queryByUid(int $uid)
{
return Db::table($this->getTable())
->alias('c')
->join('goods g','c.goods_id = g.id')
->field('c.*,g.title,g.sell_price,g.picture,g.category,g.stock')
->where('uid',$uid)
->select();
}
}

17
app/model/Goods.php Normal file
View File

@ -0,0 +1,17 @@
<?php
declare (strict_types = 1);
namespace app\model;
use app\BaseModel;
use think\Model;
/**
* @mixin \think\Model
* @property float $sell_price
* @property int $stock
*/
class Goods extends BaseModel
{
//
}

36
app/model/Order.php Normal file
View File

@ -0,0 +1,36 @@
<?php
declare (strict_types = 1);
namespace app\model;
use think\facade\Db;
use think\Model;
use app\BaseModel;
/**
* @mixin \think\Model
*/
class Order extends BaseModel
{
//
protected $pk = 'id';
protected $table = 'orders';
private $og = null;
/**
* @param $uid
* @return \think\Collection
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\DbException
* @throws \think\db\exception\ModelNotFoundException
*/
public function queryByUid($uid)
{
$orders = $this->where('uid',$uid)->order('id','desc')->select();
return $orders;
}
public function getOrderGoods($id){
return (new OrderGoods())->goods($id);
}
}

25
app/model/OrderGoods.php Normal file
View File

@ -0,0 +1,25 @@
<?php
declare (strict_types = 1);
namespace app\model;
use think\Model;
use think\facade\Db;
/**
* @mixin \think\Model
*/
class OrderGoods extends Model
{
//
protected $table = 'order_goods';
protected $pk = 'id';
public function goods($order_id){
return Db::table($this->getTable())
->alias('og')
->join('goods g','og.goods_id = g.id')
->where('order_id',$order_id)
->select();
}
}

85
app/model/StringUtil.php Normal file
View File

@ -0,0 +1,85 @@
<?php
/**
* Created by PhpStorm.
* User: yancheng<cheng@love.xiaoyan.me>
* Date: 2020/12/10
* Time: 20:19
*/
namespace app\model;
class StringUtil
{
const USER_TOKEN = 'user.token';
private static function authCode($string, $operation = 'DECODE', $key = '', $expiry = 0)
{
// 动态密匙长度,相同的明文会生成不同密文就是依靠动态密匙
$ckey_length = 4;
// 密匙
$key = md5($key);
// 密匙a会参与加解密
$keya = md5(substr($key, 0, 16));
// 密匙b会用来做数据完整性验证
$keyb = md5(substr($key, 16, 16));
// 密匙c用于变化生成的密文
$keyc = $ckey_length ? ($operation == 'DECODE' ? substr($string, 0, $ckey_length) : substr(md5(microtime()), -$ckey_length)) : '';
// 参与运算的密匙
$cryptkey = $keya . md5($keya . $keyc);
$key_length = strlen($cryptkey);
// 明文前10位用来保存时间戳解密时验证数据有效性10到26位用来保存$keyb(密匙b)
//解密时会通过这个密匙验证数据完整性
// 如果是解码的话,会从第$ckey_length位开始因为密文前$ckey_length位保存 动态密匙,以保证解密正确
$string = $operation == 'DECODE' ? base64_decode(substr($string, $ckey_length)) : sprintf('%010d', $expiry ? $expiry + time() : 0) . substr(md5($string . $keyb), 0, 16) . $string;
$string_length = strlen($string);
$result = '';
$box = range(0, 255);
$rndkey = array();
// 产生密匙簿
for ($i = 0; $i <= 255; $i++) {
$rndkey[$i] = ord($cryptkey[$i % $key_length]);
}
// 用固定的算法,打乱密匙簿,增加随机性,好像很复杂,实际上对并不会增加密文的强度
for ($j = $i = 0; $i < 256; $i++) {
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
$tmp = $box[$i];
$box[$i] = $box[$j];
$box[$j] = $tmp;
}
// 核心加解密部分
for ($a = $j = $i = 0; $i < $string_length; $i++) {
$a = ($a + 1) % 256;
$j = ($j + $box[$a]) % 256;
$tmp = $box[$a];
$box[$a] = $box[$j];
$box[$j] = $tmp;
// 从密匙簿得出密匙进行异或,再转成字符
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
}
if ($operation == 'DECODE') {
// 验证数据有效性,请看未加密明文的格式
if ((substr($result, 0, 10) == 0 || substr($result, 0, 10) - time() > 0) && substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)) {
return substr($result, 26);
} else {
return '';
}
} else {
// 把动态密匙保存在密文里,这也是为什么同样的明文,生产不同密文后能解密的原因
// 因为加密后的密文可能是一些特殊字符复制过程可能会丢失所以用base64编码
return $keyc . str_replace('=', '', base64_encode($result));
}
}
static function encryption($data, $key = 'key', $expire = 0)
{
return self::authCode($data, 'ENCODE', $key, $expire);
}
static function decryption($data, $key = 'key')
{
return self::authCode($data, 'DECODE', $key);
}
}

16
app/model/Users.php Normal file
View File

@ -0,0 +1,16 @@
<?php
declare (strict_types = 1);
namespace app\model;
use app\BaseModel;
/**
* @property int $uid
* @property string $token
*/
class Users extends BaseModel
{
//
protected $pk = 'uid';
}

9
app/provider.php Normal file
View File

@ -0,0 +1,9 @@
<?php
use app\ExceptionHandle;
use app\Request;
// 容器Provider定义文件
return [
'think\Request' => Request::class,
'think\exception\Handle' => ExceptionHandle::class,
];

9
app/service.php Normal file
View File

@ -0,0 +1,9 @@
<?php
use app\AppService;
// 系统服务定义文件
// 服务在完成全局初始化之后执行
return [
AppService::class,
];

48
composer.json Normal file
View File

@ -0,0 +1,48 @@
{
"name": "topthink/think",
"description": "the new thinkphp framework",
"type": "project",
"keywords": [
"framework",
"thinkphp",
"ORM"
],
"homepage": "http://thinkphp.cn/",
"license": "Apache-2.0",
"authors": [
{
"name": "liu21st",
"email": "liu21st@gmail.com"
},
{
"name": "yunwuxin",
"email": "448901948@qq.com"
}
],
"require": {
"php": ">=7.1.0",
"topthink/framework": "^6.0.0",
"topthink/think-orm": "^2.0"
},
"require-dev": {
"symfony/var-dumper": "^4.2",
"topthink/think-trace":"^1.0"
},
"autoload": {
"psr-4": {
"app\\": "app"
},
"psr-0": {
"": "extend/"
}
},
"config": {
"preferred-install": "dist"
},
"scripts": {
"post-autoload-dump": [
"@php think service:discover",
"@php think vendor:publish"
]
}
}

1052
composer.lock generated Normal file

File diff suppressed because it is too large Load Diff

33
config/app.php Normal file
View File

@ -0,0 +1,33 @@
<?php
// +----------------------------------------------------------------------
// | 应用设置
// +----------------------------------------------------------------------
return [
// 应用地址
'app_host' => env('app.host', ''),
'url' => env('app.url',''),
// 应用的命名空间
'app_namespace' => '',
// 是否启用路由
'with_route' => true,
// 默认应用
'default_app' => 'index',
// 默认时区
'default_timezone' => 'Asia/Shanghai',
// 应用映射(自动多应用模式有效)
'app_map' => [],
// 域名绑定(自动多应用模式有效)
'domain_bind' => [],
// 禁止URL访问的应用列表自动多应用模式有效
'deny_app_list' => [],
// 异常页面的模板文件
'exception_tmpl' => app()->getThinkPath() . 'tpl/think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
];

35
config/cache.php Normal file
View File

@ -0,0 +1,35 @@
<?php
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
return [
// 默认缓存驱动
'default' => env('cache.driver', 'file'),
// 缓存连接方式配置
'stores' => [
'file' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => '',
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
// 缓存标签前缀
'tag_prefix' => 'tag:',
// 序列化机制 例如 ['serialize', 'unserialize']
'serialize' => [],
],
// 更多的缓存连接
'redis' => [
// 驱动方式
'type' => 'redis',
// 服务器地址
'host' => '127.0.0.1',
],
],
];

9
config/console.php Normal file
View File

@ -0,0 +1,9 @@
<?php
// +----------------------------------------------------------------------
// | 控制台配置
// +----------------------------------------------------------------------
return [
// 指令定义
'commands' => [
],
];

18
config/cookie.php Normal file
View File

@ -0,0 +1,18 @@
<?php
// +----------------------------------------------------------------------
// | Cookie设置
// +----------------------------------------------------------------------
return [
// cookie 保存时间
'expire' => 0,
// cookie 保存路径
'path' => '/',
// cookie 有效域名
'domain' => '',
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => false,
// 是否使用 setcookie
'setcookie' => true,
];

60
config/database.php Normal file
View File

@ -0,0 +1,60 @@
<?php
return [
// 默认使用的数据库连接配置
'default' => env('database.driver', 'mysql'),
// 自定义时间查询规则
'time_query_rule' => [],
// 自动写入时间戳字段
// true为自动识别类型 false关闭
// 字符串则明确指定时间字段类型 支持 int timestamp datetime date
'auto_timestamp' => true,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 数据库连接配置信息
'connections' => [
'mysql' => [
// 数据库类型
'type' => env('database.type', 'mysql'),
// 服务器地址
'hostname' => env('database.hostname', '127.0.0.1'),
// 数据库名
'database' => env('database.database', ''),
// 用户名
'username' => env('database.username', 'root'),
// 密码
'password' => env('database.password', ''),
// 端口
'hostport' => env('database.hostport', '3306'),
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => env('database.charset', 'utf8'),
// 数据库表前缀
'prefix' => env('database.prefix', ''),
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 是否需要断线重连
'break_reconnect' => false,
// 监听SQL
'trigger_sql' => env('app_debug', true),
// 开启字段缓存
'fields_cache' => false,
],
// 更多的数据库配置信息
],
];

24
config/filesystem.php Normal file
View File

@ -0,0 +1,24 @@
<?php
return [
// 默认磁盘
'default' => env('filesystem.driver', 'local'),
// 磁盘列表
'disks' => [
'local' => [
'type' => 'local',
'root' => app()->getRuntimePath() . 'storage',
],
'public' => [
// 磁盘类型
'type' => 'local',
// 磁盘路径
'root' => app()->getRootPath() . 'public/storage',
// 磁盘路径对应的外部URL路径
'url' => '/storage',
// 可见性
'visibility' => 'public',
],
// 更多的磁盘配置信息
],
];

27
config/lang.php Normal file
View File

@ -0,0 +1,27 @@
<?php
// +----------------------------------------------------------------------
// | 多语言设置
// +----------------------------------------------------------------------
return [
// 默认语言
'default_lang' => env('lang.default_lang', 'zh-cn'),
// 允许的语言列表
'allow_lang_list' => [],
// 多语言自动侦测变量名
'detect_var' => 'lang',
// 是否使用Cookie记录
'use_cookie' => true,
// 多语言cookie变量
'cookie_var' => 'think_lang',
// 多语言header变量
'header_var' => 'think-lang',
// 扩展语言包
'extend_list' => [],
// Accept-Language转义为对应语言包名称
'accept_language' => [
'zh-hans-cn' => 'zh-cn',
],
// 是否支持语言分组
'allow_group' => false,
];

45
config/log.php Normal file
View File

@ -0,0 +1,45 @@
<?php
// +----------------------------------------------------------------------
// | 日志设置
// +----------------------------------------------------------------------
return [
// 默认日志记录通道
'default' => env('log.channel', 'file'),
// 日志记录级别
'level' => [],
// 日志类型记录的通道 ['error'=>'email',...]
'type_channel' => [],
// 关闭全局日志写入
'close' => false,
// 全局日志处理 支持闭包
'processor' => null,
// 日志通道列表
'channels' => [
'file' => [
// 日志记录方式
'type' => 'File',
// 日志保存目录
'path' => '',
// 单文件日志写入
'single' => false,
// 独立日志级别
'apart_level' => [],
// 最大日志文件数量
'max_files' => 0,
// 使用JSON格式记录
'json' => false,
// 日志处理
'processor' => null,
// 关闭通道日志写入
'close' => false,
// 日志输出格式化
'format' => '[%s][%s] %s',
// 是否实时写入
'realtime_write' => false,
],
// 其它日志通道配置
],
];

8
config/middleware.php Normal file
View File

@ -0,0 +1,8 @@
<?php
// 中间件配置
return [
// 别名或分组
'alias' => [],
// 优先级设置,此数组中的中间件会按照数组中的顺序优先执行
'priority' => [],
];

45
config/route.php Normal file
View File

@ -0,0 +1,45 @@
<?php
// +----------------------------------------------------------------------
// | 路由设置
// +----------------------------------------------------------------------
return [
// pathinfo分隔符
'pathinfo_depr' => '/',
// URL伪静态后缀
'url_html_suffix' => 'html',
// URL普通方式参数 用于自动生成
'url_common_param' => true,
// 是否开启路由延迟解析
'url_lazy_route' => false,
// 是否强制使用路由
'url_route_must' => false,
// 合并路由规则
'route_rule_merge' => false,
// 路由是否完全匹配
'route_complete_match' => false,
// 访问控制器层名称
'controller_layer' => 'controller',
// 空控制器名
'empty_controller' => 'Error',
// 是否使用控制器后缀
'controller_suffix' => false,
// 默认的路由变量规则
'default_route_pattern' => '[\w\.]+',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache_key' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 操作方法后缀
'action_suffix' => '',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
];

19
config/session.php Normal file
View File

@ -0,0 +1,19 @@
<?php
// +----------------------------------------------------------------------
// | 会话设置
// +----------------------------------------------------------------------
return [
// session name
'name' => 'PHPSESSID',
// SESSION_ID的提交变量,解决flash上传跨域
'var_session_id' => '',
// 驱动方式 支持file cache
'type' => 'file',
// 存储连接标识 当type使用cache的时候有效
'store' => null,
// 过期时间
'expire' => 1440,
// 前缀
'prefix' => '',
];

25
config/view.php Normal file
View File

@ -0,0 +1,25 @@
<?php
// +----------------------------------------------------------------------
// | 模板设置
// +----------------------------------------------------------------------
return [
// 模板引擎类型使用Think
'type' => 'Think',
// 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写 3 保持操作方法
'auto_rule' => 1,
// 模板目录名
'view_dir_name' => 'view',
// 模板后缀
'view_suffix' => 'html',
// 模板文件名分隔符
'view_depr' => DIRECTORY_SEPARATOR,
// 模板引擎普通标签开始标记
'tpl_begin' => '{',
// 模板引擎普通标签结束标记
'tpl_end' => '}',
// 标签库标签开始标记
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
];

2
extend/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

View File

@ -0,0 +1 @@
.g-info[data-v-3fd40480]{padding:12px 18px;position:relative;background:#fff;margin-bottom:10px}.g-title[data-v-3fd40480]{position:relative;color:#262626;overflow:hidden;font-weight:400;line-height:18px}.g-title h1[data-v-3fd40480]{font-weight:700;font-size:18px;line-height:24px;padding-right:0;margin:0}.desc[data-v-3fd40480]{color:#666;padding:18px 0 0;line-height:1.3;position:relative;font-size:12px;max-height:46px;overflow:hidden}.g-price[data-v-3fd40480]{line-height:20px;margin-bottom:5px;font-size:12px;color:#f2270c}.g-price span[data-v-3fd40480]{font-size:16px}.g-price .v[data-v-3fd40480]{font-size:32px;line-height:30px;display:inline-block}.page-detail[data-v-3fd40480]{background-color:#eee}.g-image[data-v-3fd40480]{background:#fff}.btn-go-back[data-v-3fd40480]{position:fixed;left:20px;top:20px;background-color:rgba(0,0,0,.5);width:40px;height:40px;border-radius:50%}.btn-go-back .iii[data-v-3fd40480]{color:#fff;font-size:24px;left:-2px;top:1px}

View File

@ -0,0 +1 @@
.goods-list-wrapper[data-v-fd40e072]{padding:15px 10px}.goods-item[data-v-fd40e072]{text-align:left;padding:0;padding-bottom:10px;border-bottom:1px dashed #eee}.goods-item .g-title[data-v-fd40e072]{word-break:break-all;margin-top:8px;color:#333;line-height:1.36;overflow:hidden;text-overflow:ellipsis;display:-webkit-box;-webkit-line-clamp:2;font-size:14px;-webkit-box-orient:vertical;height:38px}.goods-item .price[data-v-fd40e072]{color:#e4393c}.goods-item .price span[data-v-fd40e072]{font-weight:400;font-size:18px}.goods-item .sell-info[data-v-fd40e072]{color:#999;font-size:12px}

1
m/css/Login.86f4227f.css Normal file
View File

@ -0,0 +1 @@
.wrapper[data-v-5890dc30]{display:-webkit-box;display:-ms-flexbox;display:flex;-webkit-box-align:center;-ms-flex-align:center;align-items:center;-webkit-box-pack:center;-ms-flex-pack:center;justify-content:center;height:100%}.block[data-v-5890dc30]{width:80px;height:80px}

1
m/css/app.5cd02139.css Normal file
View File

@ -0,0 +1 @@
#app{font-family:Avenir,Helvetica,Arial,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;color:#2c3e50}.van-card__thumb{width:100px!important;height:100px!important}.clear-float:after{content:" ";display:block;clear:both}.goods-list-wrapper{padding:0 10px}.goods-list-wrapper:after{content:" ";display:block;clear:both}.goods-list-wrapper .list-item{width:50%;float:left}.goods-list-wrapper .list-item:nth-child(2n) .goods-item{margin-right:0;margin-left:5px}.goods-list-wrapper .goods-item{display:block;background-color:#fff;margin-bottom:10px;margin-right:5px;border-radius:5px;overflow:hidden}.goods-list-wrapper .p a,.goods-list-wrapper .p img{display:block;width:100%}.goods-list-wrapper .desc{padding:6px 7px 7px 6px}.goods-list-wrapper .p-title{text-decoration:none;display:block;font-size:13px;overflow:hidden;height:40px;line-height:20px;color:#1a1a1a;text-align:left;margin-bottom:5px;text-overflow:ellipsis}.goods-list-wrapper .p-info{line-height:20px;display:-webkit-box;display:-ms-flexbox;display:flex;color:#999}.goods-list-wrapper .p-price{color:#ff5000;font-family:helvetica;font-size:14px}.goods-list-wrapper .p-price strong{font-size:16px}.goods-list-wrapper .p-ext{-webkit-box-flex:1;-ms-flex:1;flex:1;text-align:right;font-size:12px}.my-swipe .van-swipe-item{color:#fff;font-size:20px;text-align:center;height:170px}.my-swipe .van-swipe-item img{width:100%;height:170px}.page-home{background-color:#eee}

File diff suppressed because one or more lines are too long

BIN
m/dist.zip Normal file

Binary file not shown.

BIN
m/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

Binary file not shown.

Binary file not shown.

BIN
m/img/logo_128.ad9f93ce.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

1
m/index.html Normal file
View File

@ -0,0 +1 @@
<!DOCTYPE html><html lang=en><head><meta charset=utf-8><meta http-equiv=X-UA-Compatible content="IE=edge"><meta name=viewport content="width=device-width,initial-scale=1"><link rel=icon href=/shop/m/favicon.ico><title>user-demo</title><link href=/shop/m/css/GoodsDetail.55089c51.css rel=prefetch><link href=/shop/m/css/GoodsList.e57b82fc.css rel=prefetch><link href=/shop/m/css/Login.86f4227f.css rel=prefetch><link href=/shop/m/js/Category.b617b409.js rel=prefetch><link href=/shop/m/js/GoodsDetail.6b467eb8.js rel=prefetch><link href=/shop/m/js/GoodsList.277cfefd.js rel=prefetch><link href=/shop/m/js/Login.87344a7c.js rel=prefetch><link href=/shop/m/css/app.5cd02139.css rel=preload as=style><link href=/shop/m/css/chunk-vendors.329e3d0a.css rel=preload as=style><link href=/shop/m/js/app.05ee882b.js rel=preload as=script><link href=/shop/m/js/chunk-vendors.0278963c.js rel=preload as=script><link href=/shop/m/css/chunk-vendors.329e3d0a.css rel=stylesheet><link href=/shop/m/css/app.5cd02139.css rel=stylesheet></head><body><noscript><strong>We're sorry but user-demo doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id=app></div><script src=/shop/m/js/chunk-vendors.0278963c.js></script><script src=/shop/m/js/app.05ee882b.js></script></body></html>

View File

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["Category"],{4886:function(t,e,n){"use strict";n.r(e);var a=function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{staticClass:"category",staticStyle:{display:"flex","flex-direction":"column",height:"calc(100vh - 50px)"}},[n("van-nav-bar",{attrs:{title:"标题","left-text":"返回","left-arrow":""},on:{"click-left":function(e){return t.$router.back()}},scopedSlots:t._u([{key:"title",fn:function(){return[n("van-search",{attrs:{placeholder:"请输入搜索关键词"},model:{value:t.searchValue,callback:function(e){t.searchValue=e},expression:"searchValue"}})]},proxy:!0}])}),n("van-tree-select",{staticStyle:{flex:"1"},attrs:{items:t.items,"active-id":t.activeId,"main-active-index":t.activeIndex},on:{"update:activeId":function(e){t.activeId=e},"update:active-id":function(e){t.activeId=e},"update:mainActiveIndex":function(e){t.activeIndex=e},"update:main-active-index":function(e){t.activeIndex=e},"click-item":t.onSelect}})],1)},c=[],i={name:"Category",data:function(){return{searchValue:"",items:[{text:"手机数码",children:[{text:"手机"},{text:"数据线"},{text:"充电宝"},{text:"耳机"}]},{text:"女装",children:[{text:"针织衫"},{text:"连衣裙"}]},{text:"电脑",children:[{text:"笔记本"},{text:"显卡"},{text:"硬盘"},{text:"SSD"}]},{text:"家用电器",children:[{text:"电视"},{text:"冰箱"},{text:"洗衣机"}]}],activeId:1,activeIndex:0}},mounted:function(){document.title="分类"},methods:{onSelect:function(t){this.$router.push("/goods-list?cate="+t.text)}}},l=i,r=n("2877"),o=Object(r["a"])(l,a,c,!1,null,null,null);e["default"]=o.exports}}]);
//# sourceMappingURL=Category.b617b409.js.map

View File

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["GoodsDetail"],{c84b:function(t,n,o){"use strict";o.r(n);var e=function(){var t=this,n=t.$createElement,o=t._self._c||n;return o("div",{staticClass:"page-detail"},[o("van-button",{staticClass:"btn-go-back",on:{click:function(n){return t.$router.back()}}},[o("van-icon",{staticClass:"iii",attrs:{name:"arrow-left"}})],1),o("div",{staticClass:"goods-detail"},[o("div",{staticClass:"g-image"},[o("img",{staticStyle:{width:"100%",display:"block"},attrs:{src:t.g.picture}})]),o("div",{staticClass:"g-info"},[o("div",{staticClass:"g-price"},[o("span",[t._v("¥")]),o("span",{staticClass:"v"},[t._v(t._s(t.g.sell_price))])]),o("div",{staticClass:"g-title"},[o("h1",[t._v(t._s(t.g.title))])]),o("div",{staticClass:"desc"},[t._v(t._s(t.g.desc))]),o("div",{staticStyle:{display:"flex",overflow:"hidden","background-color":"rgb(255, 255, 255)","padding-top":"10px","font-size":"14px",color:"#aaa","white-space":"nowrap","line-height":"17px"}},[t._m(0),o("div",{staticStyle:{flex:"1","text-align":"center"}},[o("span",[t._v("销量 "+t._s(t._f("fm")(t.g.sell_count)))])]),t._m(1)])]),o("van-coupon-cell",{attrs:{coupons:t.c.list,"chosen-coupon":t.c.chosen},on:{click:function(n){t.c.show=!0}}}),o("van-popup",{staticStyle:{height:"90%","padding-top":"4px"},attrs:{round:"",position:"bottom"},model:{value:t.c.show,callback:function(n){t.$set(t.c,"show",n)},expression:"c.show"}},[o("van-coupon-list",{attrs:{coupons:t.c.list,"chosen-coupon":t.c.chosen,"disabled-coupons":t.c.disabled,"show-exchange-bar":!1},on:{change:t.onChange}})],1),o("div",{staticStyle:{height:"50px"}})],1),o("van-goods-action",[o("van-goods-action-icon",{attrs:{icon:"chat-o",text:"客服"},on:{click:t.onClickIcon}}),o("van-goods-action-icon",{attrs:{icon:"cart-o",text:"购物车"},on:{click:function(n){return t.$router.push("/cart")}}}),o("van-goods-action-icon",{attrs:{icon:"shop-o",text:"店铺"},on:{click:t.onClickIcon}}),o("van-goods-action-button",{attrs:{color:"#be99ff",type:"danger",text:"加入购物车"},on:{click:t.buy}})],1)],1)},i=[function(){var t=this,n=t.$createElement,o=t._self._c||n;return o("div",{staticStyle:{flex:"1","text-align":"left"}},[o("span",[t._v("快递: 快递包邮")])])},function(){var t=this,n=t.$createElement,o=t._self._c||n;return o("div",{staticStyle:{flex:"1","text-align":"right"}},[o("span",[t._v("上海")])])}],s=o("495e"),a=o("2241"),c=o("f564"),l={available:1,condition:"无使用门槛\n满21元可以使用",reason:"",value:20,name:"满21减20元",startAt:1489104e3,endAt:1514592e3,valueDesc:"20",unitDesc:"元"},r={name:"GoodsDetail",data:function(){return{token:!1,id:"",loading:!1,c:{chosen:-1,show:!1,list:[l],disabled:[]},g:{title:"",picture:""}}},filters:{fm:function(t){return t?(t=parseInt(t),t>9999?(t/=1e4,t=t.toFixed(1),t+"万"):t):""}},mounted:function(){this.token=window.localStorage.getItem("gg_user_token"),this.id=this.$route.query.id,this.loadData()},methods:{onChange:function(t){},onExchange:function(t){},loadData:function(){var t=this;s["a"].shop.get("/goods?id="+this.id).then((function(n){document.title=n.title,t.g=n})).catch((function(n){a["a"].alert({title:"提示",message:n.message}).then((function(){t.$router.back()}))}))},onClickIcon:function(){},buy:function(){this.token?s["a"].shop.post("/cart/add",{token:this.token,goodsId:this.id,count:1}).then((function(t){Object(c["a"])({message:"添加到购物车成功",duration:3e3})})).catch((function(t){a["a"].alert({title:"提示",message:t.message}).then((function(){}))})):this.$router.push("/login?from="+this.$route.fullPath)}}},u=r,d=(o("d62f"),o("2877")),h=Object(d["a"])(u,e,i,!1,null,"3fd40480",null);n["default"]=h.exports},d62f:function(t,n,o){"use strict";o("f212")},f212:function(t,n,o){}}]);
//# sourceMappingURL=GoodsDetail.6b467eb8.js.map

View File

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["GoodsList"],{"0a2e":function(t,i,a){"use strict";a("65c5")},"65c5":function(t,i,a){},d2d3:function(t,i,a){"use strict";a.r(i);var e=function(){var t=this,i=t.$createElement,a=t._self._c||i;return a("div",{staticClass:"page-goods-list"},[a("van-nav-bar",{attrs:{title:t.category,fixed:!0,placeholder:!0,"left-text":"返回","left-arrow":""},on:{"click-left":function(i){return t.$router.back()}}}),a("div",{staticClass:"goods-list-wrapper"},t._l(t.dataList,(function(i){return a("div",{key:i.id},[a("van-card",{staticClass:"goods-item",attrs:{desc:i.desc,thumb:i.picture},on:{click:function(a){return t.showDetail(i)}},scopedSlots:t._u([{key:"title",fn:function(){return[a("div",{staticClass:"g-title"},[t._v(t._s(i.title))])]},proxy:!0},{key:"price",fn:function(){return[a("div",{staticClass:"g-info"},[a("div",{staticClass:"price"},[t._v("¥"),a("span",[t._v(t._s(i.sell_price))])]),a("div",{staticClass:"sell-info"},[a("span",[t._v(t._s(i.sell_count))]),t._v("人已经付款购买")])])]},proxy:!0}],null,!0)})],1)})),0)],1)},s=[],o=a("495e"),n={name:"GoodsList",data:function(){return{category:"",loading:!1,dataList:[],total:0,pageSize:15}},mounted:function(){this.category=this.$route.query.cate,document.title=this.category,this.loadData(1)},methods:{onPageChange:function(t){this.loadData(t)},showDetail:function(t){this.$router.push("/goods-detail?id="+t.id)},loadData:function(t){var i=this;this.loading=!0,o["a"].shop.get("/goods?list=y&page="+t+"&category="+this.category).then((function(t){i.loading=!1,i.dataList=t.list,i.total=t.total,i.pageSize=t.size})).catch((function(){i.loading=!1}))}}},c=n,l=(a("0a2e"),a("2877")),r=Object(l["a"])(c,e,s,!1,null,"fd40e072",null);i["default"]=r.exports}}]);
//# sourceMappingURL=GoodsList.277cfefd.js.map

2
m/js/Login.87344a7c.js Normal file
View File

@ -0,0 +1,2 @@
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([["Login"],{5402:function(e,t,a){},"65d8":function(e,t,a){"use strict";a("5402")},7856:function(e,t,a){e.exports=a.p+"img/logo_128.ad9f93ce.png"},a55b:function(e,t,a){"use strict";a.r(t);var n=function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("div",{staticClass:"page-login",staticStyle:{background:"#eee",height:"100vh"}},[a("van-nav-bar",{attrs:{title:"登录","left-text":"返回","left-arrow":""},on:{"click-left":function(t){return e.$router.back()}}}),e._m(0),a("van-form",{on:{submit:e.login}},[a("van-field",{attrs:{name:"username",label:"用户名",placeholder:"用户名",rules:[{required:!0,message:"请填写用户名"}]},model:{value:e.username,callback:function(t){e.username=t},expression:"username"}}),a("van-field",{attrs:{type:"password",name:"password",label:"密码",placeholder:"密码",rules:[{required:!0,message:"请填写密码"}]},model:{value:e.password,callback:function(t){e.password=t},expression:"password"}}),a("div",{staticStyle:{margin:"16px"}},[a("van-button",{attrs:{round:"",block:"",type:"info","native-type":"submit"}},[e._v("\r\n 提交\r\n ")])],1)],1),a("van-overlay",{attrs:{show:e.showLoading}},[a("div",{staticClass:"wrapper",on:{click:function(e){e.stopPropagation()}}},[a("div",{staticClass:"block"},[a("van-loading",{attrs:{size:"80"}})],1)])])],1)},s=[function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("div",{staticStyle:{padding:"10px","text-align":"center"}},[n("img",{attrs:{src:a("7856"),alt:""}})])}],o=a("495e"),r=a("2241"),i={name:"Login",data:function(){return{username:"",password:"",showLoading:!1}},methods:{login:function(){var e=this;this.showLoading=!0,o["a"].shop.post("/login",{username:this.username,password:this.password}).then((function(t){e.showLoading=!1,window.localStorage.setItem("gg_user_token",t.token),e.$router.back()})).catch((function(t){e.showLoading=!1,r["a"].alert({title:"提示",message:t.message}).then((function(){}))}))}}},l=i,c=(a("65d8"),a("2877")),u=Object(c["a"])(l,n,s,!1,null,"5890dc30",null);t["default"]=u.exports}}]);
//# sourceMappingURL=Login.87344a7c.js.map

2
m/js/app.05ee882b.js Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

23
route/app.php Normal file
View File

@ -0,0 +1,23 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2018 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
use think\facade\Route;
Route::get('/', 'index/index');
Route::get('/goods', 'index/goods');
Route::any('/login', 'index/login');
Route::any('/reg', 'index/reg');
Route::any('/cart/query', 'shop/queryCart');
Route::any('/cart/add', 'shop/addToCart');
Route::any('/cart/checkout', 'shop/checkout');
Route::any('/cart/update', 'shop/updateCart');
Route::any('/cart/remove', 'shop/removeCart');
Route::post('/add-goods', 'index/saveGoods');
Route::any('/orders', 'shop/queryOrder');

2
runtime/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
*
!.gitignore

1
start.sh Executable file
View File

@ -0,0 +1 @@
php think run -r api

10
think Normal file
View File

@ -0,0 +1,10 @@
#!/usr/bin/env php
<?php
namespace think;
// 命令行入口文件
// 加载基础文件
require __DIR__ . '/vendor/autoload.php';
// 应用初始化
(new App())->console->run();

1
view/README.md Normal file
View File

@ -0,0 +1 @@
如果不使用模板,可以删除该目录