init 全面去除全部3.0数据,重新构建4.0版本!

This commit is contained in:
zhaoxiang 2019-04-16 15:59:08 +08:00
parent f30fa65c1b
commit 4dfa7f1632
253 changed files with 1 additions and 47475 deletions

191
LICENSE
View File

@ -1,191 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction, and
distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by the copyright
owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all other entities
that control, are controlled by, or are under common control with that entity.
For the purposes of this definition, "control" means (i) the power, direct or
indirect, to cause the direction or management of such entity, whether by
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity exercising
permissions granted by this License.
"Source" form shall mean the preferred form for making modifications, including
but not limited to software source code, documentation source, and configuration
files.
"Object" form shall mean any form resulting from mechanical transformation or
translation of a Source form, including but not limited to compiled object code,
generated documentation, and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or Object form, made
available under the License, as indicated by a copyright notice that is included
in or attached to the work (an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object form, that
is based on (or derived from) the Work and for which the editorial revisions,
annotations, elaborations, or other modifications represent, as a whole, an
original work of authorship. For the purposes of this License, Derivative Works
shall not include works that remain separable from, or merely link (or bind by
name) to the interfaces of, the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including the original version
of the Work and any modifications or additions to that Work or Derivative Works
thereof, that is intentionally submitted to Licensor for inclusion in the Work
by the copyright owner or by an individual or Legal Entity authorized to submit
on behalf of the copyright owner. For the purposes of this definition,
"submitted" means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems, and
issue tracking systems that are managed by, or on behalf of, the Licensor for
the purpose of discussing and improving the Work, but excluding communication
that is conspicuously marked or otherwise designated in writing by the copyright
owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
of whom a Contribution has been received by Licensor and subsequently
incorporated within the Work.
2. Grant of Copyright License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the Work and such
Derivative Works in Source or Object form.
3. Grant of Patent License.
Subject to the terms and conditions of this License, each Contributor hereby
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
irrevocable (except as stated in this section) patent license to make, have
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
such license applies only to those patent claims licensable by such Contributor
that are necessarily infringed by their Contribution(s) alone or by combination
of their Contribution(s) with the Work to which such Contribution(s) was
submitted. If You institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
Contribution incorporated within the Work constitutes direct or contributory
patent infringement, then any patent licenses granted to You under this License
for that Work shall terminate as of the date such litigation is filed.
4. Redistribution.
You may reproduce and distribute copies of the Work or Derivative Works thereof
in any medium, with or without modifications, and in Source or Object form,
provided that You meet the following conditions:
You must give any other recipients of the Work or Derivative Works a copy of
this License; and
You must cause any modified files to carry prominent notices stating that You
changed the files; and
You must retain, in the Source form of any Derivative Works that You distribute,
all copyright, patent, trademark, and attribution notices from the Source form
of the Work, excluding those notices that do not pertain to any part of the
Derivative Works; and
If the Work includes a "NOTICE" text file as part of its distribution, then any
Derivative Works that You distribute must include a readable copy of the
attribution notices contained within such NOTICE file, excluding those notices
that do not pertain to any part of the Derivative Works, in at least one of the
following places: within a NOTICE text file distributed as part of the
Derivative Works; within the Source form or documentation, if provided along
with the Derivative Works; or, within a display generated by the Derivative
Works, if and wherever such third-party notices normally appear. The contents of
the NOTICE file are for informational purposes only and do not modify the
License. You may add Your own attribution notices within Derivative Works that
You distribute, alongside or as an addendum to the NOTICE text from the Work,
provided that such additional attribution notices cannot be construed as
modifying the License.
You may add Your own copyright statement to Your modifications and may provide
additional or different license terms and conditions for use, reproduction, or
distribution of Your modifications, or for any such Derivative Works as a whole,
provided Your use, reproduction, and distribution of the Work otherwise complies
with the conditions stated in this License.
5. Submission of Contributions.
Unless You explicitly state otherwise, any Contribution intentionally submitted
for inclusion in the Work by You to the Licensor shall be under the terms and
conditions of this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify the terms of
any separate license agreement you may have executed with Licensor regarding
such Contributions.
6. Trademarks.
This License does not grant permission to use the trade names, trademarks,
service marks, or product names of the Licensor, except as required for
reasonable and customary use in describing the origin of the Work and
reproducing the content of the NOTICE file.
7. Disclaimer of Warranty.
Unless required by applicable law or agreed to in writing, Licensor provides the
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
including, without limitation, any warranties or conditions of TITLE,
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
solely responsible for determining the appropriateness of using or
redistributing the Work and assume any risks associated with Your exercise of
permissions under this License.
8. Limitation of Liability.
In no event and under no legal theory, whether in tort (including negligence),
contract, or otherwise, unless required by applicable law (such as deliberate
and grossly negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special, incidental,
or consequential damages of any character arising as a result of this License or
out of the use or inability to use the Work (including but not limited to
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
any and all other commercial damages or losses), even if such Contributor has
been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability.
While redistributing the Work or Derivative Works thereof, You may choose to
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
other liability obligations and/or rights consistent with this License. However,
in accepting such obligations, You may act only on Your own behalf and on Your
sole responsibility, not on behalf of any other Contributor, and only if You
agree to indemnify, defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason of your
accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work
To apply the Apache License to your work, attach the following boilerplate
notice, with the fields enclosed by brackets "{}" replaced with your own
identifying information. (Don't include the brackets!) The text should be
enclosed in the appropriate comment syntax for the file format. We also
recommend that a file or class name and description of purpose be included on
the same "printed page" as the copyright notice for easier identification within
third-party archives.
Copyright 2018 Zhao
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -7,82 +7,4 @@
[![ApiAdmin](https://img.shields.io/badge/build-passing-brightgreen.svg)](http://www.apiadmin.org/)
[![ApiAdmin](https://img.shields.io/badge/ApiAdmin-v3.0.8-brightgreen.svg)](http://www.apiadmin.org/)
## 前端页面
ApiAdmin3.0是一个前后端完全分离的项目前端采用Vue构建如需要可视化配置的请移步[ApiAdmin-WEB](https://gitee.com/apiadmin/ApiAdmin-WEB)
## 灵 感
首先自我介绍下吧我是一个PHP程序员目前就职于某上市集团。我第一份工作是做微信开发的这也是我入行以来第一次做的商业上线项目虽然我只是充当了其中一个不是太重要的角色但是感谢它让我第一次接触了API也让我第一次对于API产生了浓厚的兴趣。之后的一段时间内甚至疯狂的收集过各种免费的API接口然而一直只是在用API却没有为API贡献过些什么。
开源框架用了很多开源代码看了很多github、git@osc、Stack Overflow这些优秀的平台帮助了我很多所以我觉得是时候为开源做点什么。更是给开源项目PhalApi贡献过代码也正是这一个契机使得我正式迈向开源社区。随着时间的推移PhalApi的战绩赫赫它的壮大更加坚定了Api的地位既然未来的互联网世界中API占了很重要的地位既然越来越多的人开始开发API那么无状态的API如何去管理呢因此**ApiAdmin**来了~
## 愿 景
> 希望有人用它,希望更多的人用它。
> 希望它能帮助到你,希望它能帮助到更多的你。
## 项目简介
**系统需求**
- PHP >= 5.6
- MySQL >= 5.5.3
- Redis
**项目构成**
- ThinkPHP v5.0.19
- Vue 2.0
- semanticUI
- ...
**功能简介**
1. 接口文档自动生成
2. 接口输入参数自动检查
3. 接口输出参数数据类型自动规整
4. 灵活的参数规则设定
5. 支持三方Api无缝融合
6. 本地二次开发友好
7. ...
```
ApiAdminPHP部分
├─ 系统维护
| ├─ 菜单管理 - 编辑访客权限,处理菜单父子关系,被权限系统依赖(极为重要)
| ├─ 用户管理 - 添加新用户,封号,删号以及给账号分配权限组
| ├─ 权限管理 - 权限组管理,给权限组添加权限,将用户提出权限组
| └─ 操作日志 - 记录管理员的操作,用于追责,回溯和备案
| ...
```
**页面截图**
![输入图片说明](https://gitee.com/uploads/images/2018/0224/095358_19cb42d0_110856.png "api.png")
![输入图片说明](https://gitee.com/uploads/images/2018/0224/095410_55dc23e1_110856.png "app.png")
![输入图片说明](https://gitee.com/uploads/images/2018/0224/095420_bddff990_110856.png "auth1.png")
![输入图片说明](https://gitee.com/uploads/images/2018/0224/095427_fa86e42d_110856.png "auth2.png")
![输入图片说明](https://gitee.com/uploads/images/2018/0224/095436_3600de17_110856.png "lock.png")
![输入图片说明](https://gitee.com/uploads/images/2018/0224/095444_d2a88da0_110856.png "user.png")
**项目特性**
- 开放源码
- 保持生机
- 不断更新
- 响应市场
**开源,我们在路上!**
## 鸣谢
ApiAdmin走到今天也正式迈入3.0时代了同时ApiAdmin也迎来了它的一岁生日我们怀着激动的心情迎来这次发布。在新版本发布之际我们真诚的感谢从1.0到2.0陪我们一路走来的朋友们。感谢你们的支持和信任!当然也感谢#开源中国#给大陆本土开源提供这样一个优秀的平台
## 附:升级指南
很抱歉的告诉大家虽然我们尽可能的和往期版本进行了兼容但是由于整体架构变化很大所以想要零成本升级有点困难。我们建议大家可以使用3.0做新接口慢慢的将2.0版本的接口移植到3.0。
# 感谢大家的支持当前项目正在进行ApiAdmin-4.0的开发ApiAdmin-3.0已被迁移至[ApiAdmin-3.0](https://gitee.com/apiadmin/ApiAdmin-3.0)。又一次颠覆性的升级。我们即将回归,敬请期待!

View File

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

View File

@ -1,52 +0,0 @@
<?php
/**
* 后台操作日志记录
* @since 2018-02-28
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\behavior;
use app\model\AdminMenu;
use app\model\AdminUserAction;
use app\util\ReturnCode;
use think\Request;
class AdminLog {
/**
* 后台操作日志记录
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return \think\response\Json
* @throws \think\Exception
* @throws \think\exception\DbException
*/
public function run() {
$header = config('apiAdmin.CROSS_DOMAIN');
$request = Request::instance();
$route = $request->routeInfo();
$ApiAuth = $request->header('ApiAuth', '');
$userInfo = cache('Login:' . $ApiAuth);
$userInfo = json_decode($userInfo, true);
$menuInfo = AdminMenu::get(['url' => $route['route']]);
if ($menuInfo) {
$menuInfo = $menuInfo->toArray();
} else {
$data = ['code' => ReturnCode::INVALID, 'msg' => '当前路由非法:'. $route['route'], 'data' => []];
return json($data, 200, $header);
}
AdminUserAction::create([
'actionName' => $menuInfo['name'],
'uid' => $userInfo['id'],
'nickname' => $userInfo['nickname'],
'addTime' => time(),
'url' => $route['route'],
'data' => json_encode($request->param())
]);
}
}

View File

@ -1,38 +0,0 @@
<?php
/**
* 处理Api接入认证
* @since 2017-07-25
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\behavior;
use app\util\ReturnCode;
use think\Request;
class ApiAuth {
/**
* 默认行为函数
* @return \think\response\Json
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function run() {
$request = Request::instance();
$header = config('apiAdmin.CROSS_DOMAIN');
$ApiAuth = $request->header('ApiAuth', '');
if ($ApiAuth) {
$userInfo = cache('Login:' . $ApiAuth);
$userInfo = json_decode($userInfo, true);
if (!$userInfo || !isset($userInfo['id'])) {
$data = ['code' => ReturnCode::AUTH_ERROR, 'msg' => 'ApiAuth不匹配', 'data' => []];
return json($data, 200, $header);
}
} else {
$data = ['code' => ReturnCode::AUTH_ERROR, 'msg' => '缺少ApiAuth', 'data' => []];
return json($data, 200, $header);
}
}
}

View File

@ -1,103 +0,0 @@
<?php
/**
* 处理后台接口请求权限
* @since 2017-07-25
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\behavior;
use app\model\AdminAuthGroup;
use app\model\AdminAuthGroupAccess;
use app\model\AdminAuthRule;
use app\util\ReturnCode;
use app\util\Tools;
use think\Request;
class ApiPermission {
/**
* 用户权限检测
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function run() {
$request = Request::instance();
$route = $request->routeInfo();
$header = config('apiAdmin.CROSS_DOMAIN');
$ApiAuth = $request->header('ApiAuth', '');
$userInfo = cache('Login:' . $ApiAuth);
$userInfo = json_decode($userInfo, true);
if (!$this->checkAuth($userInfo['id'], $route['route'])) {
$data = ['code' => ReturnCode::INVALID, 'msg' => '非常抱歉,您没有权限这么做!', 'data' => []];
return json($data, 200, $header);
}
}
/**
* 检测用户权限
* @param $uid
* @param $route
* @return bool
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
private function checkAuth($uid, $route) {
$isSupper = Tools::isAdministrator($uid);
if (!$isSupper) {
$rules = $this->getAuth($uid);
return in_array($route, $rules);
} else {
return true;
}
}
/**
* 根据用户ID获取全部权限节点
* @param $uid
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
private function getAuth($uid) {
$groups = AdminAuthGroupAccess::get(['uid' => $uid]);
if (isset($groups) && $groups->groupId) {
$openGroup = (new AdminAuthGroup())->whereIn('id', $groups->groupId)->where(['status' => 1])->select();
if (isset($openGroup)) {
$openGroupArr = [];
foreach ($openGroup as $group) {
$openGroupArr[] = $group->id;
}
$allRules = (new AdminAuthRule())->whereIn('groupId', $openGroupArr)->select();
if (isset($allRules)) {
$rules = [];
foreach ($allRules as $rule) {
$rules[] = $rule->url;
}
$rules = array_unique($rules);
return $rules;
} else {
return [];
}
} else {
return [];
}
} else {
return [];
}
}
}

View File

@ -1,26 +0,0 @@
<?php
/**
* 统一支持跨域
* @since 2017-07-25
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\behavior;
use think\Config;
use think\Response;
class BuildResponse {
/**
* 返回参数过滤(主要是将返回参数的数据类型给规范)
* @param $response
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function run(Response $response) {
$header = Config::get('apiAdmin.CROSS_DOMAIN');
$response->header($header);
}
}

View File

@ -1,224 +0,0 @@
<?php
/**
* 自动构建随机的Mock数据参考mockjs的配置
* @since 2018-08-23
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\behavior;
use app\util\ReturnCode;
use app\util\StrRandom;
use app\util\Strs;
use think\Config;
class Mock {
/**
* 拦截并且返回Mock数据
* @return \think\response\Json
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function run() {
$header = Config::get('apiAdmin.CROSS_DOMAIN');
$config = [
"myField|1-10" => "1",
"myNum|1-100" => 1,
"myFloat|1-100.1-10" => 1,
"myFa|123.1-10" => 1,
"myFb|123.3" => 1,
"object|2" => [
"name|1-3" => ['myName', 123123, '1231541asdasd', 'jjjjsssss', '2345123afasgvawe'],
"name2|2" => ['myName', 123123, '1231541asdasd', 'jjjjsssss', '2345123afasgvawe'],
'age|25-68' => 1
]
];
$data = $this->buildData($config);
$return = ['code' => ReturnCode::SUCCESS, 'msg' => '操作成功', 'data' => $data];
return json($return, 200, $header);
}
/**
* 构建随机数据
* @param $config
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
private function buildData($config) {
$data = [];
foreach ($config as $key => $value) {
$vType = gettype($value);
list($name, $rule) = explode('|', $key);
switch ($vType) {
case 'integer':
$data[$name] = $this->buildInt($rule);
break;
case 'array':
$data[$name] = $this->buildArray($rule, $value);
break;
case 'string':
$data[$name] = $this->buildString($rule);
break;
case 'double':
$data[$name] = $this->buildFloat($rule);
break;
case 'boolean':
break;
}
}
return $data;
}
/**
* 构建随机浮点数
* @param string $rule
* @return float|int
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
private function buildFloat($rule = '') {
$hasDot = strstr($rule, '.');
if (!$hasDot) {
return $this->buildInt($rule);
}
list($intPart, $floatPart) = explode('.', $rule);
$intVertical = strstr($intPart, '-');
if ($intVertical) {
list($intMin, $intMax) = explode('-', $intPart);
} else {
$intMin = $intMax = $intPart;
}
$floatVertical = strstr($floatPart, '-');
if ($floatVertical) {
list($floatMin, $floatMax) = explode('-', $floatPart);
} else {
$floatMin = $floatMax = $floatPart;
}
return StrRandom::randomFloat($intMin, $intMax, $floatMin, $floatMax);
}
/**
* 构建随机的整型数据
* @param string $rule
* @return float|integer
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
private function buildInt($rule = '') {
$hasDot = strstr($rule, '.');
if ($hasDot) {
return $this->buildFloat($rule);
}
$hasVertical = strstr($rule, '-');
if ($hasVertical) {
list($min, $max) = explode('-', $rule);
return mt_rand($min, $max);
} else {
return intval($rule);
}
}
/**
* 构建随机字符串
* @param string $rule
* @return string
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
private function buildString($rule = '') {
$hasVertical = strstr($rule, '-');
if ($hasVertical) {
list($minLen, $maxLen) = explode('-', $rule);
$len = mt_rand($minLen, $maxLen);
} else {
$len = $rule;
}
return Strs::randString($len);
}
/**
* 构建随机的数组列表数据
* @param string $rule
* @param array $value
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
private function buildArray($rule = '', $value = []) {
$isAssoc = $this->isAssoc($value);
if ($isAssoc) {
$has = strstr($rule, '-');
if ($has) {
list($min, $max) = explode('-', $rule);
$num = mt_rand($min, $max);
} else {
$num = intval($rule);
}
$res = [];
for ($i = 0; $i < $num; $i++) {
$new = [];
foreach ($value as $vKey => $item) {
$hasVertical = strstr($vKey, '|');
if ($hasVertical) {
$new = array_merge($new, $this->buildData([$vKey => $item]));
} else {
$new[$vKey] = $item;
}
}
$res[] = $new;
}
return $res;
} else {
$hasVertical = strstr($rule, '-');
if ($hasVertical) {
$new = [];
list($min, $max) = explode('-', $rule);
$num = mt_rand($min, $max);
for ($i = 0; $i < $num; $i++) {
$new = array_merge($new, $value);
}
return $new;
} else {
$rule = intval($rule);
if (count($value) <= $rule) {
return $value;
} else {
$new = [];
shuffle($value);
for ($i = 0; $i < $rule; $i++) {
$new[] = $value[$i];
}
return $new;
}
}
}
}
/**
* 判断是否是关联数组
* @param $array
* @return bool true 是关联数组 false 是索引数组
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
private function isAssoc($array) {
if (is_array($array)) {
$keys = array_keys($array);
return $keys !== array_keys($keys);
}
return false;
}
}

View File

@ -1,198 +0,0 @@
<?php
/**
* 应用管理
* @since 2018-02-11
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\controller;
use app\model\AdminApp;
use app\model\AdminList;
use app\model\AdminGroup;
use app\util\ReturnCode;
use app\util\Strs;
use app\util\Tools;
class App extends Base {
/**
* 获取应用列表
* @return array
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function index() {
$limit = $this->request->get('size', config('apiAdmin.ADMIN_LIST_DEFAULT'));
$start = $this->request->get('page', 1);
$keywords = $this->request->get('keywords', '');
$type = $this->request->get('type', '');
$status = $this->request->get('status', '');
$where = [];
if ($status === '1' || $status === '0') {
$where['app_status'] = $status;
}
if ($type) {
switch ($type) {
case 1:
$where['app_id'] = $keywords;
break;
case 2:
$where['app_name'] = ['like', "%{$keywords}%"];
break;
}
}
$listObj = (new AdminApp())->where($where)->order('app_addTime DESC')
->paginate($limit, false, ['page' => $start])->toArray();
return $this->buildSuccess([
'list' => $listObj['data'],
'count' => $listObj['total']
]);
}
/**
* 获取AppId,AppSecret,接口列表,应用接口权限细节
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
* @throws \think\Exception
* @throws \think\exception\DbException
*/
public function getAppInfo() {
$apiArr = AdminList::all();
foreach ($apiArr as $api) {
$res['apiList'][$api['groupHash']][] = $api;
}
$groupArr = AdminGroup::all();
$groupArr = Tools::buildArrFromObj($groupArr);
$res['groupInfo'] = array_column($groupArr, 'name', 'hash');
$id = $this->request->get('id', 0);
if ($id) {
$appInfo = AdminApp::get($id)->toArray();
$res['app_detail'] = json_decode($appInfo['app_api_show'], true);
} else {
$res['app_id'] = mt_rand(1, 9) . Strs::randString(7, 1);
$res['app_secret'] = Strs::randString(32);
}
return $this->buildSuccess($res);
}
/**
* 刷新APPSecret
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
*/
public function refreshAppSecret() {
$id = $this->request->get('id', 0);
$data['app_secret'] = Strs::randString(32);
if ($id) {
$res = AdminApp::update($data, ['id' => $id]);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
}
}
return $this->buildSuccess($data);
}
/**
* 新增应用
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function add() {
$postData = $this->request->post();
$data = [
'app_id' => $postData['app_id'],
'app_secret' => $postData['app_secret'],
'app_name' => $postData['app_name'],
'app_info' => $postData['app_info'],
'app_group' => $postData['app_group'],
'app_addTime' => time(),
'app_api' => '',
'app_api_show' => '',
];
if (isset($postData['app_api']) && $postData['app_api']) {
$appApi = [];
$data['app_api_show'] = json_encode($postData['app_api']);
foreach ($postData['app_api'] as $value) {
$appApi = array_merge($appApi, $value);
}
$data['app_api'] = implode(',', $appApi);
}
$res = AdminApp::create($data);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 应用状态编辑
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function changeStatus() {
$id = $this->request->get('id');
$status = $this->request->get('status');
$res = AdminApp::update([
'app_status' => $status
], [
'id' => $id
]);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 编辑应用
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function edit() {
$postData = $this->request->post();
$data = [
'app_name' => $postData['app_name'],
'app_info' => $postData['app_info'],
'app_group' => $postData['app_group'],
'app_api' => '',
'app_api_show' => '',
];
if (isset($postData['app_api']) && $postData['app_api']) {
$appApi = [];
$data['app_api_show'] = json_encode($postData['app_api']);
foreach ($postData['app_api'] as $value) {
$appApi = array_merge($appApi, $value);
}
$data['app_api'] = implode(',', $appApi);
}
$res = AdminApp::update($data, ['id' => $postData['id']]);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 删除应用
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function del() {
$id = $this->request->get('id');
if (!$id) {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少必要参数');
}
AdminApp::destroy($id);
return $this->buildSuccess([]);
}
}

View File

@ -1,137 +0,0 @@
<?php
/**
*
* @since 2018-02-11
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\controller;
use app\model\AdminApp;
use app\model\AdminAppGroup;
use app\util\ReturnCode;
use app\util\Tools;
class AppGroup extends Base {
/**
* 获取应用组列表
* @return array
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function index() {
$limit = $this->request->get('size', config('apiAdmin.ADMIN_LIST_DEFAULT'));
$start = $this->request->get('page', 1);
$keywords = $this->request->get('keywords', '');
$type = $this->request->get('type', '');
$status = $this->request->get('status', '');
$where = [];
if ($status === '1' || $status === '0') {
$where['status'] = $status;
}
if ($type) {
switch ($type) {
case 1:
$where['hash'] = $keywords;
break;
case 2:
$where['name'] = ['like', "%{$keywords}%"];
break;
}
}
$listObj = (new AdminAppGroup())->where($where)->paginate($limit, false, ['page' => $start])->toArray();
return $this->buildSuccess([
'list' => $listObj['data'],
'count' => $listObj['total']
]);
}
/**
* 获取全部有效的应用组
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getAll() {
$listInfo = (new AdminAppGroup())->where(['status' => 1])->select();
return $this->buildSuccess([
'list' => $listInfo
]);
}
/**
* 应用组状态编辑
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function changeStatus() {
$id = $this->request->get('id');
$status = $this->request->get('status');
$res = AdminAppGroup::update([
'status' => $status
], [
'id' => $id
]);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 添加应用组
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
*/
public function add() {
$postData = $this->request->post();
$res = AdminAppGroup::create($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 应用组编辑
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
*/
public function edit() {
$postData = $this->request->post();
$res = AdminAppGroup::update($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 应用组删除
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
*/
public function del() {
$hash = $this->request->get('hash');
if (!$hash) {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少必要参数');
}
$has = (new AdminApp())->where(['app_group' => $hash])->count();
if ($has) {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '当前分组存在' . $has . '个应用,禁止删除');
}
AdminAppGroup::destroy(['hash' => $hash]);
return $this->buildSuccess([]);
}
}

View File

@ -1,296 +0,0 @@
<?php
/**
* 权限相关配置
* @since 2018-02-06
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\controller;
use app\model\AdminAuthGroup;
use app\model\AdminAuthGroupAccess;
use app\model\AdminAuthRule;
use app\model\AdminMenu;
use app\util\ReturnCode;
use app\util\Tools;
class Auth extends Base {
/**
* 获取权限组列表
* @return array
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function index() {
$limit = $this->request->get('size', config('apiAdmin.ADMIN_LIST_DEFAULT'));
$start = $this->request->get('page', 1);
$keywords = $this->request->get('keywords', '');
$status = $this->request->get('status', '');
$where['name'] = ['like', "%{$keywords}%"];
if ($status === '1' || $status === '0') {
$where['status'] = $status;
}
$listObj = (new AdminAuthGroup())->where($where)->order('id DESC')
->paginate($limit, false, ['page' => $start])->toArray();
return $this->buildSuccess([
'list' => $listObj['data'],
'count' => $listObj['total']
]);
}
/**
* 获取全部已开放的可选组
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getGroups() {
$listInfo = (new AdminAuthGroup())->where(['status' => 1])->order('id', 'DESC')->select();
$count = count($listInfo);
$listInfo = Tools::buildArrFromObj($listInfo);
return $this->buildSuccess([
'list' => $listInfo,
'count' => $count
]);
}
/**
* 获取组所在权限列表
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function getRuleList() {
$groupId = $this->request->get('groupId', 0);
$list = (new AdminMenu)->where([])->order('sort', 'ASC')->select();
$list = Tools::buildArrFromObj($list);
$list = listToTree($list);
$rules = [];
if ($groupId) {
$rules = (new AdminAuthRule())->where(['groupId' => $groupId])->select();
$rules = Tools::buildArrFromObj($rules);
$rules = array_column($rules, 'url');
}
$newList = $this->buildList($list, $rules);
return $this->buildSuccess([
'list' => $newList
]);
}
/**
* 新增组
* @return array
* @throws \Exception
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function add() {
$rules = [];
$postData = $this->request->post();
if ($postData['rules']) {
$rules = $postData['rules'];
$rules = array_filter($rules);
}
unset($postData['rules']);
$res = AdminAuthGroup::create($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
if ($rules) {
$insertData = [];
foreach ($rules as $value) {
if ($value) {
$insertData[] = [
'groupId' => $res->id,
'url' => $value
];
}
}
(new AdminAuthRule())->saveAll($insertData);
}
return $this->buildSuccess([]);
}
}
/**
* 权限组状态编辑
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function changeStatus() {
$id = $this->request->get('id');
$status = $this->request->get('status');
$res = AdminAuthGroup::update([
'id' => $id,
'status' => $status
]);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 编辑用户
* @return array
* @throws \Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function edit() {
$postData = $this->request->post();
if ($postData['rules']) {
$this->editRule();
}
unset($postData['rules']);
$res = AdminAuthGroup::update($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 删除组
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function del() {
$id = $this->request->get('id');
if (!$id) {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少必要参数');
}
$listInfo = (new AdminAuthGroupAccess())->where(['groupId' => ['like', "%{$id}%"]])->select();
if ($listInfo) {
foreach ($listInfo as $value) {
$valueArr = $value->toArray();
$oldGroupArr = explode(',', $valueArr['groupId']);
$key = array_search($id, $oldGroupArr);
unset($oldGroupArr[$key]);
$newData = implode(',', $oldGroupArr);
$value->groupId = $newData;
$value->save();
}
}
AdminAuthGroup::destroy($id);
AdminAuthRule::destroy(['groupId' => $id]);
return $this->buildSuccess([]);
}
/**
* 从指定组中删除指定用户
* @return array
* @throws \think\Exception
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function delMember() {
$gid = $this->request->get('gid', 0);
$uid = $this->request->get('uid', 0);
if (!$gid || !$uid) {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少必要参数');
}
$oldInfo = AdminAuthGroupAccess::get(['uid' => $uid])->toArray();
$oldGroupArr = explode(',', $oldInfo['groupId']);
$key = array_search($gid, $oldGroupArr);
unset($oldGroupArr[$key]);
$newData = implode(',', $oldGroupArr);
$res = AdminAuthGroupAccess::update([
'groupId' => $newData
], [
'uid' => $uid
]);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 构建适用前端的权限数据
* @param $list
* @param $rules
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
private function buildList($list, $rules) {
$newList = [];
foreach ($list as $key => $value) {
$newList[$key]['title'] = $value['name'];
$newList[$key]['key'] = $value['url'];
if (isset($value['_child'])) {
$newList[$key]['expand'] = true;
$newList[$key]['children'] = $this->buildList($value['_child'], $rules);
} else {
if (in_array($value['url'], $rules)) {
$newList[$key]['checked'] = true;
}
}
}
return $newList;
}
/**
* 编辑权限细节
* @throws \Exception
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
private function editRule() {
$postData = $this->request->post();
$needAdd = [];
$has = (new AdminAuthRule())->where(['groupId' => $postData['id']])->select();
$has = Tools::buildArrFromObj($has);
$hasRule = array_column($has, 'url');
$needDel = array_flip($hasRule);
foreach ($postData['rules'] as $key => $value) {
if (!empty($value)) {
if (!in_array($value, $hasRule)) {
$data['url'] = $value;
$data['groupId'] = $postData['id'];
$needAdd[] = $data;
} else {
unset($needDel[$value]);
}
}
}
if (count($needAdd)) {
(new AdminAuthRule())->saveAll($needAdd);
}
if (count($needDel)) {
$urlArr = array_keys($needDel);
AdminAuthRule::destroy([
'groupId' => $postData['id'],
'url' => ['in', $urlArr]
]);
}
}
}

View File

@ -1,57 +0,0 @@
<?php
/**
* 工程基类
* @since 2017/02/28 创建
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\controller;
use app\util\ReturnCode;
use think\Controller;
class Base extends Controller {
private $debug = [];
protected $userInfo;
public function _initialize() {
$ApiAuth = $this->request->header('ApiAuth');
if ($ApiAuth) {
$userInfo = cache('Login:' . $ApiAuth);
$this->userInfo = json_decode($userInfo, true);
}
}
public function buildSuccess($data, $msg = '操作成功', $code = ReturnCode::SUCCESS) {
$return = [
'code' => $code,
'msg' => $msg,
'data' => $data
];
if ($this->debug) {
$return['debug'] = $this->debug;
}
return $return;
}
public function buildFailed($code, $msg, $data = []) {
$return = [
'code' => $code,
'msg' => $msg,
'data' => $data
];
if ($this->debug) {
$return['debug'] = $this->debug;
}
return $return;
}
protected function debug($data) {
if ($data) {
$this->debug[] = $data;
}
}
}

View File

@ -1,264 +0,0 @@
<?php
/**
* 接口输入输出字段维护
* @since 2018-02-21
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\controller;
use app\model\AdminFields;
use app\model\AdminList;
use app\util\DataType;
use app\util\ReturnCode;
use app\util\Tools;
class Fields extends Base {
private $dataType = array(
DataType::TYPE_INTEGER => 'Integer',
DataType::TYPE_STRING => 'String',
DataType::TYPE_BOOLEAN => 'Boolean',
DataType::TYPE_ENUM => 'Enum',
DataType::TYPE_FLOAT => 'Float',
DataType::TYPE_FILE => 'File',
DataType::TYPE_MOBILE => 'Mobile',
DataType::TYPE_OBJECT => 'Object',
DataType::TYPE_ARRAY => 'Array'
);
public function index() {
return $this->buildSuccess($this->dataType);
}
/**
* 获取请求参数
* @return array
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function request() {
$limit = $this->request->get('size', config('apiAdmin.ADMIN_LIST_DEFAULT'));
$start = $this->request->get('page', 1);
$hash = $this->request->get('hash', '');
if (!empty($hash)) {
$listObj = (new AdminFields())->where(['hash' => $hash, 'type' => 0])
->paginate($limit, false, ['page' => $start])->toArray();
return $this->buildSuccess([
'list' => $listObj['data'],
'count' => $listObj['total'],
'dataType' => $this->dataType
]);
} else {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少必要参数');
}
}
/**
* 获取返回参数
* @return array
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function response() {
$limit = $this->request->get('size', config('apiAdmin.ADMIN_LIST_DEFAULT'));
$start = $this->request->get('page', 1);
$hash = $this->request->get('hash', '');
if (!empty($hash)) {
$listObj = (new AdminFields())->where(['hash' => $hash, 'type' => 1])
->paginate($limit, false, ['page' => $start])->toArray();
return $this->buildSuccess([
'list' => $listObj['data'],
'count' => $listObj['total'],
'dataType' => $this->dataType
]);
} else {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少必要参数');
}
}
/**
* 新增字段
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
*/
public function add() {
$postData = $this->request->post();
$postData['showName'] = $postData['fieldName'];
$postData['default'] = $postData['defaults'];
unset($postData['defaults']);
$res = AdminFields::create($postData);
cache('RequestFields:NewRule:' . $postData['hash'], null);
cache('RequestFields:Rule:' . $postData['hash'], null);
cache('ResponseFieldsRule:' . $postData['hash'], null);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess('操作成功');
}
}
/**
* 字段编辑
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
*/
public function edit() {
$postData = $this->request->post();
$postData['showName'] = $postData['fieldName'];
$postData['default'] = $postData['defaults'];
unset($postData['defaults']);
$res = AdminFields::update($postData);
cache('RequestFields:NewRule:' . $postData['hash'], null);
cache('RequestFields:Rule:' . $postData['hash'], null);
cache('ResponseFieldsRule:' . $postData['hash'], null);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 字段删除
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
* @throws \think\exception\DbException
*/
public function del() {
$id = $this->request->get('id');
if (!$id) {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少必要参数');
}
$fieldsInfo = AdminFields::get($id);
cache('RequestFields:NewRule:' . $fieldsInfo->hash, null);
cache('RequestFields:Rule:' . $fieldsInfo->hash, null);
cache('ResponseFieldsRule:' . $fieldsInfo->hash, null);
AdminFields::destroy($id);
return $this->buildSuccess([]);
}
/**
* 批量上传返回字段
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function upload() {
$hash = $this->request->post('hash');
$type = $this->request->post('type');
$jsonStr = $this->request->post('jsonStr');
$jsonStr = html_entity_decode($jsonStr);
$data = json_decode($jsonStr, true);
if ($data === null) {
return $this->buildFailed(ReturnCode::EXCEPTION, 'JSON数据格式有误');
}
AdminList::update(['returnStr' => json_encode($data)], ['hash' => $hash]);
$this->handle($data['data'], $dataArr);
$old = (new AdminFields())->where([
'hash' => $hash,
'type' => $type
])->select();
$old = Tools::buildArrFromObj($old);
$oldArr = array_column($old, 'showName');
$newArr = array_column($dataArr, 'showName');
$addArr = array_diff($newArr, $oldArr);
$delArr = array_diff($oldArr, $newArr);
if ($delArr) {
AdminFields::destroy(['showName' => ['in', $delArr]]);
}
if ($addArr) {
$addData = [];
foreach ($dataArr as $item) {
if (in_array($item['showName'], $addArr)) {
$addData[] = $item;
}
}
(new AdminFields())->insertAll($addData);
}
cache('RequestFields:NewRule:' . $hash, null);
cache('RequestFields:Rule:' . $hash, null);
cache('ResponseFieldsRule:' . $hash, null);
return $this->buildSuccess([]);
}
private function handle($data, &$dataArr, $prefix = 'data', $index = 'data') {
if (!$this->isAssoc($data)) {
$addArr = array(
'fieldName' => $index,
'showName' => $prefix,
'hash' => $this->request->post('hash'),
'isMust' => 1,
'dataType' => DataType::TYPE_ARRAY,
'type' => $this->request->post('type')
);
$dataArr[] = $addArr;
$prefix .= '[]';
if (isset($data[0]) && is_array($data[0])) {
$this->handle($data[0], $dataArr, $prefix);
}
} else {
$addArr = array(
'fieldName' => $index,
'showName' => $prefix,
'hash' => $this->request->post('hash'),
'isMust' => 1,
'dataType' => DataType::TYPE_OBJECT,
'type' => $this->request->post('type')
);
$dataArr[] = $addArr;
$prefix .= '{}';
foreach ($data as $index => $datum) {
$myPre = $prefix . $index;
$addArr = array(
'fieldName' => $index,
'showName' => $myPre,
'hash' => $this->request->post('hash'),
'isMust' => 1,
'dataType' => DataType::TYPE_STRING,
'type' => $this->request->post('type')
);
if (is_numeric($datum)) {
if (preg_match('/^\d*$/', $datum)) {
$addArr['dataType'] = DataType::TYPE_INTEGER;
} else {
$addArr['dataType'] = DataType::TYPE_FLOAT;
}
$dataArr[] = $addArr;
} elseif (is_array($datum)) {
$this->handle($datum, $dataArr, $myPre, $index);
} else {
$addArr['dataType'] = DataType::TYPE_STRING;
$dataArr[] = $addArr;
}
}
}
}
/**
* 判断是否是关联数组true表示是关联数组
* @param array $arr
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return bool
*/
private function isAssoc(array $arr) {
if (array() === $arr) return false;
return array_keys($arr) !== range(0, count($arr) - 1);
}
}

View File

@ -1,53 +0,0 @@
<?php
namespace app\admin\controller;
use app\util\ReturnCode;
class Index extends Base {
public function index() {
return json(['welcome']);
}
public function upload() {
$path = '/upload/' . date('Ymd', time()) . '/';
$name = $_FILES['file']['name'];
$tmp_name = $_FILES['file']['tmp_name'];
$error = $_FILES['file']['error'];
//过滤错误
if ($error) {
switch ($error) {
case 1 :
$error_message = '您上传的文件超过了PHP.INI配置文件中UPLOAD_MAX-FILESIZE的大小';
break;
case 2 :
$error_message = '您上传的文件超过了PHP.INI配置文件中的post_max_size的大小';
break;
case 3 :
$error_message = '文件只被部分上传';
break;
case 4 :
$error_message = '文件不能为空';
break;
default :
$error_message = '未知错误';
}
die($error_message);
}
$arr_name = explode('.', $name);
$hz = array_pop($arr_name);
$new_name = md5(time() . uniqid()) . '.' . $hz;
if (!file_exists($_SERVER['DOCUMENT_ROOT'] . $path)) {
mkdir($_SERVER['DOCUMENT_ROOT'] . $path, 0755, true);
}
if (move_uploaded_file($tmp_name, $_SERVER['DOCUMENT_ROOT'] . $path . $new_name)) {
return $this->buildSuccess([
'fileName' => $new_name,
'fileUrl' => $this->request->domain() . $path . $new_name
]);
} else {
return $this->buildFailed(ReturnCode::FILE_SAVE_ERROR, '文件上传失败');
}
}
}

View File

@ -1,160 +0,0 @@
<?php
/**
* 接口组维护
* @since 2018-02-11
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\controller;
use app\model\AdminApp;
use app\model\AdminGroup;
use app\model\AdminList;
use app\util\ReturnCode;
use app\util\Tools;
class InterfaceGroup extends Base {
/**
* 获取接口组列表
* @return array
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function index() {
$limit = $this->request->get('size', config('apiAdmin.ADMIN_LIST_DEFAULT'));
$start = $this->request->get('page', 1);
$keywords = $this->request->get('keywords', '');
$type = $this->request->get('type', '');
$status = $this->request->get('status', '');
$where = [];
if ($status === '1' || $status === '0') {
$where['status'] = $status;
}
if ($type) {
switch ($type) {
case 1:
$where['hash'] = $keywords;
break;
case 2:
$where['name'] = ['like', "%{$keywords}%"];
break;
}
}
$listObj = (new AdminGroup())->where($where)->paginate($limit, false, ['page' => $start])->toArray();
return $this->buildSuccess([
'list' => $listObj['data'],
'count' => $listObj['total']
]);
}
/**
* 获取全部有效的接口组
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
*/
public function getAll() {
$listInfo = (new AdminGroup())->where(['status' => 1])->select();
return $this->buildSuccess([
'list' => $listInfo
]);
}
/**
* 接口组状态编辑
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function changeStatus() {
$id = $this->request->get('id');
$status = $this->request->get('status');
$res = AdminGroup::update([
'status' => $status
], [
'id' => $id
]);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 添加接口组
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
*/
public function add() {
$postData = $this->request->post();
$postData['addTime'] = $postData['updateTime'] = time();
$res = AdminGroup::create($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 接口组编辑
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
*/
public function edit() {
$postData = $this->request->post();
$postData['updateTime'] = time();
$res = AdminGroup::update($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 接口组删除
* @return array
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function del() {
$hash = $this->request->get('hash');
if (!$hash) {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少必要参数');
}
if ($hash === 'default') {
return $this->buildFailed(ReturnCode::INVALID, '系统预留关键数据,禁止删除!');
}
AdminList::update(['groupHash' => 'default'], ['groupHash' => $hash]);
$hashRule = AdminApp::all([
'app_api_show' => ['like', "%$hash%"]
]);
if ($hashRule) {
foreach ($hashRule as $rule) {
$appApiShowArr = json_decode($rule->app_api_show, true);
if (!empty($appApiShowArr[$hash])) {
if (isset($appApiShowArr['default'])) {
$appApiShowArr['default'] = array_merge($appApiShowArr['default'], $appApiShowArr[$hash]);
} else {
$appApiShowArr['default'] = $appApiShowArr[$hash];
}
}
unset($appApiShowArr[$hash]);
$rule->app_api_show = json_encode($appApiShowArr);
$rule->save();
}
}
AdminGroup::destroy(['hash' => $hash]);
return $this->buildSuccess([]);
}
}

View File

@ -1,194 +0,0 @@
<?php
/**
* 接口管理
* @since 2018-02-11
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\controller;
use app\model\AdminApp;
use app\model\AdminFields;
use app\model\AdminList;
use app\util\ReturnCode;
use app\util\Tools;
class InterfaceList extends Base {
/**
* 获取接口列表
* @return array
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function index() {
$limit = $this->request->get('size', config('apiAdmin.ADMIN_LIST_DEFAULT'));
$start = $this->request->get('page', 1);
$keywords = $this->request->get('keywords', '');
$type = $this->request->get('type', '');
$status = $this->request->get('status', '');
$where = [];
if ($status === '1' || $status === '0') {
$where['status'] = $status;
}
if ($type) {
switch ($type) {
case 1:
$where['hash'] = $keywords;
break;
case 2:
$where['info'] = ['like', "%{$keywords}%"];
break;
case 3:
$where['apiClass'] = ['like', "%{$keywords}%"];
break;
}
}
$listObj = (new AdminList())->where($where)->order('id', 'DESC')
->paginate($limit, false, ['page' => $start])->toArray();
return $this->buildSuccess([
'list' => $listObj['data'],
'count' => $listObj['total']
]);
}
/**
* 获取接口唯一标识
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
*/
public function getHash() {
$res['hash'] = uniqid();
return $this->buildSuccess($res);
}
/**
* 新增接口
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function add() {
$postData = $this->request->post();
if (!preg_match("/^[A-Za-z0-9_\/]+$/", $postData['apiClass'])) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '真实类名只允许填写字母,数字和/');
}
$res = AdminList::create($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 接口状态编辑
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function changeStatus() {
$hash = $this->request->get('hash');
$status = $this->request->get('status');
$res = AdminList::update([
'status' => $status
], [
'hash' => $hash
]);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
cache('ApiInfo:' . $hash, null);
return $this->buildSuccess([]);
}
}
/**
* 编辑接口
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function edit() {
$postData = $this->request->post();
if (!preg_match("/^[A-Za-z0-9_\/]+$/", $postData['apiClass'])) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '真实类名只允许填写字母,数字和/');
}
$res = AdminList::update($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
cache('ApiInfo:' . $postData['hash'], null);
return $this->buildSuccess([]);
}
}
/**
* 删除接口
* @return array
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function del() {
$hash = $this->request->get('hash');
if (!$hash) {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少必要参数');
}
$hashRule = AdminApp::all([
'app_api' => ['like', "%$hash%"]
]);
if ($hashRule) {
$oldInfo = AdminList::get(['hash' => $hash]);
foreach ($hashRule as $rule) {
$appApiArr = explode(',', $rule->app_api);
$appApiIndex = array_search($hash, $appApiArr);
array_splice($appApiArr, $appApiIndex, 1);
$rule->app_api = implode(',', $appApiArr);
$appApiShowArrOld = json_decode($rule->app_api_show, true);
$appApiShowArr = $appApiShowArrOld[$oldInfo->groupHash];
$appApiShowIndex = array_search($hash, $appApiShowArr);
array_splice($appApiShowArr, $appApiShowIndex, 1);
$appApiShowArrOld[$oldInfo->groupHash] = $appApiShowArr;
$rule->app_api_show = json_encode($appApiShowArrOld);
$rule->save();
}
}
AdminList::destroy(['hash' => $hash]);
AdminFields::destroy(['hash' => $hash]);
cache('ApiInfo:' . $hash, null);
return $this->buildSuccess([]);
}
/**
* 刷新接口路由
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
* @throws \think\exception\DbException
*/
public function refresh() {
$apiRoutePath = ROOT_PATH . 'application/apiRoute.php';
$tplPath = ROOT_PATH . 'data/apiRoute.tpl';
$methodArr = ['*', 'POST', 'GET'];
$tplStr = file_get_contents($tplPath);
$listInfo = AdminList::all(['status' => 1]);
foreach ($listInfo as $value) {
$tplStr .= 'Route::rule(\'api/' . addslashes($value->hash) . '\',\'api/' . addslashes($value->apiClass) . '\', \'' . $methodArr[$value->method] . '\', [\'after_behavior\' => $afterBehavior]);';
}
file_put_contents($apiRoutePath, $tplStr);
return $this->buildSuccess([]);
}
}

View File

@ -1,72 +0,0 @@
<?php
/**
* 后台操作日志管理
* @since 2018-02-06
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\controller;
use app\model\AdminAuthGroupAccess;
use app\model\AdminUser;
use app\model\AdminUserAction;
use app\model\AdminUserData;
use app\util\ReturnCode;
use app\util\Tools;
class Log extends Base {
/**
* 获取操作日志列表
* @return array
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function index() {
$limit = $this->request->get('size', config('apiAdmin.ADMIN_LIST_DEFAULT'));
$start = $this->request->get('page', 1);
$type = $this->request->get('type', '');
$keywords = $this->request->get('keywords', '');
$where = [];
if ($type) {
switch ($type) {
case 1:
$where['url'] = ['like', "%{$keywords}%"];
break;
case 2:
$where['nickname'] = ['like', "%{$keywords}%"];
break;
case 3:
$where['uid'] = $keywords;
break;
}
}
$listObj = (new AdminUserAction())->where($where)->order('addTime DESC')
->paginate($limit, false, ['page' => $start])->toArray();
return $this->buildSuccess([
'list' => $listObj['data'],
'count' => $listObj['total']
]);
}
/**
* 删除日志
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function del() {
$id = $this->request->get('id');
if (!$id) {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少必要参数');
}
AdminUserAction::destroy($id);
return $this->buildSuccess([]);
}
}

View File

@ -1,101 +0,0 @@
<?php
/**
* 登录登出
* @since 2017-11-02
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\controller;
use app\model\AdminAuthGroupAccess;
use app\model\AdminAuthRule;
use app\model\AdminMenu;
use app\model\AdminUser;
use app\model\AdminUserData;
use app\util\ReturnCode;
use app\util\Tools;
class Login extends Base {
/**
* 用户登录
* @return array
* @throws \think\Exception
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function index() {
$username = $this->request->post('username');
$password = $this->request->post('password');
if (!$username) {
return $this->buildFailed(ReturnCode::LOGIN_ERROR, '缺少用户名!');
}
if (!$password) {
return $this->buildFailed(ReturnCode::LOGIN_ERROR, '缺少密码!');
} else {
$password = Tools::userMd5($password);
}
$userInfo = AdminUser::get(['username' => $username, 'password' => $password]);
if (!empty($userInfo)) {
if ($userInfo['status']) {
//更新用户数据
$userData = AdminUserData::get(['uid' => $userInfo['id']]);
$data = [];
if ($userData) {
$userData->loginTimes ++;
$userData->lastLoginIp = $this->request->ip(1);
$userData->lastLoginTime = time();
$return['headImg'] = $userData['headImg'];
$userData->save();
} else {
$data['loginTimes'] = 1;
$data['uid'] = $userInfo['id'];
$data['lastLoginIp'] = $this->request->ip(1);
$data['lastLoginTime'] = time();
$data['headImg'] = '';
$return['headImg'] = '';
AdminUserData::create($data);
}
} else {
return $this->buildFailed(ReturnCode::LOGIN_ERROR, '用户已被封禁,请联系管理员');
}
} else {
return $this->buildFailed(ReturnCode::LOGIN_ERROR, '用户名密码不正确');
}
$apiAuth = md5(uniqid() . time());
cache('Login:' . $apiAuth, json_encode($userInfo), config('apiAdmin.ONLINE_TIME'));
cache('Login:' . $userInfo['id'], $apiAuth, config('apiAdmin.ONLINE_TIME'));
$return['access'] = [];
$isSupper = Tools::isAdministrator($userInfo['id']);
if ($isSupper) {
$access = AdminMenu::all(['hide' => 0]);
$access = Tools::buildArrFromObj($access);
$return['access'] = array_values(array_filter(array_column($access, 'url')));
} else {
$groups = AdminAuthGroupAccess::get(['uid' => $userInfo['id']]);
if (isset($groups) || $groups->groupId) {
$access = (new AdminAuthRule())->whereIn('groupId', $groups->groupId)->select();
$access = Tools::buildArrFromObj($access);
$return['access'] = array_values(array_unique(array_column($access, 'url')));
}
}
$return['id'] = $userInfo['id'];
$return['username'] = $userInfo['username'];
$return['nickname'] = $userInfo['nickname'];
$return['apiAuth'] = $apiAuth;
return $this->buildSuccess($return, '登录成功');
}
public function logout() {
$ApiAuth = $this->request->header('ApiAuth');
cache('Login:' . $ApiAuth, null);
cache('Login:' . $this->userInfo['id'], null);
return $this->buildSuccess([], '登出成功');
}
}

View File

@ -1,108 +0,0 @@
<?php
/**
* 目录管理
* @since 2018-01-16
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\controller;
use app\model\AdminMenu;
use app\util\ReturnCode;
use app\util\Tools;
class Menu extends Base {
/**
* 获取菜单列表
* @return array
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function index() {
$list = (new AdminMenu)->where([])->order('sort', 'ASC')->select();
$list = Tools::buildArrFromObj($list);
$list = formatTree(listToTree($list));
return $this->buildSuccess([
'list' => $list
], '登录成功');
}
/**
* 新增菜单
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function add() {
$postData = $this->request->post();
if ($postData['url']) {
$postData['url'] = 'admin/' . $postData['url'];
}
$res = AdminMenu::create($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 菜单状态编辑
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function changeStatus() {
$id = $this->request->get('id');
$status = $this->request->get('status');
$res = AdminMenu::update([
'id' => $id,
'hide' => $status
]);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 编辑菜单
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function edit() {
$postData = $this->request->post();
if ($postData['url']) {
$postData['url'] = 'admin/' . $postData['url'];
}
$res = AdminMenu::update($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 删除菜单
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function del() {
$id = $this->request->get('id');
if (!$id) {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少必要参数');
}
$childNum = AdminMenu::where(['fid' => $id])->count();
if ($childNum) {
return $this->buildFailed(ReturnCode::INVALID, '当前菜单存在子菜单,不可以被删除!');
} else {
AdminMenu::destroy($id);
return $this->buildSuccess([]);
}
}
}

View File

@ -1,15 +0,0 @@
<?php
namespace app\admin\controller;
use app\util\ReturnCode;
use think\Request;
class Miss extends Base {
public function index() {
if (Request::instance()->isOptions()) {
return $this->buildSuccess([]);
} else {
return $this->buildFailed(ReturnCode::INVALID, '接口地址异常', []);
}
}
}

View File

@ -1,269 +0,0 @@
<?php
/**
* 用户管理
* @since 2018-02-06
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\admin\controller;
use app\model\AdminAuthGroupAccess;
use app\model\AdminUser;
use app\model\AdminUserData;
use app\util\ReturnCode;
use app\util\Tools;
use think\Db;
class User extends Base {
/**
* 获取用户列表
* @return array
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function index() {
$limit = $this->request->get('size', config('apiAdmin.ADMIN_LIST_DEFAULT'));
$start = $this->request->get('page', 1);
$type = $this->request->get('type', '');
$keywords = $this->request->get('keywords', '');
$status = $this->request->get('status', '');
$where = [];
if ($status === '1' || $status === '0') {
$where['status'] = $status;
}
if ($type) {
switch ($type) {
case 1:
$where['username'] = ['like', "%{$keywords}%"];
break;
case 2:
$where['nickname'] = ['like', "%{$keywords}%"];
break;
}
}
$listObj = (new AdminUser())->where($where)->order('regTime DESC')
->paginate($limit, false, ['page' => $start])->toArray();
$listInfo = $listObj['data'];
$idArr = array_column($listInfo, 'id');
$userData = AdminUserData::all(function($query) use ($idArr) {
$query->whereIn('uid', $idArr);
});
$userData = Tools::buildArrFromObj($userData);
$userData = Tools::buildArrByNewKey($userData, 'uid');
$userGroup = AdminAuthGroupAccess::all(function($query) use ($idArr) {
$query->whereIn('uid', $idArr);
});
$userGroup = Tools::buildArrFromObj($userGroup);
$userGroup = Tools::buildArrByNewKey($userGroup, 'uid');
foreach ($listInfo as $key => $value) {
if (isset($userData[$value['id']])) {
$listInfo[$key]['lastLoginIp'] = long2ip($userData[$value['id']]['lastLoginIp']);
$listInfo[$key]['loginTimes'] = $userData[$value['id']]['loginTimes'];
$listInfo[$key]['lastLoginTime'] = date('Y-m-d H:i:s', $userData[$value['id']]['lastLoginTime']);
}
$listInfo[$key]['regIp'] = long2ip($listInfo[$key]['regIp']);
if (isset($userGroup[$value['id']])) {
$listInfo[$key]['groupId'] = explode(',', $userGroup[$value['id']]['groupId']);
} else {
$listInfo[$key]['groupId'] = [];
}
}
return $this->buildSuccess([
'list' => $listInfo,
'count' => $listObj['total']
]);
}
/**
* 新增用户
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function add() {
$groups = '';
$postData = $this->request->post();
$postData['regIp'] = request()->ip(1);
$postData['regTime'] = time();
$postData['password'] = Tools::userMd5($postData['password']);
if ($postData['groupId']) {
$groups = trim(implode(',', $postData['groupId']), ',');
}
unset($postData['groupId']);
$res = AdminUser::create($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
AdminAuthGroupAccess::create([
'uid' => $res->id,
'groupId' => $groups
]);
return $this->buildSuccess([]);
}
}
/**
* 获取当前组的全部用户
* @return array
* @throws \think\Exception
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function getUsers() {
$limit = $this->request->get('size', config('apiAdmin.ADMIN_LIST_DEFAULT'));
$page = $this->request->get('page', 1);
$gid = $this->request->get('gid', 0);
if (!$gid) {
return $this->buildFailed(ReturnCode::PARAM_INVALID, '非法操作');
}
$totalNum = (new AdminAuthGroupAccess())->where('find_in_set("' . $gid . '", `groupId`)')->count();
$start = $limit * ($page - 1);
$sql = "SELECT au.* FROM admin_user as au LEFT JOIN admin_auth_group_access as aaga " .
" ON aaga.`uid` = au.`id` WHERE find_in_set('{$gid}', aaga.`groupId`) " .
" ORDER BY au.regTime DESC LIMIT {$start}, {$limit}";
$userInfo = Db::query($sql);
$uidArr = array_column($userInfo, 'id');
$userData = (new AdminUserData())->whereIn('uid', $uidArr)->select();
$userData = Tools::buildArrByNewKey($userData, 'uid');
foreach ($userInfo as $key => $value) {
if (isset($userData[$value['id']])) {
$userInfo[$key]['lastLoginIp'] = long2ip($userData[$value['id']]['lastLoginIp']);
$userInfo[$key]['loginTimes'] = $userData[$value['id']]['loginTimes'];
$userInfo[$key]['lastLoginTime'] = date('Y-m-d H:i:s', $userData[$value['id']]['lastLoginTime']);
}
$userInfo[$key]['regIp'] = long2ip($userInfo[$key]['regIp']);
}
return $this->buildSuccess([
'list' => $userInfo,
'count' => $totalNum
]);
}
/**
* 用户状态编辑
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function changeStatus() {
$id = $this->request->get('id');
$status = $this->request->get('status');
$res = AdminUser::update([
'id' => $id,
'status' => $status,
'updateTime' => time()
]);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
return $this->buildSuccess([]);
}
}
/**
* 编辑用户
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
* @throws \think\exception\DbException
*/
public function edit() {
$groups = '';
$postData = $this->request->post();
if ($postData['password'] === 'ApiAdmin') {
unset($postData['password']);
} else {
$postData['password'] = Tools::userMd5($postData['password']);
}
if ($postData['groupId']) {
$groups = trim(implode(',', $postData['groupId']), ',');
}
$postData['updateTime'] = time();
unset($postData['groupId']);
$res = AdminUser::update($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
$has = AdminAuthGroupAccess::get(['uid' => $postData['id']]);
if ($has) {
AdminAuthGroupAccess::update([
'groupId' => $groups
], [
'uid' => $postData['id'],
]);
} else {
AdminAuthGroupAccess::create([
'uid' => $postData['id'],
'groupId' => $groups
]);
}
return $this->buildSuccess([]);
}
}
/**
* 修改自己的信息
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
* @throws \think\exception\DbException
*/
public function own() {
$postData = $this->request->post();
$headImg = $postData['headImg'];
if ($postData['password'] && $postData['oldPassword']) {
$oldPass = Tools::userMd5($postData['oldPassword']);
unset($postData['oldPassword']);
if ($oldPass === $this->userInfo['password']) {
$postData['password'] = Tools::userMd5($postData['password']);
} else {
return $this->buildFailed(ReturnCode::INVALID, '原始密码不正确');
}
} else {
unset($postData['password']);
unset($postData['oldPassword']);
}
$postData['id'] = $this->userInfo['id'];
$postData['updateTime'] = time();
unset($postData['headImg']);
$res = AdminUser::update($postData);
if ($res === false) {
return $this->buildFailed(ReturnCode::DB_SAVE_ERROR, '操作失败');
} else {
$userData = AdminUserData::get(['uid' => $postData['id']]);
$userData->headImg = $headImg;
$userData->save();
return $this->buildSuccess([]);
}
}
/**
* 删除用户
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function del() {
$id = $this->request->get('id');
if (!$id) {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少必要参数');
}
AdminUser::destroy($id);
AdminAuthGroupAccess::destroy(['uid' => $id]);
return $this->buildSuccess([]);
}
}

View File

@ -1,18 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用行为扩展定义文件
return [
// 输出结束
'response_send' => [
'app\\admin\\behavior\\BuildResponse',
],
];

View File

@ -1,279 +0,0 @@
<?php
use think\Route;
$afterBehavior = [
'\app\admin\behavior\ApiAuth',
'\app\admin\behavior\ApiPermission',
'\app\admin\behavior\AdminLog'
];
Route::group('admin', function () use ($afterBehavior) {
//一些带有特殊参数的路由写到这里
Route::rule([
'Login/index' => [
'admin/Login/index',
['method' => 'post']
],
'Index/upload' => [
'admin/Index/upload',
[
'method' => 'post',
'after_behavior' => [
'\app\admin\behavior\ApiAuth',
'\app\admin\behavior\AdminLog'
]
]
],
'Login/logout' => [
'admin/Login/logout',
[
'method' => 'get',
'after_behavior' => [
'\app\admin\behavior\ApiAuth',
'\app\admin\behavior\AdminLog'
]
]
]
]);
//大部分控制器的路由都以分组的形式写到这里
Route::group('Menu', [
'index' => [
'admin/Menu/index',
['method' => 'get']
],
'changeStatus' => [
'admin/Menu/changeStatus',
['method' => 'get']
],
'add' => [
'admin/Menu/add',
['method' => 'post']
],
'edit' => [
'admin/Menu/edit',
['method' => 'post']
],
'del' => [
'admin/Menu/del',
['method' => 'get']
]
], ['after_behavior' => $afterBehavior]);
Route::group('User', [
'index' => [
'admin/User/index',
['method' => 'get']
],
'getUsers' => [
'admin/User/getUsers',
['method' => 'get']
],
'changeStatus' => [
'admin/User/changeStatus',
['method' => 'get']
],
'add' => [
'admin/User/add',
['method' => 'post']
],
'own' => [
'admin/User/own',
['method' => 'post']
],
'edit' => [
'admin/User/edit',
['method' => 'post']
],
'del' => [
'admin/User/del',
['method' => 'get']
],
], ['after_behavior' => $afterBehavior]);
Route::group('Auth', [
'index' => [
'admin/Auth/index',
['method' => 'get']
],
'changeStatus' => [
'admin/Auth/changeStatus',
['method' => 'get']
],
'add' => [
'admin/Auth/add',
['method' => 'post']
],
'delMember' => [
'admin/Auth/delMember',
['method' => 'get']
],
'edit' => [
'admin/Auth/edit',
['method' => 'post']
],
'del' => [
'admin/Auth/del',
['method' => 'get']
],
'getGroups' => [
'admin/Auth/getGroups',
['method' => 'get']
],
'getRuleList' => [
'admin/Auth/getRuleList',
['method' => 'get']
]
], ['after_behavior' => $afterBehavior]);
Route::group('App', [
'index' => [
'admin/App/index',
['method' => 'get']
],
'refreshAppSecret' => [
'admin/App/refreshAppSecret',
['method' => 'get']
],
'changeStatus' => [
'admin/App/changeStatus',
['method' => 'get']
],
'add' => [
'admin/App/add',
['method' => 'post']
],
'getAppInfo' => [
'admin/App/getAppInfo',
['method' => 'get']
],
'edit' => [
'admin/App/edit',
['method' => 'post']
],
'del' => [
'admin/App/del',
['method' => 'get']
]
], ['after_behavior' => $afterBehavior]);
Route::group('InterfaceList', [
'index' => [
'admin/InterfaceList/index',
['method' => 'get']
],
'changeStatus' => [
'admin/InterfaceList/changeStatus',
['method' => 'get']
],
'add' => [
'admin/InterfaceList/add',
['method' => 'post']
],
'refresh' => [
'admin/InterfaceList/refresh',
['method' => 'get']
],
'edit' => [
'admin/InterfaceList/edit',
['method' => 'post']
],
'del' => [
'admin/InterfaceList/del',
['method' => 'get']
],
'getHash' => [
'admin/InterfaceList/getHash',
['method' => 'get']
]
], ['after_behavior' => $afterBehavior]);
Route::group('Fields', [
'index' => [
'admin/Fields/index',
['method' => 'get']
],
'request' => [
'admin/Fields/request',
['method' => 'get']
],
'add' => [
'admin/Fields/add',
['method' => 'post']
],
'response' => [
'admin/Fields/response',
['method' => 'get']
],
'edit' => [
'admin/Fields/edit',
['method' => 'post']
],
'del' => [
'admin/Fields/del',
['method' => 'get']
],
'upload' => [
'admin/Fields/upload',
['method' => 'post']
]
], ['after_behavior' => $afterBehavior]);
Route::group('InterfaceGroup', [
'index' => [
'admin/InterfaceGroup/index',
['method' => 'get']
],
'getAll' => [
'admin/InterfaceGroup/getAll',
['method' => 'get']
],
'add' => [
'admin/InterfaceGroup/add',
['method' => 'post']
],
'changeStatus' => [
'admin/InterfaceGroup/changeStatus',
['method' => 'get']
],
'edit' => [
'admin/InterfaceGroup/edit',
['method' => 'post']
],
'del' => [
'admin/InterfaceGroup/del',
['method' => 'get']
]
], ['after_behavior' => $afterBehavior]);
Route::group('AppGroup', [
'index' => [
'admin/AppGroup/index',
['method' => 'get']
],
'getAll' => [
'admin/AppGroup/getAll',
['method' => 'get']
],
'add' => [
'admin/AppGroup/add',
['method' => 'post']
],
'changeStatus' => [
'admin/AppGroup/changeStatus',
['method' => 'get']
],
'edit' => [
'admin/AppGroup/edit',
['method' => 'post']
],
'del' => [
'admin/AppGroup/del',
['method' => 'get']
]
], ['after_behavior' => $afterBehavior]);
Route::group('Log', [
'index' => [
'admin/Log/index',
['method' => 'get']
],
'del' => [
'admin/Log/del',
['method' => 'get']
]
], ['after_behavior' => $afterBehavior]);
Route::miss('admin/Miss/index');
});

View File

@ -1,124 +0,0 @@
<?php
/**
* 处理Api接入认证
* @since 2017-07-25
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\api\behavior;
use app\model\AdminList;
use app\util\ApiLog;
use app\util\ReturnCode;
use think\Cache;
use think\Request;
class ApiAuth {
/**
* @var Request
*/
private $request;
private $apiInfo;
private $header;
/**
* 默认行为函数
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return \think\response\Json
* @throws \think\Exception
* @throws \think\exception\DbException
*/
public function run() {
$this->request = Request::instance();
$hash = $this->request->routeInfo();
$this->header = config('apiAdmin.CROSS_DOMAIN');
if (isset($hash['rule'][1])) {
$hash = $hash['rule'][1];
$cached = Cache::has('ApiInfo:' . $hash);
if ($cached) {
$this->apiInfo = Cache::get('ApiInfo:' . $hash);
} else {
$apiInfo = AdminList::get(['hash' => $hash]);
if ($apiInfo) {
$this->apiInfo = $apiInfo->toArray();
Cache::set('ApiInfo:' . $hash, $this->apiInfo);
} else {
return json(['code' => ReturnCode::DB_READ_ERROR, 'msg' => '获取接口配置数据失败', 'data' => []], 200, $this->header);
}
}
if ($this->apiInfo['accessToken'] && !$this->apiInfo['isTest']) {
$accessRes = $this->checkAccessToken();
if ($accessRes) {
return $accessRes;
}
}
if (!$this->apiInfo['isTest']) {
$versionRes = $this->checkVersion();
if ($versionRes) {
return $versionRes;
}
}
$loginRes = $this->checkLogin();
if ($loginRes) {
return $loginRes;
}
ApiLog::setApiInfo($this->apiInfo);
}
}
/**
* Api接口合法性检测
*/
private function checkAccessToken() {
$access_token = $this->request->header('access-token');
if (!isset($access_token) || !$access_token) {
return json(['code' => ReturnCode::ACCESS_TOKEN_TIMEOUT, 'msg' => '缺少参数access-token', 'data' => []], 200, $this->header);
} else {
$appInfo = cache('AccessToken:' . $access_token);
if (!$appInfo) {
return json(['code' => ReturnCode::ACCESS_TOKEN_TIMEOUT, 'msg' => 'access-token已过期', 'data' => []], 200, $this->header);
}
ApiLog::setAppInfo($appInfo);
}
}
/**
* Api版本参数校验
*/
private function checkVersion() {
$version = $this->request->header('version');
if (!isset($version) || !$version) {
return json(['code' => ReturnCode::EMPTY_PARAMS, 'msg' => '缺少参数version', 'data' => []], 200, $this->header);
} else {
if ($version != config('apiAdmin.APP_VERSION')) {
return json(['code' => ReturnCode::VERSION_INVALID, 'msg' => 'API版本不匹配', 'data' => []], 200, $this->header);
}
}
}
/**
* TODO::需要根据实际情况另外改写
* 检测用户登录情况 检测通过请赋予USER_INFO值
*/
private function checkLogin() {
$userToken = $this->request->header('user-token', '');
if ($this->apiInfo['needLogin']) {
if (!$userToken) {
return json(['code' => ReturnCode::AUTH_ERROR, 'msg' => '缺少user-token', 'data' => []], 200, $this->header);
}
}
if ($userToken) {
$userInfo = cache('wx:openId:' . $userToken);
if (!is_array($userInfo) || !isset($userInfo['openId'])) {
return json(['code' => ReturnCode::AUTH_ERROR, 'msg' => 'user-token不匹配', 'data' => []], 200, $this->header);
}
ApiLog::setUserInfo($userInfo);
}
}
}

View File

@ -1,44 +0,0 @@
<?php
/**
* 处理app_id接入接口权限 需要重新签发AccessToken才能生效新的权限
* @since 2017-07-25
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\api\behavior;
use app\util\ReturnCode;
use think\Request;
class ApiPermission {
/**
* @var Request
*/
private $request;
/**
* 接口鉴权
* @return \think\response\Json
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function run() {
$this->request = Request::instance();
$header = config('apiAdmin.CROSS_DOMAIN');
$hash = $this->request->routeInfo();
if (isset($hash['rule'][1])) {
$hash = $hash['rule'][1];
$access_token = $this->request->header('access-token');
if ($access_token) {
$appInfo = cache('AccessToken:' . $access_token);
$allRules = explode(',', $appInfo['app_api']);
if (!in_array($hash, $allRules)) {
return json(['code' => ReturnCode::INVALID, 'msg' => '非常抱歉,您没有权限这么做!', 'data' => []], 200, $header);
}
}
}
}
}

View File

@ -1,99 +0,0 @@
<?php
/**
* 输出结果规整
* @since 2017-07-25
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\api\behavior;
use app\model\AdminFields;
use app\util\ApiLog;
use app\util\DataType;
use think\Cache;
use think\Request;
class BuildResponse {
/**
* 返回参数过滤(主要是将返回参数的数据类型给规范)
* @param $response \think\Response
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @throws \think\exception\DbException
*/
public function run($response) {
$header = config('apiAdmin.CROSS_DOMAIN');
$response->header($header);
$data = $response->getData();
$request = Request::instance();
$hash = $request->routeInfo();
if (isset($hash['rule'][1])) {
$hash = $hash['rule'][1];
$has = Cache::has('ResponseFieldsRule:' . $hash);
if ($has) {
$rule = cache('ResponseFieldsRule:' . $hash);
} else {
$rule = AdminFields::all(['hash' => $hash, 'type' => 1]);
cache('ResponseFieldsRule:' . $hash, $rule);
}
if ($rule) {
$rule = json_decode(json_encode($rule), true);
$newRule = array_column($rule, 'dataType', 'showName');
if (is_array($data)) {
$this->handle($data['data'], $newRule);
} elseif (empty($data)) {
if ($newRule['data'] == DataType::TYPE_OBJECT) {
$data = (object)[];
} elseif ($newRule['data'] == DataType::TYPE_ARRAY) {
$data = [];
}
}
$response->data($data);
}
}
ApiLog::setResponse($data);
ApiLog::save();
}
private function handle(&$data, $rule, $prefix = 'data') {
if (empty($data)) {
if ($rule[$prefix] == DataType::TYPE_OBJECT) {
$data = (object)[];
}
} else {
if ($rule[$prefix] == DataType::TYPE_OBJECT) {
$prefix .= '{}';
foreach ($data as $index => &$datum) {
$myPre = $prefix . $index;
if (isset($rule[$myPre])) {
switch ($rule[$myPre]) {
case DataType::TYPE_INTEGER:
$datum = intval($datum);
break;
case DataType::TYPE_FLOAT:
$datum = floatval($datum);
break;
case DataType::TYPE_STRING:
$datum = strval($datum);
break;
default:
$this->handle($datum, $rule, $myPre);
break;
}
}
}
} else {
$prefix .= '[]';
if (is_array($data[0])) {
foreach ($data as &$datum) {
$this->handle($datum, $rule, $prefix);
}
}
}
}
}
}

View File

@ -1,179 +0,0 @@
<?php
/**
* 输入参数过滤行为
* @since 2017-07-25
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\api\behavior;
use app\model\AdminFields;
use app\util\ApiLog;
use app\util\ReturnCode;
use app\util\DataType;
use think\Cache;
use think\Request;
use think\Validate;
class RequestFilter {
/**
* 默认行为函数
* @throws \think\Exception
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function run() {
$request = Request::instance();
$method = strtoupper($request->method());
switch ($method) {
case 'GET':
$data = $request->get();
break;
case 'POST':
$data = $request->post();
break;
case 'DELETE':
$data = $request->delete();
break;
case 'PUT':
$data = $request->put();
break;
default :
$data = [];
break;
}
ApiLog::setRequest($data);
$hash = $request->routeInfo();
if (isset($hash['rule'][1])) {
$hash = $hash['rule'][1];
$has = Cache::has('RequestFields:NewRule:' . $hash);
if ($has) {
$newRule = cache('RequestFields:NewRule:' . $hash);
$rule = cache('RequestFields:Rule:' . $hash);
} else {
$rule = AdminFields::all(['hash' => $hash, 'type' => 0]);
$newRule = $this->buildValidateRule($rule);
cache('RequestFields:NewRule:' . $hash, $newRule);
cache('RequestFields:Rule:' . $hash, $rule);
}
if ($newRule) {
$validate = new Validate($newRule);
if (!$validate->check($data)) {
$header = config('apiAdmin.CROSS_DOMAIN');
return json(['code' => ReturnCode::PARAM_INVALID, 'msg' => $validate->getError(), 'data' => []], 200, $header);
}
}
$newData = [];
foreach ($rule as $item) {
$newData[$item['fieldName']] = isset($data[$item['fieldName']])? $data[$item['fieldName']] : '';
if (!$item['isMust'] && $item['default'] !== '' && !isset($data[$item['fieldName']])) {
$newData[$item['fieldName']] = $item['default'];
}
}
switch ($method) {
case 'GET':
$request->forceGet($newData);
break;
case 'POST':
$request->forcePost($newData);
break;
case 'DELETE':
$request->forceDelete($newData);
break;
case 'PUT':
$request->forcePut($newData);
break;
}
ApiLog::setRequestAfterFilter($newData);
}
ApiLog::setHeader($request->header());
}
/**
* 将数据库中的规则转换成TP_Validate使用的规则数组
* @param array $rule
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
*/
public function buildValidateRule($rule = array()) {
$newRule = [];
if ($rule) {
foreach ($rule as $value) {
if ($value['isMust']) {
$newRule[$value['fieldName']][] = 'require';
}
switch ($value['dataType']) {
case DataType::TYPE_INTEGER:
$newRule[$value['fieldName']][] = 'number';
if ($value['range']) {
$range = htmlspecialchars_decode($value['range']);
$range = json_decode($range, true);
if (isset($range['min'])) {
$newRule[$value['fieldName']]['egt'] = $range['min'];
}
if (isset($range['max'])) {
$newRule[$value['fieldName']]['elt'] = $range['max'];
}
}
break;
case DataType::TYPE_STRING:
if ($value['range']) {
$range = htmlspecialchars_decode($value['range']);
$range = json_decode($range, true);
if (isset($range['min'])) {
$newRule[$value['fieldName']]['min'] = $range['min'];
}
if (isset($range['max'])) {
$newRule[$value['fieldName']]['max'] = $range['max'];
}
}
break;
case DataType::TYPE_ENUM:
if ($value['range']) {
$range = htmlspecialchars_decode($value['range']);
$range = json_decode($range, true);
$newRule[$value['fieldName']]['in'] = implode(',', $range);
}
break;
case DataType::TYPE_FLOAT:
$newRule[$value['fieldName']][] = 'float';
if ($value['range']) {
$range = htmlspecialchars_decode($value['range']);
$range = json_decode($range, true);
if (isset($range['min'])) {
$newRule[$value['fieldName']]['egt'] = $range['min'];
}
if (isset($range['max'])) {
$newRule[$value['fieldName']]['elt'] = $range['max'];
}
}
break;
case DataType::TYPE_ARRAY:
$newRule[$value['fieldName']][] = 'array';
if ($value['range']) {
$range = htmlspecialchars_decode($value['range']);
$range = json_decode($range, true);
if (isset($range['min'])) {
$newRule[$value['fieldName']]['min'] = $range['min'];
}
if (isset($range['max'])) {
$newRule[$value['fieldName']]['max'] = $range['max'];
}
}
break;
case DataType::TYPE_MOBILE:
$newRule[$value['fieldName']]['regex'] = '/^1[34578]\d{9}$/';
break;
}
}
}
return $newRule;
}
}

View File

@ -1,56 +0,0 @@
<?php
/**
* 工程基类
* @since 2017/02/28 创建
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\api\controller;
use app\util\ApiLog;
use app\util\ReturnCode;
use think\Controller;
class Base extends Controller {
private $debug = [];
protected $userInfo = [];
public function _initialize() {
$this->userInfo = ApiLog::getUserInfo();
}
public function buildSuccess($data, $msg = '操作成功', $code = ReturnCode::SUCCESS) {
$return = [
'code' => $code,
'msg' => $msg,
'data' => $data
];
if ($this->debug) {
$return['debug'] = $this->debug;
}
return json($return);
}
public function buildFailed($code, $msg, $data = []) {
$return = [
'code' => $code,
'msg' => $msg,
'data' => $data
];
if ($this->debug) {
$return['debug'] = $this->debug;
}
return json($return);
}
protected function debug($data) {
if ($data) {
$this->debug[] = $data;
}
}
}

View File

@ -1,90 +0,0 @@
<?php
/**
*
* @since 2017-10-26
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\api\controller;
use app\model\AdminApp;
use app\util\ApiLog;
use app\util\ReturnCode;
use app\util\Strs;
class BuildToken extends Base {
/**
* 构建AccessToken
* @return \think\response\Json
* @throws \think\db\exception\DataNotFoundException
* @throws \think\db\exception\ModelNotFoundException
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function getAccessToken() {
$param = $this->request->param();
if (empty($param['app_id'])) {
return $this->buildFailed(ReturnCode::EMPTY_PARAMS, '缺少app_id');
}
$appInfo = (new AdminApp())->where(['app_id' => $param['app_id'], 'app_status' => 1])->find();
if (empty($appInfo)) {
return $this->buildFailed(ReturnCode::INVALID, '应用ID非法');
}
$signature = $param['signature'];
unset($param['signature']);
$sign = $this->getAuthToken($appInfo['app_secret'], $param);
$this->debug($sign);
if ($sign !== $signature) {
return $this->buildFailed(ReturnCode::INVALID, '身份令牌验证失败');
}
$expires = config('apiAdmin.ACCESS_TOKEN_TIME_OUT');
$accessToken = cache('AccessToken:' . $param['device_id']);
if ($accessToken) {
cache('AccessToken:' . $accessToken, null);
cache('AccessToken:' . $param['device_id'], null);
}
$accessToken = $this->buildAccessToken($appInfo['app_id'], $appInfo['app_secret']);
$appInfo['device_id'] = $param['device_id'];
ApiLog::setAppInfo($appInfo);
cache('AccessToken:' . $accessToken, $appInfo, $expires);
cache('AccessToken:' . $param['device_id'], $accessToken, $expires);
$return['access_token'] = $accessToken;
$return['expires_in'] = $expires;
return $this->buildSuccess($return);
}
/**
* 根据AppSecret和数据生成相对应的身份认证秘钥
* @param $appSecret
* @param $data
* @return string
*/
private function getAuthToken($appSecret, $data) {
if (empty($data)) {
return '';
} else {
$preArr = array_merge($data, ['app_secret' => $appSecret]);
ksort($preArr);
$preStr = http_build_query($preArr);
return md5($preStr);
}
}
/**
* 计算出唯一的身份令牌
* @param $appId
* @param $appSecret
* @return string
*/
private function buildAccessToken($appId, $appSecret) {
$preStr = $appSecret . $appId . time() . Strs::keyGen();
return md5($preStr);
}
}

View File

@ -1,19 +0,0 @@
<?php
namespace app\api\controller;
class Index extends Base {
public function index() {
$this->debug([
'TpVersion' => THINK_VERSION
]);
return $this->buildSuccess([
'Product' => config('apiAdmin.APP_NAME'),
'Version' => config('apiAdmin.APP_VERSION'),
'Company' => config('apiAdmin.COMPANY_NAME'),
'ToYou' => "I'm glad to meet you终于等到你"
]);
}
}

View File

@ -1,22 +0,0 @@
<?php
namespace app\api\controller;
use app\util\StrRandom;
class Miss extends Base {
public function index() {
$this->debug([
'TpVersion' => THINK_VERSION,
'Float' => StrRandom::randomPhone()
]);
return $this->buildSuccess([
'Product' => config('apiAdmin.APP_NAME'),
'Version' => config('apiAdmin.APP_VERSION'),
'Company' => config('apiAdmin.COMPANY_NAME'),
'ToYou' => "I'm glad to meet you终于等到你"
]);
}
}

View File

@ -1,18 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用行为扩展定义文件
return [
// 输出结束
'response_send' => [
'app\\api\\behavior\\BuildResponse',
],
];

View File

@ -1,13 +0,0 @@
<?php
/**
* Api路由
*/
use think\Route;
Route::miss('api/Miss/index');
$afterBehavior = [
'\app\api\behavior\ApiAuth',
'\app\api\behavior\ApiPermission',
'\app\api\behavior\RequestFilter'
];

View File

@ -1,12 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
return [];

View File

@ -1,65 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: 流年 <liu21st@gmail.com>
// +----------------------------------------------------------------------
// 应用公共文件
/**
* 把返回的数据集转换成Tree
* @param $list
* @param string $pk
* @param string $pid
* @param string $child
* @param string $root
* @return array
*/
function listToTree($list, $pk='id', $pid = 'fid', $child = '_child', $root = '0') {
$tree = array();
if(is_array($list)) {
$refer = array();
foreach ($list as $key => $data) {
$refer[$data[$pk]] = &$list[$key];
}
foreach ($list as $key => $data) {
$parentId = $data[$pid];
if ($root == $parentId) {
$tree[] = &$list[$key];
}else{
if (isset($refer[$parentId])) {
$parent = &$refer[$parentId];
$parent[$child][] = &$list[$key];
}
}
}
}
return $tree;
}
function formatTree($list, $lv = 0, $title = 'name'){
$formatTree = array();
foreach($list as $key => $val){
$title_prefix = '';
for( $i=0;$i<$lv;$i++ ){
$title_prefix .= "|---";
}
$val['lv'] = $lv;
$val['namePrefix'] = $lv == 0 ? '' : $title_prefix;
$val['showName'] = $lv == 0 ? $val[$title] : $title_prefix.$val[$title];
if(!array_key_exists('_child', $val)){
array_push($formatTree, $val);
}else{
$child = $val['_child'];
unset($val['_child']);
array_push($formatTree, $val);
$middle = formatTree($child, $lv+1, $title); //进行下一层递归
$formatTree = array_merge($formatTree, $middle);
}
}
return $formatTree;
}

View File

@ -1,241 +0,0 @@
<?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>
// +----------------------------------------------------------------------
return [
// +----------------------------------------------------------------------
// | 应用设置
// +----------------------------------------------------------------------
// 应用命名空间
'app_namespace' => 'app',
// 应用调试模式
'app_debug' => true,
// 应用Trace
'app_trace' => false,
// 应用模式状态
'app_status' => '',
// 是否支持多模块
'app_multi_module' => true,
// 入口自动绑定模块
'auto_bind_module' => false,
// 注册的根命名空间
'root_namespace' => [],
// 扩展函数文件
'extra_file_list' => [THINK_PATH . 'helper' . EXT],
// 默认输出类型
'default_return_type' => 'json',
// 默认AJAX 数据返回格式,可选json xml ...
'default_ajax_return' => 'json',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
// 默认时区
'default_timezone' => 'PRC',
// 是否开启多语言
'lang_switch_on' => false,
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 默认语言
'default_lang' => 'zh-cn',
// 应用类库后缀
'class_suffix' => false,
// 控制器类后缀
'controller_suffix' => false,
// +----------------------------------------------------------------------
// | 模块设置
// +----------------------------------------------------------------------
// 默认模块名
'default_module' => 'api',
// 禁止访问模块
'deny_module_list' => ['common'],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 默认验证器
'default_validate' => '',
// 默认的空控制器名
'empty_controller' => 'Error',
// 操作方法后缀
'action_suffix' => '',
// 自动搜索控制器
'controller_auto_search' => false,
// +----------------------------------------------------------------------
// | URL设置
// +----------------------------------------------------------------------
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// pathinfo分隔符
'pathinfo_depr' => '/',
// URL伪静态后缀
'url_html_suffix' => 'html',
// URL普通方式参数 用于自动生成
'url_common_param' => false,
// URL参数方式 0 按名称成对解析 1 按顺序解析
'url_param_type' => 0,
// 是否开启路由
'url_route_on' => true,
// 路由使用完整匹配
'route_complete_match' => false,
// 路由配置文件(支持配置多个)
'route_config_file' => ['adminRoute', 'apiRoute', 'wikiRoute'],
// 是否强制使用路由
'url_route_must' => true,
// 域名部署
'url_domain_deploy' => false,
// 域名根如thinkphp.cn
'url_domain_root' => '',
// 是否自动转换URL中的控制器和操作名
'url_convert' => true,
// 默认的访问控制器层
'url_controller_layer' => 'controller',
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// +----------------------------------------------------------------------
// | 模板设置
// +----------------------------------------------------------------------
'template' => [
// 模板引擎类型 支持 php think 支持扩展
'type' => 'Think',
// 模板路径
'view_path' => '',
// 模板后缀
'view_suffix' => 'html',
// 模板文件名分隔符
'view_depr' => DS,
// 模板引擎普通标签开始标记
'tpl_begin' => '{',
// 模板引擎普通标签结束标记
'tpl_end' => '}',
// 标签库标签开始标记
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
],
// 视图输出字符串内容替换
'view_replace_str' => [],
// 默认跳转页面对应的模板文件
'dispatch_success_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
'dispatch_error_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
// +----------------------------------------------------------------------
// | 异常及错误设置
// +----------------------------------------------------------------------
// 异常页面的模板文件
'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
// 异常处理handle类 留空使用 \think\exception\Handle
'exception_handle' => '',
// +----------------------------------------------------------------------
// | 日志设置
// +----------------------------------------------------------------------
'log' => [
// 日志记录方式,内置 file socket 支持扩展
'type' => 'File',
// 日志保存目录
'path' => LOG_PATH,
// 日志记录级别
'level' => [],
],
// +----------------------------------------------------------------------
// | Trace设置 开启 app_trace 后 有效
// +----------------------------------------------------------------------
'trace' => [
// 内置Html Console 支持扩展
'type' => 'Html',
],
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
'cache' => [
// 驱动方式
'type' => 'Redis',
// 缓存保存目录
'path' => CACHE_PATH,
// 缓存前缀
'prefix' => 'ApiAdmin_',
// 缓存有效期 0表示永久缓存
'expire' => 0,
],
// +----------------------------------------------------------------------
// | 会话设置
// +----------------------------------------------------------------------
'session' => [
'id' => '',
// SESSION_ID的提交变量,解决flash上传跨域
'var_session_id' => '',
// SESSION 前缀
'prefix' => 'think',
// 驱动方式 支持redis memcache memcached
'type' => '',
// 是否自动开启 SESSION
'auto_start' => true,
],
// +----------------------------------------------------------------------
// | Cookie设置
// +----------------------------------------------------------------------
'cookie' => [
// cookie 名称前缀
'prefix' => '',
// cookie 保存时间
'expire' => 0,
// cookie 保存路径
'path' => '/',
// cookie 有效域名
'domain' => '',
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => '',
// 是否使用 setcookie
'setcookie' => true,
],
//分页配置
'paginate' => [
'type' => 'bootstrap',
'var_page' => 'page',
'list_rows' => 15,
],
];

View File

@ -1,53 +0,0 @@
<?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>
// +----------------------------------------------------------------------
return [
// 数据库类型
'type' => 'mysql',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => 'apiadmin',
// 用户名
'username' => 'root',
// 密码
'password' => '123456',
// 端口
'hostport' => '',
// 连接dsn
'dsn' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '',
// 数据库调试模式
'debug' => true,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 数据集返回类型
'resultset_type' => 'array',
// 自动写入时间戳字段
'auto_timestamp' => false,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 是否需要进行SQL性能分析
'sql_explain' => false,
];

View File

@ -1,38 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
return [
'APP_VERSION' => 'v3.0',
'APP_NAME' => 'ApiAdmin',
//鉴权相关
'USER_ADMINISTRATOR' => [1],
//安全秘钥
'AUTH_KEY' => 'I&TC{pft>L,C`wFQ>&#ROW>k{Kxlt1>ryW(>r<#R',
//后台登录状态维持时间[目前只有登录和解锁会重置登录时间]
'ONLINE_TIME' => 7200,
//AccessToken失效时间
'ACCESS_TOKEN_TIME_OUT' => 7200,
'COMPANY_NAME' => 'ApiAdmin开发维护团队',
//跨域配置
'CROSS_DOMAIN' => [
'Access-Control-Allow-Origin' => '*',
'Access-Control-Allow-Methods' => 'POST,PUT,GET,DELETE',
'Access-Control-Allow-Headers' => 'version, access-token, user-token, ApiAuth, User-Agent, Keep-Alive, Origin, No-Cache, X-Requested-With, If-Modified-Since, Pragma, Last-Modified, Cache-Control, Expires, Content-Type, X-E4M-With',
'Access-Control-Allow-Credentials' => 'true'
],
//后台列表默认一页显示数量
'ADMIN_LIST_DEFAULT' => 20,
];

View File

@ -1,8 +0,0 @@
<?php
namespace app\model;
class AdminApp extends Base {
}

View File

@ -1,13 +0,0 @@
<?php
/**
*
* @since 2018-02-11
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\model;
class AdminAppGroup extends Base {
}

View File

@ -1,17 +0,0 @@
<?php
/**
*
* @since 2018-02-08
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\model;
class AdminAuthGroup extends Base {
public function rules() {
return $this->hasMany('AdminAuthRule', 'groupId', 'id');
}
}

View File

@ -1,13 +0,0 @@
<?php
/**
*
* @since 2018-02-08
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\model;
class AdminAuthGroupAccess extends Base {
}

View File

@ -1,13 +0,0 @@
<?php
/**
*
* @since 2018-02-08
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\model;
class AdminAuthRule extends Base {
}

View File

@ -1,12 +0,0 @@
<?php
/**
* 接口字段规则模型
* @since 2017/07/25 创建
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\model;
class AdminFields extends Base {
}

View File

@ -1,13 +0,0 @@
<?php
/**
*
* @since 2018-02-11
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\model;
class AdminGroup extends Base {
}

View File

@ -1,11 +0,0 @@
<?php
/**
* @since 2017-07-30
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\model;
class AdminList extends Base {
}

View File

@ -1,8 +0,0 @@
<?php
namespace app\model;
class AdminMenu extends Base {
//
}

View File

@ -1,12 +0,0 @@
<?php
/**
* @since 2017-11-02
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\model;
class AdminUser extends Base {
}

View File

@ -1,13 +0,0 @@
<?php
/**
*
* @since 2018-02-11
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\model;
class AdminUserAction extends Base {
}

View File

@ -1,12 +0,0 @@
<?php
/**
* @since 2017-11-02
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\model;
class AdminUserData extends Base {
}

View File

@ -1,15 +0,0 @@
<?php
/**
* 模型基类
* @since 2017/07/25 创建
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\model;
use think\Model;
class Base extends Model {
}

View File

@ -1,28 +0,0 @@
<?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>
// +----------------------------------------------------------------------
// 应用行为扩展定义文件
return [
// 应用初始化
'app_init' => [],
// 应用开始
'app_begin' => [],
// 模块初始化
'module_init' => [],
// 操作开始执行
'action_begin' => [],
// 视图内容过滤
'view_filter' => [],
// 日志写入
'log_write' => [],
// 应用结束
'app_end' => [],
];

View File

@ -1,109 +0,0 @@
<?php
/**
* @since 2017-04-14
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\util;
class ApiLog {
private static $appInfo = 'null';
private static $apiInfo = 'null';
private static $request = 'null';
private static $requestAfterFilter = 'null';
private static $response = 'null';
private static $header = 'null';
private static $userInfo = 'null';
private static $separator = '###';
public static function setAppInfo($data) {
self::$appInfo =
(isset($data['app_id']) ? $data['app_id'] : '') . self::$separator .
(isset($data['app_name']) ? $data['app_name'] : '') . self::$separator .
(isset($data['device_id']) ? $data['device_id'] : '');
}
public static function setHeader($data) {
$userToken = (isset($data['user-token']) && !empty($data['user-token'])) ? $data['user-token'] : 'null';
$accessToken = (isset($data['access-token']) && !empty($data['access-token'])) ? $data['access-token'] : 'null';
$version = (isset($data['version']) && !empty($data['version'])) ? $data['version'] : 'null';
self::$header = $accessToken . self::$separator . $userToken . self::$separator . $version;
}
public static function setApiInfo($data) {
self::$apiInfo = isset($data['apiClass']) ? $data['apiClass'] : '' . self::$separator . isset($data['hash']) ? $data['hash'] : '';
}
public static function setUserInfo($data) {
if (is_array($data) || is_object($data)) {
$data = json_encode($data);
}
self::$userInfo = $data;
}
public static function getUserInfo() {
return json_decode(self::$userInfo, true);
}
public static function setRequest($data) {
if (is_array($data) || is_object($data)) {
$data = json_encode($data);
}
self::$request = $data;
}
public static function setRequestAfterFilter($data) {
if (is_array($data) || is_object($data)) {
$data = json_encode($data);
}
self::$requestAfterFilter = $data;
}
public static function setResponse($data, $code = '') {
if (is_array($data) || is_object($data)) {
$data = json_encode($data);
}
self::$response = $code . self::$separator . $data;
}
public static function save() {
$logPath = RUNTIME_PATH . 'ApiLog' . DS;
if (self::$appInfo == 'null') {
self::$appInfo = 'null' . self::$separator . 'null' . self::$separator . 'null';
}
$logStr = implode(self::$separator, array(
self::$apiInfo,
date('Y-m-d H:i:s'),
self::$request,
self::$header,
self::$response,
self::$requestAfterFilter,
self::$appInfo,
self::$userInfo
));
if (!file_exists($logPath)) {
mkdir($logPath, 0755, true);
}
@file_put_contents($logPath . date('YmdH') . '.log', $logStr . "\n", FILE_APPEND);
}
/**
* @param string $log 被记录的内容
* @param string $type 日志文件名称
* @param string $filePath
*/
public static function writeLog($log, $type = 'sql', $filePath = '') {
if(!$filePath) {
$filePath = '.' . DS . 'runtime' . DS;
}
$filename = $filePath . date("Ymd") . '_' . $type . ".log";
@$handle = fopen($filename, "a+");
@fwrite($handle, date('Y-m-d H:i:s') . "\t" . $log . "\r\n");
@fclose($handle);
}
}

View File

@ -1,24 +0,0 @@
<?php
/**
* 数据类型维护
* 特别注意:这里的数据类型包含但不限于常规数据类型,可能会存在系统自己定义的数据类型
* @since 2017/03/01 创建
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\util;
class DataType {
const TYPE_INTEGER = 1;
const TYPE_STRING = 2;
const TYPE_ARRAY = 3;
const TYPE_FLOAT = 4;
const TYPE_BOOLEAN = 5;
const TYPE_FILE = 6;
const TYPE_ENUM = 7;
const TYPE_MOBILE = 8;
const TYPE_OBJECT = 9;
}

View File

@ -1,21 +0,0 @@
<?php
/**
* mock配置和ApiAdmin内置的接口返回数据配置相互转化的类
* @since 2018-08-23
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\util;
class MockConf {
public function mockToApiAdmin() {
}
public function apiAdminToMock() {
}
}

View File

@ -1,49 +0,0 @@
<?php
/**
* 错误码统一维护
* @since 2017/02/28 创建
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\util;
class ReturnCode {
const SUCCESS = 1;
const INVALID = -1;
const DB_SAVE_ERROR = -2;
const DB_READ_ERROR = -3;
const CACHE_SAVE_ERROR = -4;
const CACHE_READ_ERROR = -5;
const FILE_SAVE_ERROR = -6;
const LOGIN_ERROR = -7;
const NOT_EXISTS = -8;
const JSON_PARSE_FAIL = -9;
const TYPE_ERROR = -10;
const NUMBER_MATCH_ERROR = -11;
const EMPTY_PARAMS = -12;
const DATA_EXISTS = -13;
const AUTH_ERROR = -14;
const OTHER_LOGIN = -16;
const VERSION_INVALID = -17;
const CURL_ERROR = -18;
const RECORD_NOT_FOUND = -19; // 记录未找到
const DELETE_FAILED = -20; // 删除失败
const ADD_FAILED = -21; // 添加记录失败
const UPDATE_FAILED = -22; // 添加记录失败
const PARAM_INVALID = -995; // 参数无效
const ACCESS_TOKEN_TIMEOUT = -996;
const SESSION_TIMEOUT = -997;
const UNKNOWN = -998;
const EXCEPTION = -999;
static public function getConstants() {
$oClass = new \ReflectionClass(__CLASS__);
return $oClass->getConstants();
}
}

View File

@ -1,186 +0,0 @@
<?php
/**
* 构建各类有意义的随机数
* @since 2018-08-07
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\util;
class StrRandom {
/**
* 构建一个随机浮点数
* @param int $min 整数部分的最小值,默认值为-999999999
* @param int $max 整数部分的最大值默认值为999999999
* @param int $dmin 小数部分位数的最小值,默认值为 0
* @param int $dmax 小数部分位数的最大值,默认值为 8
* @return float
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public static function randomFloat($min = -999999999, $max = 999999999, $dmin = 0, $dmax = 8) {
$rand = '';
$intNum = mt_rand($min, $max);
$floatLength = mt_rand($dmin, $dmax);
if ($floatLength > 1) {
$rand = Strs::randString($floatLength - 1, 1);
}
$floatEnd = mt_rand(1, 9);
return floatval($intNum . '.' . $rand . $floatEnd);
}
/**
* 获取随机的时间
* @param string $format PHP的时间日期格式化字符
* @return false|string
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public static function randomDate($format = 'Y-m-d H:i:s') {
$timestamp = time() - mt_rand(0, 86400 * 3650);
return date($format, $timestamp);
}
/**
* 构建随机IP地址
* @return string
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public static function randomIp() {
$ipLong = [
['607649792', '608174079'], // 36.56.0.0-36.63.255.255
['1038614528', '1039007743'], // 61.232.0.0-61.237.255.255
['1783627776', '1784676351'], // 106.80.0.0-106.95.255.255
['2035023872', '2035154943'], // 121.76.0.0-121.77.255.255
['2078801920', '2079064063'], // 123.232.0.0-123.235.255.255
['-1950089216', '-1948778497'], // 139.196.0.0-139.215.255.255
['-1425539072', '-1425014785'], // 171.8.0.0-171.15.255.255
['-1236271104', '-1235419137'], // 182.80.0.0-182.92.255.255
['-770113536', '-768606209'], // 210.25.0.0-210.47.255.255
['-569376768', '-564133889'], // 222.16.0.0-222.95.255.255
];
$randKey = mt_rand(0, 9);
return $ip = long2ip(mt_rand($ipLong[$randKey][0], $ipLong[$randKey][1]));
}
/**
* 随机生成一个 URL 协议
* @return mixed
* @author zhaoxiang <zhaoxiang051405@gmail','com>
*/
public static function randomProtocol() {
$proArr = [
'http',
'ftp',
'gopher',
'mailto',
'mid',
'cid',
'news',
'nntp',
'prospero',
'telnet',
'rlogin',
'tn3270',
'wais'
];
shuffle($proArr);
return $proArr[0];
}
/**
* 随机生成一个顶级域名
* @author zhaoxiang <zhaoxiang051405@gmail','com>
*/
public static function randomTld() {
$tldArr = [
'com', 'cn', 'xin', 'net', 'top', '在线',
'xyz', 'wang', 'shop', 'site', 'club', 'cc',
'fun', 'online', 'biz', 'red', 'link', 'ltd',
'mobi', 'info', 'org', 'edu', 'com.cn', 'net.cn',
'org.cn', 'gov.cn', 'name', 'vip', 'pro', 'work',
'tv', 'co', 'kim', 'group', 'tech', 'store', 'ren',
'ink', 'pub', 'live', 'wiki', 'design', '中文网',
'我爱你', '中国', '网址', '网店', '公司', '网络', '集团', 'app'
];
shuffle($tldArr);
return $tldArr[0];
}
/**
* 获取一个随机的域名
* @return string
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public static function randomDomain() {
$len = mt_rand(6, 16);
return strtolower(Strs::randString($len)) . '.' . self::randomTld();
}
/**
* 随机生成一个URL
* @param string $protocol 协议名称,可以不用指定
* @return string
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public static function randomUrl($protocol = '') {
$protocol = $protocol ? $protocol : self::randomProtocol();
return $protocol . '://' . self::randomDomain();
}
/**
* 随机生成一个邮箱地址
* @param string $domain 可以指定邮箱域名
* @return string
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public static function randomEmail($domain = '') {
$len = mt_rand(6, 16);
$domain = $domain ? $domain : self::randomDomain();
return Strs::randString($len) . '@' . $domain;
}
public static function randomPhone() {
$prefixArr = [133, 153, 173, 177, 180, 181, 189, 199, 134, 135,
136, 137, 138, 139, 150, 151, 152, 157, 158, 159, 172, 178,
182, 183, 184, 187, 188, 198, 130, 131, 132, 155, 156, 166,
175, 176, 185, 186, 145, 147, 149, 170, 171];
shuffle($prefixArr);
return $prefixArr[0] . Strs::randString(8, 1);
}
/**
* 随机创建一个身份证号码
* @return string
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public static function randomId() {
$prefixArr = [
11, 12, 13, 14, 15,
21, 22, 23,
31, 32, 33, 34, 35, 36, 37,
41, 42, 43, 44, 45, 46,
50, 51, 52, 53, 54,
61, 62, 63, 64, 65,
71, 81, 82
];
shuffle($prefixArr);
$suffixArr = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 'X'];
shuffle($suffixArr);
return $prefixArr[0] . '0000' . self::randomDate('Ymd') . Strs::randString(3, 1) . $suffixArr[0];
}
}

View File

@ -1,252 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2009 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
namespace app\util;
class Strs {
/**
* 生成UUID 单机使用
* @access public
* @return string
*/
static public function uuid() {
$charId = md5(uniqid(mt_rand(), true));
$hyphen = chr(45);
$uuid = chr(123)
. substr($charId, 0, 8) . $hyphen
. substr($charId, 8, 4) . $hyphen
. substr($charId, 12, 4) . $hyphen
. substr($charId, 16, 4) . $hyphen
. substr($charId, 20, 12)
. chr(125);
return $uuid;
}
/**
* 生成Guid主键
* @return Boolean
*/
static public function keyGen() {
return str_replace('-', '', substr(self::uuid(), 1, -1));
}
/**
* 检查字符串是否是UTF8编码
* @param string $string 字符串
* @return Boolean
*/
static public function isUtf8($string) {
$len = strlen($string);
for ($i = 0; $i < $len; $i++) {
$c = ord($string[$i]);
if ($c > 128) {
if (($c >= 254)) return false;
elseif ($c >= 252) $bits = 6;
elseif ($c >= 248) $bits = 5;
elseif ($c >= 240) $bits = 4;
elseif ($c >= 224) $bits = 3;
elseif ($c >= 192) $bits = 2;
else return false;
if (($i + $bits) > $len) return false;
while ($bits > 1) {
$i++;
$b = ord($string[$i]);
if ($b < 128 || $b > 191) return false;
$bits--;
}
}
}
return true;
}
/**
* 字符串截取,支持中文和其他编码
* @access public
* @param string $str 需要转换的字符串
* @param integer $start 开始位置
* @param string $length 截取长度
* @param string $charset 编码格式
* @param bool $suffix 截断显示字符
* @return string
*/
static public function mSubStr($str, $start = 0, $length, $charset = "utf-8", $suffix = true) {
if (function_exists("mb_substr"))
$slice = mb_substr($str, $start, $length, $charset);
elseif (function_exists('iconv_substr')) {
$slice = iconv_substr($str, $start, $length, $charset);
} else {
$re['utf-8'] = "/[\x01-\x7f]|[\xc2-\xdf][\x80-\xbf]|[\xe0-\xef][\x80-\xbf]{2}|[\xf0-\xff][\x80-\xbf]{3}/";
$re['gb2312'] = "/[\x01-\x7f]|[\xb0-\xf7][\xa0-\xfe]/";
$re['gbk'] = "/[\x01-\x7f]|[\x81-\xfe][\x40-\xfe]/";
$re['big5'] = "/[\x01-\x7f]|[\x81-\xfe]([\x40-\x7e]|\xa1-\xfe])/";
preg_match_all($re[$charset], $str, $match);
$slice = join("", array_slice($match[0], $start, $length));
}
return $suffix ? $slice . '...' : $slice;
}
/**
* 产生随机字串,可用来自动生成密码
* 默认长度6位 字母和数字混合 支持中文
* @param integer $len 长度
* @param string $type 字串类型
* 0 字母 1 数字 其它 混合
* @param string $addChars 额外字符
* @return string
*/
static public function randString($len = 6, $type = '', $addChars = '') {
$str = '';
switch ($type) {
case 0:
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz' . $addChars;
break;
case 1:
$chars = str_repeat('0123456789', 3);
break;
case 2:
$chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ' . $addChars;
break;
case 3:
$chars = 'abcdefghijklmnopqrstuvwxyz' . $addChars;
break;
case 4:
$chars = "们以我到他会作时要动国产的一是工就年阶义发成部民可出能方进在了不和有大这主中人上为来分生对于学下级地个用同行面说种过命度革而多子后自社加小机也经力线本电高量长党得实家定深法表着水理化争现所二起政三好十战无农使性前等反体合斗路图把结第里正新开论之物从当两些还天资事队批点育重其思与间内去因件日利相由压员气业代全组数果期导平各基或月毛然如应形想制心样干都向变关问比展那它最及外没看治提五解系林者米群头意只明四道马认次文通但条较克又公孔领军流入接席位情运器并飞原油放立题质指建区验活众很教决特此常石强极土少已根共直团统式转别造切九你取西持总料连任志观调七么山程百报更见必真保热委手改管处己将修支识病象几先老光专什六型具示复安带每东增则完风回南广劳轮科北打积车计给节做务被整联步类集号列温装即毫知轴研单色坚据速防史拉世设达尔场织历花受求传口断况采精金界品判参层止边清至万确究书术状厂须离再目海交权且儿青才证低越际八试规斯近注办布门铁需走议县兵固除般引齿千胜细影济白格效置推空配刀叶率述今选养德话查差半敌始片施响收华觉备名红续均药标记难存测士身紧液派准斤角降维板许破述技消底床田势端感往神便贺村构照容非搞亚磨族火段算适讲按值美态黄易彪服早班麦削信排台声该击素张密害侯草何树肥继右属市严径螺检左页抗苏显苦英快称坏移约巴材省黑武培著河帝仅针怎植京助升王眼她抓含苗副杂普谈围食射源例致酸旧却充足短划剂宣环落首尺波承粉践府鱼随考刻靠够满夫失包住促枝局菌杆周护岩师举曲春元超负砂封换太模贫减阳扬江析亩木言球朝医校古呢稻宋听唯输滑站另卫字鼓刚写刘微略范供阿块某功套友限项余倒卷创律雨让骨远帮初皮播优占死毒圈伟季训控激找叫云互跟裂粮粒母练塞钢顶策双留误础吸阻故寸盾晚丝女散焊功株亲院冷彻弹错散商视艺灭版烈零室轻血倍缺厘泵察绝富城冲喷壤简否柱李望盘磁雄似困巩益洲脱投送奴侧润盖挥距触星松送获兴独官混纪依未突架宽冬章湿偏纹吃执阀矿寨责熟稳夺硬价努翻奇甲预职评读背协损棉侵灰虽矛厚罗泥辟告卵箱掌氧恩爱停曾溶营终纲孟钱待尽俄缩沙退陈讨奋械载胞幼哪剥迫旋征槽倒握担仍呀鲜吧卡粗介钻逐弱脚怕盐末阴丰雾冠丙街莱贝辐肠付吉渗瑞惊顿挤秒悬姆烂森糖圣凹陶词迟蚕亿矩康遵牧遭幅园腔订香肉弟屋敏恢忘编印蜂急拿扩伤飞露核缘游振操央伍域甚迅辉异序免纸夜乡久隶缸夹念兰映沟乙吗儒杀汽磷艰晶插埃燃欢铁补咱芽永瓦倾阵碳演威附牙芽永瓦斜灌欧献顺猪洋腐请透司危括脉宜笑若尾束壮暴企菜穗楚汉愈绿拖牛份染既秋遍锻玉夏疗尖殖井费州访吹荣铜沿替滚客召旱悟刺脑措贯藏敢令隙炉壳硫煤迎铸粘探临薄旬善福纵择礼愿伏残雷延烟句纯渐耕跑泽慢栽鲁赤繁境潮横掉锥希池败船假亮谓托伙哲怀割摆贡呈劲财仪沉炼麻罪祖息车穿货销齐鼠抽画饲龙库守筑房歌寒喜哥洗蚀废纳腹乎录镜妇恶脂庄擦险赞钟摇典柄辩竹谷卖乱虚桥奥伯赶垂途额壁网截野遗静谋弄挂课镇妄盛耐援扎虑键归符庆聚绕摩忙舞遇索顾胶羊湖钉仁音迹碎伸灯避泛亡答勇频皇柳哈揭甘诺概宪浓岛袭谁洪谢炮浇斑讯懂灵蛋闭孩释乳巨徒私银伊景坦累匀霉杜乐勒隔弯绩招绍胡呼痛峰零柴簧午跳居尚丁秦稍追梁折耗碱殊岗挖氏刃剧堆赫荷胸衡勤膜篇登驻案刊秧缓凸役剪川雪链渔啦脸户洛孢勃盟买杨宗焦赛旗滤硅炭股坐蒸凝竟陷枪黎救冒暗洞犯筒您宋弧爆谬涂味津臂障褐陆啊健尊豆拔莫抵桑坡缝警挑污冰柬嘴啥饭塑寄赵喊垫丹渡耳刨虎笔稀昆浪萨茶滴浅拥穴覆伦娘吨浸袖珠雌妈紫戏塔锤震岁貌洁剖牢锋疑霸闪埔猛诉刷狠忽灾闹乔唐漏闻沈熔氯荒茎男凡抢像浆旁玻亦忠唱蒙予纷捕锁尤乘乌智淡允叛畜俘摸锈扫毕璃宝芯爷鉴秘净蒋钙肩腾枯抛轨堂拌爸循诱祝励肯酒绳穷塘燥泡袋朗喂铝软渠颗惯贸粪综墙趋彼届墨碍启逆卸航衣孙龄岭骗休借" . $addChars;
break;
default :
// 默认去掉了容易混淆的字符oOLl和数字01要添加请使用addChars参数
$chars = 'ABCDEFGHIJKMNPQRSTUVWXYZabcdefghijkmnpqrstuvwxyz23456789' . $addChars;
break;
}
if ($len > 10) {//位数过长重复字符串一定次数
$chars = $type == 1 ? str_repeat($chars, $len) : str_repeat($chars, 5);
}
if ($type != 4) {
$chars = str_shuffle($chars);
$str = substr($chars, 0, $len);
} else {
// 中文随机字
for ($i = 0; $i < $len; $i++) {
$str .= self::msubstr($chars, floor(mt_rand(0, mb_strlen($chars, 'utf-8') - 1)), 1, 'utf-8', false);
}
}
return $str;
}
/**
* 生成一定数量的随机数,并且不重复
* @param integer $number 数量
* @param integer $length 长度
* @param integer $mode 字串类型
* 0 字母 1 数字 其它 混合
* @return string
*/
static public function buildCountRand($number, $length = 4, $mode = 1) {
if ($mode == 1 && $length < strlen($number)) {
//不足以生成一定数量的不重复数字
return false;
}
$rand = array();
for ($i = 0; $i < $number; $i++) {
$rand[] = self::randString($length, $mode);
}
$unique = array_unique($rand);
if (count($unique) == count($rand)) {
return $rand;
}
$count = count($rand) - count($unique);
for ($i = 0; $i < $count * 3; $i++) {
$rand[] = self::randString($length, $mode);
}
$rand = array_slice(array_unique($rand), 0, $number);
return $rand;
}
/**
* 带格式生成随机字符 支持批量生成
* 但可能存在重复
* @param string $format 字符格式
* # 表示数字 * 表示字母和数字 $ 表示字母
* @param integer $number 生成数量
* @return string | array
*/
static public function buildFormatRand($format, $number = 1) {
$str = array();
$length = strlen($format);
for ($j = 0; $j < $number; $j++) {
$strTemp = '';
for ($i = 0; $i < $length; $i++) {
$char = substr($format, $i, 1);
switch ($char) {
case "*"://字母和数字混合
$strTemp .= self::randString(1);
break;
case "#"://数字
$strTemp .= self::randString(1, 1);
break;
case "$"://大写字母
$strTemp .= self::randString(1, 2);
break;
default://其他格式均不转换
$strTemp .= $char;
break;
}
}
$str[] = $strTemp;
}
return $number == 1 ? $strTemp : $str;
}
/**
* 获取一定范围内的随机数字 位数不足补零
* @param integer $min 最小值
* @param integer $max 最大值
* @return string
*/
static public function randNumber($min, $max) {
return sprintf("%0" . strlen($max) . "d", mt_rand($min, $max));
}
// 自动转换字符集 支持数组转换
static public function autoCharset($string, $from = 'gbk', $to = 'utf-8') {
$from = strtoupper($from) == 'UTF8' ? 'utf-8' : $from;
$to = strtoupper($to) == 'UTF8' ? 'utf-8' : $to;
if (strtoupper($from) === strtoupper($to) || empty($string) || (is_scalar($string) && !is_string($string))) {
//如果编码相同或者非字符串标量则不转换
return $string;
}
if (is_string($string)) {
if (function_exists('mb_convert_encoding')) {
return mb_convert_encoding($string, $to, $from);
} elseif (function_exists('iconv')) {
return iconv($from, $to, $string);
} else {
return $string;
}
} elseif (is_array($string)) {
foreach ($string as $key => $val) {
$_key = self::autoCharset($key, $from, $to);
$string[$_key] = self::autoCharset($val, $from, $to);
if ($key != $_key)
unset($string[$key]);
}
return $string;
} else {
return $string;
}
}
}

View File

@ -1,115 +0,0 @@
<?php
/**
*
* @since 2017-11-01
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\util;
class Tools {
public static function getDate($timestamp) {
$now = time();
$diff = $now - $timestamp;
if ($diff <= 60) {
return $diff . '秒前';
} elseif ($diff <= 3600) {
return floor($diff / 60) . '分钟前';
} elseif ($diff <= 86400) {
return floor($diff / 3600) . '小时前';
} elseif ($diff <= 2592000) {
return floor($diff / 86400) . '天前';
} else {
return '一个月前';
}
}
/**
* 二次封装的密码加密
* @param $str
* @param string $auth_key
* @return string
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public static function userMd5($str, $auth_key = '') {
if (!$auth_key) {
$auth_key = config('apiAdmin.AUTH_KEY');
}
return '' === $str ? '' : md5(sha1($str) . $auth_key);
}
/**
* 判断当前用户是否是超级管理员
* @param string $uid
* @return bool
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public static function isAdministrator($uid = '') {
if (!empty($uid)) {
$adminConf = config('apiAdmin.USER_ADMINISTRATOR');
if (is_array($adminConf)) {
if (is_array($uid)) {
$m = array_intersect($adminConf, $uid);
if (count($m)) {
return true;
}
} else {
if (in_array($uid, $adminConf)) {
return true;
}
}
} else {
if (is_array($uid)) {
if (in_array($adminConf, $uid)) {
return true;
}
} else {
if ($uid == $adminConf) {
return true;
}
}
}
}
return false;
}
/**
* 将查询的二维对象转换成二维数组
* @param array $res
* @param string $key 允许指定索引值
* @return array
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public static function buildArrFromObj($res, $key = '') {
$arr = [];
foreach ($res as $value) {
$value = $value->toArray();
if ($key) {
$arr[$value[$key]] = $value;
} else {
$arr[] = $value;
}
}
return $arr;
}
/**
* 将二维数组变成指定key
* @param $array
* @param $keyName
* @author zhaoxiang <zhaoxiang051405@gmail.com>
* @return array
*/
public static function buildArrByNewKey($array, $keyName = 'id') {
$list = array();
foreach ($array as $item) {
$list[$item[$keyName]] = $item;
}
return $list;
}
}

View File

@ -1,90 +0,0 @@
<?php
/**
* 工程基类
* @since 2017/02/28 创建
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\wiki\controller;
use think\Config;
use think\Controller;
use think\exception\HttpResponseException;
use think\Request;
use think\Response;
use think\View as ViewTemplate;
use think\Url;
class Base extends Controller {
protected $appInfo;
public function checkLogin() {
$appInfo = session('app_info');
if ($appInfo) {
$this->appInfo = json_decode($appInfo, true);
} else {
$this->redirect(url('/wiki/login'));
}
}
public function error($msg = '', $url = null, $data = '', $wait = 3, array $header = []) {
if (is_null($url)) {
$url = Request::instance()->isAjax() ? '' : 'javascript:history.back(-1);';
} elseif ('' !== $url && !strpos($url, '://') && 0 !== strpos($url, '/')) {
$url = Url::build($url);
}
$type = 'html';
$result = [
'code' => 0,
'msg' => $msg,
'data' => $data,
'url' => $url,
'wait' => $wait,
];
if ('html' == strtolower($type)) {
$template = Config::get('template');
$view = Config::get('view_replace_str');
$result = ViewTemplate::instance($template, $view)
->fetch(Config::get('dispatch_error_tmpl'), $result);
}
$response = Response::create($result, $type)->header($header);
throw new HttpResponseException($response);
}
public function success($msg = '', $url = null, $data = '', $wait = 3, array $header = []) {
if (is_null($url) && !is_null(Request::instance()->server('HTTP_REFERER'))) {
$url = Request::instance()->server('HTTP_REFERER');
} elseif ('' !== $url && !strpos($url, '://') && 0 !== strpos($url, '/')) {
$url = Url::build($url);
}
$type = 'html';
$result = [
'code' => 1,
'msg' => $msg,
'data' => $data,
'url' => $url,
'wait' => $wait,
];
if ('html' == strtolower($type)) {
$template = Config::get('template');
$view = Config::get('view_replace_str');
$result = ViewTemplate::instance($template, $view)
->fetch(Config::get('dispatch_success_tmpl'), $result);
}
$response = Response::create($result, $type)->header($header);
throw new HttpResponseException($response);
}
}

View File

@ -1,178 +0,0 @@
<?php
/**
*
* @since 2017/07/27 创建
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
namespace app\wiki\controller;
use app\model\AdminApp;
use app\model\AdminFields;
use app\model\AdminGroup;
use app\model\AdminList;
use app\util\DataType;
use app\util\ReturnCode;
use app\util\Tools;
class Index extends Base {
/**
* 获取应用列表
* @return \think\response\View
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function index() {
$this->checkLogin();
$groupInfo = AdminGroup::all();
$groupInfo = Tools::buildArrFromObj($groupInfo);
$groupInfo = Tools::buildArrByNewKey($groupInfo, 'hash');
$this->appInfo = AdminApp::get(['app_id' => $this->appInfo['app_id']]);
$this->appInfo['app_api_show'] = json_decode($this->appInfo['app_api_show'], true);
return view('', [
'groupInfo' => $groupInfo,
'appInfo' => $this->appInfo
]);
}
public function detail() {
$this->checkLogin();
$groupHash = $this->request->route('groupHash');
$hash = $this->request->route('hash', '');
$this->appInfo['app_api_show'] = json_decode($this->appInfo['app_api_show'], true);
if (!isset($this->appInfo['app_api_show'][$groupHash]) || empty($this->appInfo['app_api_show'][$groupHash])) {
$this->error('请求非法', url('/wiki/index'));
}
if (!$hash) {
$hash = $this->appInfo['app_api_show'][$groupHash][0];
} else {
if (!in_array($hash, $this->appInfo['app_api_show'][$groupHash])) {
$this->error('请求非法', url('/wiki/index'));
}
}
$apiList = (new AdminList())->whereIn('hash', $this->appInfo['app_api_show'][$groupHash])->where(['groupHash' => $groupHash])->select();
$apiList = Tools::buildArrFromObj($apiList);
$apiList = Tools::buildArrByNewKey($apiList, 'hash');
if (!$hash) {
$hash = $this->appInfo['app_api_show'][$groupHash][0];
}
$detail = $apiList[$hash];
$request = AdminFields::all(['hash' => $hash, 'type' => 0]);
$response = AdminFields::all(['hash' => $hash, 'type' => 1]);
$dataType = array(
DataType::TYPE_INTEGER => 'Integer',
DataType::TYPE_STRING => 'String',
DataType::TYPE_BOOLEAN => 'Boolean',
DataType::TYPE_ENUM => 'Enum',
DataType::TYPE_FLOAT => 'Float',
DataType::TYPE_FILE => 'File',
DataType::TYPE_ARRAY => 'Array',
DataType::TYPE_OBJECT => 'Object',
DataType::TYPE_MOBILE => 'Mobile'
);
$groupInfo = AdminGroup::get(['hash' => $groupHash]);
$groupInfo->hot = $groupInfo->hot + 1;
$groupInfo->save();
return view('', [
'groupInfo' => $groupInfo->toArray(),
'request' => $request,
'response' => $response,
'dataType' => $dataType,
'apiList' => $apiList,
'detail' => $detail,
'hash' => $hash,
'groupHash' => $groupHash
]);
}
public function calculation() {
$this->checkLogin();
return view();
}
public function errorCode() {
$this->checkLogin();
$codeArr = ReturnCode::getConstants();
$errorInfo = array(
ReturnCode::SUCCESS => '请求成功',
ReturnCode::INVALID => '非法操作',
ReturnCode::DB_SAVE_ERROR => '数据存储失败',
ReturnCode::DB_READ_ERROR => '数据读取失败',
ReturnCode::CACHE_SAVE_ERROR => '缓存存储失败',
ReturnCode::CACHE_READ_ERROR => '缓存读取失败',
ReturnCode::FILE_SAVE_ERROR => '文件读取失败',
ReturnCode::LOGIN_ERROR => '登录失败',
ReturnCode::NOT_EXISTS => '不存在',
ReturnCode::JSON_PARSE_FAIL => 'JSON数据格式错误',
ReturnCode::TYPE_ERROR => '类型错误',
ReturnCode::NUMBER_MATCH_ERROR => '数字匹配失败',
ReturnCode::EMPTY_PARAMS => '丢失必要数据',
ReturnCode::DATA_EXISTS => '数据已经存在',
ReturnCode::AUTH_ERROR => '权限认证失败',
ReturnCode::OTHER_LOGIN => '别的终端登录',
ReturnCode::VERSION_INVALID => 'API版本非法',
ReturnCode::CURL_ERROR => 'CURL操作异常',
ReturnCode::RECORD_NOT_FOUND => '记录未找到',
ReturnCode::DELETE_FAILED => '删除失败',
ReturnCode::ADD_FAILED => '添加记录失败',
ReturnCode::UPDATE_FAILED => '更新记录失败',
ReturnCode::PARAM_INVALID => '数据类型非法',
ReturnCode::ACCESS_TOKEN_TIMEOUT => '身份令牌过期',
ReturnCode::SESSION_TIMEOUT => 'SESSION过期',
ReturnCode::UNKNOWN => '未知错误',
ReturnCode::EXCEPTION => '系统异常',
);
return view('', [
'errorInfo' => $errorInfo,
'codeArr' => $codeArr
]);
}
public function login() {
return view();
}
/**
* 处理wiki登录
* @throws \think\Exception
* @throws \think\exception\DbException
* @author zhaoxiang <zhaoxiang051405@gmail.com>
*/
public function doLogin() {
$appId = $this->request->post('appId');
$appSecret = $this->request->post('appSecret');
$appInfo = AdminApp::get(['app_id' => $appId, 'app_secret' => $appSecret]);
if (!empty($appInfo)) {
if ($appInfo->app_status) {
//保存用户信息和登录凭证
session('app_info', json_encode($appInfo));
$this->success('登录成功', url('/wiki/index'));
} else {
$this->error('当前应用已被封禁,请联系管理员');
}
} else {
$this->error('AppId或AppSecret错误');
}
}
public function logout() {
session('app_info', null);
$this->success('退出成功', url('/wiki/login'));
}
}

View File

@ -1,44 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{:config('apiAdmin.APP_NAME')} - 算法说明</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.11/semantic.min.css" rel="stylesheet">
</head>
<body>
<br />
<div class="ui text container" style="max-width: none !important;">
<div class="ui floating message">
<h1 class="ui header">{:config('apiAdmin.APP_NAME')} - 算法说明 </h1>
<a href="{:url('/wiki/index')}">
<button class="ui green button" style="margin-top: 15px">返回接口文档</button>
</a>
<div class="ui red message">
<strong>特别说明:</strong> 此算法文档会根据业务发展需求发生变更,为了服务的稳定运行,请及时关注此文档!
</div>
<div class="ui piled segment">
<div class="ui horizontal divider">简介</div>
<p>当前算法主要服务于获取身份令牌AccessToken所进行的身份认证秘钥signature的计算。在请求高级接口的时候系统会验证应用的合法性也就是验证AccessToken。所以AccessToken是请求API的必要参数。</p>
<p>在请求获取AccessToken的接口时候服务器会对用户合法性signature进行核验具体的接口请求字段请参看具体的接口文档。</p>
<div class="ui horizontal divider">一、获取app_id和app_secret</div>
<p>目前获取应用ID和应用秘钥是由系统管理员发放如果你还没有请联系管理员。<b>请注意app_secret非常重要请妥善保管</b></p>
<div class="ui horizontal divider">二、准备加密对象,并且根据字段名降序排序</div>
<pre>//排序好后应当是如下所示的数据
{
"app_id":"服务器颁发的应用ID",
"app_secret":"服务器颁发的应用秘钥", //请注意此字段只是在计算加密串的时候在被加入API请求请勿传递此字段值
"device_id":"设备唯一ID",
"rand_str":"随机字符串",
"timestamp":当前系统时间戳
}</pre>
<div class="ui horizontal divider">三、生成原始串</div>
<p>将上面的数据构建成HTTP查询字符串如下所示:</p>
<p>app_id=服务器颁发的应用ID&amp;app_secret=服务器颁发的应用秘钥&amp;device_id=设备唯一ID&amp;rand_str=随机字符串&amp;timestamp=当前系统时间戳</p>
<div class="ui horizontal divider">四、计算秘钥</div>
<p>将第三步生成的字符串进行哈希计算md5获得最终身份认证秘钥。</p>
</div>
<p>&copy; Powered By <a href="http://www.apiadmin.org/" target="_blank">{:config('apiAdmin.APP_NAME')} {:config('apiAdmin.APP_VERSION')}</a> <p>
</div>
</div>
</body>
</html>

View File

@ -1,199 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{:config('apiAdmin.APP_NAME')} - 在线接口列表</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.11/semantic.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.11/components/tab.min.js"></script>
<link rel="stylesheet" href="__STATIC__/jsonFormater/jsonFormater.css">
<script type="text/javascript" src="__STATIC__/jsonFormater/jsonFormater.js"></script>
</head>
<body>
<br />
<div class="ui container">
<div class="ui segment">
<div class="ui items">
<div class="item">
<div class="image">
<img src="{$groupInfo['image'] ? $groupInfo['image'] : '/static/defaultImg.jpg'}">
</div>
<div class="content">
<span class="header">{$groupInfo['name']}</span>
<div class="description">
<p>{$groupInfo['description']}</p>
</div>
<div class="extra">
额外的细节
</div>
</div>
</div>
</div>
</div>
{php}$http_type = ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') || (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https')) ? 'https://' : 'http://';{/php}
<div class="ui teal big message" id="msg">接口访问地址:{$http_type}{$_SERVER['HTTP_HOST']}/api/{$hash}</div>
<div class="ui grid">
<div class="four wide column">
<div class="ui vertical menu" style="width: 100%;overflow: auto;">
{volist name="apiList" id="vo"}
<a class="{if condition="$hash == $vo['hash']"}active{/if} teal item" href="{:url('/wiki/detail/'.$groupHash.'/'.$vo["hash"])}">
{:mb_substr($vo['info'], 0, 11)}...
<div class="ui {if condition="$hash == $vo['hash']"}teal{/if} label"> &gt; </div>
</a>
{/volist}
</div>
</div>
<div class="twelve wide column">
<div class="ui floating message" id="detail" style="overflow: auto;">
<h2 class='ui header'>接口唯一标识:<a target="_blank" href="{$http_type}{$_SERVER['HTTP_HOST']}/api/{$hash}">{$hash}</a>{if condition="$detail['isTest'] == 1"}{$detail['apiClass']}{/if}</h2><br />
<div class="ui raised segment">
<span class="ui red ribbon large label">接口说明</span>
{if condition="$detail['status'] eq 0 "}
<span class='ui red label large'><i class="usb icon"></i>禁用</span>
{else /}
{if condition="$detail['isTest'] eq 1 "}
<span class='ui teal label large'><i class="usb icon"></i>测试</span>
{else /}
<span class='ui green label large'><i class="usb icon"></i>启用</span>
{/if}
{/if}
<span class="ui teal label large"><i class="certificate icon"></i>{:config('apiAdmin.APP_VERSION')}</span>
<span class="ui blue large label"><i class="chrome icon"></i>
{switch name="detail['method']"}
{case value="1" break="1"}POST{/case}
{case value="2" break="1"}GET{/case}
{default /}不限
{/switch}
</span>
<div class="ui message">
<p>{$detail['info']}</p>
</div>
</div>
<div class="ui pointing large blue three item menu">
<a class="item active" data-tab="first">请求参数</a>
<a class="item" data-tab="second">返回参数</a>
<a class="item" data-tab="third">返回示例</a>
</div>
<div class="ui tab segment active" data-tab="first">
<h3>公共请求参数</h3>
<table class="ui orange celled striped table" >
<thead>
<tr><th>参数名字</th><th>类型</th><th width="70">是否必须</th><th>默认值</th><th width="30%">其他</th><th>说明</th></tr>
</thead>
<tbody>
<tr>
<td>version</td>
<td>String</td>
<td><span class="ui green label">必填</span></td>
<td>{:config('apiAdmin.APP_VERSION')}</td>
<td></td>
<td>API版本号【请在Header头里面传递】</td>
</tr>
<tr>
<td>access-token</td>
<td>String</td>
<td>{$detail['accessToken']==1?'<span class="ui green label">必填</span>':'<span class="ui red label">勿填</span>'}</td>
<td></td>
<td></td>
<td>APP认证秘钥【请在Header头里面传递】</td>
</tr>
<tr>
<td>user-token</td>
<td>String</td>
<td>{$detail['needLogin']==1?'<span class="ui green label">必填</span>':'<span class="ui red label">勿填</span>'}</td>
<td></td>
<td></td>
<td>用户认证秘钥【请在Header头里面传递】</td>
</tr>
</tbody>
</table>
<h3>请求参数</h3>
<table class="ui red celled striped table" >
<thead>
<tr><th>参数名字</th><th>类型</th><th width="70">是否必须</th><th>默认值</th><th>其他</th><th>说明</th></tr>
</thead>
<tbody>
{volist name="request" id="vo"}
<tr>
<td>{$vo['fieldName']}</td>
<td>{$dataType[$vo['dataType']]}</td>
<td>{$vo['isMust']==1?'<span class="ui green label">必填</span>':'<span class="ui teal label">可选</span>'}</td>
<td>{$vo['default']}</td>
<td>{$vo['range']}</td>
<td>{$vo['info']}</td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="ui tab segment" data-tab="second">
<h3>公共返回参数</h3>
<table class="ui olive celled striped table" >
<thead>
<tr><th>返回字段</th><th>类型</th><th>说明</th></tr>
</thead>
<tbody>
<tr>
<td>code</td>
<td>Integer</td>
<td>返回码,详情请参阅<a href="{:url('/errorCode')}">错误码说明</a></td>
</tr>
<tr>
<td>msg</td>
<td>String</td>
<td>错误描述,当请求成功时可能为空</td>
</tr>
<tr>
<td>debug</td>
<td>String</td>
<td>调试字段,如果没有调试信息会没有此字段</td>
</tr>
</tbody>
</table>
<h3>返回参数</h3>
<table class="ui green celled striped table" >
<thead>
<tr><th>返回字段</th><th>类型</th><th>说明</th></tr>
</thead>
<tbody>
{volist name="response" id="vo"}
<tr>
<td>{$vo['showName']}</td>
<td>{$dataType[$vo['dataType']]}</td>
<td>{$vo['info']}</td>
</tr>
{/volist}
</tbody>
</table>
</div>
<div class="ui tab segment" data-tab="third">
<pre id="json" style='font-family: Arial;'></pre>
</div>
<div class="ui blue message">
<strong>温馨提示:</strong> 此接口参数列表根据后台代码自动生成,如有疑问请咨询后端开发
</div>
<p>&copy; Powered By <a href="http://www.apiadmin.org/" target="_blank">{:config('apiAdmin.APP_NAME')} {:config('apiAdmin.APP_VERSION')}</a> <p>
</div>
</div>
</div>
</div>
</body>
<script>
$('.pointing.menu .item').tab();
$(document).ready(function () {
var s = function () {
var options = {
dom: '#json',
isCollapsible: true,
quoteKeys: true,
tabSize: 2,
imgCollapsed: "__STATIC__/jsonFormater/Collapsed.gif",
imgExpanded: "__STATIC__/jsonFormater/Expanded.gif"
};
window.jf = new JsonFormater(options);
jf.doFormat({$detail["returnStr"]});
}();
});
$('.ui .vertical').css('max-height', $('#detail').outerHeight(true));
</script>
</html>

View File

@ -1,45 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{:config('apiAdmin.APP_NAME')} - 错误码说明</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.11/semantic.min.css" rel="stylesheet">
</head>
<body>
<br />
<div class="ui text container" style="max-width: none !important;">
<div class="ui floating message">
<h1 class="ui header">{:config('apiAdmin.APP_NAME')} - 错误码说明</h1>
<a href="{:url('/wiki/index')}">
<button class="ui green button" style="margin-top: 15px">返回接口文档</button>
</a>
<table class="ui red celled striped table">
<thead>
<tr>
<th>#</th><th>英文标识</th><th>错误码</th><th>中文说明</th>
</tr>
</thead>
<tbody>
{volist name="codeArr" id="vo"}
<tr>
<td>
{$i}
</td>
<td>
{$key}
</td>
<td>
<b>{$vo}</b>
</td>
<td>
{$errorInfo[$vo]}
</td>
</tr>
{/volist}
</tbody>
</table>
<p>&copy; Powered By <a href="http://www.apiadmin.org/" target="_blank">{:config('apiAdmin.APP_NAME')} {:config('apiAdmin.APP_VERSION')}</a> <p>
</div>
</div>
</body>
</html>

View File

@ -1,78 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>{:config('apiAdmin.APP_NAME')} - 在线接口文档</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.11/semantic.min.css" rel="stylesheet">
</head>
<body>
<br />
<div class="ui text container" style="max-width: none !important;">
<div class="ui floating message">
<h1 class="ui header">{:config('apiAdmin.APP_NAME')} - 接口文档</h1>
<a href="{:url('/wiki/errorCode')}">
<button class="ui red button" style="margin-top: 15px">错误码说明</button>
</a>
<a href="{:url('/wiki/calculation')}">
<button class="ui orange button" style="margin-top: 15px">算法详解</button>
</a>
<div class="ui floating message">
<div class="content">
<div class="header" style="margin-bottom: 15px">接口状态说明:</div>
<p><span class='ui teal label'>测试</span> 系统将不过滤任何字段也不进行AccessToken的认证但在必要的情况下会进行UserToken的认证</p>
<p><span class='ui blue label'>启用</span> 系统将严格过滤请求字段,并且进行全部必要认证!</p>
<p><span class='ui red label'>禁用</span> 系统将拒绝所有请求,一般应用于危机处理!</p>
</div>
</div>
<div class="ui cards four column">
{volist name="appInfo['app_api_show']" id="vo"}
{php}
$apiLength = count($vo);
{/php}
{if condition="$apiLength"}
<div class="card column">
<a class="image" href="{:url('/wiki/detail/' . $key)}">
<img src="{$groupInfo[$key]['image'] ? $groupInfo[$key]['image'] : '/static/defaultImg.jpg'}">
</a>
<div class="content">
<a class="header" href="{:url('/wiki/detail/' . $key)}">
{$groupInfo[$key]['name']}
</a>
<a class="meta" href="{:url('/wiki/detail/' . $key)}">
<span class="group" style="font-size: 0.8em;">{:date('Y-m-d', $groupInfo[$key]['updateTime'])}</span>
</a>
<a class="description" style="display: block;font-size: 0.8em;" href="{:url('/wiki/detail/' . $key)}">
{php}
$len = mb_strlen($groupInfo[$key]['description'], 'utf8');
if($len > 31) {
echo mb_substr($groupInfo[$key]['description'], 0, 31, 'utf8') . ' ...';
} else {
echo $groupInfo[$key]['description'];
}
if ($groupInfo[$key]['hot'] >= 10000) {
$hot = sprintf("%.1f", $groupInfo[$key]['hot']/10000) . '万';
} else {
$hot = $groupInfo[$key]['hot'];
}
{/php}
</a>
</div>
<div class="extra content" style="font-size: 0.9em">
<a class="right floated created" href="{:url('/wiki/detail/' . $key)}">
<i class="fire icon"></i>
热度{$hot}
</a>
<a class="friends" href="{:url('/wiki/detail/' . $key)}">
<i class="cubes icon"></i>
共{$apiLength}个接口
</a>
</div>
</div>
{/if}
{/volist}
</div>
<p>&copy; Powered By <a href="http://www.apiadmin.org/" target="_blank">{:config('apiAdmin.APP_NAME')} {:config('apiAdmin.APP_VERSION')}</a> <p>
</div>
</div>
</body>
</html>

View File

@ -1,96 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<!-- Standard Meta -->
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<!-- Site Properties -->
<title>{:config('apiAdmin.APP_NAME')} - 在线接口文档</title>
<link href="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.11/semantic.min.css" rel="stylesheet">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.11/components/form.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/semantic-ui/2.2.11/components/transition.min.js"></script>
<style type="text/css">
body {
background-color: #DADADA;
}
body > .grid {
height: 100%;
}
.image {
margin-top: -100px;
}
.column {
max-width: 450px;
}
</style>
<script>
$(document)
.ready(function() {
$('.ui.form')
.form({
fields: {
email: {
identifier : 'appId',
rules: [
{
type : 'empty',
prompt : 'AppId不能为空'
}
]
},
password: {
identifier : 'appSecret',
rules: [
{
type : 'empty',
prompt : 'AppSecret不能为空'
}
]
}
}
})
;
})
;
</script>
</head>
<body>
<div class="ui middle aligned center aligned grid">
<div class="column">
<h2 class="ui teal image header">
<div class="content">
欢迎使用{:config('apiAdmin.APP_NAME')}在线文档
</div>
</h2>
<form class="ui large form" method="post" action="{:url('/wiki/doLogin')}">
<div class="ui stacked segment">
<div class="field">
<div class="ui left icon input">
<i class="user icon"></i>
<input type="text" name="appId" placeholder="请输入您的AppId">
</div>
</div>
<div class="field">
<div class="ui left icon input">
<i class="lock icon"></i>
<input type="password" name="appSecret" placeholder="请输入您的AppSecret">
</div>
</div>
<div class="ui fluid large teal submit button">提 交</div>
</div>
<div class="ui error message"></div>
</form>
<div class="ui message">
如果您没有AppId和AppSecret请联系服务供应商获取
</div>
</div>
</div>
</body>
</html>

View File

@ -1,38 +0,0 @@
<?php
/**
* wiki路由
*/
return [
'[wiki]' => [
'login' => [
'wiki/index/login',
['method' => 'get']
],
'doLogin' => [
'wiki/index/doLogin',
['method' => 'post']
],
'index' => [
'wiki/index/index',
['method' => 'get']
],
'calculation' => [
'wiki/index/calculation',
['method' => 'get']
],
'errorCode' => [
'wiki/index/errorCode',
['method' => 'get']
],
'detail/:groupHash/[:hash]' => [
'wiki/index/detail',
['method' => 'get']
],
'logout' => [
'wiki/index/logout',
['method' => 'get']
],
'__miss__' => ['wiki/index/index'],
],
];

View File

@ -1,25 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
return [
// 生成应用公共文件
'__file__' => ['common.php', 'config.php', 'database.php'],
// 定义demo模块的自动生成 (按照实际定义的文件名生成)
'demo' => [
'__file__' => ['common.php'],
'__dir__' => ['behavior', 'controller', 'model', 'view'],
'controller' => ['Index', 'Test', 'UserType'],
'model' => ['User', 'UserType'],
'view' => ['index/index'],
],
// 其他更多的模块定义
];

View File

@ -1,33 +0,0 @@
{
"name": "apiadmin/apiadmin3",
"description": "the api manager",
"type": "project",
"keywords": [
"api",
"apiadmin",
"tp5"
],
"homepage": "http://www.apiadmin.org/",
"license": "Apache-2.0",
"authors": [
{
"name": "zhao",
"email": "756958008@qq.com"
}
],
"autoload": {
"psr-4": {
"app\\": "application"
}
},
"require": {
"php": ">=5.6.0",
"php-curl-class/php-curl-class": "^8.0"
},
"extra": {
"think-path": "thinkphp"
},
"config": {
"preferred-install": "dist"
}
}

77
composer.lock generated
View File

@ -1,77 +0,0 @@
{
"_readme": [
"This file locks the dependencies of your project to a known state",
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
"This file is @generated automatically"
],
"content-hash": "c38a84a081b633a51738b670cdfef2fd",
"packages": [
{
"name": "php-curl-class/php-curl-class",
"version": "8.0.2",
"source": {
"type": "git",
"url": "https://github.com/php-curl-class/php-curl-class.git",
"reference": "75597b28c454acd9767e6182371376916cdb8531"
},
"dist": {
"type": "zip",
"url": "https://files.phpcomposer.com/files/php-curl-class/php-curl-class/75597b28c454acd9767e6182371376916cdb8531.zip",
"reference": "75597b28c454acd9767e6182371376916cdb8531",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=5.3"
},
"require-dev": {
"phpunit/phpunit": "*",
"squizlabs/php_codesniffer": "*"
},
"type": "library",
"autoload": {
"psr-4": {
"Curl\\": "src/Curl/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"Unlicense"
],
"authors": [
{
"name": "Zach Borboa"
}
],
"description": "PHP Curl Class makes it easy to send HTTP requests and integrate with web APIs.",
"homepage": "https://github.com/php-curl-class/php-curl-class",
"keywords": [
"api",
"class",
"client",
"curl",
"framework",
"http",
"http client",
"json",
"php",
"requests",
"rest",
"restful",
"web service",
"xml"
],
"time": "2018-04-09T08:28:13+00:00"
}
],
"packages-dev": [],
"aliases": [],
"minimum-stability": "stable",
"stability-flags": [],
"prefer-stable": false,
"prefer-lowest": false,
"platform": {
"php": ">=5.6.0"
},
"platform-dev": []
}

View File

@ -1,15 +0,0 @@
<?php
/**
* Api路由
*/
use think\Route;
Route::group('api', function () {
Route::miss('api/Miss/index');
});
$afterBehavior = [
'\app\api\behavior\ApiAuth',
'\app\api\behavior\ApiPermission',
'\app\api\behavior\RequestFilter'
];

View File

@ -1,358 +0,0 @@
# ************************************************************
# Sequel Pro SQL dump
# Version 4541
#
# http://www.sequelpro.com/
# https://github.com/sequelpro/sequelpro
#
# Host: 127.0.0.1 (MySQL 5.5.5-10.2.12-MariaDB)
# Database: apiadmin_new
# Generation Time: 2018-06-10 07:00:01 +0000
# ************************************************************
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;
# Dump of table admin_app
# ------------------------------------------------------------
DROP TABLE IF EXISTS `admin_app`;
CREATE TABLE `admin_app` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`app_id` varchar(50) NOT NULL DEFAULT '' COMMENT '应用id',
`app_secret` varchar(50) NOT NULL DEFAULT '' COMMENT '应用密码',
`app_name` varchar(50) NOT NULL DEFAULT '' COMMENT '应用名称',
`app_status` tinyint(2) NOT NULL DEFAULT 1 COMMENT '应用状态0表示禁用1表示启用',
`app_info` tinytext DEFAULT NULL COMMENT '应用说明',
`app_api` text DEFAULT NULL COMMENT '当前应用允许请求的全部API接口',
`app_group` varchar(128) NOT NULL DEFAULT 'default' COMMENT '当前应用所属的应用组唯一标识',
`app_addTime` int(11) NOT NULL DEFAULT 0 COMMENT '应用创建时间',
`app_api_show` text DEFAULT NULL COMMENT '前台样式显示所需数据格式',
PRIMARY KEY (`id`),
UNIQUE KEY `app_id` (`app_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='appId和appSecret表';
# Dump of table admin_app_group
# ------------------------------------------------------------
DROP TABLE IF EXISTS `admin_app_group`;
CREATE TABLE `admin_app_group` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL DEFAULT '' COMMENT '组名称',
`description` text DEFAULT NULL COMMENT '组说明',
`status` tinyint(2) NOT NULL DEFAULT 1 COMMENT '组状态',
`hash` varchar(128) NOT NULL DEFAULT '' COMMENT '组标识',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='应用组,目前只做管理使用,没有实际权限控制';
# Dump of table admin_auth_group
# ------------------------------------------------------------
DROP TABLE IF EXISTS `admin_auth_group`;
CREATE TABLE `admin_auth_group` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '组名称',
`description` varchar(50) DEFAULT '' COMMENT '组描述',
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '组状态为1正常为0禁用',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='权限组';
# Dump of table admin_auth_group_access
# ------------------------------------------------------------
DROP TABLE IF EXISTS `admin_auth_group_access`;
CREATE TABLE `admin_auth_group_access` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`uid` mediumint(8) unsigned NOT NULL,
`groupId` varchar(255) NOT NULL DEFAULT '',
PRIMARY KEY (`id`),
KEY `uid` (`uid`),
KEY `groupId` (`groupId`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户和组的对应关系';
# Dump of table admin_auth_rule
# ------------------------------------------------------------
DROP TABLE IF EXISTS `admin_auth_rule`;
CREATE TABLE `admin_auth_rule` (
`id` mediumint(8) unsigned NOT NULL AUTO_INCREMENT,
`url` char(80) NOT NULL DEFAULT '' COMMENT '规则唯一标识',
`groupId` int(11) unsigned NOT NULL DEFAULT 0 COMMENT '权限所属组的ID',
`auth` int(11) unsigned NOT NULL DEFAULT 0 COMMENT '权限数值',
`status` tinyint(1) unsigned NOT NULL DEFAULT 1 COMMENT '状态为1正常为0禁用',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='权限细节';
# Dump of table admin_fields
# ------------------------------------------------------------
DROP TABLE IF EXISTS `admin_fields`;
CREATE TABLE `admin_fields` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`fieldName` varchar(50) NOT NULL DEFAULT '' COMMENT '字段名称',
`hash` varchar(50) NOT NULL DEFAULT '' COMMENT '对应接口的唯一标识',
`dataType` tinyint(2) NOT NULL DEFAULT 0 COMMENT '数据类型来源于DataType类库',
`default` varchar(500) NOT NULL DEFAULT '' COMMENT '默认值',
`isMust` tinyint(2) NOT NULL DEFAULT 0 COMMENT '是否必须 0为不必须1为必须',
`range` varchar(500) NOT NULL DEFAULT '' COMMENT '范围Json字符串根据数据类型有不一样的含义',
`info` varchar(500) NOT NULL DEFAULT '' COMMENT '字段说明',
`type` tinyint(2) NOT NULL DEFAULT 0 COMMENT '字段用处0为request1为response',
`showName` varchar(50) NOT NULL DEFAULT '' COMMENT 'wiki显示用字段',
PRIMARY KEY (`id`),
KEY `hash` (`hash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用于保存各个API的字段规则';
# Dump of table admin_group
# ------------------------------------------------------------
DROP TABLE IF EXISTS `admin_group`;
CREATE TABLE `admin_group` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(128) NOT NULL DEFAULT '' COMMENT '组名称',
`description` text DEFAULT NULL COMMENT '组说明',
`status` tinyint(2) NOT NULL DEFAULT 1 COMMENT '组状态',
`hash` varchar(64) NOT NULL DEFAULT '' COMMENT '组唯一标识',
`addTime` int(11) NOT NULL DEFAULT 0 COMMENT '创建时间',
`updateTime` int(11) NOT NULL DEFAULT 0 COMMENT '修改时间',
`image` varchar(256) DEFAULT NULL COMMENT '分组封面图',
`hot` int(11) NOT NULL DEFAULT 0 COMMENT '分组热度',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='接口组管理';
LOCK TABLES `admin_group` WRITE;
/*!40000 ALTER TABLE `admin_group` DISABLE KEYS */;
INSERT INTO `admin_group` (`id`, `name`, `description`, `status`, `hash`, `addTime`, `updateTime`, `image`, `hot`)
VALUES
(1,'默认分组','默认分组',1,'default',0,0,'',0);
/*!40000 ALTER TABLE `admin_group` ENABLE KEYS */;
UNLOCK TABLES;
# Dump of table admin_list
# ------------------------------------------------------------
DROP TABLE IF EXISTS `admin_list`;
CREATE TABLE `admin_list` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`apiClass` varchar(50) NOT NULL DEFAULT '' COMMENT 'api索引保存了类和方法',
`hash` varchar(50) NOT NULL DEFAULT '' COMMENT 'api唯一标识',
`accessToken` tinyint(2) NOT NULL DEFAULT 1 COMMENT '是否需要认证AccessToken 1需要0不需要',
`needLogin` tinyint(2) NOT NULL DEFAULT 1 COMMENT '是否需要认证用户token 1需要 0不需要',
`status` tinyint(2) NOT NULL DEFAULT 1 COMMENT 'API状态0表示禁用1表示启用',
`method` tinyint(2) NOT NULL DEFAULT 2 COMMENT '请求方式0不限1Post2Get',
`info` varchar(500) DEFAULT '' COMMENT 'api中文说明',
`isTest` tinyint(2) NOT NULL DEFAULT 0 COMMENT '是否是测试模式0:生产模式1测试模式',
`returnStr` text DEFAULT NULL COMMENT '返回数据示例',
`groupHash` varchar(64) NOT NULL DEFAULT 'default' COMMENT '当前接口所属的接口分组',
PRIMARY KEY (`id`),
UNIQUE KEY `hash` (`hash`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用于维护接口信息';
# Dump of table admin_menu
# ------------------------------------------------------------
DROP TABLE IF EXISTS `admin_menu`;
CREATE TABLE `admin_menu` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(50) NOT NULL DEFAULT '' COMMENT '菜单名',
`fid` int(11) NOT NULL COMMENT '父级菜单ID',
`url` varchar(50) NOT NULL DEFAULT '' COMMENT '链接',
`auth` tinyint(2) NOT NULL DEFAULT 0 COMMENT '访客权限',
`sort` int(11) NOT NULL DEFAULT 0 COMMENT '排序',
`hide` tinyint(2) NOT NULL DEFAULT 0 COMMENT '是否显示',
`icon` varchar(50) NOT NULL DEFAULT '' COMMENT '菜单图标',
`level` tinyint(2) NOT NULL DEFAULT 0 COMMENT '菜单认证等级',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='目录信息';
LOCK TABLES `admin_menu` WRITE;
/*!40000 ALTER TABLE `admin_menu` DISABLE KEYS */;
INSERT INTO `admin_menu` (`id`, `name`, `fid`, `url`, `auth`, `sort`, `hide`, `icon`, `level`)
VALUES
(1,'用户登录',0,'admin/Login/index',0,0,0,'',0),
(2,'用户登出',0,'admin/Login/logout',0,0,0,'',0),
(3,'系统管理',0,'',0,1,0,'',0),
(4,'菜单维护',3,'',0,1,0,'',0),
(5,'菜单状态修改',4,'admin/Menu/changeStatus',0,0,0,'',0),
(6,'新增菜单',4,'admin/Menu/add',0,0,0,'',0),
(7,'编辑菜单',4,'admin/Menu/edit',0,0,0,'',0),
(8,'菜单删除',4,'admin/Menu/del',0,0,0,'',0),
(9,'用户管理',3,'',0,2,0,'',0),
(10,'获取当前组的全部用户',9,'admin/User/getUsers',0,0,0,'',0),
(11,'用户状态修改',9,'admin/User/changeStatus',0,0,0,'',0),
(12,'新增用户',9,'admin/User/add',0,0,0,'',0),
(13,'用户编辑',9,'admin/User/edit',0,0,0,'',0),
(14,'用户删除',9,'admin/User/del',0,0,0,'',0),
(15,'权限管理',3,'',0,3,0,'',0),
(16,'权限组状态编辑',15,'admin/Auth/changeStatus',0,0,0,'',0),
(17,'从指定组中删除指定用户',15,'admin/Auth/delMember',0,0,0,'',0),
(18,'新增权限组',15,'admin/Auth/add',0,0,0,'',0),
(19,'权限组编辑',15,'admin/Auth/edit',0,0,0,'',0),
(20,'删除权限组',15,'admin/Auth/del',0,0,0,'',0),
(21,'获取全部已开放的可选组',15,'admin/Auth/getGroups',0,0,0,'',0),
(22,'获取组所有的权限列表',15,'admin/Auth/getRuleList',0,0,0,'',0),
(23,'应用接入',0,'',0,2,0,'',0),
(24,'应用管理',23,'',0,0,0,'',0),
(25,'应用状态编辑',24,'admin/App/changeStatus',0,0,0,'',0),
(26,'获取AppId,AppSecret,接口列表,应用接口权限细节',24,'admin/App/getAppInfo',0,0,0,'',0),
(27,'新增应用',24,'admin/App/add',0,0,0,'',0),
(28,'编辑应用',24,'admin/App/edit',0,0,0,'',0),
(29,'删除应用',24,'admin/App/del',0,0,0,'',0),
(30,'接口管理',0,'',0,3,0,'',0),
(31,'接口维护',30,'',0,0,0,'',0),
(32,'接口状态编辑',31,'admin/InterfaceList/changeStatus',0,0,0,'',0),
(33,'获取接口唯一标识',31,'admin/InterfaceList/getHash',0,0,0,'',0),
(34,'添加接口',31,'admin/InterfaceList/add',0,0,0,'',0),
(35,'编辑接口',31,'admin/InterfaceList/edit',0,0,0,'',0),
(36,'删除接口',31,'admin/InterfaceList/del',0,0,0,'',0),
(37,'获取接口请求字段',31,'admin/Fields/request',0,0,0,'',0),
(38,'获取接口返回字段',31,'admin/Fields/response',0,0,0,'',0),
(39,'添加接口字段',31,'admin/Fields/add',0,0,0,'',0),
(40,'上传接口返回字段',31,'admin/Fields/upload',0,0,0,'',0),
(41,'编辑接口字段',31,'admin/Fields/edit',0,0,0,'',0),
(42,'删除接口字段',31,'admin/Fields/del',0,0,0,'',0),
(43,'接口分组',30,'',0,1,0,'',0),
(44,'添加接口组',43,'admin/InterfaceGroup/add',0,0,0,'',0),
(45,'编辑接口组',43,'admin/InterfaceGroup/edit',0,0,0,'',0),
(46,'删除接口组',43,'admin/InterfaceGroup/del',0,0,0,'',0),
(47,'获取全部有效的接口组',43,'admin/InterfaceGroup/getAll',0,0,0,'',0),
(48,'接口组状态维护',43,'admin/InterfaceGroup/changeStatus',0,0,0,'',0),
(49,'应用分组',23,'',0,1,0,'',0),
(50,'添加应用组',49,'admin/AppGroup/add',0,0,0,'',0),
(51,'编辑应用组',49,'admin/AppGroup/edit',0,0,0,'',0),
(52,'删除应用组',49,'admin/AppGroup/del',0,0,0,'',0),
(53,'获取全部可用应用组',49,'admin/AppGroup/getAll',0,0,0,'',0),
(54,'应用组状态编辑',49,'admin/AppGroup/changeStatus',0,0,0,'',0),
(55,'菜单列表',4,'admin/Menu/index',0,0,0,'',0),
(56,'用户列表',9,'admin/User/index',0,0,0,'',0),
(57,'权限列表',15,'admin/Auth/index',0,0,0,'',0),
(58,'应用列表',24,'admin/App/index',0,0,0,'',0),
(59,'应用分组列表',49,'admin/AppGroup/index',0,0,0,'',0),
(60,'接口列表',31,'admin/InterfaceList/index',0,0,0,'',0),
(61,'接口分组列表',43,'admin/InterfaceGroup/index',0,0,0,'',0),
(62,'日志管理',3,'',0,4,0,'',0),
(63,'获取操作日志列表',62,'admin/Log/index',0,0,0,'',0),
(64,'删除单条日志记录',62,'admin/Log/del',0,0,0,'',0),
(65,'刷新路由',31,'admin/InterfaceList/refresh',0,0,0,'',0),
(67,'文件上传',0,'admin/Index/upload',0,0,0,'',0),
(68,'更新个人信息',9,'admin/User/own',0,0,0,'',0),
(69,'刷新AppSecret',24,'admin/App/refreshAppSecret',0,0,0,'',0);
/*!40000 ALTER TABLE `admin_menu` ENABLE KEYS */;
UNLOCK TABLES;
# Dump of table admin_user
# ------------------------------------------------------------
DROP TABLE IF EXISTS `admin_user`;
CREATE TABLE `admin_user` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`username` varchar(64) NOT NULL DEFAULT '' COMMENT '用户名',
`nickname` varchar(64) NOT NULL DEFAULT '' COMMENT '用户昵称',
`password` char(32) NOT NULL DEFAULT '' COMMENT '用户密码',
`regTime` int(10) NOT NULL DEFAULT 0 COMMENT '注册时间',
`regIp` bigint(11) NOT NULL COMMENT '注册IP',
`updateTime` int(10) NOT NULL DEFAULT 0 COMMENT '更新时间',
`status` tinyint(1) NOT NULL DEFAULT 1 COMMENT '账号状态 0封号 1正常',
`openId` varchar(100) DEFAULT NULL COMMENT '三方登录唯一ID',
PRIMARY KEY (`id`),
KEY `regTime` (`regTime`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管理员认证信息';
LOCK TABLES `admin_user` WRITE;
/*!40000 ALTER TABLE `admin_user` DISABLE KEYS */;
INSERT INTO `admin_user` (`id`, `username`, `nickname`, `password`, `regTime`, `regIp`, `updateTime`, `status`, `openId`)
VALUES
(1,'root','root','912601e4ad1b308c9ae41877cf6ca754',1519453594,3663623043,1524152828,1,NULL);
/*!40000 ALTER TABLE `admin_user` ENABLE KEYS */;
UNLOCK TABLES;
# Dump of table admin_user_action
# ------------------------------------------------------------
DROP TABLE IF EXISTS `admin_user_action`;
CREATE TABLE `admin_user_action` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`actionName` varchar(50) NOT NULL DEFAULT '' COMMENT '行为名称',
`uid` int(11) NOT NULL DEFAULT 0 COMMENT '操作用户ID',
`nickname` varchar(50) NOT NULL DEFAULT '' COMMENT '用户昵称',
`addTime` int(11) NOT NULL DEFAULT 0 COMMENT '操作时间',
`data` text DEFAULT NULL COMMENT '用户提交的数据',
`url` varchar(200) NOT NULL DEFAULT '' COMMENT '操作URL',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='用户操作日志';
# Dump of table admin_user_data
# ------------------------------------------------------------
DROP TABLE IF EXISTS `admin_user_data`;
CREATE TABLE `admin_user_data` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`loginTimes` int(11) NOT NULL DEFAULT 0 COMMENT '账号登录次数',
`lastLoginIp` bigint(11) NOT NULL DEFAULT 0 COMMENT '最后登录IP',
`lastLoginTime` int(11) NOT NULL DEFAULT 0 COMMENT '最后登录时间',
`uid` varchar(11) NOT NULL DEFAULT '' COMMENT '用户ID',
`headImg` text DEFAULT NULL COMMENT '用户头像',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='管理员数据表';
LOCK TABLES `admin_user_data` WRITE;
/*!40000 ALTER TABLE `admin_user_data` DISABLE KEYS */;
INSERT INTO `admin_user_data` (`id`, `loginTimes`, `lastLoginIp`, `lastLoginTime`, `uid`, `headImg`)
VALUES
(1,0,0,0,'1','');
/*!40000 ALTER TABLE `admin_user_data` ENABLE KEYS */;
UNLOCK TABLES;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;
/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;

2
extend/.gitignore vendored
View File

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

View File

@ -1,8 +0,0 @@
<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>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.1 KiB

View File

@ -1,17 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------
// [ 应用入口文件 ]
// 定义应用目录
define('APP_PATH', __DIR__ . '/../application/');
// 加载框架引导文件
require __DIR__ . '/../thinkphp/start.php';

View File

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

View File

@ -1,20 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2016 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["REQUEST_URI"])) {
return false;
} else {
if (!isset($_SERVER['PATH_INFO'])) {
$_SERVER['PATH_INFO'] = $_SERVER['REQUEST_URI'];
}
require __DIR__ . "/index.php";
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 215 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 206 B

View File

@ -1,35 +0,0 @@
@charset "utf-8";
/* CSS Document */
.jf-ObjectBrace {
color: #00AA00;
font-weight: bold;
}
.jf-ArrayBrace {
color: #0033FF;
font-weight: bold;
}
.jf-PropertyName {
color: #CC0000;
font-weight: bold;
}
.jf-String {
color: #007777;
}
.jf-Number {
color: #AA00AA;
}
.jf-Boolean {
color: #0000FF;
}
.jf-Null {
color: #0000FF;
}
.jf-Comma {
color: #000000;
font-weight: bold;
}
pre.jf-CodeContainer {
margin-top: 0;
margin-bottom: 0;
text-align: left;
}

View File

@ -1,202 +0,0 @@
function JsonFormater(opt) {
this.options = $.extend({
dom: '',
tabSize: 2,
singleTab: " ",
quoteKeys: true,
imgCollapsed: "images/Collapsed.gif",
imgExpanded: "images/Expanded.gif",
isCollapsible: true
}, opt || {});
this.isFormated = false;
this.obj = {
_dateObj: new Date(),
_regexpObj: new RegExp()
};
this.init();
}
JsonFormater.prototype = {
init: function () {
this.tab = this.multiplyString(this.options.tabSize, this.options.singleTab);
this.bindEvent();
},
doFormat: function (json) {
var html;
var obj;
try {
if(typeof json == 'object'){
obj = [json];
}else{
if (json == ""){
json = "\"\"";
}
obj = eval("[" + json + "]");
}
html = this.ProcessObject(obj[0], 0, false, false, false);
$(this.options.dom).addClass('jf-CodeContainer');
$(this.options.dom).html(html);
this.isFormated = true;
} catch (e) {
alert("JSON数据格式不正确:\n" + e.message);
$(this.options.dom).html("");
this.isFormated = false;
}
},
bindEvent: function () {
var that = this;
$(this.options.dom).off('click','.imgToggle');
$(this.options.dom).on('click', '.imgToggle', function () {
if (that.isFormated == false) {
return;
}
that.makeContentVisible($(this).parent().next(), !$(this).data('status'));
});
},
expandAll: function () {
if (this.isFormated == false) {
return;
}
var that = this;
this.traverseChildren($(this.options.dom), function(element){
if(element.hasClass('jf-collapsible')){
that.makeContentVisible(element, true);
}
}, 0);
},
collapseAll: function () {
if (this.isFormated == false) {
return;
}
var that = this;
this.traverseChildren($(this.options.dom), function(element){
if(element.hasClass('jf-collapsible')){
that.makeContentVisible(element, false);
}
}, 0);
},
collapseLevel: function(level){
if (this.isFormated == false) {
return;
}
var that = this;
this.traverseChildren($(this.options.dom), function(element, depth){
if(element.hasClass('jf-collapsible')){
if(depth >= level){
that.makeContentVisible(element, false);
}else{
that.makeContentVisible(element, true);
}
}
}, 0);
},
isArray: function (obj) {
return obj &&
typeof obj === 'object' &&
typeof obj.length === 'number' && !(obj.propertyIsEnumerable('length'));
},
getRow: function (indent, data, isPropertyContent) {
var tabs = "";
if (!isPropertyContent) {
tabs = this.multiplyString(indent, this.tab);
}
if (data != null && data.length > 0 && data.charAt(data.length - 1) != "\n") {
data = data + "\n";
}
return tabs + data;
},
formatLiteral: function (literal, quote, comma, indent, isArray, style) {
if (typeof literal == 'string') {
literal = literal.split("<").join("&lt;").split(">").join("&gt;");
}
var str = "<span class='jf-" + style + "'>" + quote + literal + quote + comma + "</span>";
if (isArray) str = this.getRow(indent, str);
return str;
},
formatFunction: function (indent, obj) {
var tabs;
var i;
var funcStrArray = obj.toString().split("\n");
var str = "";
tabs = this.multiplyString(indent, this.tab);
for (i = 0; i < funcStrArray.length; i++) {
str += ((i == 0) ? "" : tabs) + funcStrArray[i] + "\n";
}
return str;
},
multiplyString: function (num, str) {
var result = '';
for (var i = 0; i < num; i++) {
result += str;
}
return result;
},
traverseChildren: function (element, func, depth) {
var length = element.children().length;
for (var i = 0; i < length; i++) {
this.traverseChildren(element.children().eq(i), func, depth + 1);
}
func(element, depth);
},
makeContentVisible : function(element, visible){
var img = element.prev().find('img');
if(visible){
element.show();
img.attr('src', this.options.imgExpanded);
img.data('status', 1);
}else{
element.hide();
img.attr('src', this.options.imgCollapsed);
img.data('status', 0);
}
},
ProcessObject: function (obj, indent, addComma, isArray, isPropertyContent) {
var html = "";
var comma = (addComma) ? "<span class='jf-Comma'>,</span> " : "";
var type = typeof obj;
var clpsHtml = "";
var prop;
if (this.isArray(obj)) {
if (obj.length == 0) {
html += this.getRow(indent, "<span class='jf-ArrayBrace'>[ ]</span>" + comma, isPropertyContent);
} else {
clpsHtml = this.options.isCollapsible ? "<span><img class='imgToggle' data-status='1' src='" + this.options.imgExpanded + "'/></span><span class='jf-collapsible'>" : "";
html += this.getRow(indent, "<span class='jf-ArrayBrace'>[</span>" + clpsHtml, isPropertyContent);
for (var i = 0; i < obj.length; i++) {
html += this.ProcessObject(obj[i], indent + 1, i < (obj.length - 1), true, false);
}
clpsHtml = this.options.isCollapsible ? "</span>" : "";
html += this.getRow(indent, clpsHtml + "<span class='jf-ArrayBrace'>]</span>" + comma);
}
} else if (type == 'object') {
if (obj == null) {
html += this.formatLiteral("null", "", comma, indent, isArray, "Null");
} else {
var numProps = 0;
for (prop in obj) numProps++;
if (numProps == 0) {
html += this.getRow(indent, "<span class='jf-ObjectBrace'>{ }</span>" + comma, isPropertyContent);
} else {
clpsHtml = this.options.isCollapsible ? "<span><img class='imgToggle' data-status='1' src='" + this.options.imgExpanded + "'/></span><span class='jf-collapsible'>" : "";
html += this.getRow(indent, "<span class='jf-ObjectBrace'>{</span>" + clpsHtml, isPropertyContent);
var j = 0;
for (prop in obj) {
var quote = this.options.quoteKeys ? "\"" : "";
html += this.getRow(indent + 1, "<span class='jf-PropertyName'>" + quote + prop + quote + "</span>: " + this.ProcessObject(obj[prop], indent + 1, ++j < numProps, false, true));
}
clpsHtml = this.options.isCollapsible ? "</span>" : "";
html += this.getRow(indent, clpsHtml + "<span class='jf-ObjectBrace'>}</span>" + comma);
}
}
} else if (type == 'number') {
html += this.formatLiteral(obj, "", comma, indent, isArray, "Number");
} else if (type == 'boolean') {
html += this.formatLiteral(obj, "", comma, indent, isArray, "Boolean");
}else if (type == 'undefined') {
html += this.formatLiteral("undefined", "", comma, indent, isArray, "Null");
} else {
html += this.formatLiteral(obj.toString().split("\\").join("\\\\").split('"').join('\\"'), "\"", comma, indent, isArray, "String");
}
return html;
}
};

View File

17
think
View File

@ -1,17 +0,0 @@
#!/usr/bin/env php
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2016 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
// 定义项目路径
define('APP_PATH', __DIR__ . '/application/');
// 加载框架引导文件
require __DIR__.'/thinkphp/console.php';

4
thinkphp/.gitignore vendored
View File

@ -1,4 +0,0 @@
/composer.lock
/vendor
.idea
.DS_Store

View File

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

View File

@ -1,47 +0,0 @@
sudo: false
language: php
services:
- memcached
- mongodb
- mysql
- postgresql
- redis-server
matrix:
fast_finish: true
include:
- php: 5.4
- php: 5.5
- php: 5.6
- php: 7.0
- php: hhvm
allow_failures:
- php: hhvm
cache:
directories:
- $HOME/.composer/cache
before_install:
- composer self-update
- mysql -e "create database IF NOT EXISTS test;" -uroot
- psql -c 'DROP DATABASE IF EXISTS test;' -U postgres
- psql -c 'create database test;' -U postgres
install:
- ./tests/script/install.sh
script:
## LINT
- find . -path ./vendor -prune -o -type f -name \*.php -exec php -l {} \;
## PHP Copy/Paste Detector
- vendor/bin/phpcpd --verbose --exclude vendor ./ || true
## PHPLOC
- vendor/bin/phploc --exclude vendor ./
## PHPUNIT
- vendor/bin/phpunit --coverage-clover=coverage.xml --configuration=phpunit.xml
after_success:
- bash <(curl -s https://codecov.io/bash)

View File

@ -1,119 +0,0 @@
如何贡献我的源代码
===
此文档介绍了 ThinkPHP 团队的组成以及运转机制,您提交的代码将给 ThinkPHP 项目带来什么好处,以及如何才能加入我们的行列。
## 通过 Github 贡献代码
ThinkPHP 目前使用 Git 来控制程序版本,如果你想为 ThinkPHP 贡献源代码,请先大致了解 Git 的使用方法。我们目前把项目托管在 GitHub 上,任何 GitHub 用户都可以向我们贡献代码。
参与的方式很简单,`fork`一份 ThinkPHP 的代码到你的仓库中,修改后提交,并向我们发起`pull request`申请,我们会及时对代码进行审查并处理你的申请。审查通过后,你的代码将被`merge`进我们的仓库中,这样你就会自动出现在贡献者名单里了,非常方便。
我们希望你贡献的代码符合:
* ThinkPHP 的编码规范
* 适当的注释,能让其他人读懂
* 遵循 Apache2 开源协议
**如果想要了解更多细节或有任何疑问,请继续阅读下面的内容**
### 注意事项
* 本项目代码格式化标准选用 [**PSR-2**](http://www.kancloud.cn/thinkphp/php-fig-psr/3141)
* 类名和类文件名遵循 [**PSR-4**](http://www.kancloud.cn/thinkphp/php-fig-psr/3144)
* 对于 Issues 的处理,请使用诸如 `fix #xxx(Issue ID)` 的 commit title 直接关闭 issue。
* 系统会自动在 PHP 5.4 5.5 5.6 7.0 和 HHVM 上测试修改,其中 HHVM 下的测试容许报错,请确保你的修改符合 PHP 5.4 ~ 5.6 和 PHP 7.0 的语法规范;
* 管理员不会合并造成 CI faild 的修改,若出现 CI faild 请检查自己的源代码或修改相应的[单元测试文件](tests)
## GitHub Issue
GitHub 提供了 Issue 功能,该功能可以用于:
* 提出 bug
* 提出功能改进
* 反馈使用体验
该功能不应该用于:
* 提出修改意见(涉及代码署名和修订追溯问题)
* 不友善的言论
## 快速修改
**GitHub 提供了快速编辑文件的功能**
1. 登录 GitHub 帐号;
2. 浏览项目文件,找到要进行修改的文件;
3. 点击右上角铅笔图标进行修改;
4. 填写 `Commit changes` 相关内容Title 必填);
5. 提交修改,等待 CI 验证和管理员合并。
**若您需要一次提交大量修改,请继续阅读下面的内容**
## 完整流程
1. `fork`本项目;
2. 克隆(`clone`)你 `fork` 的项目到本地;
3. 新建分支(`branch`)并检出(`checkout`)新分支;
4. 添加本项目到你的本地 git 仓库作为上游(`upstream`)
5. 进行修改,若你的修改包含方法或函数的增减,请记得修改[单元测试文件](tests)
6. 变基(衍合 `rebase`)你的分支到上游 master 分支;
7. `push` 你的本地仓库到 GitHub
8. 提交 `pull request`
9. 等待 CI 验证(若不通过则重复 5~7不需要重新提交 `pull request`GitHub 会自动更新你的 `pull request`
10. 等待管理员处理,并及时 `rebase` 你的分支到上游 master 分支(若上游 master 分支有修改)。
*若有必要,可以 `git push -f` 强行推送 rebase 后的分支到自己的 `fork`*
*绝对不可以使用 `git push -f` 强行推送修改到上游*
### 注意事项
* 若对上述流程有任何不清楚的地方,请查阅 GIT 教程,如 [这个](http://backlogtool.com/git-guide/cn/)
* 对于代码**不同方面**的修改,请在自己 `fork` 的项目中**创建不同的分支**(原因参见`完整流程`第9条备注部分
* 变基及交互式变基操作参见 [Git 交互式变基](http://pakchoi.me/2015/03/17/git-interactive-rebase/)
## 推荐资源
### 开发环境
* XAMPP for Windows 5.5.x
* WampServer (for Windows)
* upupw Apache PHP5.4 ( for Windows)
或自行安装
- Apache / Nginx
- PHP 5.4 ~ 5.6
- MySQL / MariaDB
*Windows 用户推荐添加 PHP bin 目录到 PATH方便使用 composer*
*Linux 用户自行配置环境, Mac 用户推荐使用内置 Apache 配合 Homebrew 安装 PHP 和 MariaDB*
### 编辑器
Sublime Text 3 + phpfmt 插件
phpfmt 插件参数
```json
{
"autocomplete": true,
"enable_auto_align": true,
"format_on_save": true,
"indent_with_space": true,
"psr1_naming": false,
"psr2": true,
"version": 4
}
```
或其他 编辑器 / IDE 配合 PSR2 自动格式化工具
### Git GUI
* SourceTree
* GitHub Desktop
或其他 Git 图形界面客户端

View File

@ -1,32 +0,0 @@
ThinkPHP遵循Apache2开源协议发布并提供免费使用。
版权所有Copyright © 2006-2017 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.

View File

@ -1,114 +0,0 @@
ThinkPHP 5.0
===============
[![StyleCI](https://styleci.io/repos/48530411/shield?style=flat&branch=master)](https://styleci.io/repos/48530411)
[![Build Status](https://travis-ci.org/top-think/framework.svg?branch=master)](https://travis-ci.org/top-think/framework)
[![codecov.io](http://codecov.io/github/top-think/framework/coverage.svg?branch=master)](http://codecov.io/github/github/top-think/framework?branch=master)
[![Total Downloads](https://poser.pugx.org/topthink/framework/downloads)](https://packagist.org/packages/topthink/framework)
[![Latest Stable Version](https://poser.pugx.org/topthink/framework/v/stable)](https://packagist.org/packages/topthink/framework)
[![Latest Unstable Version](https://poser.pugx.org/topthink/framework/v/unstable)](https://packagist.org/packages/topthink/framework)
[![License](https://poser.pugx.org/topthink/framework/license)](https://packagist.org/packages/topthink/framework)
ThinkPHP5在保持快速开发和大道至简的核心理念不变的同时PHP版本要求提升到5.4优化核心减少依赖基于全新的架构思想和命名空间实现是ThinkPHP突破原有框架思路的颠覆之作其主要特性包括
+ 基于命名空间和众多PHP新特性
+ 核心功能组件化
+ 强化路由功能
+ 更灵活的控制器
+ 重构的模型和数据库类
+ 配置文件可分离
+ 重写的自动验证和完成
+ 简化扩展机制
+ API支持完善
+ 改进的Log类
+ 命令行访问支持
+ REST支持
+ 引导文件支持
+ 方便的自动生成定义
+ 真正惰性加载
+ 分布式环境支持
+ 支持Composer
+ 支持MongoDb
> ThinkPHP5的运行环境要求PHP5.4以上。
详细开发文档参考 [ThinkPHP5完全开发手册](http://www.kancloud.cn/manual/thinkphp5) 以及[ThinkPHP5入门系列教程](http://www.kancloud.cn/special/thinkphp5_quickstart)
## 目录结构
初始的目录结构如下:
~~~
www WEB部署目录或者子目录
├─application 应用目录
│ ├─common 公共模块目录(可以更改)
│ ├─module_name 模块目录
│ │ ├─config.php 模块配置文件
│ │ ├─common.php 模块函数文件
│ │ ├─controller 控制器目录
│ │ ├─model 模型目录
│ │ ├─view 视图目录
│ │ └─ ... 更多类库目录
│ │
│ ├─command.php 命令行工具配置文件
│ ├─common.php 公共函数文件
│ ├─config.php 公共配置文件
│ ├─route.php 路由配置文件
│ ├─tags.php 应用行为扩展定义文件
│ └─database.php 数据库配置文件
├─public WEB目录对外访问目录
│ ├─index.php 入口文件
│ ├─router.php 快速测试文件
│ └─.htaccess 用于apache的重写
├─thinkphp 框架系统目录
│ ├─lang 语言文件目录
│ ├─library 框架类库目录
│ │ ├─think Think类库包目录
│ │ └─traits 系统Trait目录
│ │
│ ├─tpl 系统模板目录
│ ├─base.php 基础定义文件
│ ├─console.php 控制台入口文件
│ ├─convention.php 框架惯例配置文件
│ ├─helper.php 助手函数文件
│ ├─phpunit.xml phpunit配置文件
│ └─start.php 框架入口文件
├─extend 扩展类库目录
├─runtime 应用的运行时目录(可写,可定制)
├─vendor 第三方类库目录Composer依赖库
├─build.php 自动生成定义文件(参考)
├─composer.json composer 定义文件
├─LICENSE.txt 授权说明文件
├─README.md README 文件
├─think 命令行入口文件
~~~
> router.php用于php自带webserver支持可用于快速测试
> 切换到public目录后启动命令php -S localhost:8888 router.php
> 上面的目录结构和名称是可以改变的,这取决于你的入口文件和配置参数。
## 命名规范
ThinkPHP5的命名规范遵循`PSR-2`规范以及`PSR-4`自动加载规范。
## 参与开发
注册并登录 Github 帐号, fork 本项目并进行改动。
更多细节参阅 [CONTRIBUTING.md](CONTRIBUTING.md)
## 版权信息
ThinkPHP遵循Apache2开源协议发布并提供免费使用。
本项目包含的第三方源码和二进制文件之版权信息另行标注。
版权所有Copyright © 2006-2018 by ThinkPHP (http://thinkphp.cn)
All rights reserved。
ThinkPHP® 商标和著作权所有者为上海顶想信息科技有限公司。
更多细节参阅 [LICENSE.txt](LICENSE.txt)

View File

@ -1,65 +0,0 @@
<?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>
// +----------------------------------------------------------------------
define('THINK_VERSION', '5.0.23');
define('THINK_START_TIME', microtime(true));
define('THINK_START_MEM', memory_get_usage());
define('EXT', '.php');
define('DS', DIRECTORY_SEPARATOR);
defined('THINK_PATH') or define('THINK_PATH', __DIR__ . DS);
define('LIB_PATH', THINK_PATH . 'library' . DS);
define('CORE_PATH', LIB_PATH . 'think' . DS);
define('TRAIT_PATH', LIB_PATH . 'traits' . DS);
defined('APP_PATH') or define('APP_PATH', dirname($_SERVER['SCRIPT_FILENAME']) . DS);
defined('ROOT_PATH') or define('ROOT_PATH', dirname(realpath(APP_PATH)) . DS);
defined('EXTEND_PATH') or define('EXTEND_PATH', ROOT_PATH . 'extend' . DS);
defined('VENDOR_PATH') or define('VENDOR_PATH', ROOT_PATH . 'vendor' . DS);
defined('RUNTIME_PATH') or define('RUNTIME_PATH', ROOT_PATH . 'runtime' . DS);
defined('LOG_PATH') or define('LOG_PATH', RUNTIME_PATH . 'log' . DS);
defined('CACHE_PATH') or define('CACHE_PATH', RUNTIME_PATH . 'cache' . DS);
defined('TEMP_PATH') or define('TEMP_PATH', RUNTIME_PATH . 'temp' . DS);
defined('CONF_PATH') or define('CONF_PATH', APP_PATH); // 配置文件目录
defined('CONF_EXT') or define('CONF_EXT', EXT); // 配置文件后缀
defined('ENV_PREFIX') or define('ENV_PREFIX', 'PHP_'); // 环境变量的配置前缀
// 环境常量
define('IS_CLI', PHP_SAPI == 'cli' ? true : false);
define('IS_WIN', strpos(PHP_OS, 'WIN') !== false);
// 载入Loader类
require CORE_PATH . 'Loader.php';
// 加载环境变量配置文件
if (is_file(ROOT_PATH . '.env')) {
$env = parse_ini_file(ROOT_PATH . '.env', true);
foreach ($env as $key => $val) {
$name = ENV_PREFIX . strtoupper($key);
if (is_array($val)) {
foreach ($val as $k => $v) {
$item = $name . '_' . strtoupper($k);
putenv("$item=$v");
}
} else {
putenv("$name=$val");
}
}
}
// 注册自动加载
\think\Loader::register();
// 注册错误和异常处理机制
\think\Error::register();
// 加载惯例配置文件
\think\Config::set(include THINK_PATH . 'convention' . EXT);

View File

@ -1,12 +0,0 @@
comment:
layout: header, changes, diff
coverage:
ignore:
- base.php
- helper.php
- convention.php
- lang/zh-cn.php
- start.php
- console.php
status:
patch: false

View File

@ -1,35 +0,0 @@
{
"name": "topthink/framework",
"description": "the new thinkphp framework",
"type": "think-framework",
"keywords": [
"framework",
"thinkphp",
"ORM"
],
"homepage": "http://thinkphp.cn/",
"license": "Apache-2.0",
"authors": [
{
"name": "liu21st",
"email": "liu21st@gmail.com"
}
],
"require": {
"php": ">=5.4.0",
"topthink/think-installer": "~1.0"
},
"require-dev": {
"phpunit/phpunit": "4.8.*",
"johnkary/phpunit-speedtrap": "^1.0",
"mikey179/vfsStream": "~1.6",
"phploc/phploc": "2.*",
"sebastian/phpcpd": "2.*",
"phpdocumentor/reflection-docblock": "^2.0"
},
"autoload": {
"psr-4": {
"think\\": "library/think"
}
}
}

View File

@ -1,20 +0,0 @@
<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK IT ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006-2017 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: yunwuxin <448901948@qq.com>
// +----------------------------------------------------------------------
namespace think;
// ThinkPHP 引导文件
// 加载基础文件
require __DIR__ . '/base.php';
// 执行应用
App::initCommon();
Console::init();

View File

@ -1,298 +0,0 @@
<?php
return [
// +----------------------------------------------------------------------
// | 应用设置
// +----------------------------------------------------------------------
// 默认Host地址
'app_host' => '',
// 应用调试模式
'app_debug' => false,
// 应用Trace
'app_trace' => false,
// 应用模式状态
'app_status' => '',
// 是否支持多模块
'app_multi_module' => true,
// 入口自动绑定模块
'auto_bind_module' => false,
// 注册的根命名空间
'root_namespace' => [],
// 扩展函数文件
'extra_file_list' => [THINK_PATH . 'helper' . EXT],
// 默认输出类型
'default_return_type' => 'html',
// 默认AJAX 数据返回格式,可选json xml ...
'default_ajax_return' => 'json',
// 默认JSONP格式返回的处理方法
'default_jsonp_handler' => 'jsonpReturn',
// 默认JSONP处理方法
'var_jsonp_handler' => 'callback',
// 默认时区
'default_timezone' => 'PRC',
// 是否开启多语言
'lang_switch_on' => false,
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 默认语言
'default_lang' => 'zh-cn',
// 应用类库后缀
'class_suffix' => false,
// 控制器类后缀
'controller_suffix' => false,
// +----------------------------------------------------------------------
// | 模块设置
// +----------------------------------------------------------------------
// 默认模块名
'default_module' => 'index',
// 禁止访问模块
'deny_module_list' => ['common'],
// 默认控制器名
'default_controller' => 'Index',
// 默认操作名
'default_action' => 'index',
// 默认验证器
'default_validate' => '',
// 默认的空控制器名
'empty_controller' => 'Error',
// 操作方法前缀
'use_action_prefix' => false,
// 操作方法后缀
'action_suffix' => '',
// 自动搜索控制器
'controller_auto_search' => false,
// +----------------------------------------------------------------------
// | URL设置
// +----------------------------------------------------------------------
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// pathinfo分隔符
'pathinfo_depr' => '/',
// HTTPS代理标识
'https_agent_name' => '',
// URL伪静态后缀
'url_html_suffix' => 'html',
// URL普通方式参数 用于自动生成
'url_common_param' => false,
// URL参数方式 0 按名称成对解析 1 按顺序解析
'url_param_type' => 0,
// 是否开启路由
'url_route_on' => true,
// 路由配置文件(支持配置多个)
'route_config_file' => ['route'],
// 路由使用完整匹配
'route_complete_match' => false,
// 是否强制使用路由
'url_route_must' => false,
// 域名部署
'url_domain_deploy' => false,
// 域名根如thinkphp.cn
'url_domain_root' => '',
// 是否自动转换URL中的控制器和操作名
'url_convert' => true,
// 默认的访问控制器层
'url_controller_layer' => 'controller',
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '_ajax',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// 是否开启请求缓存 true自动缓存 支持设置请求缓存规则
'request_cache' => false,
// 请求缓存有效期
'request_cache_expire' => null,
// 全局请求缓存排除规则
'request_cache_except' => [],
// +----------------------------------------------------------------------
// | 模板设置
// +----------------------------------------------------------------------
'template' => [
// 默认模板渲染规则 1 解析为小写+下划线 2 全部转换小写
'auto_rule' => 1,
// 模板引擎类型 支持 php think 支持扩展
'type' => 'Think',
// 视图基础目录,配置目录为所有模块的视图起始目录
'view_base' => '',
// 当前模板的视图目录 留空为自动获取
'view_path' => '',
// 模板后缀
'view_suffix' => 'html',
// 模板文件名分隔符
'view_depr' => DS,
// 模板引擎普通标签开始标记
'tpl_begin' => '{',
// 模板引擎普通标签结束标记
'tpl_end' => '}',
// 标签库标签开始标记
'taglib_begin' => '{',
// 标签库标签结束标记
'taglib_end' => '}',
],
// 视图输出字符串内容替换
'view_replace_str' => [],
// 默认跳转页面对应的模板文件
'dispatch_success_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
'dispatch_error_tmpl' => THINK_PATH . 'tpl' . DS . 'dispatch_jump.tpl',
// +----------------------------------------------------------------------
// | 异常及错误设置
// +----------------------------------------------------------------------
// 异常页面的模板文件
'exception_tmpl' => THINK_PATH . 'tpl' . DS . 'think_exception.tpl',
// 错误显示信息,非调试模式有效
'error_message' => '页面错误!请稍后再试~',
// 显示错误信息
'show_error_msg' => false,
// 异常处理handle类 留空使用 \think\exception\Handle
'exception_handle' => '',
// 是否记录trace信息到日志
'record_trace' => false,
// +----------------------------------------------------------------------
// | 日志设置
// +----------------------------------------------------------------------
'log' => [
// 日志记录方式,内置 file socket 支持扩展
'type' => 'File',
// 日志保存目录
'path' => LOG_PATH,
// 日志记录级别
'level' => [],
],
// +----------------------------------------------------------------------
// | Trace设置 开启 app_trace 后 有效
// +----------------------------------------------------------------------
'trace' => [
// 内置Html Console 支持扩展
'type' => 'Html',
],
// +----------------------------------------------------------------------
// | 缓存设置
// +----------------------------------------------------------------------
'cache' => [
// 驱动方式
'type' => 'File',
// 缓存保存目录
'path' => CACHE_PATH,
// 缓存前缀
'prefix' => '',
// 缓存有效期 0表示永久缓存
'expire' => 0,
],
// +----------------------------------------------------------------------
// | 会话设置
// +----------------------------------------------------------------------
'session' => [
'id' => '',
// SESSION_ID的提交变量,解决flash上传跨域
'var_session_id' => '',
// SESSION 前缀
'prefix' => 'think',
// 驱动方式 支持redis memcache memcached
'type' => '',
// 是否自动开启 SESSION
'auto_start' => true,
'httponly' => true,
'secure' => false,
],
// +----------------------------------------------------------------------
// | Cookie设置
// +----------------------------------------------------------------------
'cookie' => [
// cookie 名称前缀
'prefix' => '',
// cookie 保存时间
'expire' => 0,
// cookie 保存路径
'path' => '/',
// cookie 有效域名
'domain' => '',
// cookie 启用安全传输
'secure' => false,
// httponly设置
'httponly' => '',
// 是否使用 setcookie
'setcookie' => true,
],
// +----------------------------------------------------------------------
// | 数据库设置
// +----------------------------------------------------------------------
'database' => [
// 数据库类型
'type' => 'mysql',
// 数据库连接DSN配置
'dsn' => '',
// 服务器地址
'hostname' => '127.0.0.1',
// 数据库名
'database' => '',
// 数据库用户名
'username' => 'root',
// 数据库密码
'password' => '',
// 数据库连接端口
'hostport' => '',
// 数据库连接参数
'params' => [],
// 数据库编码默认采用utf8
'charset' => 'utf8',
// 数据库表前缀
'prefix' => '',
// 数据库调试模式
'debug' => false,
// 数据库部署方式:0 集中式(单一服务器),1 分布式(主从服务器)
'deploy' => 0,
// 数据库读写是否分离 主从式有效
'rw_separate' => false,
// 读写分离后 主服务器数量
'master_num' => 1,
// 指定从服务器序号
'slave_no' => '',
// 是否严格检查字段是否存在
'fields_strict' => true,
// 数据集返回类型
'resultset_type' => 'array',
// 自动写入时间戳字段
'auto_timestamp' => false,
// 时间字段取出后的默认时间格式
'datetime_format' => 'Y-m-d H:i:s',
// 是否需要进行SQL性能分析
'sql_explain' => false,
],
//分页配置
'paginate' => [
'type' => 'bootstrap',
'var_page' => 'page',
'list_rows' => 15,
],
//控制台配置
'console' => [
'name' => 'Think Console',
'version' => '0.1',
'user' => null,
],
];

View File

@ -1,589 +0,0 @@
<?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>
// +----------------------------------------------------------------------
//------------------------
// ThinkPHP 助手函数
//-------------------------
use think\Cache;
use think\Config;
use think\Cookie;
use think\Db;
use think\Debug;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\Lang;
use think\Loader;
use think\Log;
use think\Model;
use think\Request;
use think\Response;
use think\Session;
use think\Url;
use think\View;
if (!function_exists('load_trait')) {
/**
* 快速导入Traits PHP5.5以上无需调用
* @param string $class trait库
* @param string $ext 类库后缀
* @return boolean
*/
function load_trait($class, $ext = EXT)
{
return Loader::import($class, TRAIT_PATH, $ext);
}
}
if (!function_exists('exception')) {
/**
* 抛出异常处理
*
* @param string $msg 异常消息
* @param integer $code 异常代码 默认为0
* @param string $exception 异常类
*
* @throws Exception
*/
function exception($msg, $code = 0, $exception = '')
{
$e = $exception ?: '\think\Exception';
throw new $e($msg, $code);
}
}
if (!function_exists('debug')) {
/**
* 记录时间(微秒)和内存使用情况
* @param string $start 开始标签
* @param string $end 结束标签
* @param integer|string $dec 小数位 如果是m 表示统计内存占用
* @return mixed
*/
function debug($start, $end = '', $dec = 6)
{
if ('' == $end) {
Debug::remark($start);
} else {
return 'm' == $dec ? Debug::getRangeMem($start, $end) : Debug::getRangeTime($start, $end, $dec);
}
}
}
if (!function_exists('lang')) {
/**
* 获取语言变量值
* @param string $name 语言变量名
* @param array $vars 动态变量值
* @param string $lang 语言
* @return mixed
*/
function lang($name, $vars = [], $lang = '')
{
return Lang::get($name, $vars, $lang);
}
}
if (!function_exists('config')) {
/**
* 获取和设置配置参数
* @param string|array $name 参数名
* @param mixed $value 参数值
* @param string $range 作用域
* @return mixed
*/
function config($name = '', $value = null, $range = '')
{
if (is_null($value) && is_string($name)) {
return 0 === strpos($name, '?') ? Config::has(substr($name, 1), $range) : Config::get($name, $range);
} else {
return Config::set($name, $value, $range);
}
}
}
if (!function_exists('input')) {
/**
* 获取输入数据 支持默认值和过滤
* @param string $key 获取的变量名
* @param mixed $default 默认值
* @param string $filter 过滤方法
* @return mixed
*/
function input($key = '', $default = null, $filter = '')
{
if (0 === strpos($key, '?')) {
$key = substr($key, 1);
$has = true;
}
if ($pos = strpos($key, '.')) {
// 指定参数来源
list($method, $key) = explode('.', $key, 2);
if (!in_array($method, ['get', 'post', 'put', 'patch', 'delete', 'route', 'param', 'request', 'session', 'cookie', 'server', 'env', 'path', 'file'])) {
$key = $method . '.' . $key;
$method = 'param';
}
} else {
// 默认为自动判断
$method = 'param';
}
if (isset($has)) {
return request()->has($key, $method, $default);
} else {
return request()->$method($key, $default, $filter);
}
}
}
if (!function_exists('widget')) {
/**
* 渲染输出Widget
* @param string $name Widget名称
* @param array $data 传入的参数
* @return mixed
*/
function widget($name, $data = [])
{
return Loader::action($name, $data, 'widget');
}
}
if (!function_exists('model')) {
/**
* 实例化Model
* @param string $name Model名称
* @param string $layer 业务层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return \think\Model
*/
function model($name = '', $layer = 'model', $appendSuffix = false)
{
return Loader::model($name, $layer, $appendSuffix);
}
}
if (!function_exists('validate')) {
/**
* 实例化验证器
* @param string $name 验证器名称
* @param string $layer 业务层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return \think\Validate
*/
function validate($name = '', $layer = 'validate', $appendSuffix = false)
{
return Loader::validate($name, $layer, $appendSuffix);
}
}
if (!function_exists('db')) {
/**
* 实例化数据库类
* @param string $name 操作的数据表名称(不含前缀)
* @param array|string $config 数据库配置参数
* @param bool $force 是否强制重新连接
* @return \think\db\Query
*/
function db($name = '', $config = [], $force = false)
{
return Db::connect($config, $force)->name($name);
}
}
if (!function_exists('controller')) {
/**
* 实例化控制器 格式:[模块/]控制器
* @param string $name 资源地址
* @param string $layer 控制层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return \think\Controller
*/
function controller($name, $layer = 'controller', $appendSuffix = false)
{
return Loader::controller($name, $layer, $appendSuffix);
}
}
if (!function_exists('action')) {
/**
* 调用模块的操作方法 参数格式 [模块/控制器/]操作
* @param string $url 调用地址
* @param string|array $vars 调用参数 支持字符串和数组
* @param string $layer 要调用的控制层名称
* @param bool $appendSuffix 是否添加类名后缀
* @return mixed
*/
function action($url, $vars = [], $layer = 'controller', $appendSuffix = false)
{
return Loader::action($url, $vars, $layer, $appendSuffix);
}
}
if (!function_exists('import')) {
/**
* 导入所需的类库 同java的Import 本函数有缓存功能
* @param string $class 类库命名空间字符串
* @param string $baseUrl 起始路径
* @param string $ext 导入的文件扩展名
* @return boolean
*/
function import($class, $baseUrl = '', $ext = EXT)
{
return Loader::import($class, $baseUrl, $ext);
}
}
if (!function_exists('vendor')) {
/**
* 快速导入第三方框架类库 所有第三方框架的类库文件统一放到 系统的Vendor目录下面
* @param string $class 类库
* @param string $ext 类库后缀
* @return boolean
*/
function vendor($class, $ext = EXT)
{
return Loader::import($class, VENDOR_PATH, $ext);
}
}
if (!function_exists('dump')) {
/**
* 浏览器友好的变量输出
* @param mixed $var 变量
* @param boolean $echo 是否输出 默认为true 如果为false 则返回输出字符串
* @param string $label 标签 默认为空
* @return void|string
*/
function dump($var, $echo = true, $label = null)
{
return Debug::dump($var, $echo, $label);
}
}
if (!function_exists('url')) {
/**
* Url生成
* @param string $url 路由地址
* @param string|array $vars 变量
* @param bool|string $suffix 生成的URL后缀
* @param bool|string $domain 域名
* @return string
*/
function url($url = '', $vars = '', $suffix = true, $domain = false)
{
return Url::build($url, $vars, $suffix, $domain);
}
}
if (!function_exists('session')) {
/**
* Session管理
* @param string|array $name session名称如果为数组表示进行session设置
* @param mixed $value session值
* @param string $prefix 前缀
* @return mixed
*/
function session($name, $value = '', $prefix = null)
{
if (is_array($name)) {
// 初始化
Session::init($name);
} elseif (is_null($name)) {
// 清除
Session::clear('' === $value ? null : $value);
} elseif ('' === $value) {
// 判断或获取
return 0 === strpos($name, '?') ? Session::has(substr($name, 1), $prefix) : Session::get($name, $prefix);
} elseif (is_null($value)) {
// 删除
return Session::delete($name, $prefix);
} else {
// 设置
return Session::set($name, $value, $prefix);
}
}
}
if (!function_exists('cookie')) {
/**
* Cookie管理
* @param string|array $name cookie名称如果为数组表示进行cookie设置
* @param mixed $value cookie值
* @param mixed $option 参数
* @return mixed
*/
function cookie($name, $value = '', $option = null)
{
if (is_array($name)) {
// 初始化
Cookie::init($name);
} elseif (is_null($name)) {
// 清除
Cookie::clear($value);
} elseif ('' === $value) {
// 获取
return 0 === strpos($name, '?') ? Cookie::has(substr($name, 1), $option) : Cookie::get($name, $option);
} elseif (is_null($value)) {
// 删除
return Cookie::delete($name);
} else {
// 设置
return Cookie::set($name, $value, $option);
}
}
}
if (!function_exists('cache')) {
/**
* 缓存管理
* @param mixed $name 缓存名称,如果为数组表示进行缓存设置
* @param mixed $value 缓存值
* @param mixed $options 缓存参数
* @param string $tag 缓存标签
* @return mixed
*/
function cache($name, $value = '', $options = null, $tag = null)
{
if (is_array($options)) {
// 缓存操作的同时初始化
$cache = Cache::connect($options);
} elseif (is_array($name)) {
// 缓存初始化
return Cache::connect($name);
} else {
$cache = Cache::init();
}
if (is_null($name)) {
return $cache->clear($value);
} elseif ('' === $value) {
// 获取缓存
return 0 === strpos($name, '?') ? $cache->has(substr($name, 1)) : $cache->get($name);
} elseif (is_null($value)) {
// 删除缓存
return $cache->rm($name);
} elseif (0 === strpos($name, '?') && '' !== $value) {
$expire = is_numeric($options) ? $options : null;
return $cache->remember(substr($name, 1), $value, $expire);
} else {
// 缓存数据
if (is_array($options)) {
$expire = isset($options['expire']) ? $options['expire'] : null; //修复查询缓存无法设置过期时间
} else {
$expire = is_numeric($options) ? $options : null; //默认快捷缓存设置过期时间
}
if (is_null($tag)) {
return $cache->set($name, $value, $expire);
} else {
return $cache->tag($tag)->set($name, $value, $expire);
}
}
}
}
if (!function_exists('trace')) {
/**
* 记录日志信息
* @param mixed $log log信息 支持字符串和数组
* @param string $level 日志级别
* @return void|array
*/
function trace($log = '[think]', $level = 'log')
{
if ('[think]' === $log) {
return Log::getLog();
} else {
Log::record($log, $level);
}
}
}
if (!function_exists('request')) {
/**
* 获取当前Request对象实例
* @return Request
*/
function request()
{
return Request::instance();
}
}
if (!function_exists('response')) {
/**
* 创建普通 Response 对象实例
* @param mixed $data 输出数据
* @param int|string $code 状态码
* @param array $header 头信息
* @param string $type
* @return Response
*/
function response($data = [], $code = 200, $header = [], $type = 'html')
{
return Response::create($data, $type, $code, $header);
}
}
if (!function_exists('view')) {
/**
* 渲染模板输出
* @param string $template 模板文件
* @param array $vars 模板变量
* @param array $replace 模板替换
* @param integer $code 状态码
* @return \think\response\View
*/
function view($template = '', $vars = [], $replace = [], $code = 200)
{
return Response::create($template, 'view', $code)->replace($replace)->assign($vars);
}
}
if (!function_exists('json')) {
/**
* 获取\think\response\Json对象实例
* @param mixed $data 返回的数据
* @param integer $code 状态码
* @param array $header 头部
* @param array $options 参数
* @return \think\response\Json
*/
function json($data = [], $code = 200, $header = [], $options = [])
{
return Response::create($data, 'json', $code, $header, $options);
}
}
if (!function_exists('jsonp')) {
/**
* 获取\think\response\Jsonp对象实例
* @param mixed $data 返回的数据
* @param integer $code 状态码
* @param array $header 头部
* @param array $options 参数
* @return \think\response\Jsonp
*/
function jsonp($data = [], $code = 200, $header = [], $options = [])
{
return Response::create($data, 'jsonp', $code, $header, $options);
}
}
if (!function_exists('xml')) {
/**
* 获取\think\response\Xml对象实例
* @param mixed $data 返回的数据
* @param integer $code 状态码
* @param array $header 头部
* @param array $options 参数
* @return \think\response\Xml
*/
function xml($data = [], $code = 200, $header = [], $options = [])
{
return Response::create($data, 'xml', $code, $header, $options);
}
}
if (!function_exists('redirect')) {
/**
* 获取\think\response\Redirect对象实例
* @param mixed $url 重定向地址 支持Url::build方法的地址
* @param array|integer $params 额外参数
* @param integer $code 状态码
* @param array $with 隐式传参
* @return \think\response\Redirect
*/
function redirect($url = [], $params = [], $code = 302, $with = [])
{
if (is_integer($params)) {
$code = $params;
$params = [];
}
return Response::create($url, 'redirect', $code)->params($params)->with($with);
}
}
if (!function_exists('abort')) {
/**
* 抛出HTTP异常
* @param integer|Response $code 状态码 或者 Response对象实例
* @param string $message 错误信息
* @param array $header 参数
*/
function abort($code, $message = null, $header = [])
{
if ($code instanceof Response) {
throw new HttpResponseException($code);
} else {
throw new HttpException($code, $message, null, $header);
}
}
}
if (!function_exists('halt')) {
/**
* 调试变量并且中断输出
* @param mixed $var 调试变量或者信息
*/
function halt($var)
{
dump($var);
throw new HttpResponseException(new Response);
}
}
if (!function_exists('token')) {
/**
* 生成表单令牌
* @param string $name 令牌名称
* @param mixed $type 令牌生成方法
* @return string
*/
function token($name = '__token__', $type = 'md5')
{
$token = Request::instance()->token($name, $type);
return '<input type="hidden" name="' . $name . '" value="' . $token . '" />';
}
}
if (!function_exists('load_relation')) {
/**
* 延迟预载入关联查询
* @param mixed $resultSet 数据集
* @param mixed $relation 关联
* @return array
*/
function load_relation($resultSet, $relation)
{
$item = current($resultSet);
if ($item instanceof Model) {
$item->eagerlyResultSet($resultSet, $relation);
}
return $resultSet;
}
}
if (!function_exists('collection')) {
/**
* 数组转换为数据集对象
* @param array $resultSet 数据集数组
* @return \think\model\Collection|\think\Collection
*/
function collection($resultSet)
{
$item = current($resultSet);
if ($item instanceof Model) {
return \think\model\Collection::make($resultSet);
} else {
return \think\Collection::make($resultSet);
}
}
}

View File

@ -1,136 +0,0 @@
<?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>
// +----------------------------------------------------------------------
// 核心中文语言包
return [
// 系统错误提示
'Undefined variable' => '未定义变量',
'Undefined index' => '未定义数组索引',
'Undefined offset' => '未定义数组下标',
'Parse error' => '语法解析错误',
'Type error' => '类型错误',
'Fatal error' => '致命错误',
'syntax error' => '语法错误',
// 框架核心错误提示
'dispatch type not support' => '不支持的调度类型',
'method param miss' => '方法参数错误',
'method not exists' => '方法不存在',
'module not exists' => '模块不存在',
'controller not exists' => '控制器不存在',
'class not exists' => '类不存在',
'property not exists' => '类的属性不存在',
'template not exists' => '模板文件不存在',
'illegal controller name' => '非法的控制器名称',
'illegal action name' => '非法的操作名称',
'url suffix deny' => '禁止的URL后缀访问',
'Route Not Found' => '当前访问路由未定义',
'Undefined db type' => '未定义数据库类型',
'variable type error' => '变量类型错误',
'PSR-4 error' => 'PSR-4 规范错误',
'not support total' => '简洁模式下不能获取数据总数',
'not support last' => '简洁模式下不能获取最后一页',
'error session handler' => '错误的SESSION处理器类',
'not allow php tag' => '模板不允许使用PHP语法',
'not support' => '不支持',
'redisd master' => 'Redisd 主服务器错误',
'redisd slave' => 'Redisd 从服务器错误',
'must run at sae' => '必须在SAE运行',
'memcache init error' => '未开通Memcache服务请在SAE管理平台初始化Memcache服务',
'KVDB init error' => '没有初始化KVDB请在SAE管理平台初始化KVDB服务',
'fields not exists' => '数据表字段不存在',
'where express error' => '查询表达式错误',
'not support data' => '不支持的数据表达式',
'no data to update' => '没有任何数据需要更新',
'miss data to insert' => '缺少需要写入的数据',
'miss complex primary data' => '缺少复合主键数据',
'miss update condition' => '缺少更新条件',
'model data Not Found' => '模型数据不存在',
'table data not Found' => '表数据不存在',
'delete without condition' => '没有条件不会执行删除操作',
'miss relation data' => '缺少关联表数据',
'tag attr must' => '模板标签属性必须',
'tag error' => '模板标签错误',
'cache write error' => '缓存写入失败',
'sae mc write error' => 'SAE mc 写入错误',
'route name not exists' => '路由标识不存在(或参数不够)',
'invalid request' => '非法请求',
'bind attr has exists' => '模型的属性已经存在',
'relation data not exists' => '关联数据不存在',
'relation not support' => '关联不支持',
'chunk not support order' => 'Chunk不支持调用order方法',
'closure not support cache(true)' => '使用闭包查询不支持cache(true)请指定缓存Key',
// 上传错误信息
'unknown upload error' => '未知上传错误!',
'file write error' => '文件写入失败!',
'upload temp dir not found' => '找不到临时文件夹!',
'no file to uploaded' => '没有文件被上传!',
'only the portion of file is uploaded' => '文件只有部分被上传!',
'upload File size exceeds the maximum value' => '上传文件大小超过了最大值!',
'upload write error' => '文件上传保存错误!',
'has the same filename: {:filename}' => '存在同名文件:{:filename}',
'upload illegal files' => '非法上传文件',
'illegal image files' => '非法图片文件',
'extensions to upload is not allowed' => '上传文件后缀不允许',
'mimetype to upload is not allowed' => '上传文件MIME类型不允许',
'filesize not match' => '上传文件大小不符!',
'directory {:path} creation failed' => '目录 {:path} 创建失败!',
// Validate Error Message
':attribute require' => ':attribute不能为空',
':attribute must be numeric' => ':attribute必须是数字',
':attribute must be integer' => ':attribute必须是整数',
':attribute must be float' => ':attribute必须是浮点数',
':attribute must be bool' => ':attribute必须是布尔值',
':attribute not a valid email address' => ':attribute格式不符',
':attribute not a valid mobile' => ':attribute格式不符',
':attribute must be a array' => ':attribute必须是数组',
':attribute must be yes,on or 1' => ':attribute必须是yes、on或者1',
':attribute not a valid datetime' => ':attribute不是一个有效的日期或时间格式',
':attribute not a valid file' => ':attribute不是有效的上传文件',
':attribute not a valid image' => ':attribute不是有效的图像文件',
':attribute must be alpha' => ':attribute只能是字母',
':attribute must be alpha-numeric' => ':attribute只能是字母和数字',
':attribute must be alpha-numeric, dash, underscore' => ':attribute只能是字母、数字和下划线_及破折号-',
':attribute not a valid domain or ip' => ':attribute不是有效的域名或者IP',
':attribute must be chinese' => ':attribute只能是汉字',
':attribute must be chinese or alpha' => ':attribute只能是汉字、字母',
':attribute must be chinese,alpha-numeric' => ':attribute只能是汉字、字母和数字',
':attribute must be chinese,alpha-numeric,underscore, dash' => ':attribute只能是汉字、字母、数字和下划线_及破折号-',
':attribute not a valid url' => ':attribute不是有效的URL地址',
':attribute not a valid ip' => ':attribute不是有效的IP地址',
':attribute must be dateFormat of :rule' => ':attribute必须使用日期格式 :rule',
':attribute must be in :rule' => ':attribute必须在 :rule 范围内',
':attribute be notin :rule' => ':attribute不能在 :rule 范围内',
':attribute must between :1 - :2' => ':attribute只能在 :1 - :2 之间',
':attribute not between :1 - :2' => ':attribute不能在 :1 - :2 之间',
'size of :attribute must be :rule' => ':attribute长度不符合要求 :rule',
'max size of :attribute must be :rule' => ':attribute长度不能超过 :rule',
'min size of :attribute must be :rule' => ':attribute长度不能小于 :rule',
':attribute cannot be less than :rule' => ':attribute日期不能小于 :rule',
':attribute cannot exceed :rule' => ':attribute日期不能超过 :rule',
':attribute not within :rule' => '不在有效期内 :rule',
'access IP is not allowed' => '不允许的IP访问',
'access IP denied' => '禁止的IP访问',
':attribute out of accord with :2' => ':attribute和确认字段:2不一致',
':attribute cannot be same with :2' => ':attribute和比较字段:2不能相同',
':attribute must greater than or equal :rule' => ':attribute必须大于等于 :rule',
':attribute must greater than :rule' => ':attribute必须大于 :rule',
':attribute must less than or equal :rule' => ':attribute必须小于等于 :rule',
':attribute must less than :rule' => ':attribute必须小于 :rule',
':attribute must equal :rule' => ':attribute必须等于 :rule',
':attribute has exists' => ':attribute已存在',
':attribute not conform to the rules' => ':attribute不符合指定规则',
'invalid Request method' => '无效的请求类型',
'invalid token' => '令牌数据无效',
'not conform to the rules' => '规则错误',
];

View File

@ -1,677 +0,0 @@
<?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>
// +----------------------------------------------------------------------
namespace think;
use think\exception\ClassNotFoundException;
use think\exception\HttpException;
use think\exception\HttpResponseException;
use think\exception\RouteNotFoundException;
/**
* App 应用管理
* @author liu21st <liu21st@gmail.com>
*/
class App
{
/**
* @var bool 是否初始化过
*/
protected static $init = false;
/**
* @var string 当前模块路径
*/
public static $modulePath;
/**
* @var bool 应用调试模式
*/
public static $debug = true;
/**
* @var string 应用类库命名空间
*/
public static $namespace = 'app';
/**
* @var bool 应用类库后缀
*/
public static $suffix = false;
/**
* @var bool 应用路由检测
*/
protected static $routeCheck;
/**
* @var bool 严格路由检测
*/
protected static $routeMust;
/**
* @var array 请求调度分发
*/
protected static $dispatch;
/**
* @var array 额外加载文件
*/
protected static $file = [];
/**
* 执行应用程序
* @access public
* @param Request $request 请求对象
* @return Response
* @throws Exception
*/
public static function run(Request $request = null)
{
$request = is_null($request) ? Request::instance() : $request;
try {
$config = self::initCommon();
// 模块/控制器绑定
if (defined('BIND_MODULE')) {
BIND_MODULE && Route::bind(BIND_MODULE);
} elseif ($config['auto_bind_module']) {
// 入口自动绑定
$name = pathinfo($request->baseFile(), PATHINFO_FILENAME);
if ($name && 'index' != $name && is_dir(APP_PATH . $name)) {
Route::bind($name);
}
}
$request->filter($config['default_filter']);
// 默认语言
Lang::range($config['default_lang']);
// 开启多语言机制 检测当前语言
$config['lang_switch_on'] && Lang::detect();
$request->langset(Lang::range());
// 加载系统语言包
Lang::load([
THINK_PATH . 'lang' . DS . $request->langset() . EXT,
APP_PATH . 'lang' . DS . $request->langset() . EXT,
]);
// 监听 app_dispatch
Hook::listen('app_dispatch', self::$dispatch);
// 获取应用调度信息
$dispatch = self::$dispatch;
// 未设置调度信息则进行 URL 路由检测
if (empty($dispatch)) {
$dispatch = self::routeCheck($request, $config);
}
// 记录当前调度信息
$request->dispatch($dispatch);
// 记录路由和请求信息
if (self::$debug) {
Log::record('[ ROUTE ] ' . var_export($dispatch, true), 'info');
Log::record('[ HEADER ] ' . var_export($request->header(), true), 'info');
Log::record('[ PARAM ] ' . var_export($request->param(), true), 'info');
}
// 监听 app_begin
Hook::listen('app_begin', $dispatch);
// 请求缓存检查
$request->cache(
$config['request_cache'],
$config['request_cache_expire'],
$config['request_cache_except']
);
$data = self::exec($dispatch, $config);
} catch (HttpResponseException $exception) {
$data = $exception->getResponse();
}
// 清空类的实例化
Loader::clearInstance();
// 输出数据到客户端
if ($data instanceof Response) {
$response = $data;
} elseif (!is_null($data)) {
// 默认自动识别响应输出类型
$type = $request->isAjax() ?
Config::get('default_ajax_return') :
Config::get('default_return_type');
$response = Response::create($data, $type);
} else {
$response = Response::create();
}
// 监听 app_end
Hook::listen('app_end', $response);
return $response;
}
/**
* 初始化应用,并返回配置信息
* @access public
* @return array
*/
public static function initCommon()
{
if (empty(self::$init)) {
if (defined('APP_NAMESPACE')) {
self::$namespace = APP_NAMESPACE;
}
Loader::addNamespace(self::$namespace, APP_PATH);
// 初始化应用
$config = self::init();
self::$suffix = $config['class_suffix'];
// 应用调试模式
self::$debug = Env::get('app_debug', Config::get('app_debug'));
if (!self::$debug) {
ini_set('display_errors', 'Off');
} elseif (!IS_CLI) {
// 重新申请一块比较大的 buffer
if (ob_get_level() > 0) {
$output = ob_get_clean();
}
ob_start();
if (!empty($output)) {
echo $output;
}
}
if (!empty($config['root_namespace'])) {
Loader::addNamespace($config['root_namespace']);
}
// 加载额外文件
if (!empty($config['extra_file_list'])) {
foreach ($config['extra_file_list'] as $file) {
$file = strpos($file, '.') ? $file : APP_PATH . $file . EXT;
if (is_file($file) && !isset(self::$file[$file])) {
include $file;
self::$file[$file] = true;
}
}
}
// 设置系统时区
date_default_timezone_set($config['default_timezone']);
// 监听 app_init
Hook::listen('app_init');
self::$init = true;
}
return Config::get();
}
/**
* 初始化应用或模块
* @access public
* @param string $module 模块名
* @return array
*/
private static function init($module = '')
{
// 定位模块目录
$module = $module ? $module . DS : '';
// 加载初始化文件
if (is_file(APP_PATH . $module . 'init' . EXT)) {
include APP_PATH . $module . 'init' . EXT;
} elseif (is_file(RUNTIME_PATH . $module . 'init' . EXT)) {
include RUNTIME_PATH . $module . 'init' . EXT;
} else {
// 加载模块配置
$config = Config::load(CONF_PATH . $module . 'config' . CONF_EXT);
// 读取数据库配置文件
$filename = CONF_PATH . $module . 'database' . CONF_EXT;
Config::load($filename, 'database');
// 读取扩展配置文件
if (is_dir(CONF_PATH . $module . 'extra')) {
$dir = CONF_PATH . $module . 'extra';
$files = scandir($dir);
foreach ($files as $file) {
if ('.' . pathinfo($file, PATHINFO_EXTENSION) === CONF_EXT) {
$filename = $dir . DS . $file;
Config::load($filename, pathinfo($file, PATHINFO_FILENAME));
}
}
}
// 加载应用状态配置
if ($config['app_status']) {
Config::load(CONF_PATH . $module . $config['app_status'] . CONF_EXT);
}
// 加载行为扩展文件
if (is_file(CONF_PATH . $module . 'tags' . EXT)) {
Hook::import(include CONF_PATH . $module . 'tags' . EXT);
}
// 加载公共文件
$path = APP_PATH . $module;
if (is_file($path . 'common' . EXT)) {
include $path . 'common' . EXT;
}
// 加载当前模块语言包
if ($module) {
Lang::load($path . 'lang' . DS . Request::instance()->langset() . EXT);
}
}
return Config::get();
}
/**
* 设置当前请求的调度信息
* @access public
* @param array|string $dispatch 调度信息
* @param string $type 调度类型
* @return void
*/
public static function dispatch($dispatch, $type = 'module')
{
self::$dispatch = ['type' => $type, $type => $dispatch];
}
/**
* 执行函数或者闭包方法 支持参数调用
* @access public
* @param string|array|\Closure $function 函数或者闭包
* @param array $vars 变量
* @return mixed
*/
public static function invokeFunction($function, $vars = [])
{
$reflect = new \ReflectionFunction($function);
$args = self::bindParams($reflect, $vars);
// 记录执行信息
self::$debug && Log::record('[ RUN ] ' . $reflect->__toString(), 'info');
return $reflect->invokeArgs($args);
}
/**
* 调用反射执行类的方法 支持参数绑定
* @access public
* @param string|array $method 方法
* @param array $vars 变量
* @return mixed
*/
public static function invokeMethod($method, $vars = [])
{
if (is_array($method)) {
$class = is_object($method[0]) ? $method[0] : self::invokeClass($method[0]);
$reflect = new \ReflectionMethod($class, $method[1]);
} else {
// 静态方法
$reflect = new \ReflectionMethod($method);
}
$args = self::bindParams($reflect, $vars);
self::$debug && Log::record('[ RUN ] ' . $reflect->class . '->' . $reflect->name . '[ ' . $reflect->getFileName() . ' ]', 'info');
return $reflect->invokeArgs(isset($class) ? $class : null, $args);
}
/**
* 调用反射执行类的实例化 支持依赖注入
* @access public
* @param string $class 类名
* @param array $vars 变量
* @return mixed
*/
public static function invokeClass($class, $vars = [])
{
$reflect = new \ReflectionClass($class);
$constructor = $reflect->getConstructor();
$args = $constructor ? self::bindParams($constructor, $vars) : [];
return $reflect->newInstanceArgs($args);
}
/**
* 绑定参数
* @access private
* @param \ReflectionMethod|\ReflectionFunction $reflect 反射类
* @param array $vars 变量
* @return array
*/
private static function bindParams($reflect, $vars = [])
{
// 自动获取请求变量
if (empty($vars)) {
$vars = Config::get('url_param_type') ?
Request::instance()->route() :
Request::instance()->param();
}
$args = [];
if ($reflect->getNumberOfParameters() > 0) {
// 判断数组类型 数字数组时按顺序绑定参数
reset($vars);
$type = key($vars) === 0 ? 1 : 0;
foreach ($reflect->getParameters() as $param) {
$args[] = self::getParamValue($param, $vars, $type);
}
}
return $args;
}
/**
* 获取参数值
* @access private
* @param \ReflectionParameter $param 参数
* @param array $vars 变量
* @param string $type 类别
* @return array
*/
private static function getParamValue($param, &$vars, $type)
{
$name = $param->getName();
$class = $param->getClass();
if ($class) {
$className = $class->getName();
$bind = Request::instance()->$name;
if ($bind instanceof $className) {
$result = $bind;
} else {
if (method_exists($className, 'invoke')) {
$method = new \ReflectionMethod($className, 'invoke');
if ($method->isPublic() && $method->isStatic()) {
return $className::invoke(Request::instance());
}
}
$result = method_exists($className, 'instance') ?
$className::instance() :
new $className;
}
} elseif (1 == $type && !empty($vars)) {
$result = array_shift($vars);
} elseif (0 == $type && isset($vars[$name])) {
$result = $vars[$name];
} elseif ($param->isDefaultValueAvailable()) {
$result = $param->getDefaultValue();
} else {
throw new \InvalidArgumentException('method param miss:' . $name);
}
return $result;
}
/**
* 执行调用分发
* @access protected
* @param array $dispatch 调用信息
* @param array $config 配置信息
* @return Response|mixed
* @throws \InvalidArgumentException
*/
protected static function exec($dispatch, $config)
{
switch ($dispatch['type']) {
case 'redirect': // 重定向跳转
$data = Response::create($dispatch['url'], 'redirect')
->code($dispatch['status']);
break;
case 'module': // 模块/控制器/操作
$data = self::module(
$dispatch['module'],
$config,
isset($dispatch['convert']) ? $dispatch['convert'] : null
);
break;
case 'controller': // 执行控制器操作
$vars = array_merge(Request::instance()->param(), $dispatch['var']);
$data = Loader::action(
$dispatch['controller'],
$vars,
$config['url_controller_layer'],
$config['controller_suffix']
);
break;
case 'method': // 回调方法
$vars = array_merge(Request::instance()->param(), $dispatch['var']);
$data = self::invokeMethod($dispatch['method'], $vars);
break;
case 'function': // 闭包
$data = self::invokeFunction($dispatch['function']);
break;
case 'response': // Response 实例
$data = $dispatch['response'];
break;
default:
throw new \InvalidArgumentException('dispatch type not support');
}
return $data;
}
/**
* 执行模块
* @access public
* @param array $result 模块/控制器/操作
* @param array $config 配置参数
* @param bool $convert 是否自动转换控制器和操作名
* @return mixed
* @throws HttpException
*/
public static function module($result, $config, $convert = null)
{
if (is_string($result)) {
$result = explode('/', $result);
}
$request = Request::instance();
if ($config['app_multi_module']) {
// 多模块部署
$module = strip_tags(strtolower($result[0] ?: $config['default_module']));
$bind = Route::getBind('module');
$available = false;
if ($bind) {
// 绑定模块
list($bindModule) = explode('/', $bind);
if (empty($result[0])) {
$module = $bindModule;
$available = true;
} elseif ($module == $bindModule) {
$available = true;
}
} elseif (!in_array($module, $config['deny_module_list']) && is_dir(APP_PATH . $module)) {
$available = true;
}
// 模块初始化
if ($module && $available) {
// 初始化模块
$request->module($module);
$config = self::init($module);
// 模块请求缓存检查
$request->cache(
$config['request_cache'],
$config['request_cache_expire'],
$config['request_cache_except']
);
} else {
throw new HttpException(404, 'module not exists:' . $module);
}
} else {
// 单一模块部署
$module = '';
$request->module($module);
}
// 设置默认过滤机制
$request->filter($config['default_filter']);
// 当前模块路径
App::$modulePath = APP_PATH . ($module ? $module . DS : '');
// 是否自动转换控制器和操作名
$convert = is_bool($convert) ? $convert : $config['url_convert'];
// 获取控制器名
$controller = strip_tags($result[1] ?: $config['default_controller']);
if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) {
throw new HttpException(404, 'controller not exists:' . $controller);
}
$controller = $convert ? strtolower($controller) : $controller;
// 获取操作名
$actionName = strip_tags($result[2] ?: $config['default_action']);
if (!empty($config['action_convert'])) {
$actionName = Loader::parseName($actionName, 1);
} else {
$actionName = $convert ? strtolower($actionName) : $actionName;
}
// 设置当前请求的控制器、操作
$request->controller(Loader::parseName($controller, 1))->action($actionName);
// 监听module_init
Hook::listen('module_init', $request);
try {
$instance = Loader::controller(
$controller,
$config['url_controller_layer'],
$config['controller_suffix'],
$config['empty_controller']
);
} catch (ClassNotFoundException $e) {
throw new HttpException(404, 'controller not exists:' . $e->getClass());
}
// 获取当前操作名
$action = $actionName . $config['action_suffix'];
$vars = [];
if (is_callable([$instance, $action])) {
// 执行操作方法
$call = [$instance, $action];
// 严格获取当前操作方法名
$reflect = new \ReflectionMethod($instance, $action);
$methodName = $reflect->getName();
$suffix = $config['action_suffix'];
$actionName = $suffix ? substr($methodName, 0, -strlen($suffix)) : $methodName;
$request->action($actionName);
} elseif (is_callable([$instance, '_empty'])) {
// 空操作
$call = [$instance, '_empty'];
$vars = [$actionName];
} else {
// 操作不存在
throw new HttpException(404, 'method not exists:' . get_class($instance) . '->' . $action . '()');
}
Hook::listen('action_begin', $call);
return self::invokeMethod($call, $vars);
}
/**
* URL路由检测根据PATH_INFO)
* @access public
* @param \think\Request $request 请求实例
* @param array $config 配置信息
* @return array
* @throws \think\Exception
*/
public static function routeCheck($request, array $config)
{
$path = $request->path();
$depr = $config['pathinfo_depr'];
$result = false;
// 路由检测
$check = !is_null(self::$routeCheck) ? self::$routeCheck : $config['url_route_on'];
if ($check) {
// 开启路由
if (is_file(RUNTIME_PATH . 'route.php')) {
// 读取路由缓存
$rules = include RUNTIME_PATH . 'route.php';
is_array($rules) && Route::rules($rules);
} else {
$files = $config['route_config_file'];
foreach ($files as $file) {
if (is_file(CONF_PATH . $file . CONF_EXT)) {
// 导入路由配置
$rules = include CONF_PATH . $file . CONF_EXT;
is_array($rules) && Route::import($rules);
}
}
}
// 路由检测根据路由定义返回不同的URL调度
$result = Route::check($request, $path, $depr, $config['url_domain_deploy']);
$must = !is_null(self::$routeMust) ? self::$routeMust : $config['url_route_must'];
if ($must && false === $result) {
// 路由无效
throw new RouteNotFoundException();
}
}
// 路由无效 解析模块/控制器/操作/参数... 支持控制器自动搜索
if (false === $result) {
$result = Route::parseUrl($path, $depr, $config['controller_auto_search']);
}
return $result;
}
/**
* 设置应用的路由检测机制
* @access public
* @param bool $route 是否需要检测路由
* @param bool $must 是否强制检测路由
* @return void
*/
public static function route($route, $must = false)
{
self::$routeCheck = $route;
self::$routeMust = $must;
}
}

View File

@ -1,235 +0,0 @@
<?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>
// +----------------------------------------------------------------------
namespace think;
class Build
{
/**
* 根据传入的 build 资料创建目录和文件
* @access public
* @param array $build build 列表
* @param string $namespace 应用类库命名空间
* @param bool $suffix 类库后缀
* @return void
* @throws Exception
*/
public static function run(array $build = [], $namespace = 'app', $suffix = false)
{
// 锁定
$lock = APP_PATH . 'build.lock';
// 如果锁定文件不可写(不存在)则进行处理,否则表示已经有程序在处理了
if (!is_writable($lock)) {
if (!touch($lock)) {
throw new Exception(
'应用目录[' . APP_PATH . ']不可写,目录无法自动生成!<BR>请手动生成项目目录~',
10006
);
}
foreach ($build as $module => $list) {
if ('__dir__' == $module) {
// 创建目录列表
self::buildDir($list);
} elseif ('__file__' == $module) {
// 创建文件列表
self::buildFile($list);
} else {
// 创建模块
self::module($module, $list, $namespace, $suffix);
}
}
// 解除锁定
unlink($lock);
}
}
/**
* 创建目录
* @access protected
* @param array $list 目录列表
* @return void
*/
protected static function buildDir($list)
{
foreach ($list as $dir) {
// 目录不存在则创建目录
!is_dir(APP_PATH . $dir) && mkdir(APP_PATH . $dir, 0755, true);
}
}
/**
* 创建文件
* @access protected
* @param array $list 文件列表
* @return void
*/
protected static function buildFile($list)
{
foreach ($list as $file) {
// 先创建目录
if (!is_dir(APP_PATH . dirname($file))) {
mkdir(APP_PATH . dirname($file), 0755, true);
}
// 再创建文件
if (!is_file(APP_PATH . $file)) {
file_put_contents(
APP_PATH . $file,
'php' == pathinfo($file, PATHINFO_EXTENSION) ? "<?php\n" : ''
);
}
}
}
/**
* 创建模块
* @access public
* @param string $module 模块名
* @param array $list build 列表
* @param string $namespace 应用类库命名空间
* @param bool $suffix 类库后缀
* @return void
*/
public static function module($module = '', $list = [], $namespace = 'app', $suffix = false)
{
$module = $module ?: '';
// 创建模块目录
!is_dir(APP_PATH . $module) && mkdir(APP_PATH . $module);
// 如果不是 runtime 目录则需要创建配置文件和公共文件、创建模块的默认页面
if (basename(RUNTIME_PATH) != $module) {
self::buildCommon($module);
self::buildHello($module, $namespace, $suffix);
}
// 未指定文件和目录,则创建默认的模块目录和文件
if (empty($list)) {
$list = [
'__file__' => ['config.php', 'common.php'],
'__dir__' => ['controller', 'model', 'view'],
];
}
// 创建子目录和文件
foreach ($list as $path => $file) {
$modulePath = APP_PATH . $module . DS;
if ('__dir__' == $path) {
// 生成子目录
foreach ($file as $dir) {
self::checkDirBuild($modulePath . $dir);
}
} elseif ('__file__' == $path) {
// 生成(空白)文件
foreach ($file as $name) {
if (!is_file($modulePath . $name)) {
file_put_contents(
$modulePath . $name,
'php' == pathinfo($name, PATHINFO_EXTENSION) ? "<?php\n" : ''
);
}
}
} else {
// 生成相关 MVC 文件
foreach ($file as $val) {
$val = trim($val);
$filename = $modulePath . $path . DS . $val . ($suffix ? ucfirst($path) : '') . EXT;
$space = $namespace . '\\' . ($module ? $module . '\\' : '') . $path;
$class = $val . ($suffix ? ucfirst($path) : '');
switch ($path) {
case 'controller': // 控制器
$content = "<?php\nnamespace {$space};\n\nclass {$class}\n{\n\n}";
break;
case 'model': // 模型
$content = "<?php\nnamespace {$space};\n\nuse think\Model;\n\nclass {$class} extends Model\n{\n\n}";
break;
case 'view': // 视图
$filename = $modulePath . $path . DS . $val . '.html';
self::checkDirBuild(dirname($filename));
$content = '';
break;
default:
// 其他文件
$content = "<?php\nnamespace {$space};\n\nclass {$class}\n{\n\n}";
}
if (!is_file($filename)) {
file_put_contents($filename, $content);
}
}
}
}
}
/**
* 创建模块的欢迎页面
* @access protected
* @param string $module 模块名
* @param string $namespace 应用类库命名空间
* @param bool $suffix 类库后缀
* @return void
*/
protected static function buildHello($module, $namespace, $suffix = false)
{
$filename = APP_PATH . ($module ? $module . DS : '') .
'controller' . DS . 'Index' .
($suffix ? 'Controller' : '') . EXT;
if (!is_file($filename)) {
$module = $module ? $module . '\\' : '';
$suffix = $suffix ? 'Controller' : '';
$content = str_replace(
['{$app}', '{$module}', '{layer}', '{$suffix}'],
[$namespace, $module, 'controller', $suffix],
file_get_contents(THINK_PATH . 'tpl' . DS . 'default_index.tpl')
);
self::checkDirBuild(dirname($filename));
file_put_contents($filename, $content);
}
}
/**
* 创建模块的公共文件
* @access protected
* @param string $module 模块名
* @return void
*/
protected static function buildCommon($module)
{
$config = CONF_PATH . ($module ? $module . DS : '') . 'config.php';
self::checkDirBuild(dirname($config));
if (!is_file($config)) {
file_put_contents($config, "<?php\n//配置文件\nreturn [\n\n];");
}
$common = APP_PATH . ($module ? $module . DS : '') . 'common.php';
if (!is_file($common)) file_put_contents($common, "<?php\n");
}
/**
* 创建目录
* @access protected
* @param string $dirname 目录名称
* @return void
*/
protected static function checkDirBuild($dirname)
{
!is_dir($dirname) && mkdir($dirname, 0755, true);
}
}

Some files were not shown because too many files have changed in this diff Show More